graphql-engine/docs/graphql/manual/mutations/insert.rst
Rakesh Emmadi 5bafdce9a3 fix delete mutation returning incorrect data (fix #1794) (fix #1763) (#1827)
From `alpha-40` we've been using a `WHERE` clause to fetch required rows and generate mutation response. This has a few limitations like the requirement of a primary key/unique constraint. This also returns inconsistent data on `delete` mutation as mentioned in #1794. 
Now, we're using `VALUES (..)` (refer [here](https://www.postgresql.org/docs/current/sql-values.html)) expression to form virtual table rows in `SQL` to generate mutation response.

Internal changes:-
- Not to use primary key/unique constraint columns:-
  - Revert back to `ConstraintName` from `TableConstraint` in `TableInfo` type
  - Remove `tcCols` field in `TableConstraint` type
  - Modify `table_info.sql` and `fetchTableMeta` function `SQL`
- A test case to perform `delete` mutation and returning relational objects.
2019-03-22 12:38:42 +05:30

449 lines
9.5 KiB
ReStructuredText

Insert mutation
===============
.. contents:: Table of contents
:backlinks: none
:depth: 1
:local:
Auto-generated insert mutation schema
-------------------------------------
**For example**, the auto-generated schema for the insert mutation field for a table ``article`` looks like this:
.. code-block:: graphql
insert_article (
objects: [article_insert_input!]!
on_conflict: article_on_conflict
): article_mutation_response
# response of any mutation on the table "article"
type article_mutation_response {
# number of affected rows by the mutation
affected_rows: Int!
#data of the affected rows by the mutation
returning: [article!]!
}
As you can see from the schema:
- ``objects`` argument is necessary and you can pass multiple ``objects`` to the mutation.
- You can pass an ``on_conflict`` argument to convert the mutation to an :doc:`upsert mutation <upsert>`
- You can return the number of affected rows and the affected objects (with nested objects) in the response.
See the :ref:`insert mutation API reference <insert_upsert_syntax>` for the full specifications
.. note::
If a table is not in the ``public`` Postgres schema, the insert mutation field will be of the format
``insert_<schema_name>_<table_name>``.
Insert a single object
----------------------
**Example:** Insert a new ``article`` object and return the inserted article object in the response
.. graphiql::
:view_only:
:query:
mutation insert_article {
insert_article(
objects: [
{
id: 21,
title: "Article 1",
content: "Sample article content",
author_id: 3
}
]
) {
returning {
id
title
}
}
}
:response:
{
"data": {
"insert_article": {
"affected_rows": 1,
"returning": [
{
"id": 21,
"title": "Article 1"
}
]
}
}
}
Insert a single object (using variables)
----------------------------------------
**Example:** Insert a new ``article`` object and return the inserted article object in the response
.. graphiql::
:view_only:
:query:
mutation insert_article($objects: [article_insert_input!]! ) {
insert_article(objects: $objects) {
returning {
id
title
}
}
}
:response:
{
"data": {
"insert_article": {
"affected_rows": 1,
"returning": [
{
"id": 21,
"title": "Article 1"
}
]
}
}
}
:variables:
{
"objects": [
{
"id": 21,
"title": "Article 1",
"content": "Sample article content",
"author_id": 3
}
]
}
Insert multiple objects of the same type in the same mutation
-------------------------------------------------------------
**Example:** Insert 2 new ``article`` objects and return both the article objects in the response
.. graphiql::
:view_only:
:query:
mutation insert_article {
insert_article(
objects: [
{
id: 22,
title: "Article 2",
content: "Sample article content",
author_id: 4
},
{
id: 23,
title: "Article 3",
content: "Sample article content",
author_id: 5
}
]
) {
returning {
id
title
}
}
}
:response:
{
"data": {
"insert_article": {
"affected_rows": 2,
"returning": [
{
"id": 22,
"title": "Article 2"
},
{
"id": 23,
"title": "Article 3"
}
]
}
}
}
Insert an object and get a nested object in response
----------------------------------------------------
**Example:** Insert a new ``article`` object and return the inserted article object with its author in the response
.. graphiql::
:view_only:
:query:
mutation insert_article {
insert_article(
objects: [
{
id: 21,
title: "Article 1",
content: "Sample article content",
author_id: 3
}
]
) {
returning {
id
title
author {
id
name
}
}
}
}
:response:
{
"data": {
"insert_article": {
"affected_rows": 1,
"returning": [
{
"id": 21,
"title": "Article 1",
"author": {
"id": 3,
"name": "Sidney"
}
}
]
}
}
}
Insert an object and its nested object in the same mutation
-----------------------------------------------------------
**Example:** Insert a new ``article`` object with its ``author`` and return the inserted article object with its author
in the response
.. graphiql::
:view_only:
:query:
mutation insert_article {
insert_article(
objects: [
{
id: 21,
title: "Article 1",
content: "Sample article content",
author: {
data: {
id: 11,
name: "Cory"
}
}
}
]
) {
affected_rows
returning {
id
title
author {
id
name
}
}
}
}
:response:
{
"data": {
"insert_article": {
"affected_rows": 2,
"returning": [
{
"id": 21,
"title": "Article 1",
"author": {
"id": 11,
"name": "Cory"
}
}
]
}
}
}
Insert an object with a JSONB column
------------------------------------
**Example:** Insert a new ``author`` object with a JSONB ``address`` column
.. graphiql::
:view_only:
:query:
mutation insert_author($address: jsonb) {
insert_author (
objects: [
{
id: 1,
name: "Ash",
address: $address
}
]
) {
affected_rows
returning {
id
name
address
}
}
}
:response:
{
"data": {
"insert_author": {
"affected_rows": 1,
"returning": [
{
"id": 1,
"name": "Ash",
"address": {
"city": "Bengaluru",
"phone": "9090909090",
"state": "Karnataka",
"pincode": 560095,
"street_address": "161, 19th Main Road, Koramangala 6th Block"
}
}
]
}
}
}
:variables:
{
"address": {
"street_address": "161, 19th Main Road, Koramangala 6th Block",
"city": "Bengaluru",
"phone": "9090909090",
"state": "Karnataka",
"pincode": 560095
}
}
Set a field to its default value during insert
----------------------------------------------
To set a field to its ``default`` value, just omit it from the input object, irrespective of the
:doc:`default value configuration <../schema/default-values/index>` i.e. via Postgres defaults or using column presets.
**Example:** if default value of ``id`` is set to auto-incrementing integer, no need to pass ``id`` field in input object
.. graphiql::
:view_only:
:query:
mutation insert_article_with_def_id {
insert_article(
objects: [
{
title: "Article 1",
content: "Sample article content",
author_id: 3
}
]
) {
returning {
id
title
}
}
}
:response:
{
"data": {
"insert_article": {
"affected_rows": 1,
"returning": [
{
"id": 21,
"title": "Article 1"
}
]
}
}
}
Set a field to NULL during insert
---------------------------------
If a field is ``nullable`` in the database, to set its value to ``null``, either pass its value as ``null`` or
just omit it from the input object.
**Example:** if ``age`` is a nullable field, either don't pass ``age`` field in input object or pass it as ``null``
to set it to ``null``
.. graphiql::
:view_only:
:query:
mutation insert_author_with_null_age {
insert_author(
objects: [
{
name: "Jeff",
}
]
) {
returning {
id
name
age
}
}
}
:response:
{
"data": {
"insert_author": {
"returning": [
{
"id": 11,
"name": "Jeff",
"age": null
}
]
}
}
}
OR
.. graphiql::
:view_only:
:query:
mutation insert_author_with_null_age {
insert_author(
objects: [
{
name: "Jeff",
age: null
}
]
) {
returning {
id
name
age
}
}
}
:response:
{
"data": {
"insert_author": {
"returning": [
{
"id": 11,
"name": "Jeff",
"age": null
}
]
}
}
}