Search code examples
graphqlpostgraphile

GraphQL - Cannot update a table row


Say I have a table Person with attributes id and name. The GraphQL server is all setup by Postgraphile and working as I can query and create new entry. However, I could not update it. Scratching my head over and over again and I am still unable to find out the cause for this.

This is the mutation I tried that failed me every now and then.

mutation($id: Int!, $patch: PersonPatch!) {
  updatePersonById(input: { id: $id, patch: $patch }) {
    clientMutationId
  }
}

The variables

{
    id: 1, 
    patch: {"name": "newname"}
}

I was using Altair GraphQL client to submit the mutation request and the error message returned was "No values were updated in collection 'people' because no values were found."

The person of id = 1 does exist, confirmed by sending a query personById over to get his name. But I just couldn't update his name.

Edit #1

Below is the gql generated by Altair GraphQL Client

updatePersonById(
  input: UpdatePersonByIdInput!
): UpdatePersonPayload


input UpdatePersonByIdInput {
  clientMutationId: String
  patch: PersonPatch!
  id: Int!
}

input PersonPatch {
  id: Int
  name: String
}

Solution

  • Assuming you're using row-level security (RLS) it sounds like the row to be updated does not pass the required security policies for the currently authenticated user.

    Here's a small example; you'll want to adjust it to fit your own permissions system

    create table person (id serial primary key, name text);
    alter table person enable row level security;
    grant select, insert(name), update(name), delete on person to graphql;
    create policy select_all on person for select using (true);
    create policy insert_all on person for insert with check(true);
    create policy update_self on person for update using (id = current_person_id());
    create policy delete_self on person for delete using (id = current_person_id());
    

    where

    create function current_person_id() returns int as $$
      select nullif(current_setting('jwt.claims.person_id', true), '')::int;
    $$ language sql stable;
    

    If you need more guidance, feel free to drop into the Graphile chat.