Add the dependency
In your project’s ziran.toml; pin ref to a commit for reproducible builds.
[dependencies.sqlite]
git = "https://github.com/ziranlang/sqlite.git"
ref = "master"Overview
ziran add https://github.com/ziranlang/sqlite.git
#import "sqlite/SQLite"
database: *void = null
flags: s32 = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
if SqliteOpenText(":memory:", *database, flags) == SQLITE_OK {
SqliteExecText(database, "create table if not exists votes (voter text, score integer)")
SqliteClose(database)
}
The functions keep SQLite's names and return codes (SqlitePrepare,
SqliteStep, SqliteColumnText, SqliteBindInt64, …). The *Text and
*String variants take Ziran strings and copy them to the NUL-terminated
text SQLite expects, so a temporary string is safe to pass.
The module provides connections, prepared statements, text and binary
bindings, integer and floating-point values, NULLs, error reporting, busy
timeouts, change counts and database backup. SqliteOpenText opens a path
from a Ziran string; SqliteBindBlob copies bytes including embedded NULs,
and an empty slice binds an empty BLOB. Column pointers and error messages
are borrowed from SQLite; consume or copy them before their owner changes.
SqliteGetAutocommit(database) reports whether the live connection has no
active transaction, following SQLite's sqlite3_get_autocommit. It returns
false for a null handle. Keep the connection alive while calling it.
SqliteCreateFunction binds sqlite3_create_function_v2 directly. Its
SqliteScalar and SqliteDestructor types use #c_call; callback programs
require the native C backend. The common connection and statement APIs still
support C and Go. Pass a NUL-terminated function name and SQLite's documented
argument count and encoding flags; use null step/final callbacks for a scalar.
No validation or early return in the binding changes SQLite's destructor rules.
The data pointer remains the caller's responsibility until SQLite calls its
destructor. SQLite calls that destructor on replacement, deletion, connection
close, and registration failure, including a name longer than 255 UTF-8 bytes.
Do not free the same data again after an error. SqliteUserData returns this
pointer inside the registered callback; each connection has its own
registration. See the function registration contract
and user data contract.
SqliteValueType, SqliteValueBytes and SqliteValueBlob inspect callback
arguments; blob bytes are borrowed and may be null for empty values. Inspect
the type before conversions and consume bytes within the callback, following
SQLite's value lifetime rules.
SqliteResultDouble sets the callback result. Keep callback context, argument
pointers and returned user data within their documented lifetimes; a callback
must not close its active database or reset/finalize its active statement.
The complete official SQLite source is a Git source dependency pinned to
an exact upstream commit in ziran.lock. ziran fetch --locked retrieves
it and ziran pkg path sqlite3 locates it. A submodule is unnecessary:
Ziran's lockfile records and fetches the original source itself.
On Linux, make native generates the upstream amalgamation out of tree
and builds build/native/libsqlite3.a and libsqlite3.so, without an
installed system SQLite. Link with LDFLAGS=-L/path/to/build/native and
LDLIBS='-lsqlite3 -lm -ldl -pthread'. C and C++ use its C ABI, Go uses
cgo (CGO_ENABLED=1), Rust carries the flags in its Cargo project, and
Python uses ctypes with the shared library. Add build/native to
LD_LIBRARY_PATH when running linked programs. These bindings all use
the same SQLite engine and database format. The portable .zib VM cannot
call arbitrary native libraries.
Test
make check # available backends, source and saved IR; native C callbacks
make check TARGET=go # one backend
The current toolchain check needs a C compiler, Python and Go. Older toolchains also provide C++, Rust and Python backends and require their build tools. It tests Unicode text, statement reuse, large integers, binary data, empty BLOBs, floating-point values, NULLs, invalid SQL and database backup. This is a binding for the documented API above, rather than every SQLite extension. A separate C source/saved callback suite exercises value types, binary bytes, connection-local data, replacement, deletion, close and real failed-registration destructor calls, without requiring callback support from Go.
sqlite/src/SQLite.zi
SQLite
The SQLite C library for Ziran programs. Databases and statements are opaque handles owned by SQLite. The functions follow SQLite's own names and return codes; the *Text variants take Ziran strings and copy them to the NUL-terminated text SQLite expects. Programs link libsqlite3, or compile SQLite's amalgamation into their own build.
Import with #import "sqlite/SQLite".
SQLITE_OK :: 0SQLITE_ROW :: 100SQLITE_DONE :: 101SQLITE_BUSY :: 5SQLITE_TRANSIENT :: -1SQLITE_LOCKED :: 6SQLITE_NOMEM :: 7SQLITE_TOOBIG :: 18SQLITE_MISUSE :: 21SQLITE_OPEN_READWRITE :: 0x2SQLITE_OPEN_CREATE :: 0x4SQLITE_OPEN_FULLMUTEX :: 0x10000SQLITE_INTEGER :: 1SQLITE_FLOAT :: 2SQLITE_TEXT :: 3SQLITE_BLOB :: 4SQLITE_NULL :: 5SqliteScalar :: #type (context: *void, argc: s32, argv: **void)C callbacks. The caller keeps data alive until SQLite invokes destroy.
SqliteDestructor :: #type (data: *void)SqlitePrepare :: (db: *void, sql: *u8, length: s32, statement: **void, tail: **u8) -> s32SqlitePrepareText :: (db: *void, sql: string, length: s32, statement: **void, tail: **u8) -> s32SqliteBindTextString :: (statement: *void, index: s32, value: string, length: s32) -> s32SqliteStep :: (statement: *void) -> s32SqliteFinalize :: (statement: *void) -> s32SqliteColumnText :: (statement: *void, column: s32) -> *u8SqliteColumnInt64 :: (statement: *void, column: s32) -> s64SqliteBindText :: (statement: *void, index: s32, value: *u8, length: s32, destructor: *void) -> s32SqliteBindInt64 :: (statement: *void, index: s32, value: s64) -> s32SqliteBindInt :: (statement: *void, index: s32, value: s32) -> s32SqliteColumnInt :: (statement: *void, column: s32) -> s32SqliteReset :: (statement: *void) -> s32SqliteClearBindings :: (statement: *void) -> s32SqliteOpen :: (path: *u8, database: **void, flags: s32) -> s32SqliteOpenText :: (path: string, database: **void, flags: s32) -> s32SqliteClose :: (database: *void) -> s32SqliteGetAutocommit :: (database: *void) -> boolTrue when this connection has no active transaction. A null handle is false. As with SQLite itself, the caller must keep the connection alive for the call.
SqliteBackupInit :: (destination: *void, source: *void) -> *voidSqliteBackupStep :: (backup: *void, pages: s32) -> s32SqliteBackupFinish :: (backup: *void) -> s32SqliteLastInsertRowid :: (database: *void) -> s64The rowid of the last row inserted through this connection.
SqliteExec :: (database: *void, sql: *u8) -> s32SqliteExecText :: (database: *void, sql: string) -> s32SqliteVersionNumber :: () -> s32SqliteErrorCode :: (database: *void) -> s32SqliteErrorMessage :: (database: *void) -> *u8The message is borrowed until another operation changes the connection.
SqliteBusyTimeout :: (database: *void, milliseconds: s32) -> s32SqliteChanges :: (database: *void) -> s32SqliteBindNull :: (statement: *void, index: s32) -> s32SqliteBindDouble :: (statement: *void, index: s32, value: float64) -> s32SqliteBindBlob :: (statement: *void, index: s32, value: []u8) -> s32Copies binary bytes, including embedded NULs. Empty bytes are an empty BLOB.
SqliteColumnBlob :: (statement: *void, column: s32) -> *u8Column bytes are borrowed until Step, Reset or Finalize changes the statement.
SqliteColumnBytes :: (statement: *void, column: s32) -> s32SqliteColumnDouble :: (statement: *void, column: s32) -> float64SqliteColumnType :: (statement: *void, column: s32) -> s32SqliteColumnCount :: (statement: *void) -> s32SqliteCreateFunction :: (database: *void, name: *u8, argc: s32, flags: s32, data: *void, callback: SqliteScalar, step: *void, final: *void, destroy: SqliteDestructor) -> s32Direct SQLite lifetime: destroy also runs when registration fails.
SqliteUserData :: (context: *void) -> *voidSqliteValueType :: (value: *void) -> s32SqliteValueBytes :: (value: *void) -> s32SqliteValueBlob :: (value: *void) -> *voidCallback value bytes are borrowed; consume them before the callback returns.
SqliteResultDouble :: (context: *void, value: float64)