Master save¶
Saves a whole tree of related rows in one call : an order with its customer and its items, a city with its state and country. Each row is inserted, or updated when its primary key is already there.
In short
POST /api/schema/<user-path>/<instance>/<database>/<table>/master-save- A row with the key of a row that is there updates that row. Any other row is inserted.
- The relations of the schemas say which table each nested object goes to.
- If one row fails, every row the call wrote is taken back.
| Method | POST |
| URL | /api/schema/admin/mysql8/inventory/customers/master-save |
| Body | one object, or a list of objects, with nested related objects |
| Query params | select and deep shape the answer. returnData=false : the count only. |
| Answer | 201. data : the saved rows, with the ids of their related rows. With returnData=false : { savedRowsCount }. |
| Databases | MongoDB, MySQL, MariaDB, PostgreSQL, SQL Server, Oracle, TiDB, Percona |
| Cached | no. It clears the cached answers of the table. |
| From code | g.sys.db.masterSave |
| API id | SCHEMA_MASTER_SAVE |
| Without a schema | /api/gen/admin/mysql8/inventory/customers/master-save : below |
Insert or update¶
- The same rule holds at every level of the tree.
- An update changes only the columns you send.
- A key that matches no row is inserted, with that key.
- A list in the body saves each object, and the answer is a list.
A tree of rows¶
Each nested object needs a relation in the schema of its column (table, column, and database or instance when they differ). The nested row is saved first, in its own table. Then its id goes into the column of the parent.
{
"city_name": "Wembley",
"state_id": {
"state_name": "London",
"country_id": { "country_name": "UK" }
}
}
{
"success": true,
"statusCode": 201,
"data": { "id": 107, "city_name": "Wembley", "state_id": 205 }
}
The country is saved first, and its id goes into the state. Then the state is saved, and its id goes into the city. The tables can be in other databases and instances : the relation says where.
To get the related rows back in the answer, add deep : ?deep=[{s_key:'state_id',deep:[{s_key:'country_id'}]}].
A list of child rows : virtual fields¶
A virtual field (isVirtualField, with s_columnVirtualLinker and t_columnVirtualLinker) takes a list. Each item is saved in the other table, with the key of the parent.
{
"order_no": 1001,
"customer_id": 1,
"items": [
{ "product_id": "66fa1c9a9b1e4a0012a3c002", "qty": 2 },
{ "id": 55, "qty": 3 }
]
}
The first item is inserted. The second has its primary key, so it is updated.
When something fails¶
- Every row the call wrote is taken back when a later row fails. A wrong column in the country of the tree above leaves no city and no state behind.
- The schema checks each row as save single or multiple does. The errors name the column. A
uniqueerror also names the row withdataIndex.
Only the count : returnData=false¶
POST .../master-save?returnData=false answers { "savedRowsCount": 2 } : how many rows of the body were saved, nested rows not counted. The nested rows are saved and linked as always.
Optimistic concurrency control¶
A table whose schema has a version column (isConcurrencyControlField) needs the version in every update. An old version is refused with 400. See Optimistic concurrency control.
From your code¶
g.sys.db.masterSave makes the same call from custom APIs, hooks, events, schedulers and test cases. Pass returnData: false next to saveData for the count only.
Without a schema : /api/gen¶
Every table also answers this operation under /api/gen, with or without a schema :
| URL | /api/gen/admin/mysql8/inventory/customers/master-save |
| API id | GEN_MASTER_SAVE |
| From code | g.sys.db.gen.masterSaveGen |
Without a schema, nothing says which rows belong to other tables. So master save works like save single or multiple : every row is inserted as you send it, nothing is updated. On MongoDB, a nested object stays an embedded document.
Headers and errors¶
This operation takes the request headers of every API. It answers the envelope, with the status codes and the messages of every API.
Related : All APIs · Table schema · Pre hooks · Post hooks · API group permission