SQLite for Raven, with the database engine bundled in. There is no system
SQLite to install: the C amalgamation ships with the package and is compiled and
linked into your program by rvpm build. You only need a C compiler, which
Raven's FFI already requires.
[dependencies]
"github.com/martian56/raven-sqlite" = "v0.2.0"Needs Raven 2.26.1 or newer.
import "github.com/martian56/raven-sqlite" { Db }
fun main() {
match Db.open(":memory:") {
Ok(db) -> {
let _ = db.exec("create table users (id integer primary key, name text)")
let _ = db.exec("insert into users (name) values ('Alice'), ('Bob')")
match db.prepare("select id, name from users order by id") {
Ok(q) -> {
let reading = true
while reading {
match q.next() {
Ok(true) -> print("${q.int(0)}: ${q.text(1)}"),
Ok(false) -> reading = false,
Err(message) -> {
print("query failed: ${message}")
reading = false
},
}
}
q.finalize()
},
Err(e) -> print(e),
}
db.close()
},
Err(e) -> print(e),
}
}Use ":memory:" for an in-memory database, or a file path to persist to disk.
Use ? placeholders and bind by 1-based index. Checked binds report invalid
indices and other SQLite errors:
fun insert_person(db: Db) -> Result<Bool, String> {
let statement = db.prepare("insert into users (name, age) values (?, ?)")?
let _ = statement.try_bind_text(1, "Carol")?
let _ = statement.try_bind_int(2, 31)?
let _ = statement.next()?
let _ = statement.try_finalize()?
return Ok(true)
}Db.open(path) -> Result<Db, String>: open a connection (":memory:"or a file path; the file is created if missing).db.exec(sql) -> Result<Int, String>: run statements that return no rows (CREATE, INSERT, UPDATE, ...). TheOkvalue is the number of rows changed.db.prepare(sql) -> Result<Stmt, String>: compile a statement with?placeholders.db.last_insert_id() -> Intanddb.changes() -> Int.db.set_busy_timeout_ms(ms)configures lock waiting.db.try_close()reports live statements that prevent closing.db.close()remains as a compatibility convenience when the result is intentionally ignored.
try_bind_int,try_bind_float,try_bind_text, andtry_bind_null: bind the 1-based parameter and returnResult<Stmt, String>.- The original chainable
bind_int,bind_float,bind_text, andbind_nullremain available for compatibility when bind errors are intentionally ignored. next() -> Result<Bool, String>advances to the next row and distinguishes normal completion from constraint, locking, I/O, and execution failures.step() -> Boolis the legacy lossy form; prefernext().int(col),float(col),text(col),is_null(col): read the 0-based column of the current row.try_int,try_float,try_text, andtry_is_nulladditionally validate the column index.column_count(),column_name(col), andparameter_count()expose statement metadata.try_reset()andclear_bindings()support safe statement reuse.try_finalize()reports the last execution error while releasing the statement.finalize()is the compatibility form that ignores it.
SQLite's single-file amalgamation (c/sqlite3.c, public domain) and a thin C
shim are listed in the package's [ffi] section, so they are compiled and
linked into your binary. Handles and values cross the FFI as plain integers,
floats, and strings, so the Raven API is ordinary Raven types: there are no
pointers to manage.
- Always
finalize()a statement andclose()a database. raven-sqlite does not release them for you. - Bind parameter indices are 1-based and column indices are 0-based, following SQLite's own conventions.
- Text binding and retrieval preserve embedded NUL bytes instead of truncating them at the C string boundary.
- SQL strings and database paths reject embedded NUL bytes explicitly.
The test suite is fully self-contained because SQLite is bundled:
rvpm fmt --check
rvpm build
rvpm test
rvpm docCI runs the same suite on Linux and Windows. Coverage includes checked binding and column failures, constraint errors during stepping, transactions, statement reuse, connection-close failures, Unicode, embedded NUL bytes, and large text.
The binding is MIT (see LICENSE). Bundled SQLite (c/sqlite3.c,
c/sqlite3.h) is in the public domain; see https://www.sqlite.org/copyright.html.