floor icon indicating copy to clipboard operation
floor copied to clipboard

Impossible to return int value from COUNT(*)

Open alectogeek opened this issue 4 years ago • 23 comments

`[INFO] Generating build script... [INFO] Generating build script completed, took 409ms

[INFO] Initializing inputs [INFO] Reading cached asset graph... [INFO] Reading cached asset graph completed, took 151ms

[INFO] Checking for updates since last build... [INFO] Checking for updates since last build completed, took 1.1s

[INFO] Running build... [INFO] 1.1s elapsed, 0/16 actions completed. [INFO] 2.1s elapsed, 0/16 actions completed. [INFO] 3.2s elapsed, 0/16 actions completed. [INFO] 4.3s elapsed, 0/16 actions completed. [INFO] 12.5s elapsed, 1/16 actions completed. [SEVERE] floor_generator:floor_generator on lib/data/db_configs/AppDatabase.dart: Error running FloorGenerator NoSuchMethodError: The getter 'name' was called on null. Receiver: null Tried calling: name [INFO] Running build completed, took 13.6s

[INFO] Caching finalized dependency graph... [INFO] Caching finalized dependency graph completed, took 121ms

[SEVERE] Failed after 13.8s pub finished with exit code 1 iMac-Tim:learnlanguage-mobile alectogeek$ flutter packages pub run build_runner build --delete-conflicting-outputs [INFO] Generating build script... [INFO] Generating build script completed, took 408ms

[INFO] Initializing inputs [INFO] Reading cached asset graph... [INFO] Reading cached asset graph completed, took 125ms

[INFO] Checking for updates since last build... [INFO] Checking for updates since last build completed, took 1.1s

[INFO] Running build... [INFO] 1.1s elapsed, 0/16 actions completed. [INFO] 2.1s elapsed, 0/16 actions completed. [INFO] 3.2s elapsed, 0/16 actions completed. [INFO] 4.3s elapsed, 0/16 actions completed. [INFO] 12.2s elapsed, 1/16 actions completed. [SEVERE] floor_generator:floor_generator on lib/data/db_configs/AppDatabase.dart: Error running FloorGenerator NoSuchMethodError: The getter 'name' was called on null. Receiver: null Tried calling: name [INFO] Running build completed, took 13.4s

[INFO] Caching finalized dependency graph... [INFO] Caching finalized dependency graph completed, took 118ms

[SEVERE] Failed after 13.5s pub finished with exit code 1 iMac-Tim:learnlanguage-mobile alectogeek$ flutter packages pub run build_runner build --delete-conflicting-outputs --help [INFO] Generating build script... [INFO] Generating build script completed, took 419ms

Performs a single build on the specified targets and then exits.

Usage: build_runner build [arguments] [directories] -h, --help Print this usage information. --delete-conflicting-outputs By default, the user will be prompted to delete any files which already exist but were not known to be generated by this specific build script.

                                Enabling this option skips the prompt and
                                deletes the files. This should typically be
                                used in continues integration servers and
                                tests, but not otherwise.

--low-resources-mode            Reduce the amount of memory consumed by the
                                build process. This will slow down builds
                                but allow them to progress in resource
                                constrained environments.

-c, --config Read build.<name>.yaml instead of the default build.yaml

--[no-]track-performance        Enables performance tracking and the /$perf
                                page.

--log-performance               A directory to write performance logs to,
                                must be in the current package. Implies
                                `--track-performance`.

-o, --output A directory to copy the fully built package to. Or a mapping from a top-level directory in the package to the directory to write a filtered build output to. For example "web:deploy".

-v, --verbose Enables verbose logging. -r, --[no-]release Build with release mode defaults for builders.

--define                        Sets the global `options` config for a
                                builder by key.

--[no-]symlink                  Symlink files in the output directories,
                                instead of copying.

--build-filter                  An explicit filter of files to build.
                                Relative paths and `package:` uris are
                                supported, including glob syntax for paths
                                portions (but not package names).
                                
                                If multiple filters are applied then outputs
                                matching any filter will be built (they do
                                not need to match all filters).

Run "build_runner help" to see global options. iMac-Tim:learnlanguage-mobile alectogeek$ flutter packages pub run build_runner build --delete-conflicting-outputs --verbose [INFO] Generating build script... [INFO] Generating build script completed, took 411ms

[INFO] BuildDefinition:Initializing inputs [INFO] BuildDefinition:Reading cached asset graph... [INFO] BuildDefinition:Reading cached asset graph completed, took 129ms

[INFO] BuildDefinition:Checking for updates since last build... [INFO] BuildDefinition:Checking for updates since last build completed, took 1.1s

[INFO] Build:Running build... [INFO] Heartbeat:1.1s elapsed, 0/16 actions completed. [INFO] Heartbeat:2.2s elapsed, 0/16 actions completed. [INFO] Heartbeat:3.2s elapsed, 0/16 actions completed. [INFO] Heartbeat:4.3s elapsed, 0/16 actions completed. [FINE] floor_generator:floor_generator on test/widget_test.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/subcategory_page/subcategory_page_bloc.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/subcategory_page/subcateegory_page_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/section_description_page/categories_grid_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/section_description_page/section_description_page_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/home_page/home_page_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/home_page/home_page_bloc.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/home_page/categories_footer.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/home_page/alphabet_footer.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/alphabet_testing_page/alphabet_testing_page_bloc.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/alphabet_testing_page/task_views/draw_letter_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/alphabet_testing_page/task_views/testing_letter_result_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/alphabet_testing_page/alphabet_testing_page_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/alphabet_description_page/alphabet_description_page_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/alphabet_description_page/alphabet_description_page_bloc.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/section_description_page/section_description_page_bloc.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/words_learning_page/task_views/picture_choice_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/words_learning_page/task_views/acquaintance_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/words_learning_page/task_views/build_word_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/words_learning_page/task_views/word_memorized_confirmation.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/words_learning_page/task_views/translation_choice_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/words_learning_page/words_learning_page_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/words_learning_page/words_learning_page_bloc.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/alphabet_learning_page/task_views/letter_acquaintance_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/alphabet_learning_page/task_views/draw_letter_task_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/alphabet_learning_page/task_views/letter_memorized_confirmation.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/alphabet_learning_page/alphabet_learning_page_bloc.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/alphabet_learning_page/alphabet_learning_page_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/testing_page/testing_result_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/testing_page/testing_page_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/testing_page/testing_page_bloc.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/ui/testing_page/testing_translation_choice_view.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/main.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/injection/injector.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/data/repository/study_data_repository.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/data/dao/study/section_dao.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/data/db_configs/AppDatabase.dart:Running FloorGenerator [SEVERE] floor_generator:floor_generator on lib/data/db_configs/AppDatabase.dart: Error running FloorGenerator NoSuchMethodError: The getter 'name' was called on null. Receiver: null Tried calling: name dart:core Object.noSuchMethod package:floor_generator/writer/query_method_writer.dart 66:57 QueryMethodWriter._generateMethodBody package:floor_generator/writer/query_method_writer.dart 28:21 QueryMethodWriter._generateQueryMethod package:floor_generator/writer/query_method_writer.dart 19:12 QueryMethodWriter.write package:floor_generator/writer/dao_writer.dart 217:52 DaoWriter._generateQueryMethods. dart:_internal ListIterable.toList package:floor_generator/writer/dao_writer.dart 218:10 DaoWriter._generateQueryMethods package:floor_generator/writer/dao_writer.dart 165:24 DaoWriter.write package:floor_generator/generator.dart 30:64 FloorGenerator.generateForAnnotatedElement. dart:core List.addAll package:built_collection/src/list/list_builder.dart 106:14 ListBuilder.addAll package:floor_generator/generator.dart 36:14 FloorGenerator.generateForAnnotatedElement. package:code_builder/src/specs/library.g.dart 108:33 _$LibraryBuilder.update package:code_builder/src/specs/library.g.dart 26:30 new _$Library package:floor_generator/generator.dart 32:21 FloorGenerator.generateForAnnotatedElement package:source_gen/src/generator_for_annotation.dart 47:30 GeneratorForAnnotation.generate package:source_gen/src/builder.dart 280:35 _generate package:source_gen/src/builder.dart 73:15 _Builder._generateForLibrary package:source_gen/src/builder.dart 67:11 _Builder.build package:build runBuilder package:build_runner_core/src/generate/build_impl.dart 478:19 _SingleBuild._runForInput... package:build_runner_core/src/generate/performance_tracker.dart 300:15 _NoOpBuilderActionTracker.trackStage package:build_runner_core/src/generate/build_impl.dart 476:23 _SingleBuild._runForInput.. package:timing/src/timing.dart 222:44 NoOpTimeTracker.track package:build_runner_core/src/generate/build_impl.dart 434:22 _SingleBuild._runForInput. package:pool/pool.dart 127:28 Pool.withResource package:build_runner_core/src/generate/build_impl.dart 430:17 _SingleBuild._runForInput package:build_runner_core/src/generate/build_impl.dart 378:38 _SingleBuild._runBuilder. dart:async Future.wait package:build_runner_core/src/generate/build_impl.dart 377:36 _SingleBuild._runBuilder dart:async _AsyncAwaitCompleter.start package:build_runner_core/src/generate/build_impl.dart 375:40 _SingleBuild._runBuilder package:build_runner_core/src/generate/build_impl.dart 323:20 _SingleBuild._runPhases.. dart:async _completeOnAsyncReturn package:build_runner_core/src/generate/build_impl.dart _SingleBuild._matchingPrimaryInputs

[FINE] floor_generator:floor_generator on lib/data/service/dictionary_data_service.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/data/service/letters_service.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/data/service/testing_service.dart:Running FloorGenerator [FINE] floor_generator:floor_generator on lib/data/service/words_learning_service.dart:Running FloorGenerator [INFO] Build:Running build completed, took 13.6s

[INFO] Build:Caching finalized dependency graph... [INFO] Build:Caching finalized dependency graph completed, took 113ms

[SEVERE] Build: Failed after 13.7s pub finished with exit code 1

#0 throwToolExit (package:flutter_tools/src/base/common.dart:28:3) #1 pubInteractively (package:flutter_tools/src/dart/pub.dart:191:5) #2 PackagesPassthroughCommand.runCommand (package:flutter_tools/src/commands/packages.dart:227:11) #3 FlutterCommand.verifyThenRunCommand (package:flutter_tools/src/runner/flutter_command.dart:490:18) #4 _asyncThenWrapperHelper. (dart:async-patch/async_patch.dart:71:64) #5 _rootRunUnary (dart:async/zone.dart:1132:38) #6 _CustomZone.runUnary (dart:async/zone.dart:1029:19) #7 _FutureListener.handleValue (dart:async/future_impl.dart:137:18) #8 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:678:45) #9 Future._propagateToListeners (dart:async/future_impl.dart:707:32) #10 Future._completeWithValue (dart:async/future_impl.dart:522:5) #11 Future._asyncComplete. (dart:async/future_impl.dart:552:7) #12 _rootRun (dart:async/zone.dart:1124:13) #13 _CustomZone.run (dart:async/zone.dart:1021:19) #14 _CustomZone.runGuarded (dart:async/zone.dart:923:7) #15 _CustomZone.bindCallbackGuarded. (dart:async/zone.dart:963:23) #16 _microtaskLoop (dart:async/schedule_microtask.dart:41:21) #17 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5) #18 _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:116:13) #19 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:173:5)`

