begin;
    comment on schema public is '@graphql({"inflect_names": true})';
    create table account(
        id serial primary key,
        email varchar(255) not null,
        priority int,
        status text default 'active'
    );
    create table blog(
        id serial primary key,
        owner_id integer not null references account(id)
    );
    comment on table blog is e'@graphql({"totalCount": {"enabled": true}})';
    -- Make sure functions still work
    create function _echo_email(account)
        returns text
        language sql
    as $$ select $1.email $$;
    /*
        Literals
    */
    select graphql.resolve($$
    mutation {
      insertIntoAccountCollection(objects: [
        { email: "foo@barsley.com", priority: 1 },
        { email: "bar@foosworth.com" }
      ]) {
        affectedCount
        records {
          id
          status
          echoEmail
          blogCollection {
            totalCount
          }
        }
      }
    }
    $$);
                                                                                                                                        resolve                                                                                                                                         
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 {"data": {"insertIntoAccountCollection": {"records": [{"id": 1, "status": "active", "echoEmail": "foo@barsley.com", "blogCollection": {"totalCount": 0}}, {"id": 2, "status": "active", "echoEmail": "bar@foosworth.com", "blogCollection": {"totalCount": 0}}], "affectedCount": 2}}}
(1 row)

    select graphql.resolve($$
    mutation {
      insertIntoBlogCollection(objects: [{
        ownerId: 1
      }]) {
        records {
          id
          owner {
            id
          }
        }
      }
    }
    $$);
                                       resolve                                        
--------------------------------------------------------------------------------------
 {"data": {"insertIntoBlogCollection": {"records": [{"id": 1, "owner": {"id": 1}}]}}}
(1 row)

    -- Override a default on status with null
    select graphql.resolve($$
    mutation {
      insertIntoAccountCollection(objects: [
        { email: "baz@baz.com", status: null },
      ]) {
        affectedCount
        records {
          email
          status
        }
      }
    }
    $$);
                                                        resolve                                                         
------------------------------------------------------------------------------------------------------------------------
 {"data": {"insertIntoAccountCollection": {"records": [{"email": "baz@baz.com", "status": null}], "affectedCount": 1}}}
(1 row)

    /*
        Variables
    */
    select graphql.resolve($$
    mutation newAccount($emailAddress: String) {
       xyz: insertIntoAccountCollection(objects: [
        { email: $emailAddress },
        { email: "other@email.com" }
       ]) {
        affectedCount
        records {
          id
          email
        }
      }
    }
    $$,
    variables := '{"emailAddress": "foo@bar.com"}'::jsonb
    );
                                                            resolve                                                             
--------------------------------------------------------------------------------------------------------------------------------
 {"data": {"xyz": {"records": [{"id": 4, "email": "foo@bar.com"}, {"id": 5, "email": "other@email.com"}], "affectedCount": 2}}}
(1 row)

    -- Variable override of default with null results in null
    select graphql.resolve($$
    mutation newAccount($status: String) {
       xyz: insertIntoAccountCollection(objects: [
        { email: "1@email.com", status: $status}
       ]) {
        affectedCount
        records {
          email
          status
        }
      }
    }
    $$,
    variables := '{"status": null}'::jsonb
    );
                                            resolve                                             
------------------------------------------------------------------------------------------------
 {"data": {"xyz": {"records": [{"email": "1@email.com", "status": null}], "affectedCount": 1}}}
(1 row)

    -- Skipping variable override of default results in default
    select graphql.resolve($$
    mutation newAccount($status: String) {
       xyz: insertIntoAccountCollection(objects: [
        { email: "x@y.com", status: $status},
       ]) {
        affectedCount
        records {
          email
          status
        }
      }
    }
    $$,
    variables := '{}'::jsonb
    );
                                            resolve                                             
------------------------------------------------------------------------------------------------
 {"data": {"xyz": {"records": [{"email": "x@y.com", "status": "active"}], "affectedCount": 1}}}
(1 row)

    select graphql.resolve($$
    mutation newAccount($acc: AccountInsertInput!) {
       insertIntoAccountCollection(objects: [$acc]) {
        affectedCount
        records {
          id
          email
        }
      }
    }
    $$,
    variables := '{"acc": {"email": "bar@foo.com"}}'::jsonb
    );
                                                     resolve                                                     
-----------------------------------------------------------------------------------------------------------------
 {"data": {"insertIntoAccountCollection": {"records": [{"id": 8, "email": "bar@foo.com"}], "affectedCount": 1}}}
(1 row)

    select graphql.resolve($$
    mutation newAccounts($acc: [AccountInsertInput!]!) {
       insertIntoAccountCollection(objects: $accs) {
        affectedCount
        records {
          id
          email
        }
      }
    }
    $$,
    variables := '{"accs": [{"email": "bar@foo.com"}]}'::jsonb
    );
                                                     resolve                                                     
-----------------------------------------------------------------------------------------------------------------
 {"data": {"insertIntoAccountCollection": {"records": [{"id": 9, "email": "bar@foo.com"}], "affectedCount": 1}}}
(1 row)

    -- Single object coerces to a list
    select graphql.resolve($$
    mutation {
      insertIntoBlogCollection(objects: {ownerId: 1}) {
        affectedCount
      }
    }
    $$);
                           resolve                            
--------------------------------------------------------------
 {"data": {"insertIntoBlogCollection": {"affectedCount": 1}}}
(1 row)

    /*
        Errors
    */
    -- Field does not exist
    select graphql.resolve($$
    mutation createAccount($acc: AccountInsertInput) {
       insertIntoAccountCollection(objects: [$acc]) {
        affectedCount
        records {
          id
          email
        }
      }
    }
    $$,
    variables := '{"acc": {"doesNotExist": "other"}}'::jsonb
    );
                                                       resolve                                                       
---------------------------------------------------------------------------------------------------------------------
 {"data": null, "errors": [{"message": "Input for type AccountInsertInput contains extra keys [\"doesNotExist\"]"}]}
(1 row)

    -- Wrong input type (list of string, not list of object)
    select graphql.resolve($$
    mutation {
      insertIntoBlogCollection(objects: ["not an object"]) {
        affectedCount
      }
    }
    $$);
                                      resolve                                      
-----------------------------------------------------------------------------------
 {"data": null, "errors": [{"message": "Invalid input for BlogInsertInput type"}]}
(1 row)

    -- objects argument is missing
    select graphql.resolve($$
    mutation {
      insertIntoBlogCollection {
        affectedCount
      }
    }
    $$);
                                  resolve                                  
---------------------------------------------------------------------------
 {"data": null, "errors": [{"message": "Invalid input for NonNull type"}]}
(1 row)

    -- Empty call
    select graphql.resolve($$
    mutation {
      insertIntoBlogCollection(objects: []) {
        affectedCount
      }
    }
    $$);
                                          resolve                                           
--------------------------------------------------------------------------------------------
 {"data": null, "errors": [{"message": "At least one record must be provided to objects"}]}
(1 row)

rollback;
