Skip to content
This page View Markdown Open in ChatGPT Open in Claude

Save single or multiple

Inserts one row (an object) or many (a list). It answers 201 with the saved rows, ids included.

In short

  • POST /api/schema/<user-path>/<instance>/<database>/<table>/save-single-or-multiple
  • The schema checks every row first. One error, and nothing is saved.
  • ?returnData=false answers only how many rows were saved : best for imports.
Method POST
URL /api/schema/admin/mysql8/inventory/customers/save-single-or-multiple
Body one object, or a list of objects
Query params select and deep shape the answer. returnData=false : the count only.
Answer 201. data : the saved row, or the list of saved 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.saveSingleOrMultiple
API id SCHEMA_POST_BULK_INSERT
Without a schema /api/gen/admin/mysql8/inventory/customers/save-single-or-multiple : below
Save, Update and Remove on Any Database with the Same API Calls8 chapters and the transcript

The examples write the table of get all.

One row

POST /api/schema/admin/mysql8/inventory/customers/save-single-or-multiple
Body
{ "first_name": "Bob", "last_name": "Lin", "pincode": 382345 }
Answer
{
    "success": true,
    "statusCode": 201,
    "data": { "customer_id": 6, "first_name": "Bob", "last_name": "Lin", "pincode": 382345 }
}

Send the primary key ("customer_id": 27), or leave it out. Then the database or API Maker makes it : isAutoIncrementByDB, isAutoIncrementByAM or isAutoGenerateByAM in the schema, _id on MongoDB.

Many rows

Body
[
    { "first_name": "Bob", "last_name": "Lin" },
    { "customer_id": 29, "first_name": "Eve", "last_name": "Page" }
]
  • The answer is a list, in the same order.
  • Rows with and without a primary key can mix.

What the schema checks

Before anything is written, the schema works on every row :

  1. A key the schema does not have is refused (schemaKeyNotFound).
  2. Values take their types, texts are trimmed and cased, conversionFun runs.
  3. Columns are encrypted or hashed, ids and defaults are filled.
  4. The rules and validatorFun run.

Every error comes back at once, with 400, and nothing is saved. A unique error names its row with dataIndex : its place in the list, from 0.

A column with a relation in the schema (table and column) takes a whole object. API Maker saves it to its own table first, then puts its id in the column. If a save fails, the rows saved so far are removed again.

Body : the state goes to the table states, then the city is saved with its id
{ "city_name": "Wembley", "state_id": { "state_name": "London", "country_id": 302 } }

To update related rows too, or to save lists of them, use master save.

The answer you want

POST /api/schema/admin/mysql8/inventory/customers/save-single-or-multiple?select=customer_id,first_name

select keeps some columns of the saved rows. deep adds their related rows.

Only the count : returnData=false

POST /api/schema/admin/mysql8/inventory/customers/save-single-or-multiple?returnData=false
Body
[ { "first_name": "Bob", "last_name": "Lin" }, { "first_name": "Alice", "last_name": "Ray" } ]
Answer
{ "success": true, "statusCode": 201, "data": { "savedRowsCount": 2 } }
  • The saved rows are not read back. So the save costs the insert only : no extra query, no memory for the rows.
  • The schema checks the rows as always.
  • Without returnData, the answer is the saved rows.

After the save

The cached answers of the table are cleared. Subscribed WebSocket clients get the news, and the events of this API run. Post hooks get the answer in g.res.output : the saved rows, or { savedRowsCount }.

From your code

g.sys.db.saveSingleOrMultiple 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/save-single-or-multiple
API id GEN_POST_BULK_INSERT
From code g.sys.db.gen.saveSingleOrMultipleGen

The rows go to the database as you send them : nothing is converted, checked, filled, encrypted or numbered. On MongoDB, a text that looks like an ObjectId is turned into one.

  • On MongoDB, a nested object stays an embedded document. It is not saved to another collection : that needs the relations of a schema.
  • On an SQL table, every key must be a column.
  • On SQL, the answer is what the database says about the insert (affectedRows…). Without a schema, API Maker knows no column to read the rows back by. returnData=false answers { savedRowsCount } here too.

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