aws-amplify / amplify-flutter

A declarative library with an easy-to-use interface for building Flutter applications on AWS.
https://docs.amplify.aws
Apache License 2.0
1.31k stars 243 forks source link

relational datastor queris are not working since 5.0.1 #1643

Closed thomasklaush closed 2 years ago

thomasklaush commented 2 years ago

Description

Relational querie return a empty list List comments = await Amplify.DataStore.query(Comment.classType, where: Post.STATUS.eq(PostStatus.ACTIVE));

Categories

Steps to Reproduce

5.0.0 Datastore is working

5.0.1 return an empty list

Screenshots

No response

Platforms

Android Device/Emulator API Level

No response

Environment

Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 3.0.1, on Microsoft Windows [Version 10.0.22000.675], locale de-DE)
Checking Android licenses is taking an unexpectedly long time...[√] Android toolchain - develop for Android devices (Android SDK version 32.1.0-rc1)
[√] Chrome - develop for the web
[√] Visual Studio - develop for Windows (Visual Studio Community 2022 17.1.3)
[√] Android Studio (version 2021.2)
[√] VS Code (version 1.67.2)
[√] Connected device (4 available)
[√] HTTP Host Availability

• No issues found!

Dependencies

Dart SDK 2.17.1
Flutter SDK 3.0.1
kubikos 1.0.18+31

dependencies:
- amplify_api 0.5.0 [amplify_api_plugin_interface amplify_core amplify_api_android amplify_api_ios collection flutter meta plugin_platform_interface]
- amplify_auth_cognito 0.5.0 [amplify_auth_cognito_android amplify_auth_cognito_ios amplify_auth_plugin_interface amplify_core collection flutter plugin_platform_interface]
- amplify_authenticator 0.1.2 [amplify_auth_cognito amplify_auth_plugin_interface amplify_core amplify_flutter collection flutter flutter_localizations intl]
- amplify_datastore 0.5.0 [flutter amplify_datastore_plugin_interface amplify_core plugin_platform_interface meta collection async]
- amplify_flutter 0.5.0 [amplify_analytics_plugin_interface amplify_api_plugin_interface amplify_auth_plugin_interface amplify_core amplify_datastore_plugin_interface amplify_flutter_android amplify_flutter_ios amplify_storage_plugin_interface collection flutter json_annotation meta plugin_platform_interface]
- amplify_storage_s3 0.5.0 [flutter amplify_storage_plugin_interface plugin_platform_interface amplify_storage_s3_android amplify_storage_s3_ios amplify_core]
- bloc 8.0.3 [meta]
- bloc_test 9.0.3 [bloc diff_match_patch meta mocktail test]
- cached_network_image 3.2.1 [flutter flutter_cache_manager octo_image cached_network_image_platform_interface cached_network_image_web]
- cbor 4.1.0 [typed_data convert meta]
- convert 3.0.1 [typed_data]
- cupertino_icons 1.0.4
- dartz 0.10.1
- data_connection_checker 0.3.4
- date_time_picker 2.1.0 [flutter intl]
- equatable 2.0.3 [collection meta]
- firebase_analytics 9.1.9 [firebase_analytics_platform_interface firebase_analytics_web firebase_core firebase_core_platform_interface flutter]
- firebase_core 1.17.1 [firebase_core_platform_interface firebase_core_web flutter meta]
- firebase_crashlytics 2.8.1 [firebase_core firebase_core_platform_interface firebase_crashlytics_platform_interface flutter stack_trace]
- fl_chart 0.50.6 [flutter equatable]
- flutter 0.0.0 [characters collection material_color_utilities meta vector_math sky_engine]
- flutter_bloc 8.0.1 [flutter bloc provider]
- flutter_localizations 0.0.0 [flutter intl characters clock collection material_color_utilities meta path vector_math]
- flutter_nfc_kit 3.3.1 [flutter flutter_web_plugins json_annotation ndef convert logging js]
- flutter_reactive_ble 5.0.2 [collection flutter functional_data meta reactive_ble_mobile reactive_ble_platform_interface]
- flutter_svg 1.1.0 [flutter meta path_drawing vector_math xml]
- font_awesome_flutter 10.1.0 [flutter]
- formz 0.4.1
- freezed_annotation 2.0.3 [collection json_annotation meta]
- get_it 7.2.0 [async collection]
- google_fonts 3.0.1 [flutter http path_provider crypto]
- http 0.13.4 [async http_parser meta path]
- image_picker 0.8.5+3 [flutter image_picker_android image_picker_for_web image_picker_ios image_picker_platform_interface]
- injectable 1.5.3 [get_it]
- intl 0.17.0 [clock path]
- json_annotation 4.5.0 [meta]
- logger 1.1.0
- mocktail 0.3.0 [collection matcher test]
- move_to_background 1.0.2 [flutter]
- path 1.8.1
- path_provider 2.0.10 [flutter path_provider_android path_provider_ios path_provider_linux path_provider_macos path_provider_platform_interface path_provider_windows]
- permission_handler 9.2.0 [flutter meta permission_handler_android permission_handler_apple permission_handler_windows permission_handler_platform_interface]
- radar_chart 2.1.0 [flutter]
- rxdart 0.27.3
- shared_preferences 2.0.15 [flutter shared_preferences_android shared_preferences_ios shared_preferences_linux shared_preferences_macos shared_preferences_platform_interface shared_preferences_web shared_preferences_windows]
- stats 2.0.0 [json_annotation]
- svg_path_parser 1.1.1 [string_scanner flutter]
- wakelock 0.6.1+2 [flutter meta wakelock_macos wakelock_platform_interface wakelock_web wakelock_windows]

