Incorrect codegen error - DataStore does not support 1 to 1 connection with both sides of connection as optional field
Describe the bug Codegen produces the following error even though both sides of the connection are actually non-optional: "DataStore does not support 1 to 1 connection with both sides of connection as optional field"
To Reproduce
- Create the schema below
- Add api, push, then run
amplify codegen models - See error
Expected behavior Generates the code
Environment:
- Amplify Framework Version: 4.21.0
- Dependency Manager: Cocoapods
- Swift Version : 5.0
Device Information:
- Device: Simulator
- iOS Version: iOS 13.5
Additional context Schema:
type PhoneCall @model {
id: ID!
caller: Person! @connection(name: "PhoneCallCaller")
callee: Person! @connection(name: "PhoneCallCallee")
transcript: Transcript! @connection(name: "PhoneCallTranscript")
}
type Person @model {
id: ID!
name: String!
callerOf: [PhoneCall!] @connection(name: "PhoneCallCaller")
calleeOf: [PhoneCall!] @connection(name: "PhoneCallCallee")
}
type Transcript @model {
id: ID!
text: String!
language: String
phoneCall: PhoneCall! @connection(name: "PhoneCallTranscript")
}
I'm having the same issue on amplify-android library. Maybe this is related to amplify-cli...
+1
type TestModel @model {
id: ID!
name: String
}
type TestModel2 @model {
id: ID!
test1: TestModel! @connection
}
this works well, but
type TestModel @model {
id: ID!
name: String
}
type TestModel2 @model {
id: ID!
test1Id: ID!
test1: TestModel! @connection(fields: ["test1Id"])
}
this causes error: DataStore does not support 1 to 1 connection with both sides of connection as optional field
But,
type TestModel @model {
id: ID!
name: String
}
type TestModel2 @model {
id: ID!
test1Id: ID!
test1: TestModel @connection(fields: ["test1Id"]) # `!` removed
}
This works!!! 🙃 @anthonymoretti @watanabethais
Thanks guys. I've been told it's being looked into, has to do with which side of the relationship should be the "owner". I've made a feature request that possibly addresses this and other issues RFC - Simplified @connection directive
I just ran into this, and can confirm paradoxically removing the ! from the connected model (TestModel in the example above) avoids the error as well for me.
The downside is now the generated TypeScript binding has the field as a nullable field when I want it non-nullable, especially as the key (test1Id in the example above) is defined as non-nullable, so it doesn't make sense that the connected field is nullable.
I wonder if there's any update to this bug?
Isn't the bug here?: https://github.com/aws-amplify/amplify-cli/blob/master/packages/amplify-codegen-appsync-model-plugin/src/utils/process-connections.ts#L201
There are only 3 branches in the if statement checking if both sides of the connection are null or not:
if (!field.isNullable && otherSideField.isNullable)else if (field.isNullable && !otherSideField.isNullable)else
But there are 4 separate possibilities, and 2 of them are being swallowed up by the last else clause. It looks like there should be a separate clause checking that both are not null and not throwing an error in that case.
I confirmed by monkey patch that if there was this 4th branch added (!field.isNullable && !otherSideField.isNullable), then it would fall into it and not error out for the schema @wooklym provided above.
@drochetti is the above known, and any idea if this will be fixed any time soon if so?
This issue is stale because it has been open 14 days with no activity. Please, provide an update or this will be automatically closed in 7 days.
This is still a relevant issue and needs to be triaged and prioritized.
I'm using a translation tool, so it may be confusing
I added a child element connection to the parent element and verified that it works
In @wooklym, amplify codegen models does not output an error, but DataStore.query cannot get it as Connection.
type TestModel @model {
id: ID!
name: String
children: [TestModel2] @connection(fields: ["id"])
}
type TestModel2 @model {
id: ID!
test1Id: ID!
test1: TestModel! @connection(fields: ["test1Id"])
}
@danrivett did any downstream issues come up from your monkey patch?
@kldeb we removed the connection for now instead of money-patching; we monkey-patched just to prove out the theory that the if-block is missing a clause and it would fall into that missing clause if added instead of erroring.
@drochetti I guess everyone is busy, but been 6 months since this ticket was opened and the issue looks relatively simple to triage if someone is available to.
If this is an easy fix maybe i'll try my luck with a PR
@danrivett how did you apply the monkey patch?
For the record this isn't just a iOS issue. Hit it today trying to get the new Admin UI working on an existing schema, this requires DataStore to be configurated which throws this error when I push :(
@kldeb we removed the connection for now instead of money-patching; we monkey-patched just to prove out the theory that the if-block is missing a clause and it would fall into that missing clause if added instead of erroring.
@drochetti I guess everyone is busy, but been 6 months since this ticket was opened and the issue looks relatively simple to triage if someone is available to.
I mentioned it earlier in https://github.com/aws-amplify/amplify-ios/issues/505#issuecomment-639804984 - I was told it's being looked into and has to do with determining which side of the relationship should be the "owner". If the missing else clause is added I think you still have the problem of determining the "owner" and thus have a problem setting deletion rules. I've made a feature request that might solve this and other problems: RFC - Simplified @connection directive
Any updates?
Thanks for taking the time to comment. We’re working on ways to make DataStore relationships simpler. We’ll update this issue as soon as we have more information.
What's the rationale for not generating models when both sides of a connection are optional?
Any update on this yet?
Any update on this?
With the launch of TransformerV2 directives (hasOne/belongsTo/hasMany/etc), I started off by translating the schema over to
type PhoneCall @model {
id: ID!
callerId: ID! @index(name: "byCaller")
calleeId: ID! @index(name: "byCallee")
caller: Person! @belongsTo(fields: ["callerId"])
callee: Person! @belongsTo(fields: ["calleeId"])
transcript: Transcript @hasOne
}
type Person @model {
id: ID!
name: String!
callerOf: [PhoneCall!] @hasMany(indexName: "byCaller")
calleeOf: [PhoneCall!] @hasMany(indexName: "byCallee")
}
type Transcript @model {
id: ID!
text: String!
language: String
phoneCall: PhoneCall @belongsTo
}
I kept both 1:1 Transcript to PhoneCall as optional, but now that I reviewed the conversation here, I believe one side can made required. Let's take, for example, the calling code when using DataStore (Swift). We have to create individual instances of PhoneCall and Transcript, so at least one of the sides have to be optional to allow the FK to be set later:
// Create both instances
var phoneCall = PhoneCall(caller: savedCaller, callee: savedCallee)
let transcript = Transcript(text: "text", phoneCall: phoneCall)
// Set the PhoneCall's FK to the Transcript, ie.
phoneCall.setTranscript(transcript)
phoneCall.phoneCallTranscriptId = transcript.id
// Save both models
try await DataStore.save(phoneCall)
try await DataStore.save(transcript)
In this calling pattern, I think the Transcript's connected model to PhoneCall can be made required. This use case is enabled by the latest codegen and library changes we are currently working on in https://github.com/aws-amplify/amplify-swift/pull/2583
The Lazy Loading feature was released in version 2.4.0. This should address this issue.
This support requires the lazy loading feature flag. Please use the latest version of the amplify CLI and review or make updates to cli.json (in the amplify folder) to ensure you have the following settings:
"transformerversion":2 "respectprimarykeyattributesonconnectionfield": true "generatemodelsforlazyloadandcustomselectionset": true
Please open a new issue if this release does not resolve the problem.
This is yet another bug that makes me regret every relying on Amplify.
I can't go to V2 because of https://github.com/aws-amplify/amplify-category-api/issues/110
My schema worked perfectly, but not I am getting this error and it is stopping releases.
Hey @spc16670, this issue was closed since we released the changes in 2.4.0 of the library. It was related to representing 1:1 relationships in the swift codegenerated model types. At a glance, I don't see the correlation between the two issues, the linked issue sounds like it's about auth rules with groupsField and groupClaim not working. If i'm wrong here, please open a new issue in the library repo with more details, and reference the related issue you're referring to https://github.com/aws-amplify/amplify-swift/issues/new?assignees=&labels=&projects=&template=bug_report.yaml