Appender supports targeting specific catalogs,
feeding arbitrary queries, projecting a subset of columns, and bulk-ingesting whole
data chunks. It also has strict error semantics worth understanding.
Catalog & query appenders
Address
[catalog.]schema.table explicitly. None catalog uses DuckDB’s default.INSERT/UPDATE/DELETE/MERGE,
referring to the appended data by table_name (default "appended_data"):
Rows appended here feed
query. types gives the appended columns’ logical types; column_names
optionally names them (default col1, col2, …).LogicalType::of::<T>() builds a logical type
from a Rust type.
Column introspection
Both reflect the appender’s active column list (the table’s columns, unless projected):column_count() -> u64.column_type(col_idx: u64) -> Option<LogicalType>.
Projected columns & default rows
Supply only some columns and let the rest take theirDEFAULT. Projection must be configured
before the first row (otherwise an error):
add_column(name)— addnameto the active column list (pre-first-row only).clear_columns()— restore the full column set (pre-first-row only).append_default_row()— append one row where every column takes itsDEFAULT(a column with noDEFAULTbecomesNULL); opens and closes the row safely.
Raw chunk ingestion
Append whole data chunks in one call rather than value-by-value. Always available (operate on the internalDataChunk fetched from a query result):
append_chunk(&DataChunk) -> Result<()>— append every row of aDataChunk. The chunk is only read; the column count must match (validated Rust-side).append_default_to_chunk(&mut DataChunk, col: u64, row: u64)— write a column’sDEFAULTinto a raw chunk cell.
udf / columnar feature, the DataChunkHandle counterparts:
append_chunk_handle(&DataChunkHandle) -> Result<()>— append a chunk you built column-by-column. The shape check is strict — column count and each column’s type id must match — and runs entirely before the chunk reaches DuckDB, so a rejected chunk leaves the appender usable.set_chunk_default(&mut DataChunkHandle, col: usize, row: usize)— write a column’sDEFAULTinto a built chunk cell.
Poisoning & error handling
- Engine-side failures (e.g. a deferred
CHECKconstraint caught at flush) surface asError::Enginewith DuckDB’s typed classification. - A Rust-side value conversion failure mid-row also poisons the appender but returns the original conversion error unchanged.
- The originating connection stays usable after an appender poisons.
finish() (not drop) when you need the flush/close error reported.
See also
- Appender basics — lifecycle,
append,save/finish. - Data chunks and vectors — building a
DataChunkHandle. - Composite types —
LogicalType. - Errors —
Error::Engineand theEngineErrorclassification.