Module: Sqlite
- Defined in:
- lib/tep/sqlite.rb
Overview
Tep::SQLite -- a thin wrapper around the system libsqlite3 for
spinel-AOT'd apps. Uses tep_sqlite.c (compiled to tep_sqlite.o)
as a stable C ABI surface, exposed via spinel's ffi_func DSL.
Why not the sqlite3 gem? It's a CRuby-MRI native extension
(loadable .so/.bundle), which spinel can't link -- spinel
produces a single static binary with everything resolved at
compile time. The C-shim approach (same pattern as tep's HTTP
server in sphttp.c) replaces "load a gem at runtime" with
"link a .o at compile time."
Usage
db = Tep::SQLite.new
db.open("./app.db")
db.exec("CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, body TEXT)")
# Parameterised insert: prepare once, bind, step, finalize.
db.prepare("INSERT INTO notes (body) VALUES (?)")
db.bind_str(1, "hello")
db.step
db.finalize
id = db.last_rowid
# Single-row, single-column read.
body = db.first_str("SELECT body FROM notes WHERE id = ?", id.to_s)
# Iterating rows.
db.prepare("SELECT id, body FROM notes ORDER BY id")
while db.step == 1
puts db.col_int(0).to_s + ": " + db.col_str(1)
end
db.finalize
Constraints
- One in-flight cursor per process (the
prepare/step/finalizetrio shares a single C-sidesqlite3_stmt *). Nesting one query inside another's loop will overwrite the parent cursor. The framework runs handlers serially per worker so this is fine for "one DB call per request". - Columns are read as either str or int. Floats / blobs / NULL aren't first-class -- a NULL column returns "" (str) or 0 (int).
- The C side caps a single col_str result at 64 KiB. Large blobs would truncate.
All FFI plumbing lives at the top level (parallel to Sock) so
spinel's name resolver finds it from anywhere in the Tep tree.