summary-v0.4.0.md 6.4 KB

m2SQLITE summary — v0.4.0 (2026-09-24)

SQLite bindings for GNU Modula-2 (gm2 16.0.1, SQLite 3.46.1 system libsqlite3.so.0, Linux; API reference sqlite-master/ 3.54.0). All builds verified with make; tests 7/7 green, showcase exits 0.

v0.1.0 — core binding + showcase

  • src/SQLite.def — thin FOR "C" core API (~60 procedures): version/sourceid/threadsafe, open/open_v2/close/close_v2, exec, errcode/errmsg/errstr/error-offset/free, complete, busy-timeout, autocommit, changes/rowid, extended codes, limit, prepare_v2/prepare_v3, step/finalize/reset/clear-bindings, data/column-count, sql/expanded-sql, stmt-readonly/busy, all bind_*, all column_*, parameter count/name/index; result-code, open-flag, column-type, prepare-flag and limit-id constants
  • lib/SQLiteUtils.def/.mod — CStrToM2, ErrMsg/ErrStr/ LibVersionStr, StaticDestr/TransientDestr (STATIC/TRANSIENT sentinels), BindTextCopy/BindBlobCopy, ExecSimple/ExecWithErr
  • tests/ — version, open (+open_v2), exec (incl. change counters and error capture), prepare/bind/column round trip + run_tests.sh
  • examples/ — version, hello_db (bind-insert, select-print)
  • showcases/showcase_all — calls every SQLite procedure and every SQLiteUtils helper in 7 sections; verifies values, prints results
  • Makefile — gm2 build (-c helper to .o, then link) for tests, examples and showcases; pkg-config with runtime-lib fallback; optional local-sqlite amalgamation target
  • .gitignore — ignores sqlite-master/, build/, artefacts, *.db
  • README.md — status table, layout, build/test, usage, FFI notes

v0.2.0 — custom SQL functions

  • src/SQLite.def — function API (+30 procedures): XFunc/XStep/ XFinal/XDestroy callback types (ContextHandle, ValueHandle), create_function/create_function_v2, all value_* readers (blob/double/int/int64/text/bytes/type/numeric-type), all result_* writers (blob/blob64/double/error(+code/toobig/nomem)/int/int64/null/ text/text64/value/zeroblob/zeroblob64), context helpers (aggregate_context, user_data, context_db_handle, get/set_auxdata); UTF-encoding and function-flag constants
  • lib/SQLiteUtils — ValueText, ResultTextCopy
  • tests/test_func — 17 registered functions: scalars, sized results, error paths (exact codes 1/18/7), msum aggregate with shared state, user_data counting, context_db_handle check, auxdata round trip
  • showcases/showcase_all — section [8]: m2tax scalar, m2total aggregate

v0.3.0 — BLOB I/O and online backup

  • src/SQLite.def — handle APIs (+11 procedures): BlobHandle and BackupHandle opaque types, blob_open/reopen/close/bytes/ read/write, backup_init (returns the handle or NIL), backup_step/finish/remaining/pagecount
  • lib/SQLiteUtils — BackupToFile one-call copy of a live database to a file path (open, init, page loop with Busy/Locked retry bound, finish, close; step/finish errors propagate)
  • tests/test_blob — 256-byte write/read round trip with offset, reopen across rows, read-only write refusal (code 8), close relaying the pending handle error, direct backup (step(-1) to Done, remaining/pagecount) verified by row count, BackupToFile to /tmp verified and unlinked
  • showcases/showcase_all — section [10]: 64-byte blob write/read, file backup, reopen-and-count, temp-file removal (close moves to [11])

v0.4.0 — extended codes and result tables

  • src/SQLite.def — all 82 extended result codes as named constants (SQLiteConstraintUnique = 2067 etc., values generated from sqlite.h.in so base | (n<<8) arithmetic cannot drift), plus get_table/free_table (+2 procedures). The triple-pointer OUT param needs no special support: VAR tbl: ADDRESS passes the pointer the C side writes through.
  • lib/SQLiteUtils — GetTable (one call returning table, dims and error text; frees on failure), TableCell (header row via row -1, NULL and out-of-range read as empty), FreeTable
  • tests/test_codes — triggers UNIQUE (2067), NOTNULL (1299), PRIMARYKEY (1555) and FOREIGNKEY (787) and checks each against both the return code and extended_errcode; raw get_table call (dims, header, NULL cell, int cell) plus the helper path incl. the failing-statement branch
  • showcases/showcase_all — section [11]: unique-violation code printout, fx table dump via TableCell (close moves to [12])

GM2 FFI rules learned (encoded in code)

  1. DEFINITION MODULE FOR "C" needs EXPORT UNQUALIFIED, otherwise the linker looks for Module_proc instead of the C symbol.
  2. No *) and no (* inside (* *) comments (nested-comment open and early close) — C pointer spellings need spaces (char * never char *), destructor never void (*)).
  3. INTEGER <-> int, LONGINT <-> sqlite3_int64, REAL <-> double (libc.atof/strtod return REAL); opaque handles = ADDRESS.
  4. ARRAY OF CHAR params = char * (pass literals, -1 for lengths); mandatory ** OUT params = VAR, optional ones (errmsg, pzTail) = plain ADDRESS taking ADR(var) or NIL.
  5. SQLITE_TRANSIENT/STATIC are macros, pass VAL(ADDRESS, -1/0) (wrapped by TransientDestr/StaticDestr).
  6. INTEGER constants garble through C varargs (printf("%d")) — route them via variables first.
  7. No dev package needed: link /usr/lib/x86_64-linux-gnu/libsqlite3.so.0 directly when pkg-config sqlite3 is absent.
  8. Callback types (PROCEDURE (ADDRESS, ...)) cross into C as plain function pointers; NIL fills unused slots. Index C pointer arrays with a VAL overlay onto POINTER TO ARRAY OF ADDRESS.
  9. This SQLite build rejects the AS t(v) column-alias form in FROM (VALUES ...); use bare column1 names in tests.
  10. ORD returns CARDINAL: mix with INTEGER only via VAL, and compare HIGH() (also CARDINAL) the same way. blob_close relays a handle's pending operation error while still releasing it — expect codes, not just Ok.
  11. libc.unlink takes ADDRESS (ADR of a NUL buffer) and its [INTEGER] result may be assigned or dropped as a statement.
  12. Generate large constant families from the C header with a script instead of hand arithmetic; each constant keeps its C name in a trailing comment for audit.

Next

Window functions (create_window_function) + collations, sessions/changesets (ext/session).