The code fails on this part: `String _generateMethodBody() { final _methodBody = StringBuffer();

final valueLists = _generateInClauseValueLists();
if (valueLists.isNotEmpty) {
  _methodBody.write(valueLists.join(''));
}

final arguments = _generateArguments();
if (_queryMethod.returnsVoid) {
  _methodBody.write(_generateNoReturnQuery(arguments));
  return _methodBody.toString();
}

final mapper = '_${decapitalize(_queryMethod.entity.name)}Mapper';
if (_queryMethod.returnsStream) {
  _methodBody.write(_generateStreamQuery(arguments, mapper));
} else {
  _methodBody.write(_generateQuery(arguments, mapper));
}

return _methodBody.toString();

}`

My queries: `@Query('SELECT COUNT(*) FROM word ' 'INNER JOIN word_category_join' 'ON word.id=word_category_join.word_id ' 'WHERE word_category_join.category_id=(' 'SELECT id FROM category ' 'WHERE section_id=:sectionId LIMIT 1' ')' 'AND word.status=:status') Future getSectionWordsCountByStatus(int sectionId, String status);

@Query('SELECT COUNT(*) FROM word ' 'INNER JOIN word_category_join' 'ON word.id=word_category_join.word_id ' 'WHERE word_category_join.category_id=(' 'SELECT id FROM category' 'WHERE section_id=:sectionId LIMIT 1' ')') Future getAllSectionWordsCount(int sectionId);

`

