kyo-sql-doltlite
The embedded Dolt driver for kyo-sql.
kyo-sql is the SQL module, and it names no engine: the sql"…" interpolator, the typed DSL, SqlSchema and row decoding, transactions, streaming, pooling, configuration, and error handling all live there and are documented there. This artifact is what makes doltlite:// one of the URLs that module can open.
DoltLite is a SQLite fork that keeps the sqlite3_* C API and replaces the storage engine with a content-addressed prolly tree. One file therefore carries a whole history: branches, commits, merges and diffs over the data, reachable through the same Dolt the server backend implements.
val recent: Chunk[String] < (Async & Abort[SqlException]) =
DB.run("doltlite://inventory.db") {
sql"SELECT sku FROM item ORDER BY id".as[String].run
}Nothing in that body names DoltLite. Point it at a dolt:// URL and it runs against a Dolt server.
Adding the driver
Depend on kyo-sql and this artifact. There is nothing to wire:
libraryDependencies ++= Seq(
"io.getkyo" %% "kyo-sql" % "<latest version>",
"io.getkyo" %% "kyo-sql-doltlite" % "<latest version>"
)The artifact carries one META-INF/services/kyo.db.Backend entry naming DoltLiteBackendFactory, which claims the scheme doltlite and nothing else. It deliberately does not claim sqlite, even though this engine forks it: claiming it would make which backend a sqlite:// URL reaches depend on classpath order.
Platforms
The engine is a compiled library rather than C source, so it ships per platform:
| x86_64 | aarch64 | |
|---|---|---|
| macOS | ✅ | ✅ |
| Linux (glibc) | ✅ | ✅ |
| Linux (musl) | ✅ | ✅ |
| Windows | ❌ | ❌ |
Windows is the one gap, and it is upstream's rather than a packaging choice here. There is no win-arm64 build at all, and its autoconf build runs through MSYS2/MinGW, which that platform has no native toolchain for. The win-x64 release does exist, but it carries doltlite.h and libdoltlite.dll and nothing else: no static archive, and no import library. This driver links the archive INTO its shim so the engine travels with it, and a DLL cannot stand in, because the shim is extracted to a temp directory the DLL is not in and the link then fails at run time rather than at build time.
Opening a doltlite:// URL on Windows fails with DoltLiteEngineUnavailableException rather than deep inside a native call. The message always says the engine is not published for the platform, and carries the loader's search detail, the platform it looked for and every path it tried, on the runtimes that report it.
kyo-sql-sqlite is the embedded engine that does run everywhere. It compiles from C source, so it has no per-platform artifact and no such gap. What it does not have is version control.
Opening a database
The URL is a file path, or :memory: for a database that lives only as long as the connection:
SqlClient.init("doltlite://inventory.db", SqlConfig(maxConnections = 1)).map { client =>
DB.run(client)(Dolt.use(dolt => dolt.commit("import")))
}:memory: gives every CONNECTION its own private database, so a pool of more than one connection opening that name is several databases rather than one. Pin maxConnections = 1 when using it.
The version-control surface
Dolt is shared with kyo-sql-dolt, and that README documents the whole surface: branches, the difference between a SQL commit and a Dolt commit, merging where a conflict is a value, reading history, and remotes. Everything there applies here, because a program written against Dolt runs on either backend unchanged.
What differs is only what an embedded engine cannot have. There is no server to authenticate to, so a URL carries no user, password, host or port. There are no advisory locks and no configurable isolation level, both of which are refused by name rather than silently downgraded, exactly as kyo-sql-sqlite describes for the engine this one forks.
A conflict is the one merge outcome whose aftermath differs. The engine never keeps a conflict past a transaction, so a conflicting merge, stageMerge or pull answers the same Dolt.Merge.Conflicted a server does and leaves the branch as it was before the merge, with no conflicts in the working set to resolve.
In a browser
The WebAssembly build runs in a browser, where there is no shared library to load. Initialize the module and register it before opening a database:
// Skipped rather than compiled: `DoltLiteWasm` is JS/Wasm source, so it is absent from the JVM
// artifact this README is validated against, and `sqlite3` is the module the caller supplies.
DoltLiteWasm.init(sqlite3).map(_ => SqlClient.init("doltlite://app.db"))The default VFS keeps a database in memory and loses it at reload. SqliteVfs("opfs") is what makes one survive, and it carries two requirements: the page must be cross-origin isolated (COOP same-origin plus COEP require-corp), and the database must be opened from a worker. The pooled opfs-sahpool VFS looks like an alternative and does not work here: this engine replaces SQLite's storage layer and needs file-control operations that VFS does not implement, so a database opens on it and then every statement fails SQLITE_NOTFOUND.
kyo-sql-doltlite/scripts/browser-check.sh drives the published build in a real browser and checks that a database survives a reload.