transitive dependencies:
- _fe_analyzer_shared 38.0.0 [meta]
- amplify_analytics_plugin_interface 0.5.0 [amplify_core flutter meta]
- amplify_api_android 0.5.0 [flutter]
- amplify_api_ios 0.5.0 [amplify_core flutter]
- amplify_api_plugin_interface 0.5.0 [amplify_core collection flutter json_annotation meta]
- amplify_auth_cognito_android 0.5.0 [flutter]
- amplify_auth_cognito_ios 0.5.0 [amplify_core flutter]
- amplify_auth_plugin_interface 0.5.0 [amplify_core flutter meta]
- amplify_core 0.5.0 [collection date_time_format flutter meta plugin_platform_interface uuid]
- amplify_datastore_plugin_interface 0.5.0 [flutter meta collection amplify_core]
- amplify_flutter_android 0.5.0 [flutter]
- amplify_flutter_ios 0.5.0 [amplify_core flutter]
- amplify_storage_plugin_interface 0.5.0 [flutter meta amplify_core]
- amplify_storage_s3_android 0.5.0 [flutter]
- amplify_storage_s3_ios 0.5.0 [flutter]
- analyzer 3.4.1 [_fe_analyzer_shared collection convert crypto glob meta package_config path pub_semver source_span watcher yaml]
- args 2.3.1
- async 2.8.2 [collection meta]
- boolean_selector 2.1.0 [source_span string_scanner]
- cached_network_image_platform_interface 1.0.0 [flutter flutter_cache_manager]
- cached_network_image_web 1.0.1 [flutter flutter_cache_manager cached_network_image_platform_interface]
- characters 1.2.0
- charcode 1.3.1
- clock 1.1.0
- collection 1.16.0
- coverage 1.2.0 [args logging package_config path source_maps stack_trace vm_service]
- cross_file 0.3.3+1 [js meta]
- crypto 3.0.1 [collection typed_data]
- date_time_format 2.0.1
- diff_match_patch 0.4.1
- ffi 1.2.1
- file 6.1.2 [meta path]
- firebase_analytics_platform_interface 3.1.7 [firebase_core flutter meta plugin_platform_interface]
- firebase_analytics_web 0.4.0+14 [firebase_analytics_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins js]
- firebase_core_platform_interface 4.4.0 [collection flutter meta plugin_platform_interface]
- firebase_core_web 1.6.4 [firebase_core_platform_interface flutter flutter_web_plugins js meta]
- firebase_crashlytics_platform_interface 3.2.7 [collection firebase_core flutter meta plugin_platform_interface]
- fixnum 1.0.1
- flutter_blurhash 0.7.0 [flutter]
- flutter_cache_manager 3.3.0 [clock collection file flutter http path path_provider pedantic rxdart sqflite uuid]
- flutter_plugin_android_lifecycle 2.0.6 [flutter]
- flutter_web_plugins 0.0.0 [flutter js characters collection material_color_utilities meta vector_math]
- frontend_server_client 2.1.3 [async path]
- functional_data 1.0.0 [meta collection]
- glob 2.0.2 [async collection file path string_scanner]
- http_multi_server 3.2.0 [async]
- http_parser 4.0.1 [collection source_span string_scanner typed_data]
- image_picker_android 0.8.4+13 [flutter flutter_plugin_android_lifecycle image_picker_platform_interface]
- image_picker_for_web 2.1.8 [flutter flutter_web_plugins image_picker_platform_interface]
- image_picker_ios 0.8.5+5 [flutter image_picker_platform_interface]
- image_picker_platform_interface 2.5.0 [cross_file flutter http plugin_platform_interface]
- io 1.0.3 [meta path string_scanner]
- js 0.6.4
- logging 1.0.2
- matcher 0.12.11 [stack_trace]
- material_color_utilities 0.1.4
- meta 1.7.0
- mime 1.0.2
- ndef 0.3.1 [uuid]
- nested 1.0.0 [flutter]
- node_preamble 2.0.1
- octo_image 1.0.2 [flutter flutter_blurhash]
- package_config 2.0.2 [path]
- path_drawing 1.0.0 [vector_math meta path_parsing flutter]
- path_parsing 1.0.0 [vector_math meta]
- path_provider_android 2.0.14 [flutter path_provider_platform_interface]
- path_provider_ios 2.0.9 [flutter path_provider_platform_interface]
- path_provider_linux 2.1.6 [ffi flutter path path_provider_platform_interface xdg_directories]
- path_provider_macos 2.0.6 [flutter path_provider_platform_interface]
- path_provider_platform_interface 2.0.4 [flutter platform plugin_platform_interface]
- path_provider_windows 2.0.6 [ffi flutter path path_provider_platform_interface win32]
- pedantic 1.11.1
- permission_handler_android 9.0.2+1 [flutter permission_handler_platform_interface]
- permission_handler_apple 9.0.4 [flutter permission_handler_platform_interface]
- permission_handler_platform_interface 3.7.0 [flutter meta plugin_platform_interface]
- permission_handler_windows 0.1.0 [flutter permission_handler_platform_interface]
- petitparser 5.0.0 [meta]
- platform 3.1.0
- plugin_platform_interface 2.1.2 [meta]
- pool 1.5.0 [async stack_trace]
- process 4.2.4 [file path platform]
- protobuf 2.0.1 [fixnum collection]
- provider 6.0.3 [collection flutter nested]
- pub_semver 2.1.1 [collection meta]
- reactive_ble_mobile 5.0.2 [flutter protobuf reactive_ble_platform_interface]
- reactive_ble_platform_interface 5.0.2 [collection flutter functional_data meta plugin_platform_interface]
- shared_preferences_android 2.0.12 [flutter shared_preferences_platform_interface]
- shared_preferences_ios 2.1.1 [flutter shared_preferences_platform_interface]
- shared_preferences_linux 2.1.1 [file flutter path path_provider_linux path_provider_platform_interface shared_preferences_platform_interface]
- shared_preferences_macos 2.0.4 [flutter shared_preferences_platform_interface]
- shared_preferences_platform_interface 2.0.0 [flutter]
- shared_preferences_web 2.0.4 [flutter flutter_web_plugins shared_preferences_platform_interface]
- shared_preferences_windows 2.1.1 [file flutter path path_provider_platform_interface path_provider_windows shared_preferences_platform_interface]
- shelf 1.3.0 [async collection http_parser path stack_trace stream_channel]
- shelf_packages_handler 3.0.0 [path shelf shelf_static]
- shelf_static 1.1.0 [convert http_parser mime path shelf]
- shelf_web_socket 1.0.1 [shelf stream_channel web_socket_channel]
- sky_engine 0.0.99
- source_map_stack_trace 2.1.0 [path stack_trace source_maps]
- source_maps 0.10.10 [source_span]
- source_span 1.8.2 [collection path term_glyph]
- sqflite 2.0.2+1 [flutter sqflite_common path]
- sqflite_common 2.2.1+1 [synchronized path meta]
- stack_trace 1.10.0 [path]
- stream_channel 2.1.0 [async]
- string_scanner 1.1.0 [charcode source_span]
- synchronized 3.0.0+2
- term_glyph 1.2.0
- test 1.21.1 [analyzer async boolean_selector collection coverage http_multi_server io js node_preamble package_config path pool shelf shelf_packages_handler shelf_static shelf_web_socket source_span stack_trace stream_channel typed_data web_socket_channel webkit_inspection_protocol yaml test_api test_core]
- test_api 0.4.9 [async boolean_selector collection meta source_span stack_trace stream_channel string_scanner term_glyph matcher]
- test_core 0.4.13 [analyzer async args boolean_selector collection coverage frontend_server_client glob io meta package_config path pool source_map_stack_trace source_maps source_span stack_trace stream_channel vm_service yaml matcher test_api]
- typed_data 1.3.0 [collection]
- uuid 3.0.6 [crypto]
- vector_math 2.1.2
- vm_service 8.2.2
- wakelock_macos 0.4.0 [flutter flutter_web_plugins wakelock_platform_interface]
- wakelock_platform_interface 0.3.0 [flutter meta]
- wakelock_web 0.4.0 [flutter flutter_web_plugins js wakelock_platform_interface]
- wakelock_windows 0.2.0 [flutter wakelock_platform_interface win32]
- watcher 1.0.1 [async path]
- web_socket_channel 2.2.0 [async crypto stream_channel]
- webkit_inspection_protocol 1.1.0 [logging]
- win32 2.6.1 [ffi]
- xdg_directories 0.2.0+1 [meta path process]
- xml 6.1.0 [collection meta petitparser]
- yaml 3.1.1 [collection source_span string_scanner]

