Homogeneous bulk DML
db.bulk(inputs, factory) is the SQLBraid throughput primitive for homogeneous
DML. It is deliberately different from db.batch(queries), which executes a
heterogeneous list of queries.
const result = await db.bulk( accounts.map(({ id, amount }) => ({ id, amount })), (input) => sql.command` UPDATE account SET amount = ${input.amount} WHERE id = ${input.id} `,);
// { inputCount, affectedRows? }Contract
Section titled “Contract”- Only
CommandQueryvalues are accepted. Bulk does not return row sets and does not combine with DMLRETURNING/OUTPUT. - The first rendered statement establishes one logical shape. Later rows must preserve its Braid structure, list/cardinality, hints, and bind directions.
- Shape or materialization errors happen before database I/O.
sql.out()andsql.inOut()are not valid bulk parameters. - Empty input returns
{ inputCount: 0 }without acquiring a lease. - One physical lease is used for the operation. Drivers report the actual mode:
native-bulk,pipeline,prepared-loop, orremote-batch. - Observers see one bulk operation, not N ordinary query lifecycles. Per-item values and diagnostic SQL are available through the bulk description without replicating statement metadata N times.
Atomicity and chunking
Section titled “Atomicity and chunking”Root bulk has no portable transaction promise and is never implicitly wrapped in one. Use a transaction callback when all changes must share a transaction:
await db.tx(async (tx) => { await tx.bulk(inputs, factory);});There is no portable auto-chunking contract. A driver may have stronger native batch semantics, but applications must not depend on those semantics outside the selected adapter’s documentation.
Driver modes
Section titled “Driver modes”| Adapter | Mode | Structural evidence target |
|---|---|---|
PostgreSQL / pg |
prepared-loop |
sequential named execution; bounded per-client statement reuse |
MySQL / mysql2 |
prepared-loop |
one prepare, N execute calls, unprepare() closes and evicts the cached handle |
| MariaDB / Connector/Node.js | native-bulk |
one connection.batch() call |
SQLite / node:sqlite |
prepared-loop |
one prepared statement reused |
| SQLite / WASM | prepared-loop |
one OO1 statement reset repeatedly |
| Cloudflare D1 | remote-batch |
one D1Database.batch() call |
| Oracle Thin | native-bulk |
one executeMany() call |
| SQL Server / Tedious | prepared-loop |
one prepare/unprepare around N executes |
See Runtime and driver support for revision-specific profile and capability conditions.