session-2026-10-26-sqlite-binding.md 5.1 KB

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:

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:

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:

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

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