Open albttx opened 2 years ago
can confirm issue happen on 2.8.x also confirmed the workaround works.
I've created a minimal reproduction of this issue here if anyone wants a simple fork.
@albttx I'm afraid the order of insertion matters. This is described in the documentation in a few places, but it's easy to overlook.
In this sub-section in Mutations : Postgres : Insert : see the the !NOTE:
The order of object insertion can be controlled using the insertion_order option while creating a manual relationship. This is necessary to ensure nested inserts in one-to-one relationships are possible using either side as the parent which would otherwise error out with a Not-NULL violation error in one of the cases.
Following the links therein, we come to a sub-section with the sub-title **** where it's written:
Due to the way nested inserts are typically handled (described here), the order of object insertion needs to be specified using the insertion_order option while creating one-to-one relationships via the API. This is necessary to ensure nested inserts are possible using either side as the parent which would otherwise error out with a Not-NULL violation error in one of the cases.
This can be changed via calls to the metadata API, however it might be simpler just to re-order the GraphQL insert operations. Instead of treating user_company
as the nested object, treat user
as the nested object:
mutation MyMutation {
insert_user_company(objects: {company_name: "test42", user: {data: {email: "test42@gmail.com"}}}) {
returning {
company_name
user {
email
id
}
}
}
}
!CAVEAT EMPTOR: I reversed the GraphQL mutation above by hand. It might have a typo. :grin:
The error is thrown from here. We explicitly check for any column overlap between columns that are part of the relationship definition, columns provided from the input, and columns provided from the parent insert.
This may be an oversight: as thing stand currently, it seems it's not possible to insert a parent record with a known value if that value is also a foreign key for a child record. Example:
Database schema:
CREATE TABLE "public"."user" (
id INT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
name TEXT,
email TEXT NOT NULL UNIQUE
);
CREATE TABLE "public"."user_details" (
id INT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
user_email TEXT NOT NULL UNIQUE REFERENCES "public"."user" (email),
name TEXT
);
user
table metadata.
table:
name: user
schema: public
object_relationships:
- name: user_detail
using:
manual_configuration:
column_mapping:
email: user_email
insertion_order: after_parent
remote_table:
name: user_details
schema: public
user_details
table metadata
table:
name: user_details
schema: public
Mutation
mutation InsertUser {
insert_user (objects: {
name: "bob",
email: "name@domain.com",
user_detail: {
data: {
name: "bob"
}
}
}) {
affected_rows
}
}
Error
{
"errors": [
{
"extensions": {
"code": "validation-failed",
"path": "$.selectionSet.insert_user.args.objects[0].user_detail"
},
"message": "cannot insert object relationship \"user_detail\" as \"email\" column values are already determined"
}
]
}
This feels like an unintended oversight, and perhaps something we should improve on.
Based on the test case for this error, this may be an unintended interaction caused by setting the insertion order. It seems the check intends to prevent child records from setting values for the parent record when the parent record is created in the same mutation. However in this case the insertion order is reversed, so this should insertion should be permitted.
Note that as a workaround, it's possible to reverse the mutation to insert the child object as parent (assuming we add the relationship):
mutation InsertUser {
insert_user_details (objects: {
name: "bob",
user: {
data: {
name: "bob"
email: "name@domain.com",
}
}
}) {
affected_rows
}
}
This has been addressed in v2.30.0-beta.1.
We now skip the check that relationship columns can be over-specified when the insertion order is 'after_parent', allowing the parent row to provide the key columns for a child relationship.
Commit: https://github.com/hasura/graphql-engine/commit/57690491af9669420307a69c6d26d6204016e14f
Version Information
Server Version: CLI Version (for CLI related issue):
CLI Version : v2.5.2 hasura docker image: hasura/graphql-engine:v2.3.1
I want to upsert data into a nested table, Here is my schemas.
This is the GraphQL Query
And this is the output
Noticed that:
Using the email as constraint works, (I can upsert)