alectogeek avatar Oct 01 '19 15:10 alectogeek

You need to define the return type of each DAO functions explicitly.Future is not enough. The fixed version of your query methods can be seen in the following.

@query('SELECT COUNT(*) FROM word '
  'INNER JOIN word_category_join'
  'ON word.id=word_category_join.word_id '
  'WHERE word_category_join.category_id=('
  'SELECT id FROM category '
  'WHERE section_id=:sectionId LIMIT 1'
  ')'
  'AND word.status=:status')
-Future getSectionWordsCountByStatus(int sectionId, String status);
+Future<int> getSectionWordsCountByStatus(int sectionId, String status);

@query('SELECT COUNT(*) FROM word '
  'INNER JOIN word_category_join'
  'ON word.id=word_category_join.word_id '
  'WHERE word_category_join.category_id=('
  'SELECT id FROM category'
  'WHERE section_id=:sectionId LIMIT 1'
  ')')
-Future getAllSectionWordsCount(int sectionId);
+Future<int> getAllSectionWordsCount(int sectionId);

Please report back if that has fixed the problems.

vitusortner avatar Oct 04 '19 07:10 vitusortner

Oh, excuse me, it was just a typo. I always define types and I have also tried with Future, but always see the following: [SEVERE] floor_generator:floor_generator on lib/data/db_configs/AppDatabase.dart: Error running FloorGenerator NoSuchMethodError: The getter 'name' was called on null. Receiver: null Tried calling: name There is a method in the package's source code that tries to get a class name for a mapper and code fails there. final mapper = '_${decapitalize(_queryMethod.entity.name)}Mapper';

