Highlights
- Manual statement lifecycle:
Xqlite.prepare/2,bind/2(positional or keyword-named),step/1,multi_step/2,reset/1,clear_bindings/1,column_names/1,finalize/1— prepare once, rebind in a loop, consume partially without LIMIT rewrites.multi_step_cancellable/3adds token-based cancellable batch stepping; abandoned statements are finalized by garbage collection. - Deny-list authorizer:
Xqlite.set_authorizer/2/remove_authorizer/1reject a chosen set of SQLite action kinds at statement-preparation time — denied statements fail with{:error, {:authorization_denied, message}}, and the action list is validated atomically. v1 is action-kind granularity, deny-only. - Type extensions rounded out: new built-ins
JSON,UUID, andDecimal(encode-only; xqlite's first optional dependency), plus encode-onlyInstant(DateTime→ int64 epoch nanoseconds) and exact-unitDuration(→ int64 nanosecond spans).:type_extensionsnow also works on one-shotquery/4andexecute/4, not just streams.
Breaking
ColumnInfo.default_valueis now a typed classification —:none,{:literal, value},{:blob, bytes},{:current, :time | :date | :timestamp}, or{:expr, sql}— parsed in Rust at the NIF boundary, instead of the rawdflt_valuetext.mix precommitis nowmix verify— same checks, same order, new name.
Fixed
- Raw statement/stream binding accepts TEXT with interior NUL bytes (binds pointer+length instead of building a
CString). - Statement column metadata is read live:
SELECT *through a prepared statement re-expands after a schema change (SQLite's v2 auto-reprepare) instead of freezing the prepare-time row width andcolumn_names. - Finalizing after a failed step no longer reports a phantom error —
sqlite3_finalize's echo of the last evaluation error is no longer treated as a cleanup failure.
Changed
- rusqlite 0.39 → 0.40.1 (bundled SQLite 3.51.3 → 3.53.2) and rustler 0.37 → 0.38. No API changes on the xqlite surface.
Full details in CHANGELOG.md.