append_rows bulk-inserts an array of JSON objects into a table as one multi-row INSERT. It is
the ergonomic path for pushing in-memory data from the webview without hand-building SQL or writing
a file.
- Signature:
appendRows(table: string, rows: Record<string, unknown>[]): Promise<ExecuteResult>. ExecuteResult.rowsAffectedis the number of rows inserted.
Semantics
1
Column order comes from the first row
The columns of the generated
INSERT are taken from rows[0]’s keys, in iteration order.2
Missing keys bind NULL
For later rows, any column present in the first row but absent here binds
NULL. Extra keys not
present in the first row are ignored.3
Values bind as parameters
Every cell is bound as a positional parameter (same JS → DuckDB mapping
as
execute), not interpolated — so values are injection-safe.4
Empty input is a no-op
An empty
rows array returns { rowsAffected: 0 } without running any SQL.Because the column list is fixed from the first row, make sure the first object carries every
column you intend to populate. If row 1 omits a column that later rows set, that column is never
part of the
INSERT and those later values are silently dropped.When to use it
Policy and permissions
append_rowsis a write: rejected underread_only(true)withdenied by policy: ….- Permission:
better-duck-tauri:allow-append-rows(not in the default set). It also honors theAfterWritescheckpoint strategy if configured.
See also
- Query & execute — single-statement inserts and the parameter model.
- Import & export — load rows from files instead.
- The Appender — the high-throughput bulk-load API on the core driver.