Skip to content

id is non-nullable in mutation input in view using INSTEAD OF INSERT #1544

@jsmnbom

Description

@jsmnbom

Summary

I made a view, to expose an underlying translationlayer in a way that react-admin would understand. This works great for showing it, but when trying to create a new one, I ran into an issue where I cannot get postgraphile to output a correct mutation.

Steps to reproduce

  • Create a db (viewinsertbug for example purposes)
  • Execute this sql (i tried removing as much as I could while still having it make sense in terms of how I use it)
create extension if not exists "hstore";

create table public.tr_language (
    code text primary key,
    display_name text not null
);

create table public.event (
    id serial primary key,
    starts_at timestamptz not null,
    ends_at timestamptz not null
);

create table public.event_tr (
    event_id integer references public.event (id),
    language_code text references public.tr_language (code),
    title text not null,
    primary key (event_id, language_code)
);

create view public.admin_event as
select
    e.id,
    e.starts_at,
    e.ends_at,
    hstore (array_agg(et.language_code), array_agg(et.title)) title
from
    public.event e
    inner join public.event_tr et on et.event_id = e.id
group by
    e.id;

comment on view public.admin_event is E'@primaryKey id';

comment on column public.admin_event.starts_at is E'@notNull';

comment on column public.admin_event.ends_at is E'@notNull';

comment on column public.admin_event.title is E'@notNull';

create function public.admin_event_insert ()
    returns trigger
    as $$
declare
    e_id int;
    f record;
begin
    insert into public.event
        values (default, new.starts_at, new.ends_at)
    returning
        id into e_id;
    for f in
    select
        title.key as language_code,
        title.value as title
    from
        each (new.title::hstore) title loop insert into public.event_tr
            values (e_id, f.language_code, f.title);
end loop;
    return new;
end;
$$
language plpgsql;

create trigger admin_event_insert
    instead of INSERT on public.admin_event for each row
    execute procedure public.admin_event_insert ();

--comment on function public.admin_event_insert() IS E'@arg0variant patch';
--comment on column public.admin_event.id IS E'@omit create'
  • Start postgraphile, e.g. using
~/.node_modules/bin/postgraphile \
  --connection postgres://localhost/viewinsertbug \
  --owner-connection postgres://localhost/viewinsertbug \
  --schema public \
  --enhance-graphiql \
  --append-plugins @graphile-contrib/pg-simplify-inflector \
  --no-ignore-rbac

Expected results

The mutation below should work and create an event, as well as two event_trs.

mutation MyMutation {
  createAdminEvent(
    input: {
      adminEvent: {
        startsAt: "2021-10-20T21:49:23.051Z"
        endsAt: "2021-10-29T21:49:00.000Z"
        title: { en: "ent", da: "dat" }
      }
    }
  ) {
    endsAt
      startsAt
      id
      title
  }
}

Actual results

When running the above query the following error is outputted.
"Field \"AdminEventInput.id\" of required type \"Int!\" was not provided."

Additional context

Linux 5.14.12-arch1-1
Node v16.11.1
NPM 8.1.0
PostgreSQL 13.4
PostGraphile 4.12.4

Possible Solution

I tried solving it by adding a smart comment.
comment on column public.admin_event.id IS E'@omit create';

And this helps a lot and the mutation actually succeeds, but then we get another issue. The returned data is

{
  "data": {
    "createAdminEvent": {
      "adminEvent": {
        "endsAt": "2021-10-29T23:49:00+02:00",
        "startsAt": "2021-10-20T23:49:23.051+02:00",
        "id": null,
        "title": {
          "da": "dat",
          "en": "ent"
        }
      }
    }
  }
}

which has no id field, even tho the mutation did get an id assigned in the database, and I need the id.

Another thing i tried was adding the smart comment
comment on function public.admin_event_insert() IS E'@arg0variant patch';
but this obviously doesn't work since admin_event_insert() doesn't actually accept any arguments.

I think a solution might be to add a smart comment @newVariant, that sets the type of NEW inside the function, but I honestly have no idea anymore :/

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions