Tursox
Tursox is an Elixir wrapper around the embedded Turso engine. It preserves Turso's ownership model: one database derives independent connections, real prepared statements, and bounded row cursors. Optional shared-handle DBConnection pools and caller-supervised multi-database managers build on the same resources. There is no global registry.
Version 0.2.1 pins Turso 0.7.2 and Rust 1.91.0. It deliberately enables tested Turso FTS while MVCC and advanced builder features remain explicit experimental opt-ins. See the Roadmap 2 capability report, capability matrix, and compatibility notes.
Installation
After release, add:
def deps, do: [{:tursox, "~> 0.2.1"}]
Supported targets use NIF 2.16 precompiled binaries after their published
checksums are committed. Set TURSOX_BUILD=1 to force a source build with the
pinned Rust toolchain. A missing or invalid precompiled artifact fails loudly;
it never silently falls back to an unverified binary.
Direct resources
{:ok, database} = Tursox.Database.open("data/app.db", journal_mode: :wal)
{:ok, connection} = Tursox.Database.connect(database, busy_timeout: 5_000)
:ok = Tursox.Connection.execute(connection, "CREATE TABLE IF NOT EXISTS users (id INTEGER, name TEXT)")
{:ok, statement} = Tursox.Connection.prepare(connection, "INSERT INTO users VALUES (?, ?)")
{:ok, _result} = Tursox.Statement.execute(statement, [1, "Ada"])
{:ok, cursor} = Tursox.Connection.query(connection, "SELECT id, name FROM users ORDER BY id")
{:done, rows} = Tursox.Cursor.fetch(cursor, 100)
:ok = Tursox.Connection.close(connection)
:ok = Tursox.Database.close(database)
Rows are ordered lists. Parameters are strict positional lists or named maps;
use {:blob, binary} for BLOBs. Fetches are bounded to 10,000 rows. For details,
see databases and connections,
queries and cursors, and
transactions and MVCC.
Tursox 0.2.1 verifies core SQL, safe argument-bearing PRAGMAs, STRICT and advanced schema behavior, Tantivy-backed FTS, built-in extensions, and platform-limited multiprocess WAL. Unsupported and unsafe pinned-engine results are published with executable evidence. Enable ordinary experimental switches at database open; no consumer recompilation is required:
{:ok, db} =
Tursox.Database.open("app.db",
features: [:index_method, :autovacuum, :attach, :without_rowid]
)
DANGER:
unsafe_featuresexposes pinned engine paths that may terminate the entire BEAM. They are intentionally available for cutting-edge use:Tursox.Database.open("edge.db",journal_mode: :mvcc,unsafe_features: [:views, :custom_types, :generated_columns,:vacuum, :mvcc_passive_checkpoint, :runtime_extensions])
Encryption is compiled into every build and accepts raw 16/32-byte keys via
features: [:encryption], encryption: [cipher: ..., key: ...]. Runtime native
libraries load with Tursox.Connection.load_extension/2; they must implement
Turso's extension ABI. SQLite-only binaries such as SQLean 0.28.3 do not.
Pool and manager
{:ok, pool} = Tursox.Pool.start_link(database: "data/app.db", pool_size: 4)
{:ok, result} = Tursox.Pool.execute(pool, "UPDATE users SET name = ? WHERE id = ?", ["Grace", 1])
{:ok, manager} = Tursox.Manager.start_link(max_databases: 100)
{:ok, tenant_pool} = Tursox.Manager.open(manager, tenant_id, "data/tenant.db", pool_size: 4)
One pool owns one database and derives N workers from that shared handle. A manager atomically enforces tenant IDs, canonical paths, and capacity without creating dynamic atoms. See pools and managers.
Runtime and observability
Native work runs on dirty schedulers through one process-lifetime Tokio runtime.
Resource close is logical, idempotent, ancestry-aware, and inspect-safe.
Telemetry events under [:tursox, ...] include durations and result classes but
never SQL, parameters, rows, tokens, or database contents. Tursox.resources/0
returns logical native resource gauges.
Development
bin/qa_check.sh
No sibling checkout or network service is required for normal QA. Precompiled release publication is a separate manual workflow and is never implied by a source commit.
License
MIT. See LICENSE and THIRD_PARTY_NOTICES.md.