Device

Pixel 6 Pro

OS

Android 12

CLI Version

stable

Additional Context

No response

ragingsquirrel3 commented 2 years ago

@thomasklaush do you mind providing a copy of your graphql schema here so we can reproduce this (and potentially advise a workaround)?

thomasklaush commented 2 years ago

Workaround is to use 5.0.0 :-)

Sorry no other workaround currently

Query:

final List<ActivityEntry> activityEntries = await Amplify.DataStore.query(
        ActivityEntry.classType,
        where: ActivityEntry.ACTIVITYTYPE.eq(
          ActivityType.KUBIKOS_ACTIVITY,
        ),
      );

      activityEntries.forEach((element) async {
        final List<ActivityStepEntry> activityStepEntries = await Amplify.DataStore.query(
          ActivityStepEntry.classType,
          where: ActivityEntry.ID.eq(element.id),
        );
        logger.wtf('Kubikos Activity: ${element.name} with ${activityStepEntries.length} entries and id ${element.id}');
      });

Schema:

type UserStatusEntry @model @auth(rules: [{
    allow: owner,
    }]) {
  id: ID!
  cognitoUser: String
  entryType: EntryType!
  timestamp: String!
  jsonEntry: String!
}

enum EntryType {
  GENERAL_ATTRIBUTES
  FINGER_STRENGTH_STATUS
  MUSCLE_STRENGTH_STATUS
}

