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 :: 0
SQLITE_ROW :: 100
SQLITE_DONE :: 101
SQLITE_BUSY :: 5
SQLITE_TRANSIENT :: -1
SQLITE_LOCKED :: 6
SQLITE_NOMEM :: 7
SQLITE_TOOBIG :: 18
SQLITE_MISUSE :: 21
SQLITE_OPEN_READWRITE :: 0x2
SQLITE_OPEN_CREATE :: 0x4
SQLITE_OPEN_FULLMUTEX :: 0x10000
SQLITE_INTEGER :: 1
SQLITE_FLOAT :: 2
SQLITE_TEXT :: 3
SQLITE_BLOB :: 4
SQLITE_NULL :: 5
SqliteScalar :: #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) -> s32
SqlitePrepareText :: (db: *void, sql: string, length: s32, statement: **void, tail: **u8) -> s32
SqliteBindTextString :: (statement: *void, index: s32, value: string, length: s32) -> s32
SqliteStep :: (statement: *void) -> s32
SqliteFinalize :: (statement: *void) -> s32
SqliteColumnText :: (statement: *void, column: s32) -> *u8
SqliteColumnInt64 :: (statement: *void, column: s32) -> s64
SqliteBindText :: (statement: *void, index: s32, value: *u8, length: s32, destructor: *void) -> s32
SqliteBindInt64 :: (statement: *void, index: s32, value: s64) -> s32
SqliteBindInt :: (statement: *void, index: s32, value: s32) -> s32
SqliteColumnInt :: (statement: *void, column: s32) -> s32
SqliteReset :: (statement: *void) -> s32
SqliteClearBindings :: (statement: *void) -> s32
SqliteOpen :: (path: *u8, database: **void, flags: s32) -> s32
SqliteOpenText :: (path: string, database: **void, flags: s32) -> s32
SqliteClose :: (database: *void) -> s32
SqliteGetAutocommit :: (database: *void) -> bool

True 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) -> *void
SqliteBackupStep :: (backup: *void, pages: s32) -> s32
SqliteBackupFinish :: (backup: *void) -> s32
SqliteLastInsertRowid :: (database: *void) -> s64

The rowid of the last row inserted through this connection.

SqliteExec :: (database: *void, sql: *u8) -> s32
SqliteExecText :: (database: *void, sql: string) -> s32
SqliteVersionNumber :: () -> s32
SqliteErrorCode :: (database: *void) -> s32
SqliteErrorMessage :: (database: *void) -> *u8

The message is borrowed until another operation changes the connection.

SqliteBusyTimeout :: (database: *void, milliseconds: s32) -> s32
SqliteChanges :: (database: *void) -> s32
SqliteBindNull :: (statement: *void, index: s32) -> s32
SqliteBindDouble :: (statement: *void, index: s32, value: float64) -> s32
SqliteBindBlob :: (statement: *void, index: s32, value: []u8) -> s32

Copies binary bytes, including embedded NULs. Empty bytes are an empty BLOB.

SqliteColumnBlob :: (statement: *void, column: s32) -> *u8

Column bytes are borrowed until Step, Reset or Finalize changes the statement.

SqliteColumnBytes :: (statement: *void, column: s32) -> s32
SqliteColumnDouble :: (statement: *void, column: s32) -> float64
SqliteColumnType :: (statement: *void, column: s32) -> s32
SqliteColumnCount :: (statement: *void) -> s32
SqliteCreateFunction :: (database: *void, name: *u8, argc: s32, flags: s32, data: *void, callback: SqliteScalar, step: *void, final: *void, destroy: SqliteDestructor) -> s32

Direct SQLite lifetime: destroy also runs when registration fails.

SqliteUserData :: (context: *void) -> *void
SqliteValueType :: (value: *void) -> s32
SqliteValueBytes :: (value: *void) -> s32
SqliteValueBlob :: (value: *void) -> *void

Callback value bytes are borrowed; consume them before the callback returns.

SqliteResultDouble :: (context: *void, value: float64)

Source ↗