sqlite: map the full practical C API

src/db/sqlite.sx grows from the P5.1 subset (~19 fns) to the complete
practical surface (~100): open_v2 + flags, extended errcodes +
error_offset, txn_state/autocommit, changes64/total_changes64, limits,
the full bind/column families (double/blob/zeroblob), parameter and
column introspection (built with SQLITE_ENABLE_COLUMN_METADATA),
table_column_metadata, statement introspection (sql/expanded_sql/
readonly/busy/isexplain/status), incremental blob I/O (SqliteBlob),
online backup (SqliteBackup + sqlite_backup_run), serialize/
deserialize, and library utilities (complete, strglob/strlike/stricmp,
randomness, memory, compileoptions). One variant per duplicate family
(modern/64-bit preferred; bind_text/blob keep the 32-bit length forms
that skip text64's encoding arg). Not bound, by design: callback-taking
APIs (hooks/UDFs/collations need C->sx callbacks), sqlite3_value_*
(UDF-coupled), varargs config, UTF-16, and subsystems this build omits
— the boundary list lives in the module header and vendor README.

rename.h is now GENERATED by make into build/vendor/ from the bindings'
#foreign names — src/db/sqlite.sx is the single source of truth and the
rename list cannot drift (checked-in vendor/sqlite/rename.h removed).

make test 21/21 (new: sqlite_api.sx — 15 cases over every wrapper
family, including a blob round trip with interior NULs, UNIQUE
constraint extended errcodes, txn_state through BEGIN IMMEDIATE,
backup db->db, and a serialize->deserialize round trip).

KNOWN sx BOUNDARY (filed as a followup): 'if !e' on an error binding
evaluates true even when the error is set — negated error logic in
tests routes through plain bools.
This commit is contained in:
agra
2026-06-12 13:11:14 +03:00
parent ad34fe88f2
commit fabc9062cb
5 changed files with 1131 additions and 106 deletions

View File

@@ -16,6 +16,31 @@ search directory, and the AOT binary must link the static copy.
`tests/sqlite_smoke.sx` asserts `sqlite3_libversion()` equals the version
above, so a fallback to the OS libsqlite3 fails loudly in both modes.
## Symbol renaming
The sx JIT resolves `#foreign` symbols via `dlsym(RTLD_DEFAULT)`, which
searches every image already loaded into the process — the OS libsqlite3
is usually among them and wins by load order. So every API function the
bindings use is renamed `dist_sqlite3_*` in the vendored build: those
symbols exist ONLY here, making resolution unambiguous in both JIT and
AOT modes. The rename header is GENERATED by `make` into
`build/vendor/rename.h` from the `#foreign` names in
`src/db/sqlite.sx` — the bindings file is the single source of truth,
and the rename list cannot drift from it.
## Bound surface
`src/db/sqlite.sx` maps the full practical C API (~100 functions):
connection lifecycle + open_v2 flags, errors (extended codes included),
statements with the complete bind/column families, parameter and column
introspection (built with `SQLITE_ENABLE_COLUMN_METADATA`), incremental
blob I/O, the online backup API, serialize/deserialize, and the library
utilities. Not bound, by design: callback-taking APIs (hooks, UDFs,
collations, authorizers — they need C→sx callbacks), the
`sqlite3_value_*` family (UDF-coupled), varargs configuration, UTF-16
variants, and subsystems this build omits (mutex/VFS under
`SQLITE_THREADSAFE=0`, sessions/snapshots/vtabs, deprecated API).
To upgrade: replace `sqlite3.c`/`sqlite3.h` with a newer amalgamation,
update this file and the version constant in `tests/sqlite_smoke.sx`, and
run `make clean test`.

View File

@@ -1,34 +0,0 @@
/*
* Symbol prefix for the vendored SQLite build.
*
* The sx JIT resolves #foreign symbols via dlsym(RTLD_DEFAULT), which
* searches every image already loaded into the process — and the OS
* libsqlite3 is usually among them, so the standard names would silently
* bind to the system copy instead of this vendored one. Prefixing the
* API surface makes resolution unambiguous in both JIT (dlopen) and AOT
* (static link) modes: dist_sqlite3_* exists ONLY in the vendored build.
*
* Only the functions bound in src/db/sqlite.sx are renamed; extend BOTH
* files together when new API is needed. Injected via `-include` in the
* Makefile's SQLITE_DEFS, so sqlite3.c and its embedded sqlite3.h see
* the renames consistently.
*/
#define sqlite3_open dist_sqlite3_open
#define sqlite3_close dist_sqlite3_close
#define sqlite3_exec dist_sqlite3_exec
#define sqlite3_prepare_v2 dist_sqlite3_prepare_v2
#define sqlite3_step dist_sqlite3_step
#define sqlite3_finalize dist_sqlite3_finalize
#define sqlite3_reset dist_sqlite3_reset
#define sqlite3_bind_text dist_sqlite3_bind_text
#define sqlite3_bind_int64 dist_sqlite3_bind_int64
#define sqlite3_bind_null dist_sqlite3_bind_null
#define sqlite3_column_int64 dist_sqlite3_column_int64
#define sqlite3_column_text dist_sqlite3_column_text
#define sqlite3_column_bytes dist_sqlite3_column_bytes
#define sqlite3_column_type dist_sqlite3_column_type
#define sqlite3_column_count dist_sqlite3_column_count
#define sqlite3_errmsg dist_sqlite3_errmsg
#define sqlite3_libversion dist_sqlite3_libversion
#define sqlite3_last_insert_rowid dist_sqlite3_last_insert_rowid
#define sqlite3_changes dist_sqlite3_changes