alectogeek avatar Oct 04 '19 10:10 alectogeek

I guess I've found the cause! I've been trying to execute the raw query exactly in entityDao instead of calling appDatabase.query('sql'). It wasn't obvious to me :)

alectogeek avatar Oct 08 '19 16:10 alectogeek

I guess I've found the cause! I've been trying to execute the raw query exactly in entityDao instead of calling appDatabase.query('sql'). It wasn't obvious to me :)

Faced with the same situation. Where did you place this line? appDatabase.query('sql'). Thanks in advance!

SergeiMikhailovskii avatar Oct 17 '19 13:10 SergeiMikhailovskii

I guess I've found the cause! I've been trying to execute the raw query exactly in entityDao instead of calling appDatabase.query('sql'). It wasn't obvious to me :)

Faced with the same situation. Where did you place this line? appDatabase.query('sql'). Thanks in advance!

AppDatabase _appDatabase = await $FloorAppDatabase.databaseBuilder('app_database.db').build(); Map<String, dynamic> anyQuery = await _database.database.rawQuery('your sql', [arguments]);

Hope, it's clear now. If you have any difficulties, feel free to ask!

alectogeek avatar Oct 17 '19 14:10 alectogeek

@alectogeek , so, I can't create a query with SUM in annotation, as I understand?

SergeiMikhailovskii avatar Oct 17 '19 14:10 SergeiMikhailovskii

@SergeiMikhailovskii Why not? let's assume we have a table called 'bill' with fields [id, amount], then: final int numbersSum = await _database.database.rawQuery('SELECT SUM(amount) FROM bill')['SUM(amount)']; You just receive a map with needed fields. If you provide an alias in your sql query, you can use that as the key of map instead of 'SUM(amount)'.

Highly recommend you to take a look to autogenerated by floor files in order to understand how it works under the hood

alectogeek avatar Oct 17 '19 14:10 alectogeek

@alectogeek I understand it. I thought that I can do like @Query("SELECT SUM(amount) FROM Steps" " WHERE date=:_date")

SergeiMikhailovskii avatar Oct 17 '19 15:10 SergeiMikhailovskii

@SergeiMikhailovskii No, from DAO you can return only that data type, for which dao was created. But you still can do that by the direct raw query (including using WHERE clause and ":_date" as an argument)

alectogeek avatar Oct 17 '19 16:10 alectogeek

@alectogeek yes, got it, thanks a lot!

SergeiMikhailovskii avatar Oct 17 '19 16:10 SergeiMikhailovskii

I Have some same problem about return value

@Query('SELECT Count(*) FROM User WHERE id = :id') Future<int> checkDuplicateId(String id);

NoSuchMethodError: The getter 'name' was called on null. Receiver: null Tried calling: name [INFO] Running build completed, took 9.1s

JAICHANGPARK avatar Mar 05 '20 01:03 JAICHANGPARK

@JAICHANGPARK Try to implement it using rawQuery, works fine.

AppDatabase _database = await $FloorAppDatabase.databaseBuilder('myDb.db').build();
print(
await _database.database.rawQuery(
'SELECT Count(*) FROM User WHERE id = :id',
<dynamic>[id])).elementAt(0)['COUNT(*)']
)
);