type UserStatusData @model @auth(rules: [{
    allow: owner,
    }]) {
  id: ID!
  nickname: String
  weight: Float!
  birthday: AWSDateTime!
}

type ActivityEntry @model @auth(rules: [{
    allow: owner,
    }]) {
  id: ID!
  activityType: ActivityType!
  name: String!
  timestamp: AWSDateTime!
  trainingTime: Int!
  activityStepEntries: [ActivityStepEntry] @hasMany(indexName: "byActivityEntry", fields: ["id"])
  s3Key: String
}

enum ActivityType {
  TRAINING_PLAN
  KUBIKOS_ACTIVITY
  KUBIKOS_FORCE_TEST
}

type ActivityStepEntry @model @auth(rules: [{
    allow: owner,
    }]) {
  id: ID!
  activityEntryID: ID @index(name: "byActivityEntry")
  activityEntry: ActivityEntry @belongsTo(fields: ["activityEntryID"])
  name: String!
  text: String!
  exerciseId: Int
  weight: Int
  numReps: Int
}
HuiSF commented 2 years ago

Hello @thomasklaush thanks for reporting this issue.

Nested query predicates are not well supported at this moment. It was working partially in Android but this behavior is not officially documented. v0.5.1 fixed an issue not being able to create sync expression on model id field. This fix may break the partial support of nested predicate in Android.

The recommended way is to make separate queries like the workaround that you are using. We have some improvements on the roadmap providing better experience related model association, including well supported nested predicate. Please feel free to follow the updates in this feature request, and please provide suggestions and use case sample if you have any.

thomasklaush commented 2 years ago

Hi @HuiSF ,

I use the workaround with separate queries, like written on AWS.

final List<ActivityStepEntry> activityStepEntries = await Amplify.DataStore.query(
          ActivityStepEntry.classType,
          where: ActivityEntry.ID.eq(element.id),
        );

It seems, that : where: ActivityEntry.ID.eq(element.id), is not working since 5.0.1.

HuiSF commented 2 years ago

Ok @thomasklaush thanks for the follow up, I'll take a look.

HuiSF commented 2 years ago

Hi @thomasklaush Looking at your code snippet and the schema

