sqlite bindings: adopt the cstring type

Whole C strings now cross as cstring (sx 1d17b0a): IN via to_cstring
with literal coercion, OUT as ?cstring copied through sq_from_cstr
(std from_cstring + substr) before sqlite's buffer dies. sq_cstr and
the manual strlen loop are gone. column_text/column_blob/serialize
deliberately stay ?*u8 + explicit byte counts — their payloads may
carry interior NULs that a strlen would truncate. 21/21 green.
This commit is contained in:
agra
2026-06-12 14:56:09 +03:00
parent cd896f92ec
commit b5b8ab092b

View File

@@ -33,16 +33,14 @@
// FFI type choices: handles cross as `usize` (`sqlite3*`,
// `sqlite3_stmt*`, `sqlite3_blob*`, `sqlite3_backup*` are opaque and
// never dereferenced; `usize` keeps out-params single-level `*usize`
// instead of `**void`). Whole C strings IN are `[:0]u8` (the std FFI
// convention — build terminated copies with `cstring`);
// `prepare_v2/v3` and `bind_text/blob` take `[*]u8` + explicit byte
// length instead, so un-terminated sx string views pass without
// copying. Nullable C strings OUT are `?*u8` — the null lives in the
// type. `?[:0]u8` is the contract these should carry (a nullable thin
// char*), but [:0]u8 returns/optionals don't cross the FFI correctly
// yet — sx issue 0128. Returned strings are COPIED into
// `context.allocator` before returning — sqlite's buffers die on the
// next step/finalize/close.
// instead of `**void`). Whole C strings cross as `cstring` — IN via
// `to_cstring` (literals coerce), OUT as `?cstring` copied through
// `sq_from_cstr` before sqlite's buffer dies on the next
// step/finalize/close. `prepare_v2/v3` and `bind_text/blob` take
// `[*]u8` + explicit byte length instead, so un-terminated sx string
// views pass without copying — and `column_text`/`column_blob`/
// `serialize` return `?*u8` + explicit byte counts, never `cstring`:
// their payloads may carry interior NULs that a strlen would truncate.
// =====================================================================
#import "modules/std.sx";
@@ -50,16 +48,16 @@
sqlib :: #library "sqlite3";
// ── FFI: connection lifecycle ─────────────────────────────────────────
sqlite3_open :: (path: [:0]u8, out_db: *usize) -> i32 #foreign sqlib "dist_sqlite3_open";
sqlite3_open_v2 :: (path: [:0]u8, out_db: *usize, flags: i32, vfs: usize) -> i32 #foreign sqlib "dist_sqlite3_open_v2";
sqlite3_open :: (path: cstring, out_db: *usize) -> i32 #foreign sqlib "dist_sqlite3_open";
sqlite3_open_v2 :: (path: cstring, out_db: *usize, flags: i32, vfs: usize) -> i32 #foreign sqlib "dist_sqlite3_open_v2";
sqlite3_close :: (db: usize) -> i32 #foreign sqlib "dist_sqlite3_close";
sqlite3_close_v2 :: (db: usize) -> i32 #foreign sqlib "dist_sqlite3_close_v2";
// ── FFI: errors ───────────────────────────────────────────────────────
sqlite3_errcode :: (db: usize) -> i32 #foreign sqlib "dist_sqlite3_errcode";
sqlite3_extended_errcode :: (db: usize) -> i32 #foreign sqlib "dist_sqlite3_extended_errcode";
sqlite3_errmsg :: (db: usize) -> ?*u8 #foreign sqlib "dist_sqlite3_errmsg";
sqlite3_errstr :: (code: i32) -> ?*u8 #foreign sqlib "dist_sqlite3_errstr";
sqlite3_errmsg :: (db: usize) -> ?cstring #foreign sqlib "dist_sqlite3_errmsg";
sqlite3_errstr :: (code: i32) -> ?cstring #foreign sqlib "dist_sqlite3_errstr";
sqlite3_error_offset :: (db: usize) -> i32 #foreign sqlib "dist_sqlite3_error_offset";
sqlite3_extended_result_codes :: (db: usize, onoff: i32) -> i32 #foreign sqlib "dist_sqlite3_extended_result_codes";
@@ -68,9 +66,9 @@ sqlite3_busy_timeout :: (db: usize, ms: i32) -> i32 #foreign sqlib "dist_s
sqlite3_interrupt :: (db: usize) #foreign sqlib "dist_sqlite3_interrupt";
sqlite3_is_interrupted :: (db: usize) -> i32 #foreign sqlib "dist_sqlite3_is_interrupted";
sqlite3_get_autocommit :: (db: usize) -> i32 #foreign sqlib "dist_sqlite3_get_autocommit";
sqlite3_txn_state :: (db: usize, schema: [:0]u8) -> i32 #foreign sqlib "dist_sqlite3_txn_state";
sqlite3_db_filename :: (db: usize, db_name: [:0]u8) -> ?*u8 #foreign sqlib "dist_sqlite3_db_filename";
sqlite3_db_readonly :: (db: usize, db_name: [:0]u8) -> i32 #foreign sqlib "dist_sqlite3_db_readonly";
sqlite3_txn_state :: (db: usize, schema: cstring) -> i32 #foreign sqlib "dist_sqlite3_txn_state";
sqlite3_db_filename :: (db: usize, db_name: cstring) -> ?cstring #foreign sqlib "dist_sqlite3_db_filename";
sqlite3_db_readonly :: (db: usize, db_name: cstring) -> i32 #foreign sqlib "dist_sqlite3_db_readonly";
sqlite3_db_cacheflush :: (db: usize) -> i32 #foreign sqlib "dist_sqlite3_db_cacheflush";
sqlite3_db_release_memory :: (db: usize) -> i32 #foreign sqlib "dist_sqlite3_db_release_memory";
sqlite3_last_insert_rowid :: (db: usize) -> i64 #foreign sqlib "dist_sqlite3_last_insert_rowid";
@@ -78,8 +76,8 @@ sqlite3_set_last_insert_rowid :: (db: usize, rowid: i64) #foreign sqlib "dist_sq
sqlite3_changes64 :: (db: usize) -> i64 #foreign sqlib "dist_sqlite3_changes64";
sqlite3_total_changes64 :: (db: usize) -> i64 #foreign sqlib "dist_sqlite3_total_changes64";
sqlite3_limit :: (db: usize, id: i32, new_val: i32) -> i32 #foreign sqlib "dist_sqlite3_limit";
sqlite3_exec :: (db: usize, sql: [:0]u8, cb: usize, arg: usize, errmsg: usize) -> i32 #foreign sqlib "dist_sqlite3_exec";
sqlite3_table_column_metadata :: (db: usize, db_name: [:0]u8, table: [:0]u8, column: [:0]u8, 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_exec :: (db: usize, sql: cstring, cb: usize, arg: usize, errmsg: usize) -> i32 #foreign sqlib "dist_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";
// ── FFI: statements ───────────────────────────────────────────────────
sqlite3_prepare_v2 :: (db: usize, sql: [*]u8, nbyte: i32, out_stmt: *usize, out_tail: usize) -> i32 #foreign sqlib "dist_sqlite3_prepare_v2";
@@ -88,8 +86,8 @@ sqlite3_step :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_step";
sqlite3_reset :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_reset";
sqlite3_finalize :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_finalize";
sqlite3_clear_bindings :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_clear_bindings";
sqlite3_sql :: (stmt: usize) -> ?*u8 #foreign sqlib "dist_sqlite3_sql";
sqlite3_expanded_sql :: (stmt: usize) -> ?*u8 #foreign sqlib "dist_sqlite3_expanded_sql";
sqlite3_sql :: (stmt: usize) -> ?cstring #foreign sqlib "dist_sqlite3_sql";
sqlite3_expanded_sql :: (stmt: usize) -> ?cstring #foreign sqlib "dist_sqlite3_expanded_sql";
sqlite3_stmt_busy :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_stmt_busy";
sqlite3_stmt_readonly :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_stmt_readonly";
sqlite3_stmt_isexplain :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_stmt_isexplain";
@@ -100,8 +98,8 @@ sqlite3_next_stmt :: (db: usize, stmt: usize) -> usize #foreign sqlib "dist_s
// ── FFI: binding ──────────────────────────────────────────────────────
sqlite3_bind_parameter_count :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_bind_parameter_count";
sqlite3_bind_parameter_index :: (stmt: usize, name: [:0]u8) -> i32 #foreign sqlib "dist_sqlite3_bind_parameter_index";
sqlite3_bind_parameter_name :: (stmt: usize, idx: i32) -> ?*u8 #foreign sqlib "dist_sqlite3_bind_parameter_name";
sqlite3_bind_parameter_index :: (stmt: usize, name: cstring) -> i32 #foreign sqlib "dist_sqlite3_bind_parameter_index";
sqlite3_bind_parameter_name :: (stmt: usize, idx: i32) -> ?cstring #foreign sqlib "dist_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_blob :: (stmt: usize, idx: i32, data: [*]u8, n: i32, destructor: isize) -> i32 #foreign sqlib "dist_sqlite3_bind_blob";
sqlite3_bind_double :: (stmt: usize, idx: i32, v: f64) -> i32 #foreign sqlib "dist_sqlite3_bind_double";
@@ -117,15 +115,15 @@ sqlite3_column_text :: (stmt: usize, icol: i32) -> ?*u8 #foreign sqlib "dist_s
sqlite3_column_bytes :: (stmt: usize, icol: i32) -> i32 #foreign sqlib "dist_sqlite3_column_bytes";
sqlite3_column_type :: (stmt: usize, icol: i32) -> i32 #foreign sqlib "dist_sqlite3_column_type";
sqlite3_column_count :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_column_count";
sqlite3_column_name :: (stmt: usize, icol: i32) -> ?*u8 #foreign sqlib "dist_sqlite3_column_name";
sqlite3_column_decltype :: (stmt: usize, icol: i32) -> ?*u8 #foreign sqlib "dist_sqlite3_column_decltype";
sqlite3_column_database_name :: (stmt: usize, icol: i32) -> ?*u8 #foreign sqlib "dist_sqlite3_column_database_name";
sqlite3_column_table_name :: (stmt: usize, icol: i32) -> ?*u8 #foreign sqlib "dist_sqlite3_column_table_name";
sqlite3_column_origin_name :: (stmt: usize, icol: i32) -> ?*u8 #foreign sqlib "dist_sqlite3_column_origin_name";
sqlite3_column_name :: (stmt: usize, icol: i32) -> ?cstring #foreign sqlib "dist_sqlite3_column_name";
sqlite3_column_decltype :: (stmt: usize, icol: i32) -> ?cstring #foreign sqlib "dist_sqlite3_column_decltype";
sqlite3_column_database_name :: (stmt: usize, icol: i32) -> ?cstring #foreign sqlib "dist_sqlite3_column_database_name";
sqlite3_column_table_name :: (stmt: usize, icol: i32) -> ?cstring #foreign sqlib "dist_sqlite3_column_table_name";
sqlite3_column_origin_name :: (stmt: usize, icol: i32) -> ?cstring #foreign sqlib "dist_sqlite3_column_origin_name";
sqlite3_data_count :: (stmt: usize) -> i32 #foreign sqlib "dist_sqlite3_data_count";
// ── FFI: incremental blob I/O ─────────────────────────────────────────
sqlite3_blob_open :: (db: usize, db_name: [:0]u8, table: [:0]u8, column: [:0]u8, 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 "dist_sqlite3_blob_open";
sqlite3_blob_reopen :: (blob: usize, rowid: i64) -> i32 #foreign sqlib "dist_sqlite3_blob_reopen";
sqlite3_blob_close :: (blob: usize) -> i32 #foreign sqlib "dist_sqlite3_blob_close";
sqlite3_blob_bytes :: (blob: usize) -> i32 #foreign sqlib "dist_sqlite3_blob_bytes";
@@ -133,24 +131,24 @@ sqlite3_blob_read :: (blob: usize, buf: [*]u8, n: i32, offset: i32) -> i32 #fo
sqlite3_blob_write :: (blob: usize, buf: [*]u8, n: i32, offset: i32) -> i32 #foreign sqlib "dist_sqlite3_blob_write";
// ── FFI: online backup ────────────────────────────────────────────────
sqlite3_backup_init :: (dst: usize, dst_name: [:0]u8, src: usize, src_name: [:0]u8) -> usize #foreign sqlib "dist_sqlite3_backup_init";
sqlite3_backup_init :: (dst: usize, dst_name: cstring, src: usize, src_name: cstring) -> usize #foreign sqlib "dist_sqlite3_backup_init";
sqlite3_backup_step :: (bk: usize, n_page: i32) -> i32 #foreign sqlib "dist_sqlite3_backup_step";
sqlite3_backup_finish :: (bk: usize) -> i32 #foreign sqlib "dist_sqlite3_backup_finish";
sqlite3_backup_remaining :: (bk: usize) -> i32 #foreign sqlib "dist_sqlite3_backup_remaining";
sqlite3_backup_pagecount :: (bk: usize) -> i32 #foreign sqlib "dist_sqlite3_backup_pagecount";
// ── FFI: serialization ────────────────────────────────────────────────
sqlite3_serialize :: (db: usize, schema: [:0]u8, out_size: *i64, flags: u32) -> ?*u8 #foreign sqlib "dist_sqlite3_serialize";
sqlite3_deserialize :: (db: usize, schema: [:0]u8, data: usize, sz_db: i64, sz_buf: i64, flags: u32) -> i32 #foreign sqlib "dist_sqlite3_deserialize";
sqlite3_serialize :: (db: usize, schema: cstring, out_size: *i64, flags: u32) -> ?*u8 #foreign sqlib "dist_sqlite3_serialize";
sqlite3_deserialize :: (db: usize, schema: cstring, data: usize, sz_db: i64, sz_buf: i64, flags: u32) -> i32 #foreign sqlib "dist_sqlite3_deserialize";
// ── FFI: library utilities ────────────────────────────────────────────
sqlite3_libversion :: () -> ?*u8 #foreign sqlib "dist_sqlite3_libversion";
sqlite3_libversion :: () -> ?cstring #foreign sqlib "dist_sqlite3_libversion";
sqlite3_libversion_number :: () -> i32 #foreign sqlib "dist_sqlite3_libversion_number";
sqlite3_sourceid :: () -> ?*u8 #foreign sqlib "dist_sqlite3_sourceid";
sqlite3_sourceid :: () -> ?cstring #foreign sqlib "dist_sqlite3_sourceid";
sqlite3_threadsafe :: () -> i32 #foreign sqlib "dist_sqlite3_threadsafe";
sqlite3_compileoption_used :: (name: [:0]u8) -> i32 #foreign sqlib "dist_sqlite3_compileoption_used";
sqlite3_compileoption_get :: (n: i32) -> ?*u8 #foreign sqlib "dist_sqlite3_compileoption_get";
sqlite3_complete :: (sql: [:0]u8) -> i32 #foreign sqlib "dist_sqlite3_complete";
sqlite3_compileoption_used :: (name: cstring) -> i32 #foreign sqlib "dist_sqlite3_compileoption_used";
sqlite3_compileoption_get :: (n: i32) -> ?cstring #foreign sqlib "dist_sqlite3_compileoption_get";
sqlite3_complete :: (sql: cstring) -> i32 #foreign sqlib "dist_sqlite3_complete";
sqlite3_free :: (p: usize) #foreign sqlib "dist_sqlite3_free";
sqlite3_malloc64 :: (n: u64) -> usize #foreign sqlib "dist_sqlite3_malloc64";
sqlite3_msize :: (p: usize) -> u64 #foreign sqlib "dist_sqlite3_msize";
@@ -161,10 +159,10 @@ sqlite3_soft_heap_limit64 :: (n: i64) -> i64 #foreign sqlib "dist_sqlite3_soft_h
sqlite3_hard_heap_limit64 :: (n: i64) -> i64 #foreign sqlib "dist_sqlite3_hard_heap_limit64";
sqlite3_randomness :: (n: i32, buf: [*]u8) #foreign sqlib "dist_sqlite3_randomness";
sqlite3_sleep :: (ms: i32) -> i32 #foreign sqlib "dist_sqlite3_sleep";
sqlite3_stricmp :: (a: [:0]u8, b: [:0]u8) -> i32 #foreign sqlib "dist_sqlite3_stricmp";
sqlite3_strnicmp :: (a: [:0]u8, b: [:0]u8, n: i32) -> i32 #foreign sqlib "dist_sqlite3_strnicmp";
sqlite3_strglob :: (glob: [:0]u8, s: [:0]u8) -> i32 #foreign sqlib "dist_sqlite3_strglob";
sqlite3_strlike :: (like: [:0]u8, s: [:0]u8, esc: u32) -> i32 #foreign sqlib "dist_sqlite3_strlike";
sqlite3_stricmp :: (a: cstring, b: cstring) -> i32 #foreign sqlib "dist_sqlite3_stricmp";
sqlite3_strnicmp :: (a: cstring, b: cstring, n: i32) -> i32 #foreign sqlib "dist_sqlite3_strnicmp";
sqlite3_strglob :: (glob: cstring, s: cstring) -> i32 #foreign sqlib "dist_sqlite3_strglob";
sqlite3_strlike :: (like: cstring, s: cstring, esc: u32) -> i32 #foreign sqlib "dist_sqlite3_strlike";
// ── Result codes (primary; full set) ──────────────────────────────────
SQLITE_OK :: 0;
@@ -298,23 +296,14 @@ SqliteErr :: error {
// ── string helpers ────────────────────────────────────────────────────
// `s` as a null-terminated heap copy, passable where `[:0]u8` is expected.
sq_cstr :: (s: string) -> string {
z := cstring(s.len);
if s.len > 0 { memcpy(z.ptr, s.ptr, s.len); }
return z;
}
// Copy the C string at `p` (null = empty) into context.allocator.
sq_from_cstr :: (p: ?*u8) -> string {
// Copy the C string at `p` (null = empty) into context.allocator —
// sqlite's buffer dies on the next step/finalize/close, so the view from
// `from_cstring` must not escape.
sq_from_cstr :: (p: ?cstring) -> string {
if p == null { return ""; }
cp : [*]u8 = xx p!;
n := 0;
while cp[n] != 0 { n += 1; }
raw : [*]u8 = xx context.allocator.alloc_bytes(n + 1);
if n > 0 { memcpy(raw, cp, xx n); }
raw[n] = 0;
return string.{ ptr = raw, len = n };
v := from_cstring(p!);
if v.len == 0 { return ""; }
return substr(v, 0, v.len);
}
// `n` raw bytes at `p` as a context.allocator copy ("" when p is null).
@@ -343,7 +332,7 @@ sqlite_threadsafe :: () -> bool {
return sqlite3_threadsafe() != 0;
}
sqlite_compileoption_used :: (name: string) -> bool {
return sqlite3_compileoption_used(sq_cstr(name)) != 0;
return sqlite3_compileoption_used(to_cstring(name)) != 0;
}
// The n'th compile option ("" past the end).
sqlite_compileoption_get :: (n: i64) -> string {
@@ -355,7 +344,7 @@ sqlite_errstr :: (code: i64) -> string {
}
// True iff `sql` ends in a complete SQL statement.
sqlite_complete :: (sql: string) -> bool {
return sqlite3_complete(sq_cstr(sql)) != 0;
return sqlite3_complete(to_cstring(sql)) != 0;
}
// `n` bytes from SQLite's CSPRNG.
sqlite_randomness :: (n: i64) -> string {
@@ -386,13 +375,13 @@ sqlite_hard_heap_limit :: (n: i64) -> i64 {
// GLOB / LIKE / case-insensitive compare, sqlite's own semantics.
// strglob/strlike answer 0 on MATCH (C convention) — exposed as bools.
sqlite_strglob :: (glob: string, s: string) -> bool {
return sqlite3_strglob(sq_cstr(glob), sq_cstr(s)) == 0;
return sqlite3_strglob(to_cstring(glob), to_cstring(s)) == 0;
}
sqlite_strlike :: (like: string, s: string, esc: i64) -> bool {
return sqlite3_strlike(sq_cstr(like), sq_cstr(s), xx esc) == 0;
return sqlite3_strlike(to_cstring(like), to_cstring(s), xx esc) == 0;
}
sqlite_stricmp :: (a: string, b: string) -> i64 {
return xx sqlite3_stricmp(sq_cstr(a), sq_cstr(b));
return xx sqlite3_stricmp(to_cstring(a), to_cstring(b));
}
// ── prepared statements ───────────────────────────────────────────────
@@ -445,7 +434,7 @@ SqliteStmt :: struct {
}
// 1-based index of a named parameter (":name" / "@name" / "?N"), 0 if absent.
parameter_index :: (self: *SqliteStmt, name: string) -> i64 {
return xx sqlite3_bind_parameter_index(self.handle, sq_cstr(name));
return xx sqlite3_bind_parameter_index(self.handle, to_cstring(name));
}
// The name of parameter `idx` ("" for nameless `?` parameters).
parameter_name :: (self: *SqliteStmt, idx: i64) -> string {
@@ -560,7 +549,7 @@ Sqlite :: struct {
open :: (path: string) -> (Sqlite, !SqliteErr) {
h : usize = 0;
rc := sqlite3_open(sq_cstr(path), @h);
rc := sqlite3_open(to_cstring(path), @h);
if rc != SQLITE_OK {
if h != 0 { sqlite3_close(h); }
raise error.Open;
@@ -570,7 +559,7 @@ Sqlite :: struct {
open_v2 :: (path: string, flags: i64) -> (Sqlite, !SqliteErr) {
h : usize = 0;
rc := sqlite3_open_v2(sq_cstr(path), @h, xx flags, 0);
rc := sqlite3_open_v2(to_cstring(path), @h, xx flags, 0);
if rc != SQLITE_OK {
if h != 0 { sqlite3_close(h); }
raise error.Open;
@@ -592,7 +581,7 @@ Sqlite :: struct {
// Run one or more ;-separated statements with no result rows
// (DDL, pragmas, BEGIN/COMMIT). Detail via errmsg on failure.
exec :: (self: *Sqlite, sql: string) -> !SqliteErr {
rc := sqlite3_exec(self.handle, sq_cstr(sql), 0, 0, 0);
rc := sqlite3_exec(self.handle, to_cstring(sql), 0, 0, 0);
if rc != SQLITE_OK { raise error.Exec; }
return;
}
@@ -645,14 +634,14 @@ Sqlite :: struct {
}
// SQLITE_TXN_NONE / _READ / _WRITE for the "main" schema.
txn_state :: (self: *Sqlite) -> i64 {
return xx sqlite3_txn_state(self.handle, sq_cstr("main"));
return xx sqlite3_txn_state(self.handle, to_cstring("main"));
}
db_filename :: (self: *Sqlite) -> string {
return sq_from_cstr(sqlite3_db_filename(self.handle, sq_cstr("main")));
return sq_from_cstr(sqlite3_db_filename(self.handle, to_cstring("main")));
}
// 1 readonly, 0 read-write, -1 no such database name.
db_readonly :: (self: *Sqlite) -> i64 {
return xx sqlite3_db_readonly(self.handle, sq_cstr("main"));
return xx sqlite3_db_readonly(self.handle, to_cstring("main"));
}
cacheflush :: (self: *Sqlite) {
sqlite3_db_cacheflush(self.handle);
@@ -685,7 +674,7 @@ Sqlite :: struct {
nn : i32 = 0;
pk : i32 = 0;
ai : i32 = 0;
rc := sqlite3_table_column_metadata(self.handle, sq_cstr("main"), sq_cstr(table), sq_cstr(column), @dt, @cs, @nn, @pk, @ai);
rc := sqlite3_table_column_metadata(self.handle, to_cstring("main"), to_cstring(table), to_cstring(column), @dt, @cs, @nn, @pk, @ai);
if rc != SQLITE_OK { raise error.Metadata; }
dtp : ?*u8 = if dt != 0 then cast(?*u8) cast(*u8) dt else null;
csp : ?*u8 = if cs != 0 then cast(?*u8) cast(*u8) cs else null;
@@ -699,7 +688,7 @@ Sqlite :: struct {
// The whole "main" database as bytes (a valid database image).
serialize :: (self: *Sqlite) -> (string, !SqliteErr) {
size : i64 = 0;
p := sqlite3_serialize(self.handle, sq_cstr("main"), @size, 0);
p := sqlite3_serialize(self.handle, to_cstring("main"), @size, 0);
if p == null { raise error.Serialize; }
out := sq_copy_bytes(p, size);
sqlite3_free(xx p!);
@@ -713,7 +702,7 @@ Sqlite :: struct {
if buf == 0 { raise error.Serialize; }
bp : [*]u8 = xx buf;
memcpy(bp, bytes.ptr, bytes.len);
rc := sqlite3_deserialize(self.handle, sq_cstr("main"), buf, bytes.len, bytes.len,
rc := sqlite3_deserialize(self.handle, to_cstring("main"), buf, bytes.len, bytes.len,
SQLITE_DESERIALIZE_FREEONCLOSE | SQLITE_DESERIALIZE_RESIZEABLE);
if rc != SQLITE_OK { raise error.Serialize; }
return;
@@ -730,7 +719,7 @@ SqliteBlob :: struct {
open :: (db: *Sqlite, table: string, column: string, rowid: i64, writable: bool) -> (SqliteBlob, !SqliteErr) {
h : usize = 0;
rc := sqlite3_blob_open(db.handle, sq_cstr("main"), sq_cstr(table), sq_cstr(column),
rc := sqlite3_blob_open(db.handle, to_cstring("main"), to_cstring(table), to_cstring(column),
rowid, if writable then 1 else 0, @h);
if rc != SQLITE_OK { raise error.Blob; }
return SqliteBlob.{ handle = h };
@@ -772,7 +761,7 @@ SqliteBackup :: struct {
handle: usize;
init :: (dst: *Sqlite, src: *Sqlite) -> (SqliteBackup, !SqliteErr) {
h := sqlite3_backup_init(dst.handle, sq_cstr("main"), src.handle, sq_cstr("main"));
h := sqlite3_backup_init(dst.handle, to_cstring("main"), src.handle, to_cstring("main"));
if h == 0 { raise error.Backup; }
return SqliteBackup.{ handle = h };
}