SQLITE-MUMU sqlite-mumu is a SQLite plugin for the mumu runtime. It exposes a compact API to open a database, run parameterized SQL, stream results through mumu’s iterator pipeline, and close the connection.
TL;DR
- Build: make (or: cargo build --release)
- Install (Linux): sudo make install → copies to /usr/local/lib/libmumusqlite.so and runs ldconfig
- Load in mumu: extend("sqlite")
- Use: sqlite:open(...), sqlite:query(...), sqlite:close(...)
TABLE OF CONTENTS
- Installation
- Loading the plugin
- API 3.1 sqlite:open 3.2 sqlite:query 3.3 sqlite:close
- Examples 4.1 Create table, insert, select 4.2 Parameterized updates 4.3 NULLs and booleans
- Result shapes and type mapping
- Behavior details
- Troubleshooting
- Design notes and limitations
- License
- INSTALLATION
Prerequisites
- Rust (stable)
- A working C toolchain (to build a cdylib)
- SQLite via rusqlite (pulled in as a Cargo dependency)
Build Option A: with Makefile make
Option B: with Cargo cargo build --release
Artifacts (target/release):
- Linux: libmumusqlite.so
- macOS: libmumusqlite.dylib
- Windows: mumusqlite.dll
Install (Linux) sudo make install This copies target/release/libmumusqlite.so to /usr/local/lib/ and runs ldconfig.
If you prefer a custom location, copy the built library there and ensure your loader can find it (see search order below).
- LOADING THE PLUGIN
In a mumu script or the REPL: extend("sqlite")
The loader looks for a library named:
- Linux: libmumusqlite.so
- macOS: libmumusqlite.dylib
- Windows: mumusqlite.dll
Search order (first match wins):
- ./libmumusqlite.{so|dylib|dll}
- ./sqlite/libmumusqlite.{so|dylib|dll}
- /usr/local/lib/libmumusqlite.{so|dylib|dll}
When loaded, the plugin registers these functions in mumu:
- sqlite:open
- sqlite:query
- sqlite:close
- API
3.1 sqlite:open Open (or create) a SQLite database and return a numeric connection handle.
Call handle = sqlite:open([path: ":memory:"]) handle = sqlite:open([path: "example.db"])
Arguments
- A keyed array (map). At minimum: path: String, a file path or ":memory:".
Return
- Int connection handle. Store this and pass it to sqlite:query and sqlite:close (keys: handle or db or conn).
Notes
- Connections are tracked internally and protected with a mutex.
- Additional options may be added in future; see source for details.
3.2 sqlite:query Run SQL (optionally parameterized) using an existing connection.
Minimal result = sqlite:query([db: handle, sql: "select 1 as x"])
With parameters result = sqlite:query([ handle: handle, sql: "insert into users(name, active) values (?, ?)", params: ["Ada", true] ])
Arguments (keyed array)
- handle or db or conn: Int connection handle (from sqlite:open)
- sql: String (or a single-element StrArray)
- params (optional): one of the following shapes • IntArray → binds each element as integer • FloatArray → binds each element as real • StrArray → binds each element as text • BoolArray → binds each element as integer (true→1, false→0) • MixedArray → element-wise mapping: Int → integer Long → integer Float → real SingleString → text StrArray(len=1) → text (the only element) Bool → integer (1/0) Placeholder → NULL any other → NULL • Placeholder → means “no parameters” (equivalent to omitting params)
Return
- For SELECT, PRAGMA, or WITH (classification is a lowercase prefix check after trimming): Returns an InkIterator over rows (see section 5).
- For all other statements (INSERT, UPDATE, DELETE, DDL): Returns Int = number of rows changed.
3.3 sqlite:close Close a previously opened connection.
Call ok = sqlite:close([db: handle])
Arguments
- A keyed array with handle or db or conn.
Return
- Bool(true) on success.
- Error if the handle is not known.
- EXAMPLES
4.1 Create table, insert, select
extend("sqlite")
db = sqlite:open([path: ":memory:"])
_ = sqlite:query([db: db, sql: "create table users(id integer primary key, name text, active integer)"])
_ = sqlite:query([db: db, sql: "insert into users(name, active) values (?, ?)", params: ["Ada", 1]]) _ = sqlite:query([db: db, sql: "insert into users(name, active) values (?, ?)", params: ["Bob", 0]]) _ = sqlite:query([db: db, sql: "insert into users(name, active) values (?, ?)", params: ["Cyd", 1]])
rows = sqlite:query([db: db, sql: "select id, name, active from users order by id"])
slog(rows) ; prints each row as it is iterated (REPL-friendly)
_ = sqlite:close([db: db])
4.2 Parameterized updates
count = sqlite:query([ db: db, sql: "update users set active = ? where name = ?", params: [0, "Ada"] ]) slog(count) ; prints rows changed
4.3 NULLs and booleans
_ = sqlite:query([db: db, sql: "insert into flags(val) values (?)", params: [true]]) ; binds 1
_ = sqlite:query([db: db, sql: "insert into maybe_vals(v) values (?)", params: [_]]) ; binds NULL
; Reminder: using params: _ (a lone placeholder) means “no parameters”, not “one NULL”.
- RESULT SHAPES AND TYPE MAPPING
Row-producing statements (SELECT, PRAGMA, WITH) return an InkIterator of rows. Each row is a keyed array keyed by the column names reported by SQLite.
Example row shape { id: 1, name: "Ada", active: 1 }
SQLite type → mumu Value mapping
- NULL → Placeholder (_)
- INTEGER → Long (i64)
- REAL → Float (f64)
- TEXT → SingleString
- BLOB → SingleString("[BLOB]") (sentinel string)
Because results are an InkIterator, they compose nicely with slog and other iterator-aware utilities in mumu.
- BEHAVIOR DETAILS
Statement classification
- The plugin trims and lowercases the SQL and treats it as row-producing if it starts with “select”, “pragma”, or “with”. Otherwise it returns a changed-row count.
Parameter conversion
- See sqlite:query parameters above. MixedArray and Placeholder inside arrays are supported; a lone Placeholder as params means “no parameters”.
Verbose logging
- If the mumu interpreter is in verbose mode, the plugin emits diagnostic lines (for example, showing rows as they are buffered for iteration).
Thread-safety
- Connections are stored as Arc<Mutex> and locked per call.
Column names
- Taken directly from rusqlite’s column metadata.
- TROUBLESHOOTING
Message: sqlite:query expects a keyed array argument
- Ensure the call shape is a keyed array: [db: handle, sql: "..."].
Message: sqlite:query: 'handle' (or 'db' or 'conn') missing or not int
- Pass the integer handle returned by sqlite:open.
Message: sqlite:query: invalid handle
- The handle is unknown (already closed or was never opened).
Message: sqlite:query: prepare error / rows error / row error / execute error
- The underlying operation failed. Check your SQL and parameters.
BLOB values appear as “[BLOB]”
- This is a sentinel string in this version. If you need text, transform in SQL (e.g., hex(blob_col)).
Loader can’t find the library
- Verify the search order and filename. On Linux, copying to /usr/local/lib and running ldconfig is often sufficient.