Most useful programs eventually keep something, and for twenty-five years the answer to “keep it where?” has very often been sqlite — a library whose reliability and testing culture we admire and do not pretend to match. What we can do is meet it well. As of today the starter repository carries libraries/sqlite: a reusable Mica library over the system sqlite3, the first rung of the libraries shelf.

What using it looks like

db := Open("notes.db") on fail e do WriteLn("open failed");

q := Query(db, "select title, stars from notes where stars >= ? order by stars desc") on fail e do WriteLn("query failed");
BindInt64(q, 1, 3) on fail e do WriteLn("bind failed");

for row in Rows(q) do
begin
    WriteLn("%ls (%lld)", ColumnText(row, 0), ColumnInt64(row, 1));
end
on fail e do WriteLn("step failed");

Close(db);

Prepared statements with binds, rows arriving through a for loop, text columns as real strings, and failure on the language’s own channel — Open and Query fail with a named error domain, and forgetting to handle that is a compile error, never a silent nil. The database handle is a borrow: sqlite owns its cells, Close returns them, and the ownership analysis holds the program to exactly that story.

Not a binding — source you own

The rung is three files you copy into your project: the library unit, its contract, and a four-function C shim. No package manager, no version to chase, no wrapper layer to trust blindly. The unit is written as teaching material — every procedure carries the why, not just the what — so the code you depend on is code you can read in one sitting and change when your application needs something we did not think of.

The build is one Makefile with two steps, and it bakes C and Mica together: the shim compiles like any C file, the library compiles once into an archive and emits its own contract, and your program links against the two contracts — each side speaking its own language, the contracts telling the truth between them. We think mixed C-and-Mica projects should feel exactly this boring.

The boundary, honestly

Mica has no function pointers, and sqlite’s sqlite3_exec wants one. That meeting produced the language’s third declared subprogram kind, the callback — bound by name at a contract-declared slot, fired only by the library while the call runs, its whole environment the context record the call visibly hands over. And where C answers a handle through a pointer-to-pointer parameter, a spelling Mica’s value model deliberately does not have, a two-line shim answers the handle directly. The library names both patterns in its README, because every later rung of the shelf — compression, HTTP, postgres — will reuse them.

To the sqlite community

Thank you for a quarter century of software we could build on with a straight face. If you find something in our binding that sqlite would do differently or better, we want to hear it — the shelf exists to meet great C libraries on their own terms, and to help the communities around them wherever a Mica program can. The tutorial builds a small notes application on this rung, start to finish.