final List<ActivityEntry> activityEntries = await Amplify.DataStore.query(
  ActivityEntry.classType,
  where: ActivityEntry.ACTIVITYTYPE.eq(
    ActivityType.KUBIKOS_ACTIVITY,
  ),
);

activityEntries.forEach((element) async {
  final List<ActivityStepEntry> activityStepEntries = await Amplify.DataStore.query(
    ActivityStepEntry.classType,
    where: ActivityEntry.ID.eq(element.id),
  );
  logger.wtf('Kubikos Activity: ${element.name} with ${activityStepEntries.length} entries and id ${element.id}');
});

You were trying to query all children ActivityStepEntry records of parent ActivityEntry correct? if so I think the query should be

final List<ActivityStepEntry> activityStepEntries = await Amplify.DataStore.query(
  ActivityStepEntry.classType,
  where: ActivityEntry.ACTIVITYENTRY.eq(element.id),
);

From my tests, query by id works normally with version 0.5.1. (when providing correct predicate values.)

thomasklaush commented 2 years ago

Dear @HuiSF, this solution is not working at all

image

thomasklaush commented 2 years ago

@HuiSF your hint was good, just one mistake.

This is working, thanks.

Strange is, that it was working until 5.0.1 but now breaks.
I followed the documentation.

final List<ActivityStepEntry> activityStepEntries = await Amplify.DataStore.query(
            ActivityStepEntry.classType,
            where: ActivityStepEntry.ACTIVITYENTRY.eq(activityEntry.id),
          );
HuiSF commented 2 years ago

This is working, thanks.

Glad to hear @thomasklaush

Strange is, that it was working until 5.0.1 but now breaks.

It should've never worked, if there is no match on the model id filed with given value it always returns empty list, unless the value happened to match the id of ActivityStepEntry model.

Also could you point me which documentation you are referring to?

thomasklaush commented 2 years ago

@HuiSF maybe it's a misinterpretation, classical layer 8 issue.
I used [https://docs.amplify.aws/lib/datastore/relational/q/platform/flutter/#querying-relations]

List<Comment> comments = await Amplify.DataStore.query(Comment.classType,
    where: Post.STATUS.eq(PostStatus.ACTIVE));

I just changed STATUS to ID, since there is the id stored and I have the Id from the parent.
Sounded logical for me :-)
And it worked!
Until now. Anyway, thanks, problem solved.

HuiSF commented 2 years ago

Thanks! I'll verify the document

HuiSF commented 2 years ago

Update

The nested query listed in documentation is supposed to work

List<Comment> comments = await Amplify.DataStore.query(Comment.classType,
    where: Post.STATUS.eq(PostStatus.ACTIVE));

Tested this functionality with different versions

  1. version <= 0.5.0 without fix https://github.com/aws-amplify/amplify-flutter/pull/1600
    • This query predicate doesn't work in iOS which returns empty list (no match)
    • This query predicate returns expected results in Android
  2. version 0.5.1
    • This query predicate doesn't work in both iOS and Android

Causes

For test 1, it didn't work is iOS because of that below logic https://github.com/aws-amplify/amplify-flutter/blob/26509326680a4a9d9d3cf47746a8fb492ae6cf6f/packages/amplify_datastore/ios/Classes/types/query/QueryPredicateBuilder.swift#L22-L29 removes model name from model id field name which generates a wrong SQL command

select
  "root"."id" as "id", "root"."created" as "created", "root"."createdAt" as "createdAt",
  "root"."rating" as "rating", "root"."title" as "title", "root"."updatedAt" as "updatedAt",
  "root"."blogID" as "blogID", "blog"."id" as "blog.id", "blog"."createdAt" as "blog.createdAt",
  "blog"."name" as "blog.name", "blog"."updatedAt" as "blog.updatedAt"
from "Post" as "root"
left outer join "Blog" as "blog"
  on "blog"."id" = "root"."blogID"
where 1 = 1
  # "root"."id" should be "blog"."id" in order to return expected results
  and "root"."id" = ?

For test 1, it worked in Android, because of that model field id is named as <modelName>.id, which allows Android to generated correct SQL command.

For test 2, as we enforce the logic above, the query predicate stopped work in both iOS and Android.

Will keep investigation for a solution to fix this issue. In the meantime, please use the workaround to unblock dev works.

HuiSF commented 2 years ago

Closing this issue in favor of https://github.com/aws-amplify/amplify-flutter/issues/1449 which tracks the progress on better dev experience around model associations.