Closed skim037 closed 6 months ago
Hi @skim037 thanks for reposting this issue. I've copied your model schemas and code and will test later tomorrow.
Hi @skim037 I am able to reproduce this issue and get the following error:
Unhandled Exception: DataStoreException(message: Received a create mutation for an item that has already been created, recoverySuggestion: Review your app code and ensure you are not issuing incorrect DataStore.save() calls for the same model.
Many people are gone for holidays now and I'd like to double check with them if using the same custom primary key value for 3 different models is expected or recommended in your case and in general.
From what you are doing I imagine you want to use the same custom primary key to easily 'link' these 3 different model types together. Could you instead use 1 primary model that has a '@hasOne' relationship to the 3 different model types you need. So something like below. You can access the Parent model with the profileId and then use that to access the testTableOne/Two/Three objects.
type Parent @model {
id: ID!
profile_id: ID! @primaryKey
testTableChild: TestTableOne @hasOne
testTableChild2: TestTableTwo @hasOne
testTableChild3: TestTableThree @hasOne
}
type TestTableOne @model @auth(rules: [{allow: public}]) {
id: ID!
profile_id: ID! @primaryKey
count: Int
}
type TestTableTwo @model @auth(rules: [{allow: public}]) {
id: ID!
profile_id: ID! @primaryKey
count: Int
}
type TestTableThree @model @auth(rules: [{allow: public}]) {
id: ID!
profile_id: ID! @primaryKey
count: Int
}
Hi @fjnoyp
I think the model change you propose would work if I use unique profile_id
for all three models but that would defeat the purpose of using custom primary key in the first place, wouldn't it?
Sorry if I didn't get your point properly.
Unless we fully understand what conditions would trigger such exception, it makes us very uncomfortable to use custom primary key at all.
Hi @skim037 thanks for all the details, I'm wondering how to you query by using the value of profile_id
? I hope to understand your case better.
In addition to also checked that this issue is applicable to Android, have you seen the exact behavior in Android as well please?
@fjnoyp has confirm that the same exception appears in Android as well.
Dug into the implementation which throws this exception in amplify-swift it looks like the logic doesn't allow different model types having the same primary key value (not really custom primary key feature specific). If I remembered correctly, there was an effort in both amplify-swift and amplify-android to allow this use case. This might be a missing spot. I will follow up with amplify-swift and amplify-android maintainers to confirm and determine a solution.
@skim037 - I believe this issue has been addressed in the native iOS library. Were you seeing this issue in iOS only, or was it an issue for you on Android as well?
@skim037 - I've confirmed this is working in amplify_datastore: ^1.4.0
. I'm going to close this as resolved. Please reach out if you have any concerns.
Apologies, this is fixed in iOS, but I'm seeing an exception being thrown on Android. Will work with the Android team to get it resolved.
Android exception:
Sync failed: foreign key constraint violation: ModelWithMetadata{model=SerializedModel{id='1a696661-2d5a-47e7-b4c4-6d57fcfd63d8', serializedData={count=100, createdAt=2023-10-06T18:37:45.532Z, id=6447a0cf-1641-44de-921e-8939c7c611ca, profile_id=1a696661-2d5a-47e7-b4c4-6d57fcfd63d8, updatedAt=2023-10-06T18:37:45.532Z}, modelName=TestTableOne}, syncMetadata=ModelMetadata{id='TestTableOne|1a696661-2d5a-47e7-b4c4-6d57fcfd63d8', _deleted=null, _version=1, _lastChangedAt=Temporal.Timestamp{timestamp=1696617465563}}}
W/amplify:aws-datastore(17630): DataStoreException{message=Invalid SQL statement: INSERT INTO `TestTableOne` (`id`, `count`, `createdAt`, `profile_id`, `updatedAt`) VALUES (?, ?, ?, ?, ?), cause=android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: TestTableOne.profile_id (code 1555 SQLITE_CONSTRAINT_PRIMARYKEY), recoverySuggestion=There is a possibility that there is a bug if this error persists. Please take a look at
W/amplify:aws-datastore(17630): https://github.com/aws-amplify/amplify-android/issues to see if there are any existing issues that
W/amplify:aws-datastore(17630): match your scenario, and file an issue with the details of the bug if there isn't.}
W/amplify:aws-datastore(17630): at com.amplifyframework.datastore.storage.sqlite.SQLCommandProcessor.dataStoreException(SQLCommandProcessor.java:87)
W/amplify:aws-datastore(17630): at com.amplifyframework.datastore.storage.sqlite.SQLCommandProcessor.execute(SQLCommandProcessor.java:82)
W/amplify:aws-datastore(17630): at com.amplifyframework.datastore.storage.sqlite.SQLiteStorageAdapter.writeData(SQLiteStorageAdapter.java:769)
W/amplify:aws-datastore(17630): at com.amplifyframework.datastore.storage.sqlite.SQLiteStorageAdapter.lambda$save$3$com-amplifyframework-datastore-storage-sqlite-SQLiteStorageAdapter(SQLiteStorageAdapter.java:366)
W/amplify:aws-datastore(17630): at com.amplifyframework.datastore.storage.sqlite.SQLiteStorageAdapter$$ExternalSyntheticLambda7.run(Unknown Source:12)
W/amplify:aws-datastore(17630): at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:463)
W/amplify:aws-datastore(17630): at java.util.concurrent.FutureTask.run(FutureTask.java:264)
W/amplify:aws-datastore(17630): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
W/amplify:aws-datastore(17630): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
W/amplify:aws-datastore(17630): at java.lang.Thread.run(Thread.java:1012)
W/amplify:aws-datastore(17630): Caused by: android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: TestTableOne.profile_id (code 1555 SQLITE_CONSTRAINT_PRIMARYKEY)
W/amplify:aws-datastore(17630): at android.database.sqlite.SQLiteConnection.nativeExecute(Native Method)
W/amplify:aws-datastore(17630): at android.database.sqlite.SQLiteConnection.execute(SQLiteConnection.java:730)
W/amplify:aws-datastore(17630): at android.database.sqlite.SQLiteSession.execute(SQLiteSession.java:621)
W/amplify:aws-datastore(17630): at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:47)
W/amplify:aws-datastore(17630): at com.amplifyframework.datastore.storage.sqlite.SQLCommandProcessor.execute(SQLCommandProcessor.java:78)
W/amplify:aws-datastore(17630): ... 8 more
Thank you for your patience. The issue has been fixed in version 1.8.0. and I'm closing it. However, if you encounter any issues after updating to version 1.8.0, please don't hesitate to reopen it.
Description
I noticed that this issue was closed. I tried again but the issue is still there.
I will try to provide clear repro steps.
model
Make sure to use
@primaryKey
annotation.Code to save model
Make sure to use same profileId for all three models.
Repository class
Result I expect
A record in
TestTableOne
with profileId and count 100 A record inTestTableTwo
with profileId and count 101 (Same profileId as in TestTableOne) A record inTestTableThree
with profileId and count 102 (Same profileId as in TestTableOne)Result I see
A record in
TestTableOne
with profileId and count 100 A record inTestTableTwo
with the same profileId and count 101 No record inTestTableThree
Interesting observations
Categories
Steps to Reproduce
No response
Screenshots
No response
Platforms
Android Device/Emulator API Level
No response
Environment
Dependencies
Device
iPhone 12
OS
iOS 16.1.2
Deployment Method
Amplify CLI
CLI Version
10.5.2
Additional Context
No response
Amplify Config
{}