alectogeek avatar Mar 05 '20 08:03 alectogeek

@alectogeek Awesome ! Thank you

JAICHANGPARK avatar Mar 05 '20 08:03 JAICHANGPARK

I Have some same problem about return value

@Query('SELECT Count(*) FROM User WHERE id = :id') Future<int> checkDuplicateId(String id);

NoSuchMethodError: The getter 'name' was called on null. Receiver: null Tried calling: name [INFO] Running build completed, took 9.1s

Same issue here. I'm trying to do a simple count as select count(1) from MyTable:


@Query('select count(*) from Product where enabled = 1')
Future<int> count();

`` 

jaumzera avatar Mar 17 '20 22:03 jaumzera

This is not possible right now because floor does not look at the queries to derive the type and also can't output arbitrary types. This will be adressed in #94 and #321 .

mqus avatar May 05 '20 12:05 mqus

It would be nice if the DAO could parse the generic results into primitive types. I understand the current limitations.

As an alternative I think it's possible to create a custom model with primitive type int and parse the result into it instead using raw queries. However it's just a hack!

cassioseffrin avatar Aug 03 '20 20:08 cassioseffrin

@alectogeek

@dao
abstract class Notesdao {
  @Query('SELECT * FROM Notes WHERE id = :id')
  Future<Notes?> findNotesById(int id);

  @Query('SELECT MAX(id) FROM Notes')
  Future<int?> getMaxCount();}

after code generation you can edit like this

 @override
  Future<int?> getMaxCount() async {
//_queryAdapter.queryNoReturn(sql) ====instedad of this
    var list = await database.rawQuery("SELECT max(id) as id FROM Notes");
    return int.parse(list.first["id"].toString());
  }

lavahasif avatar Sep 19 '21 22:09 lavahasif

Oh boy, I see https://github.com/vitusortner/floor/pull/361 is abandoned?

MrCsabaToth avatar Dec 24 '21 21:12 MrCsabaToth

I finally took a compromise and now I'm working well with generator: 1. Define an auxiliary entity: @Entity(tableName: "CountVO") class CountVO { @PrimaryKey(autoGenerate: true) int cnt;

CountVO({required this.cnt}); }

2. Define dao function @Query("SELECT COUNT(*) cnt FROM Task WHERE pid=:pid") Future<CountVO?> countByPid(int pid);

3. Use CountVO? countVO = await db.taskDao.countByPid(id); if (countVO != null && countVO.cnt > 0) { int cnt = countVO.cnt; return; }

liaoxuewei avatar Apr 02 '22 03:04 liaoxuewei

To add: an auxiliary table CountVO is created, too.

liaoxuewei avatar Apr 02 '22 03:04 liaoxuewei

Opened a discussion about the feature that should solve issues like it.

dkaera avatar Aug 10 '22 12:08 dkaera

Opened a discussion about the feature that should solve issues like it.

Unfortunately floor doesn't support this yet.

You can do something like what @alectogeek said for count field.

Future<int?> count() async {
    final floor = await AppDatabase.getInstance();
    var result = await floor!.database.rawQuery('SELECT COUNT(*) FROM GameResult');
    return result.first['COUNT(*)'] as int;
  }

tulioccalazans avatar Aug 10 '22 13:08 tulioccalazans

Unfortunately floor doesn't support this yet.

Yeah, that's true. My suggestion is to implement that 😁 I can do this after I've finished working on the RawQuery feature. The example I added in the discussion above demonstrates what the generated code should look like (in the future).

dkaera avatar Aug 10 '22 16:08 dkaera

Version 1.4.0 and 1.4.1 support DAO functions with COUNT queries, such as the one in the DAO docs https://github.com/pinchbv/floor/blob/develop/docs/daos.md#queries:

@Query('SELECT COUNT(id) FROM Person')
Future<int?> getPeopleCount(); // fetch records count
@Query('SELECT name FROM Person')
Future<List<String>> getAllPeopleNames(); // fetch all records from one column

So actually it's possible to return now int?.

MrCsabaToth avatar Jan 01 '23 05:01 MrCsabaToth

@MrCsabaToth yes, that's true The example project contains a sample for counting the number of records.

dkaera avatar Jan 03 '23 23:01 dkaera

Closed since the feature was added in version 1.4.0.

dkaera avatar Jan 04 '23 10:01 dkaera