# Session save — 2026-10-26 (SQLite binding) ## Where we are The V3 SQLite binding under `bindings/sqlite3` now covers the core connection, statement, scalar, BLOB, callback and hook APIs. Binding code is committed through: ```text 9dd2a80 bindings: add SQLite connection hooks 9df09ae bindings: add SQLite callback support 0f235a1 bindings: add SQLite BLOB and connection APIs 5d5faa1 bindings: add SQLite scalar and error APIs f40a026 bindings: add SQLite showcase ae7ce54 bindings: add SQLite prepared statements d3be70c bindings: add SQLite open/exec/close smoke test ``` The binding tests and showcase pass. The compiler gate is **323/323**. `master` is one commit ahead of `origin/master` at the time of writing. ## What this session added ### Connection and scalar layer - `sqlite3_open_v2`, `close_v2`, open flags - `sqlite3_bind_int64`, `bind_double`, `bind_null` - `sqlite3_reset`, `clear_bindings` - `sqlite3_column_count`, `data_count`, `column_type`, `column_bytes` - `sqlite3_column_int64`, `double`, `name`, `decltype` - error APIs and `sqlite3_exec` `VAR errmsg` - result-code and storage-class constants ### BLOB layer - `sqlite3_bind_blob`, `bind_zeroblob` - `sqlite3_column_blob` - `sqlite3_blob_open`, `blob_close`, `blob_read`, `blob_write`, `blob_bytes`, `blob_reopen` - `sqlite3_changes`, `total_changes`, `last_insert_rowid` ### Callbacks - `sqlite3_exec` row callbacks (`char **argv` / `char **colNames`) - `sqlite3_create_function_v2` - `sqlite3_value_*` and `sqlite3_result_*` scalar families - `SQLiteArrayAt` to index C pointer arrays - user data and context DB handle ### Connection hooks - `sqlite3_busy_timeout`, `busy_handler`, `interrupt` - `sqlite3_progress_handler` - `sqlite3_trace_v2` - `sqlite3_update_hook` - `sqlite3_commit_hook`, `rollback_hook` - `sqlite3_set_authorizer` - `sqlite3_db_handle` - `SQLiteOp*`, `SQLiteAuth*`, `SQLiteTrace*` constants ## Tests Current binding tests in `bindings/sqlite3/tests`: - `SQLiteSmoke.mod` — open/exec/close - `SQLitePrepared.mod` — prepared insert/select - `SQLiteScalar.mod` — scalar types and column metadata - `SQLiteErrors.mod` — errcode/errmsg/extended codes/free - `SQLiteBlob.mod` — bind/column/incremental BLOB, zeroblob - `SQLiteConnection.mod` — open_v2/close_v2/changes/rowid/read-only - `SQLiteCallback.mod` — exec callbacks and scalar UDFs - `SQLiteHooks.mod` — busy/progress/trace/update/commit/rollback/auth Showcase output remains: ```text 1: Ada 2: Grace ``` ## Key decisions and gotchas - Opaque SQLite handles stay `ADDRESS`; no by-value struct ABI. - `sqlite3_exec` takes `VAR errmsg : ADDRESS`; non-NIL messages are caller-owned and freed with `sqlite3_free`. - `SQLiteTransient()` supplies `SQLITE_TRANSIENT`; bound text/BLOB data is copied by SQLite. - For raw C buffers from V3 arrays, use `ADR(a[0])`, not `ADR(a)`. `ADR(a)` points at the V3 array descriptor. - Callbacks must be top-level V3 procedures; nested procedures still carry a hidden frame link and are not C-callable. - `sqlite3_update_hook` / `commit_hook` return the previous hook pointer; assign it to an `ADDRESS`. - `sqlite3_set_authorizer` returns `SQLiteAuthOk`, `SQLiteAuthDeny` or `SQLiteAuthIgnore`. - Compiler observation: a long V3 string literal used as SQL text was truncated (61 bytes generated). Keep SQL literals short or build longer SQL through buffers; adjacent string literal concatenation is not supported by V3. ## Test-inventory analysis The full analysis is saved at: ```text bindings/sqlite3/TEST-INVENTORY.md ``` Sources examined: - sibling `m2SQLITE/tests` — 7 original GNU Modula-2 binding tests - sibling `m2SQLITE/sqlite-master/test` — 1,195 upstream SQLite tests - `compiler/tests` — 806 compiler/ABI tests, not SQLite-specific Highest-value items identified: 1. `m2SQLITE/tests/test_prepare.mod` + upstream `bind.test` — parameter count/name/index, unbound parameters as NULL, reset/reuse, 64-bit values. 2. `incrblob*.test` + `m2SQLITE/tests/test_blob.mod` — read-only BLOB writes, invalid opens, bounds, handle invalidation, backup. 3. `m2SQLITE/tests/test_codes.mod` — not-null/foreign-key/check extended codes, `get_table`. 4. `test_func.mod` / upstream `func*.test` — aggregates, auxdata, more result writers and error paths. 5. `auth.test`, `busy.test`, `progress.test`, `trace.test` — deeper hook semantics. ## Recommended next slice Add: - `sqlite3_bind_parameter_count` - `sqlite3_bind_parameter_name` - `sqlite3_bind_parameter_index` with a new `SQLiteParams.mod` ported from `test_prepare.mod` and `bind.test`. This is the smallest high-value gap in the current binding. Then extend BLOB and hook tests with the upstream error/abort cases. ## Resume commands ```sh cd bindings/sqlite3 ./run.sh cd ../../compiler ./run_tests.sh # expect 323/323 ``` ## Remaining API gaps - statement parameter introspection - extended constraint codes beyond PK/unique - aggregates and auxdata - backup API - `sqlite3_get_table` / `free_table` - library version/source id/threadsafe - statement metadata (`sql`, `expanded_sql`, `readonly`, `busy`) - limits, autocommit and error offsets - extension loading and WAL/checkpoint helpers