graphql-engine/rfcs/mssql-delete-mutations.md
Abby Sassel 7e3c9acfe2 server/mssql: delete mutations rfc
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/2596
Co-authored-by: Gil Mizrahi <8547573+soupi@users.noreply.github.com>
GitOrigin-RevId: f6c0049114d4d009d588efe650aed1063a8b87ed
2021-10-26 13:24:04 +00:00

6.0 KiB

DELETE mutations on SQL Server

Metadata

---
authors: Abby (@sassela), Gil (@soupi)
---

User story

As a user, I would like to be able to delete rows from a certain mssql table using a predicate, similarly to how I'm able to do so for a postgres table.

Deleting rows from a table should be done via sending a GraphQL mutation to the /v1/graphql endpoint.

Delete mutations should respect row-level permissions.

Interface

Request

Users can specify a deletion mutation in one of the following ways:

Response

The mutation response is specified in the GraphQL spec, including:

{ data # the returned data is specified by the `mutation-response` section
    {
    affected_rows
    returning { # the `returning` statement can include nested objects
        response-field1
        response-field2
        ..
    }
    }
}

or ...

{ errors {
    extensions
    message
  }
}

Success

  • test_graphql_mutations.py tests pass for MSSQL:
    • test for each of the above linked queries
    • basic deletes: TestGraphqlDeleteBasic
    • table permissions: TestGraphqlDeletePermissions
    • constraints and errors: TestGraphqlDeleteConstraints
    • custom schema
      • custom names: TestGraphqlMutationCustomGraphQLTableName
      • custom root fields: TestGraphqlMutationCustomSchema
  • delete mutations are executable via the console and CLI
  • delete mutations on SQL Server are documented in Hasura docs. The existing Postgres docs can be used as a guide.

Checkpoints

These checkpoints do not necessarily need to be delivered in the same PR. In fact, prefer smaller PRs where they are functional, tested, and self-contained.

  • generate DELETE mutations schema by completing the msBuildTableDeleteMutationFields function
  • generate and execute DELETE SQL by adding an executeDelete function
    • convertDelete can be used as a reference implementation for SQL generation

    • executeInsert can be used as a reference implementation for mutation response generation

    • We cannot retrieve returning fields once the delete statement is executed.Consider the following options to fetch returning output:

      1. Use table variables in conjunction with the OUTPUT clause to capture the delete statement's output.
      2. SELECT then DELETE: Fetch the data for returning and affected_rows fields first, by running the SELECT query generated by mkMutationOutputSelect inclusive of the DELETE query's WHERE and permissions filters, i.e.
        WITH with_alias AS (
          SELECT * FROM table_name WHERE <where-from-delete-query>
        )
        <select statement generated by mkMutationOutputSelect function>
        
        ...before executing the generated DELETE statement

      Developers should consider the possible interaction with transaction isolation levels of both approaches when implementing. Whilst the first option is recommended after some internal discussion, developers should revive the discussion with @hasura/server-data-sources or do a short technical spike if there is any uncertainty about the better approach.

    • Nested return statements can be supported by drawing inspiration from the existing mkMutationOutputSelect function.

    • Delete permissions are bundled in the IR with the WHERE expression, in mkDeleteObject; the generated SQL should contain the filter expression and permissions in the same WHERE clause.

    • Regarding INSTEAD OF DELETE triggers: we need not try and do anything better than the limitations of the OUTPUT statement.