Tursox

Hex.pmHexDocsCILicense: MIT

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_features exposes 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.