sqlite is part of the program: #import c unit replaces the Makefile cc build
src/db/sqlite.sx declares the vendored amalgamation as a named '#import c' unit (pinned defines + -O2 + #source); every #foreign binding resolves against it with UNPREFIXED sqlite3_* names. sx compiles the unit through its content-addressed object cache — once per checkout — links the objects into 'sx build' binaries, and loads them as a priority symbol target under 'sx run', so the OS libsqlite3 can never shadow the vendored copy (the version pin in sqlite_smoke proves it). Retired: the Makefile vendor targets (cc -> .a + jit/.dylib), the GENERATED dist_sqlite3_* rename.h (the JIT no longer resolves program-owned symbols through the process images, so the rename's reason is gone), and the -L plumbing in make build + tests/run.sh. make test 22/22; otool -L build/dist carries no libsqlite3.
This commit is contained in:
BIN
.sx-cache/c-11a77f91b0e34902.o
Normal file
BIN
.sx-cache/c-11a77f91b0e34902.o
Normal file
Binary file not shown.
BIN
.sx-cache/c-532fd2a7a0245e62.o
Normal file
BIN
.sx-cache/c-532fd2a7a0245e62.o
Normal file
Binary file not shown.
47
Makefile
47
Makefile
@@ -9,48 +9,23 @@ BUILD_DIR := build
|
|||||||
# Programs compiled by `make build`: the smoke program and the `dist`
|
# Programs compiled by `make build`: the smoke program and the `dist`
|
||||||
# product entry point. Further entry points under src/ get added here as
|
# product entry point. Further entry points under src/ get added here as
|
||||||
# they land.
|
# they land.
|
||||||
|
#
|
||||||
|
# The vendored SQLite (vendor/sqlite/) is part of the PROGRAM, not the
|
||||||
|
# build system: src/db/sqlite.sx declares it as a named `#import c` unit
|
||||||
|
# (pinned defines + -O2 + #source), so sx compiles and links it through
|
||||||
|
# its content-addressed object cache (.sx-cache/) — once per checkout.
|
||||||
|
# `sx build` links the unit's objects into the binary; `sx run` loads
|
||||||
|
# them as a priority symbol target the OS libsqlite3 cannot shadow.
|
||||||
SMOKE := tests/smoke.sx
|
SMOKE := tests/smoke.sx
|
||||||
DIST := src/dist.sx
|
DIST := src/dist.sx
|
||||||
|
|
||||||
# Vendored SQLite (vendor/sqlite/README.md): one amalgamation, two build
|
.PHONY: build test publish-example clean
|
||||||
# products in two DIRECTORIES — the macOS linker prefers a dylib over an
|
|
||||||
# archive in the same -L directory, and `sx build` must link the static
|
|
||||||
# copy while `sx run` (the test runner) dlopens the dylib.
|
|
||||||
#
|
|
||||||
# rename.h is GENERATED from the bindings: every `dist_sqlite3_*` symbol
|
|
||||||
# named in src/db/sqlite.sx gets a #define, so the rename list and the
|
|
||||||
# bound surface cannot drift (see the README for why renaming exists).
|
|
||||||
VENDOR_DIR := $(BUILD_DIR)/vendor
|
|
||||||
SQLITE_SRC := vendor/sqlite/sqlite3.c
|
|
||||||
SQLITE_DEFS := -DSQLITE_DQS=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_MEMSTATUS=0 \
|
|
||||||
-DSQLITE_OMIT_DEPRECATED -DSQLITE_OMIT_SHARED_CACHE \
|
|
||||||
-DSQLITE_LIKE_DOESNT_MATCH_BLOBS -DSQLITE_ENABLE_COLUMN_METADATA \
|
|
||||||
-include $(VENDOR_DIR)/rename.h
|
|
||||||
|
|
||||||
$(VENDOR_DIR)/rename.h: src/db/sqlite.sx
|
|
||||||
@mkdir -p $(VENDOR_DIR)
|
|
||||||
@{ echo '/* GENERATED by make from src/db/sqlite.sx — do not edit. */'; \
|
|
||||||
grep -o '"dist_sqlite3_[a-z0-9_]*"' src/db/sqlite.sx | tr -d '"' | sort -u | \
|
|
||||||
sed 's/^dist_\(.*\)/#define \1 dist_\1/'; } > $@
|
|
||||||
|
|
||||||
$(VENDOR_DIR)/libsqlite3.a: $(SQLITE_SRC) vendor/sqlite/sqlite3.h $(VENDOR_DIR)/rename.h
|
|
||||||
@mkdir -p $(VENDOR_DIR)
|
|
||||||
cc $(SQLITE_DEFS) -O2 -c $(SQLITE_SRC) -o $(VENDOR_DIR)/sqlite3.o
|
|
||||||
ar rcs $@ $(VENDOR_DIR)/sqlite3.o
|
|
||||||
|
|
||||||
$(VENDOR_DIR)/jit/libsqlite3.dylib: $(SQLITE_SRC) vendor/sqlite/sqlite3.h $(VENDOR_DIR)/rename.h
|
|
||||||
@mkdir -p $(VENDOR_DIR)/jit
|
|
||||||
cc $(SQLITE_DEFS) -O2 -dynamiclib $(SQLITE_SRC) -o $@
|
|
||||||
|
|
||||||
.PHONY: build test publish-example vendor clean
|
|
||||||
|
|
||||||
vendor: $(VENDOR_DIR)/libsqlite3.a $(VENDOR_DIR)/jit/libsqlite3.dylib
|
|
||||||
|
|
||||||
# Compile the product sources (and the smoke program) without running.
|
# Compile the product sources (and the smoke program) without running.
|
||||||
build: vendor
|
build:
|
||||||
@mkdir -p $(BUILD_DIR)
|
@mkdir -p $(BUILD_DIR)
|
||||||
$(SX) build -o $(BUILD_DIR)/smoke $(SMOKE)
|
$(SX) build -o $(BUILD_DIR)/smoke $(SMOKE)
|
||||||
$(SX) build -o $(BUILD_DIR)/dist $(DIST) -L $(VENDOR_DIR)
|
$(SX) build -o $(BUILD_DIR)/dist $(DIST)
|
||||||
|
|
||||||
# Run the test runner over every tests/**/*.sx. Exits non-zero on any
|
# Run the test runner over every tests/**/*.sx. Exits non-zero on any
|
||||||
# failure. Depends on `build` so the CLI acceptance test (tests/cli_*.sx)
|
# failure. Depends on `build` so the CLI acceptance test (tests/cli_*.sx)
|
||||||
@@ -67,4 +42,4 @@ publish-example: build
|
|||||||
./$(BUILD_DIR)/dist ci publish --manifest examples/dist.json --local-store .sx-tmp/publish-example --json
|
./$(BUILD_DIR)/dist ci publish --manifest examples/dist.json --local-store .sx-tmp/publish-example --json
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -rf $(BUILD_DIR)
|
@rm -rf $(BUILD_DIR) .sx-cache
|
||||||
|
|||||||
228
src/db/sqlite.sx
228
src/db/sqlite.sx
@@ -2,15 +2,17 @@
|
|||||||
// sqlite.sx — sx bindings over the VENDORED SQLite amalgamation
|
// sqlite.sx — sx bindings over the VENDORED SQLite amalgamation
|
||||||
// (vendor/sqlite/, see its README for version + upgrade notes).
|
// (vendor/sqlite/, see its README for version + upgrade notes).
|
||||||
//
|
//
|
||||||
// `#library "sqlite3"` resolves to the vendored build products under
|
// The amalgamation is part of THIS program: the named `#import c`
|
||||||
// build/vendor/ (never the OS copy): `sx build` links the static
|
// unit below compiles vendor/sqlite/sqlite3.c with the pinned options
|
||||||
// archive via `-L build/vendor`; `sx run` dlopens the dylib via
|
// (through sx's content-addressed object cache, so it compiles once
|
||||||
// `-L build/vendor/jit` (tests/run.sh). Every bound symbol is renamed
|
// per checkout, not once per run) and every `#foreign sqlib` decl
|
||||||
// `dist_sqlite3_*` in the vendored build — `build/vendor/rename.h` is
|
// binds against it. Under `sx run` the unit's dylib is a PRIORITY
|
||||||
// GENERATED by the Makefile from THIS FILE's `#foreign` names, so the
|
// symbol-search target consulted before the process images, so the OS
|
||||||
// rename list and the bindings cannot drift. tests/sqlite_smoke.sx pins
|
// libsqlite3 (loaded into the compiler via CoreServices) can never
|
||||||
// `sqlite3_libversion()` to the vendored version so a silent fallback
|
// shadow the vendored copy; under `sx build` the unit's objects link
|
||||||
// to the system library fails the suite.
|
// directly into the binary. tests/sqlite_smoke.sx pins
|
||||||
|
// `sqlite3_libversion()` to the vendored version so any fallback
|
||||||
|
// fails the suite.
|
||||||
//
|
//
|
||||||
// COVERAGE — the full practical C API, ONE variant per function (the
|
// COVERAGE — the full practical C API, ONE variant per function (the
|
||||||
// modern/64-bit form where duplicates exist; `bind_text`/`bind_blob`
|
// modern/64-bit form where duplicates exist; `bind_text`/`bind_blob`
|
||||||
@@ -24,7 +26,7 @@
|
|||||||
// * the sqlite3_value_* family + bind/column_value — only
|
// * the sqlite3_value_* family + bind/column_value — only
|
||||||
// meaningful with user-defined functions (callbacks, above);
|
// meaningful with user-defined functions (callbacks, above);
|
||||||
// * varargs APIs (sqlite3_config, db_config, log, mprintf) —
|
// * varargs APIs (sqlite3_config, db_config, log, mprintf) —
|
||||||
// configuration happens via compile-time defines in the Makefile;
|
// configuration happens via the unit's compile-time defines;
|
||||||
// * UTF-16 variants (we are UTF-8 only), the mutex/VFS layer
|
// * UTF-16 variants (we are UTF-8 only), the mutex/VFS layer
|
||||||
// (built SQLITE_THREADSAFE=0), sessions/snapshots/vtabs/loadable
|
// (built SQLITE_THREADSAFE=0), sessions/snapshots/vtabs/loadable
|
||||||
// extensions (not compiled in), deprecated API (compiled out via
|
// extensions (not compiled in), deprecated API (compiled out via
|
||||||
@@ -49,124 +51,134 @@
|
|||||||
|
|
||||||
#import "modules/std.sx";
|
#import "modules/std.sx";
|
||||||
|
|
||||||
sqlib :: #library "sqlite3";
|
sqlib :: #import c {
|
||||||
|
#define "SQLITE_DQS=0";
|
||||||
|
#define "SQLITE_THREADSAFE=0";
|
||||||
|
#define "SQLITE_DEFAULT_MEMSTATUS=0";
|
||||||
|
#define "SQLITE_OMIT_DEPRECATED";
|
||||||
|
#define "SQLITE_OMIT_SHARED_CACHE";
|
||||||
|
#define "SQLITE_LIKE_DOESNT_MATCH_BLOBS";
|
||||||
|
#define "SQLITE_ENABLE_COLUMN_METADATA";
|
||||||
|
#flags "-O2";
|
||||||
|
#source "../../vendor/sqlite/sqlite3.c";
|
||||||
|
};
|
||||||
|
|
||||||
// ── FFI: connection lifecycle ─────────────────────────────────────────
|
// ── FFI: connection lifecycle ─────────────────────────────────────────
|
||||||
sqlite3_open :: (path: cstring, out_db: *usize) -> i32 #foreign sqlib "dist_sqlite3_open";
|
sqlite3_open :: (path: cstring, out_db: *usize) -> i32 #foreign sqlib "sqlite3_open";
|
||||||
sqlite3_open_v2 :: (path: cstring, out_db: *usize, flags: i32, vfs: usize) -> i32 #foreign sqlib "dist_sqlite3_open_v2";
|
sqlite3_open_v2 :: (path: cstring, out_db: *usize, flags: i32, vfs: usize) -> i32 #foreign sqlib "sqlite3_open_v2";
|
||||||
sqlite3_close :: (db: usize) -> i32 #foreign sqlib "dist_sqlite3_close";
|
sqlite3_close :: (db: usize) -> i32 #foreign sqlib "sqlite3_close";
|
||||||
sqlite3_close_v2 :: (db: usize) -> i32 #foreign sqlib "dist_sqlite3_close_v2";
|
sqlite3_close_v2 :: (db: usize) -> i32 #foreign sqlib "sqlite3_close_v2";
|
||||||
|
|
||||||
// ── FFI: errors ───────────────────────────────────────────────────────
|
// ── FFI: errors ───────────────────────────────────────────────────────
|
||||||
sqlite3_errcode :: (db: usize) -> i32 #foreign sqlib "dist_sqlite3_errcode";
|
sqlite3_errcode :: (db: usize) -> i32 #foreign sqlib "sqlite3_errcode";
|
||||||
sqlite3_extended_errcode :: (db: usize) -> i32 #foreign sqlib "dist_sqlite3_extended_errcode";
|
sqlite3_extended_errcode :: (db: usize) -> i32 #foreign sqlib "sqlite3_extended_errcode";
|
||||||
sqlite3_errmsg :: (db: usize) -> ?cstring #foreign sqlib "dist_sqlite3_errmsg";
|
sqlite3_errmsg :: (db: usize) -> ?cstring #foreign sqlib "sqlite3_errmsg";
|
||||||
sqlite3_errstr :: (code: i32) -> ?cstring #foreign sqlib "dist_sqlite3_errstr";
|
sqlite3_errstr :: (code: i32) -> ?cstring #foreign sqlib "sqlite3_errstr";
|
||||||
sqlite3_error_offset :: (db: usize) -> i32 #foreign sqlib "dist_sqlite3_error_offset";
|
sqlite3_error_offset :: (db: usize) -> i32 #foreign sqlib "sqlite3_error_offset";
|
||||||
sqlite3_extended_result_codes :: (db: usize, onoff: i32) -> i32 #foreign sqlib "dist_sqlite3_extended_result_codes";
|
sqlite3_extended_result_codes :: (db: usize, onoff: i32) -> i32 #foreign sqlib "sqlite3_extended_result_codes";
|
||||||
|
|
||||||
// ── FFI: connection state & control ───────────────────────────────────
|
// ── FFI: connection state & control ───────────────────────────────────
|
||||||
sqlite3_busy_timeout :: (db: usize, ms: i32) -> i32 #foreign sqlib "dist_sqlite3_busy_timeout";
|
sqlite3_busy_timeout :: (db: usize, ms: i32) -> i32 #foreign sqlib "sqlite3_busy_timeout";
|
||||||
sqlite3_interrupt :: (db: usize) #foreign sqlib "dist_sqlite3_interrupt";
|
sqlite3_interrupt :: (db: usize) #foreign sqlib "sqlite3_interrupt";
|
||||||
sqlite3_is_interrupted :: (db: usize) -> i32 #foreign sqlib "dist_sqlite3_is_interrupted";
|
sqlite3_is_interrupted :: (db: usize) -> i32 #foreign sqlib "sqlite3_is_interrupted";
|
||||||
sqlite3_get_autocommit :: (db: usize) -> i32 #foreign sqlib "dist_sqlite3_get_autocommit";
|
sqlite3_get_autocommit :: (db: usize) -> i32 #foreign sqlib "sqlite3_get_autocommit";
|
||||||
sqlite3_txn_state :: (db: usize, schema: cstring) -> i32 #foreign sqlib "dist_sqlite3_txn_state";
|
sqlite3_txn_state :: (db: usize, schema: cstring) -> i32 #foreign sqlib "sqlite3_txn_state";
|
||||||
sqlite3_db_filename :: (db: usize, db_name: cstring) -> ?cstring #foreign sqlib "dist_sqlite3_db_filename";
|
sqlite3_db_filename :: (db: usize, db_name: cstring) -> ?cstring #foreign sqlib "sqlite3_db_filename";
|
||||||
sqlite3_db_readonly :: (db: usize, db_name: cstring) -> i32 #foreign sqlib "dist_sqlite3_db_readonly";
|
sqlite3_db_readonly :: (db: usize, db_name: cstring) -> i32 #foreign sqlib "sqlite3_db_readonly";
|
||||||
sqlite3_db_cacheflush :: (db: usize) -> i32 #foreign sqlib "dist_sqlite3_db_cacheflush";
|
sqlite3_db_cacheflush :: (db: usize) -> i32 #foreign sqlib "sqlite3_db_cacheflush";
|
||||||
sqlite3_db_release_memory :: (db: usize) -> i32 #foreign sqlib "dist_sqlite3_db_release_memory";
|
sqlite3_db_release_memory :: (db: usize) -> i32 #foreign sqlib "sqlite3_db_release_memory";
|
||||||
sqlite3_last_insert_rowid :: (db: usize) -> i64 #foreign sqlib "dist_sqlite3_last_insert_rowid";
|
sqlite3_last_insert_rowid :: (db: usize) -> i64 #foreign sqlib "sqlite3_last_insert_rowid";
|
||||||
sqlite3_set_last_insert_rowid :: (db: usize, rowid: i64) #foreign sqlib "dist_sqlite3_set_last_insert_rowid";
|
sqlite3_set_last_insert_rowid :: (db: usize, rowid: i64) #foreign sqlib "sqlite3_set_last_insert_rowid";
|
||||||
sqlite3_changes64 :: (db: usize) -> i64 #foreign sqlib "dist_sqlite3_changes64";
|
sqlite3_changes64 :: (db: usize) -> i64 #foreign sqlib "sqlite3_changes64";
|
||||||
sqlite3_total_changes64 :: (db: usize) -> i64 #foreign sqlib "dist_sqlite3_total_changes64";
|
sqlite3_total_changes64 :: (db: usize) -> i64 #foreign sqlib "sqlite3_total_changes64";
|
||||||
sqlite3_limit :: (db: usize, id: i32, new_val: i32) -> i32 #foreign sqlib "dist_sqlite3_limit";
|
sqlite3_limit :: (db: usize, id: i32, new_val: i32) -> i32 #foreign sqlib "sqlite3_limit";
|
||||||
sqlite3_exec :: (db: usize, sql: cstring, cb: usize, arg: usize, errmsg: usize) -> i32 #foreign sqlib "dist_sqlite3_exec";
|
sqlite3_exec :: (db: usize, sql: cstring, cb: usize, arg: usize, errmsg: usize) -> i32 #foreign sqlib "sqlite3_exec";
|
||||||
sqlite3_table_column_metadata :: (db: usize, db_name: cstring, table: cstring, column: cstring, out_data_type: *usize, out_coll_seq: *usize, out_not_null: *i32, out_primary_key: *i32, out_autoinc: *i32) -> i32 #foreign sqlib "dist_sqlite3_table_column_metadata";
|
sqlite3_table_column_metadata :: (db: usize, db_name: cstring, table: cstring, column: cstring, out_data_type: *usize, out_coll_seq: *usize, out_not_null: *i32, out_primary_key: *i32, out_autoinc: *i32) -> i32 #foreign sqlib "sqlite3_table_column_metadata";
|
||||||
|
|
||||||
// ── FFI: statements ───────────────────────────────────────────────────
|
// ── FFI: statements ───────────────────────────────────────────────────
|
||||||
sqlite3_prepare_v2 :: (db: usize, sql: [*]u8, nbyte: i32, out_stmt: *usize, out_tail: usize) -> i32 #foreign sqlib "dist_sqlite3_prepare_v2";
|
sqlite3_prepare_v2 :: (db: usize, sql: [*]u8, nbyte: i32, out_stmt: *usize, out_tail: usize) -> i32 #foreign sqlib "sqlite3_prepare_v2";
|
||||||
sqlite3_prepare_v3 :: (db: usize, sql: [*]u8, nbyte: i32, prep_flags: u32, out_stmt: *usize, out_tail: usize) -> i32 #foreign sqlib "dist_sqlite3_prepare_v3";
|
sqlite3_prepare_v3 :: (db: usize, sql: [*]u8, nbyte: i32, prep_flags: u32, out_stmt: *usize, out_tail: usize) -> i32 #foreign sqlib "sqlite3_prepare_v3";
|
||||||
sqlite3_step :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_step";
|
sqlite3_step :: (stmt: usize) -> i32 #foreign sqlib "sqlite3_step";
|
||||||
sqlite3_reset :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_reset";
|
sqlite3_reset :: (stmt: usize) -> i32 #foreign sqlib "sqlite3_reset";
|
||||||
sqlite3_finalize :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_finalize";
|
sqlite3_finalize :: (stmt: usize) -> i32 #foreign sqlib "sqlite3_finalize";
|
||||||
sqlite3_clear_bindings :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_clear_bindings";
|
sqlite3_clear_bindings :: (stmt: usize) -> i32 #foreign sqlib "sqlite3_clear_bindings";
|
||||||
sqlite3_sql :: (stmt: usize) -> ?cstring #foreign sqlib "dist_sqlite3_sql";
|
sqlite3_sql :: (stmt: usize) -> ?cstring #foreign sqlib "sqlite3_sql";
|
||||||
sqlite3_expanded_sql :: (stmt: usize) -> ?cstring #foreign sqlib "dist_sqlite3_expanded_sql";
|
sqlite3_expanded_sql :: (stmt: usize) -> ?cstring #foreign sqlib "sqlite3_expanded_sql";
|
||||||
sqlite3_stmt_busy :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_stmt_busy";
|
sqlite3_stmt_busy :: (stmt: usize) -> i32 #foreign sqlib "sqlite3_stmt_busy";
|
||||||
sqlite3_stmt_readonly :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_stmt_readonly";
|
sqlite3_stmt_readonly :: (stmt: usize) -> i32 #foreign sqlib "sqlite3_stmt_readonly";
|
||||||
sqlite3_stmt_isexplain :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_stmt_isexplain";
|
sqlite3_stmt_isexplain :: (stmt: usize) -> i32 #foreign sqlib "sqlite3_stmt_isexplain";
|
||||||
sqlite3_stmt_explain :: (stmt: usize, mode: i32) -> i32 #foreign sqlib "dist_sqlite3_stmt_explain";
|
sqlite3_stmt_explain :: (stmt: usize, mode: i32) -> i32 #foreign sqlib "sqlite3_stmt_explain";
|
||||||
sqlite3_stmt_status :: (stmt: usize, op: i32, reset: i32) -> i32 #foreign sqlib "dist_sqlite3_stmt_status";
|
sqlite3_stmt_status :: (stmt: usize, op: i32, reset: i32) -> i32 #foreign sqlib "sqlite3_stmt_status";
|
||||||
sqlite3_db_handle :: (stmt: usize) -> usize #foreign sqlib "dist_sqlite3_db_handle";
|
sqlite3_db_handle :: (stmt: usize) -> usize #foreign sqlib "sqlite3_db_handle";
|
||||||
sqlite3_next_stmt :: (db: usize, stmt: usize) -> usize #foreign sqlib "dist_sqlite3_next_stmt";
|
sqlite3_next_stmt :: (db: usize, stmt: usize) -> usize #foreign sqlib "sqlite3_next_stmt";
|
||||||
|
|
||||||
// ── FFI: binding ──────────────────────────────────────────────────────
|
// ── FFI: binding ──────────────────────────────────────────────────────
|
||||||
sqlite3_bind_parameter_count :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_bind_parameter_count";
|
sqlite3_bind_parameter_count :: (stmt: usize) -> i32 #foreign sqlib "sqlite3_bind_parameter_count";
|
||||||
sqlite3_bind_parameter_index :: (stmt: usize, name: cstring) -> i32 #foreign sqlib "dist_sqlite3_bind_parameter_index";
|
sqlite3_bind_parameter_index :: (stmt: usize, name: cstring) -> i32 #foreign sqlib "sqlite3_bind_parameter_index";
|
||||||
sqlite3_bind_parameter_name :: (stmt: usize, idx: i32) -> ?cstring #foreign sqlib "dist_sqlite3_bind_parameter_name";
|
sqlite3_bind_parameter_name :: (stmt: usize, idx: i32) -> ?cstring #foreign sqlib "sqlite3_bind_parameter_name";
|
||||||
sqlite3_bind_text :: (stmt: usize, idx: i32, text: [*]u8, n: i32, destructor: isize) -> i32 #foreign sqlib "dist_sqlite3_bind_text";
|
sqlite3_bind_text :: (stmt: usize, idx: i32, text: [*]u8, n: i32, destructor: isize) -> i32 #foreign sqlib "sqlite3_bind_text";
|
||||||
sqlite3_bind_blob :: (stmt: usize, idx: i32, data: [*]u8, n: i32, destructor: isize) -> i32 #foreign sqlib "dist_sqlite3_bind_blob";
|
sqlite3_bind_blob :: (stmt: usize, idx: i32, data: [*]u8, n: i32, destructor: isize) -> i32 #foreign sqlib "sqlite3_bind_blob";
|
||||||
sqlite3_bind_double :: (stmt: usize, idx: i32, v: f64) -> i32 #foreign sqlib "dist_sqlite3_bind_double";
|
sqlite3_bind_double :: (stmt: usize, idx: i32, v: f64) -> i32 #foreign sqlib "sqlite3_bind_double";
|
||||||
sqlite3_bind_int64 :: (stmt: usize, idx: i32, v: i64) -> i32 #foreign sqlib "dist_sqlite3_bind_int64";
|
sqlite3_bind_int64 :: (stmt: usize, idx: i32, v: i64) -> i32 #foreign sqlib "sqlite3_bind_int64";
|
||||||
sqlite3_bind_null :: (stmt: usize, idx: i32) -> i32 #foreign sqlib "dist_sqlite3_bind_null";
|
sqlite3_bind_null :: (stmt: usize, idx: i32) -> i32 #foreign sqlib "sqlite3_bind_null";
|
||||||
sqlite3_bind_zeroblob64 :: (stmt: usize, idx: i32, n: u64) -> i32 #foreign sqlib "dist_sqlite3_bind_zeroblob64";
|
sqlite3_bind_zeroblob64 :: (stmt: usize, idx: i32, n: u64) -> i32 #foreign sqlib "sqlite3_bind_zeroblob64";
|
||||||
|
|
||||||
// ── FFI: result columns ───────────────────────────────────────────────
|
// ── FFI: result columns ───────────────────────────────────────────────
|
||||||
sqlite3_column_blob :: (stmt: usize, icol: i32) -> ?*u8 #foreign sqlib "dist_sqlite3_column_blob";
|
sqlite3_column_blob :: (stmt: usize, icol: i32) -> ?*u8 #foreign sqlib "sqlite3_column_blob";
|
||||||
sqlite3_column_double :: (stmt: usize, icol: i32) -> f64 #foreign sqlib "dist_sqlite3_column_double";
|
sqlite3_column_double :: (stmt: usize, icol: i32) -> f64 #foreign sqlib "sqlite3_column_double";
|
||||||
sqlite3_column_int64 :: (stmt: usize, icol: i32) -> i64 #foreign sqlib "dist_sqlite3_column_int64";
|
sqlite3_column_int64 :: (stmt: usize, icol: i32) -> i64 #foreign sqlib "sqlite3_column_int64";
|
||||||
sqlite3_column_text :: (stmt: usize, icol: i32) -> ?*u8 #foreign sqlib "dist_sqlite3_column_text";
|
sqlite3_column_text :: (stmt: usize, icol: i32) -> ?*u8 #foreign sqlib "sqlite3_column_text";
|
||||||
sqlite3_column_bytes :: (stmt: usize, icol: i32) -> i32 #foreign sqlib "dist_sqlite3_column_bytes";
|
sqlite3_column_bytes :: (stmt: usize, icol: i32) -> i32 #foreign sqlib "sqlite3_column_bytes";
|
||||||
sqlite3_column_type :: (stmt: usize, icol: i32) -> i32 #foreign sqlib "dist_sqlite3_column_type";
|
sqlite3_column_type :: (stmt: usize, icol: i32) -> i32 #foreign sqlib "sqlite3_column_type";
|
||||||
sqlite3_column_count :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_column_count";
|
sqlite3_column_count :: (stmt: usize) -> i32 #foreign sqlib "sqlite3_column_count";
|
||||||
sqlite3_column_name :: (stmt: usize, icol: i32) -> ?cstring #foreign sqlib "dist_sqlite3_column_name";
|
sqlite3_column_name :: (stmt: usize, icol: i32) -> ?cstring #foreign sqlib "sqlite3_column_name";
|
||||||
sqlite3_column_decltype :: (stmt: usize, icol: i32) -> ?cstring #foreign sqlib "dist_sqlite3_column_decltype";
|
sqlite3_column_decltype :: (stmt: usize, icol: i32) -> ?cstring #foreign sqlib "sqlite3_column_decltype";
|
||||||
sqlite3_column_database_name :: (stmt: usize, icol: i32) -> ?cstring #foreign sqlib "dist_sqlite3_column_database_name";
|
sqlite3_column_database_name :: (stmt: usize, icol: i32) -> ?cstring #foreign sqlib "sqlite3_column_database_name";
|
||||||
sqlite3_column_table_name :: (stmt: usize, icol: i32) -> ?cstring #foreign sqlib "dist_sqlite3_column_table_name";
|
sqlite3_column_table_name :: (stmt: usize, icol: i32) -> ?cstring #foreign sqlib "sqlite3_column_table_name";
|
||||||
sqlite3_column_origin_name :: (stmt: usize, icol: i32) -> ?cstring #foreign sqlib "dist_sqlite3_column_origin_name";
|
sqlite3_column_origin_name :: (stmt: usize, icol: i32) -> ?cstring #foreign sqlib "sqlite3_column_origin_name";
|
||||||
sqlite3_data_count :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_data_count";
|
sqlite3_data_count :: (stmt: usize) -> i32 #foreign sqlib "sqlite3_data_count";
|
||||||
|
|
||||||
// ── FFI: incremental blob I/O ─────────────────────────────────────────
|
// ── FFI: incremental blob I/O ─────────────────────────────────────────
|
||||||
sqlite3_blob_open :: (db: usize, db_name: cstring, table: cstring, column: cstring, rowid: i64, flags: i32, out_blob: *usize) -> i32 #foreign sqlib "dist_sqlite3_blob_open";
|
sqlite3_blob_open :: (db: usize, db_name: cstring, table: cstring, column: cstring, rowid: i64, flags: i32, out_blob: *usize) -> i32 #foreign sqlib "sqlite3_blob_open";
|
||||||
sqlite3_blob_reopen :: (blob: usize, rowid: i64) -> i32 #foreign sqlib "dist_sqlite3_blob_reopen";
|
sqlite3_blob_reopen :: (blob: usize, rowid: i64) -> i32 #foreign sqlib "sqlite3_blob_reopen";
|
||||||
sqlite3_blob_close :: (blob: usize) -> i32 #foreign sqlib "dist_sqlite3_blob_close";
|
sqlite3_blob_close :: (blob: usize) -> i32 #foreign sqlib "sqlite3_blob_close";
|
||||||
sqlite3_blob_bytes :: (blob: usize) -> i32 #foreign sqlib "dist_sqlite3_blob_bytes";
|
sqlite3_blob_bytes :: (blob: usize) -> i32 #foreign sqlib "sqlite3_blob_bytes";
|
||||||
sqlite3_blob_read :: (blob: usize, buf: [*]u8, n: i32, offset: i32) -> i32 #foreign sqlib "dist_sqlite3_blob_read";
|
sqlite3_blob_read :: (blob: usize, buf: [*]u8, n: i32, offset: i32) -> i32 #foreign sqlib "sqlite3_blob_read";
|
||||||
sqlite3_blob_write :: (blob: usize, buf: [*]u8, n: i32, offset: i32) -> i32 #foreign sqlib "dist_sqlite3_blob_write";
|
sqlite3_blob_write :: (blob: usize, buf: [*]u8, n: i32, offset: i32) -> i32 #foreign sqlib "sqlite3_blob_write";
|
||||||
|
|
||||||
// ── FFI: online backup ────────────────────────────────────────────────
|
// ── FFI: online backup ────────────────────────────────────────────────
|
||||||
sqlite3_backup_init :: (dst: usize, dst_name: cstring, src: usize, src_name: cstring) -> usize #foreign sqlib "dist_sqlite3_backup_init";
|
sqlite3_backup_init :: (dst: usize, dst_name: cstring, src: usize, src_name: cstring) -> usize #foreign sqlib "sqlite3_backup_init";
|
||||||
sqlite3_backup_step :: (bk: usize, n_page: i32) -> i32 #foreign sqlib "dist_sqlite3_backup_step";
|
sqlite3_backup_step :: (bk: usize, n_page: i32) -> i32 #foreign sqlib "sqlite3_backup_step";
|
||||||
sqlite3_backup_finish :: (bk: usize) -> i32 #foreign sqlib "dist_sqlite3_backup_finish";
|
sqlite3_backup_finish :: (bk: usize) -> i32 #foreign sqlib "sqlite3_backup_finish";
|
||||||
sqlite3_backup_remaining :: (bk: usize) -> i32 #foreign sqlib "dist_sqlite3_backup_remaining";
|
sqlite3_backup_remaining :: (bk: usize) -> i32 #foreign sqlib "sqlite3_backup_remaining";
|
||||||
sqlite3_backup_pagecount :: (bk: usize) -> i32 #foreign sqlib "dist_sqlite3_backup_pagecount";
|
sqlite3_backup_pagecount :: (bk: usize) -> i32 #foreign sqlib "sqlite3_backup_pagecount";
|
||||||
|
|
||||||
// ── FFI: serialization ────────────────────────────────────────────────
|
// ── FFI: serialization ────────────────────────────────────────────────
|
||||||
sqlite3_serialize :: (db: usize, schema: cstring, out_size: *i64, flags: u32) -> ?*u8 #foreign sqlib "dist_sqlite3_serialize";
|
sqlite3_serialize :: (db: usize, schema: cstring, out_size: *i64, flags: u32) -> ?*u8 #foreign sqlib "sqlite3_serialize";
|
||||||
sqlite3_deserialize :: (db: usize, schema: cstring, data: usize, sz_db: i64, sz_buf: i64, flags: u32) -> i32 #foreign sqlib "dist_sqlite3_deserialize";
|
sqlite3_deserialize :: (db: usize, schema: cstring, data: usize, sz_db: i64, sz_buf: i64, flags: u32) -> i32 #foreign sqlib "sqlite3_deserialize";
|
||||||
|
|
||||||
// ── FFI: library utilities ────────────────────────────────────────────
|
// ── FFI: library utilities ────────────────────────────────────────────
|
||||||
sqlite3_libversion :: () -> ?cstring #foreign sqlib "dist_sqlite3_libversion";
|
sqlite3_libversion :: () -> ?cstring #foreign sqlib "sqlite3_libversion";
|
||||||
sqlite3_libversion_number :: () -> i32 #foreign sqlib "dist_sqlite3_libversion_number";
|
sqlite3_libversion_number :: () -> i32 #foreign sqlib "sqlite3_libversion_number";
|
||||||
sqlite3_sourceid :: () -> ?cstring #foreign sqlib "dist_sqlite3_sourceid";
|
sqlite3_sourceid :: () -> ?cstring #foreign sqlib "sqlite3_sourceid";
|
||||||
sqlite3_threadsafe :: () -> i32 #foreign sqlib "dist_sqlite3_threadsafe";
|
sqlite3_threadsafe :: () -> i32 #foreign sqlib "sqlite3_threadsafe";
|
||||||
sqlite3_compileoption_used :: (name: cstring) -> i32 #foreign sqlib "dist_sqlite3_compileoption_used";
|
sqlite3_compileoption_used :: (name: cstring) -> i32 #foreign sqlib "sqlite3_compileoption_used";
|
||||||
sqlite3_compileoption_get :: (n: i32) -> ?cstring #foreign sqlib "dist_sqlite3_compileoption_get";
|
sqlite3_compileoption_get :: (n: i32) -> ?cstring #foreign sqlib "sqlite3_compileoption_get";
|
||||||
sqlite3_complete :: (sql: cstring) -> i32 #foreign sqlib "dist_sqlite3_complete";
|
sqlite3_complete :: (sql: cstring) -> i32 #foreign sqlib "sqlite3_complete";
|
||||||
sqlite3_free :: (p: usize) #foreign sqlib "dist_sqlite3_free";
|
sqlite3_free :: (p: usize) #foreign sqlib "sqlite3_free";
|
||||||
sqlite3_malloc64 :: (n: u64) -> usize #foreign sqlib "dist_sqlite3_malloc64";
|
sqlite3_malloc64 :: (n: u64) -> usize #foreign sqlib "sqlite3_malloc64";
|
||||||
sqlite3_msize :: (p: usize) -> u64 #foreign sqlib "dist_sqlite3_msize";
|
sqlite3_msize :: (p: usize) -> u64 #foreign sqlib "sqlite3_msize";
|
||||||
sqlite3_memory_used :: () -> i64 #foreign sqlib "dist_sqlite3_memory_used";
|
sqlite3_memory_used :: () -> i64 #foreign sqlib "sqlite3_memory_used";
|
||||||
sqlite3_memory_highwater :: (reset: i32) -> i64 #foreign sqlib "dist_sqlite3_memory_highwater";
|
sqlite3_memory_highwater :: (reset: i32) -> i64 #foreign sqlib "sqlite3_memory_highwater";
|
||||||
sqlite3_release_memory :: (n: i32) -> i32 #foreign sqlib "dist_sqlite3_release_memory";
|
sqlite3_release_memory :: (n: i32) -> i32 #foreign sqlib "sqlite3_release_memory";
|
||||||
sqlite3_soft_heap_limit64 :: (n: i64) -> i64 #foreign sqlib "dist_sqlite3_soft_heap_limit64";
|
sqlite3_soft_heap_limit64 :: (n: i64) -> i64 #foreign sqlib "sqlite3_soft_heap_limit64";
|
||||||
sqlite3_hard_heap_limit64 :: (n: i64) -> i64 #foreign sqlib "dist_sqlite3_hard_heap_limit64";
|
sqlite3_hard_heap_limit64 :: (n: i64) -> i64 #foreign sqlib "sqlite3_hard_heap_limit64";
|
||||||
sqlite3_randomness :: (n: i32, buf: [*]u8) #foreign sqlib "dist_sqlite3_randomness";
|
sqlite3_randomness :: (n: i32, buf: [*]u8) #foreign sqlib "sqlite3_randomness";
|
||||||
sqlite3_sleep :: (ms: i32) -> i32 #foreign sqlib "dist_sqlite3_sleep";
|
sqlite3_sleep :: (ms: i32) -> i32 #foreign sqlib "sqlite3_sleep";
|
||||||
sqlite3_stricmp :: (a: cstring, b: cstring) -> i32 #foreign sqlib "dist_sqlite3_stricmp";
|
sqlite3_stricmp :: (a: cstring, b: cstring) -> i32 #foreign sqlib "sqlite3_stricmp";
|
||||||
sqlite3_strnicmp :: (a: cstring, b: cstring, n: i32) -> i32 #foreign sqlib "dist_sqlite3_strnicmp";
|
sqlite3_strnicmp :: (a: cstring, b: cstring, n: i32) -> i32 #foreign sqlib "sqlite3_strnicmp";
|
||||||
sqlite3_strglob :: (glob: cstring, s: cstring) -> i32 #foreign sqlib "dist_sqlite3_strglob";
|
sqlite3_strglob :: (glob: cstring, s: cstring) -> i32 #foreign sqlib "sqlite3_strglob";
|
||||||
sqlite3_strlike :: (like: cstring, s: cstring, esc: u32) -> i32 #foreign sqlib "dist_sqlite3_strlike";
|
sqlite3_strlike :: (like: cstring, s: cstring, esc: u32) -> i32 #foreign sqlib "sqlite3_strlike";
|
||||||
|
|
||||||
// ── Result codes (primary; full set) ──────────────────────────────────
|
// ── Result codes (primary; full set) ──────────────────────────────────
|
||||||
SQLITE_OK :: 0;
|
SQLITE_OK :: 0;
|
||||||
|
|||||||
11
tests/run.sh
11
tests/run.sh
@@ -8,15 +8,14 @@
|
|||||||
#
|
#
|
||||||
# Locate the compiler via SX (overridable); defaults to the sibling sx repo.
|
# Locate the compiler via SX (overridable); defaults to the sibling sx repo.
|
||||||
#
|
#
|
||||||
# `-L build/vendor/jit` lets the JIT dlopen the VENDORED libsqlite3.dylib
|
# The vendored SQLite needs no flags here: src/db/sqlite.sx declares it
|
||||||
# (built by `make build`) instead of falling back to the OS copy — the
|
# as a `#import c` unit, so `sx run` compiles (cached) and loads it as a
|
||||||
# version assert in tests/sqlite_smoke.sx depends on it.
|
# priority symbol target — the version assert in tests/sqlite_smoke.sx
|
||||||
|
# proves the OS copy never shadows it.
|
||||||
set -u
|
set -u
|
||||||
|
|
||||||
SX="${SX:-/Users/agra/projects/sx/zig-out/bin/sx}"
|
SX="${SX:-/Users/agra/projects/sx/zig-out/bin/sx}"
|
||||||
TESTS_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
TESTS_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
||||||
REPO_DIR=$(CDPATH= cd -- "$TESTS_DIR/.." && pwd)
|
|
||||||
SX_RUN_FLAGS="-L $REPO_DIR/build/vendor/jit"
|
|
||||||
|
|
||||||
pass=0
|
pass=0
|
||||||
fail=0
|
fail=0
|
||||||
@@ -26,7 +25,7 @@ fail=0
|
|||||||
# pass/fail counters survive).
|
# pass/fail counters survive).
|
||||||
for t in $(find "$TESTS_DIR" -name '*.sx' -type f | sort); do
|
for t in $(find "$TESTS_DIR" -name '*.sx' -type f | sort); do
|
||||||
name=${t#"$TESTS_DIR"/}
|
name=${t#"$TESTS_DIR"/}
|
||||||
if "$SX" run "$t" $SX_RUN_FLAGS >/dev/null 2>&1; then
|
if "$SX" run "$t" >/dev/null 2>&1; then
|
||||||
printf ' %-44s ok\n' "$name"
|
printf ' %-44s ok\n' "$name"
|
||||||
pass=$((pass + 1))
|
pass=$((pass + 1))
|
||||||
else
|
else
|
||||||
|
|||||||
40
vendor/sqlite/README.md
vendored
40
vendor/sqlite/README.md
vendored
@@ -7,26 +7,21 @@
|
|||||||
`sqlite3ext.h` dropped — no shell, no loadable extensions)
|
`sqlite3ext.h` dropped — no shell, no loadable extensions)
|
||||||
- License: public domain (<https://sqlite.org/copyright.html>)
|
- License: public domain (<https://sqlite.org/copyright.html>)
|
||||||
|
|
||||||
`make build` compiles this into `build/vendor/libsqlite3.a` (statically
|
The amalgamation is part of the program, not the build system:
|
||||||
linked into the `dist` binary via `-L build/vendor`) and
|
`src/db/sqlite.sx` declares it as a named `#import c` unit carrying the
|
||||||
`build/vendor/jit/libsqlite3.dylib` (dlopen'd by `sx run`, which is how
|
pinned compile options (`SQLITE_DQS=0`, `SQLITE_THREADSAFE=0`,
|
||||||
`make test` executes the test programs). The two locations are separate
|
`SQLITE_DEFAULT_MEMSTATUS=0`, `SQLITE_OMIT_DEPRECATED`,
|
||||||
on purpose: the macOS linker prefers a dylib over an archive in the same
|
`SQLITE_OMIT_SHARED_CACHE`, `SQLITE_LIKE_DOESNT_MATCH_BLOBS`,
|
||||||
search directory, and the AOT binary must link the static copy.
|
`SQLITE_ENABLE_COLUMN_METADATA`, `-O2`), and every `#foreign sqlib`
|
||||||
`tests/sqlite_smoke.sx` asserts `sqlite3_libversion()` equals the version
|
binding resolves against that unit. sx compiles the unit through its
|
||||||
above, so a fallback to the OS libsqlite3 fails loudly in both modes.
|
content-addressed object cache (`.sx-cache/`), so the 250k-line source
|
||||||
|
builds once per checkout — `sx build` links the objects into the
|
||||||
## Symbol renaming
|
binary, `sx run` loads them as a PRIORITY symbol-search target ahead of
|
||||||
|
the process images, which is why the OS libsqlite3 (a different
|
||||||
The sx JIT resolves `#foreign` symbols via `dlsym(RTLD_DEFAULT)`, which
|
version, loaded into the compiler process by CoreServices) can never
|
||||||
searches every image already loaded into the process — the OS libsqlite3
|
shadow this copy. `tests/sqlite_smoke.sx` asserts
|
||||||
is usually among them and wins by load order. So every API function the
|
`sqlite3_libversion()` equals the version above, so any fallback fails
|
||||||
bindings use is renamed `dist_sqlite3_*` in the vendored build: those
|
loudly in both modes.
|
||||||
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
|
## Bound surface
|
||||||
|
|
||||||
@@ -42,5 +37,6 @@ variants, and subsystems this build omits (mutex/VFS under
|
|||||||
`SQLITE_THREADSAFE=0`, sessions/snapshots/vtabs, deprecated API).
|
`SQLITE_THREADSAFE=0`, sessions/snapshots/vtabs, deprecated API).
|
||||||
|
|
||||||
To upgrade: replace `sqlite3.c`/`sqlite3.h` with a newer amalgamation,
|
To upgrade: replace `sqlite3.c`/`sqlite3.h` with a newer amalgamation,
|
||||||
update this file and the version constant in `tests/sqlite_smoke.sx`, and
|
update this file and the version constant in `tests/sqlite_smoke.sx`,
|
||||||
run `make clean test`.
|
and run `make clean test` (the object cache keys on the source bytes,
|
||||||
|
so the new amalgamation recompiles automatically).
|
||||||
|
|||||||
Reference in New Issue
Block a user