crystal
crystal copied to clipboard
Required/non-nullable field is removed from create due to being part of relation
Reason why: https://github.com/graphile/crystal/blob/00825e526b657ae9c498cd401eb3c24898ce583a/postgraphile/postgraphile/src/presets/relay.ts#L143
Summary
Required/non-nullable field is removed from create due to being part of relation
Steps to reproduce
Use relay plugin with a table that has a NOT NULL field which also has a relation on it
Expected results
It's part of the create mutation
Actual results
It's not
Additional context
Possible Solution
I think we can just remove the highlighted line? Or will it have unintended consequences
I can make the PR if so
for example i have Trips(id, userid, name, description) and userid was not part of the create. I tried using it and it resulted in a constraint error. When i removed the line i marked above, i got a graphql error as expected that this field was required.
Is user: ID not present instead? That’s the intention. The idea is that you should never deal with the underlying column values for primary keys and instead always use the global node identifier (ID)
Is
user: IDnot present instead? That’s the intention. The idea is that you should never deal with the underlying column values for primary keys and instead always use the global node identifier (ID)
How am I supposed to create/insert into the underlying table when the non nullable field userid is missing from the graphql schema?
You've not provided an example so it's hard to guide you, but typically you'd do something like:
create table topics (
id serial primary key,
title text not null
-- ...
);
create table posts (
id serial primary key,
topic_id int not null references topics,
body text not null
-- ...
);
insert into topics (title) values ('example');
mutation {
createPost(input: { post: {
topic: "WyJUb3BpYyIsMV0=" # < The `id` of the topic - NOT the underlying primary key.
body: "Hello world"
}}) {
post {
id
body
topic { id title }
}
}
}
Here is an example
CREATE TABLE currencies (
name varchar not null,
code char(3) not null PRIMARY KEY
CHECK(length(code) = 3 AND upper(code) = code),
UNIQUE(name, code)
);
CREATE TABLE tickets (
id SERIAL PRIMARY KEY,
userid INT NOT NULL,
price NUMERIC(12, 2) NOT NULL, -- 10 before decimal.
currency VARCHAR NULL,
FOREIGN KEY (userid) REFERENCES users(id),
FOREIGN KEY (currency) REFERENCES currencies(code)
);
mutation TicketEdit(
$id: Int!
$price: BigFloat
$currency: String
) {
updateTicket(
input: {
id: $id
patch: { currency: $currency, price: $price }
}
) {
ticket {
name
}
}
}
Fails:
{
"errors": [
{
"message": "Field \"currency\" is not defined by type \"TicketPatch\".",
"locations": [
{
"line": 9,
"column": 16
}
],
"extensions": {}
}
]
}
currency is completely missing!
I'm a bit confused, and there might be two different things going on.
But if we go back to the create mutations, i get issues with missing userid (it's represented as user { id } in queries), and also the currency, as stated above.
If i comment out
// `nodeId:insert` handles this
newBehavior.push(`-attribute:insert`);
then both of them come back.
You're using the Relay preset but you're also using $id: Int!... this doesn't make sense to me. The point of the Relay preset is that you shouldn't use the underlying database identifiers anywhere.
(i.e. it should be $id: ID!)
Please create a minimal reproduction using https://github.com/benjie/ouch-my-finger
I created a database with this SQL:
drop table if exists currencies, users, tickets cascade;
CREATE TABLE currencies (
name varchar not null,
code char(3) not null PRIMARY KEY CHECK(length(code) = 3 AND upper(code) = code),
UNIQUE(name, code)
);
create table users (
id serial primary key,
username text not null
);
CREATE TABLE tickets (
id SERIAL PRIMARY KEY,
userid INT NOT NULL,
price NUMERIC(12, 2) NOT NULL, -- 10 before decimal.
currency VARCHAR NULL,
FOREIGN KEY (userid) REFERENCES users(id),
FOREIGN KEY (currency) REFERENCES currencies(code)
);
insert into users (username) values ('Alice'), ('Bob'), ('Caroline');
insert into currencies (name, code) values ('£', 'GBP'), ('$', 'USD');
insert into tickets (userid, price, currency) values (1, 12.34, 'USD'), (2, 23.45, 'GBP'), (2, 34.56, 'GBP'), (3, 11.11, 'USD');
I configured PostGraphile to use the Amber and Relay presets.
I then ran this query to determine the IDs of the users:
query Q {
allUsers {
nodes {
username
id
}
}
}
I then used this ID perform a mutation:
mutation M {
createTicket(input: {
ticket: {
userByUserid: "WyJVc2VyIiwyXQ=="
price: "123.45"
}
}) {
ticket {
id
price
currencyByCurrency {
id
name
}
userByUserid {
id
username
}
}
}
}
The record was created exactly as would be expected:
{
"data": {
"createTicket": {
"ticket": {
"id": "WyJUaWNrZXQiLDVd",
"price": "123.45",
"currencyByCurrency": null,
"userByUserid": {
"id": "WyJVc2VyIiwyXQ==",
"username": "Bob"
}
}
}
}
}
I do not see an issue here; and no complete reproduction was made, so I'm going to go ahead and close this.