libsql2
An alternative to turso_libsql with a native Rust extension.
Features
- Native Rust extension — no FFI overhead
- Full libSQL support — local files, in-memory, remote (Turso Cloud), and Embedded Replicas
Installation
Add to your Gemfile:
gem "libsql2"
Then run:
bundle install
Usage
Opening a Database
require "libsql2"
# Local file
db = Libsql::Database.open("/path/to/file.db")
# In-memory
db = Libsql::Database.open(":memory:")
# Remote (Turso Cloud)
db = Libsql::Database.open("libsql://xxx.turso.io", auth_token: "xxx")
# Embedded Replica
db = Libsql::Database.open("libsql://xxx.turso.io",
auth_token: "xxx",
local_path: "/path/to/replica.db",
sync_interval: 60,
read_your_writes: true
)
# Block form (auto-close)
Libsql::Database.open(":memory:") do |db|
# ...
end
Querying
db.connect do |conn|
conn.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)")
conn.execute("INSERT INTO users (name, age) VALUES (?, ?)", ["Alice", 30])
rows = conn.query("SELECT * FROM users WHERE age > ?", [20])
rows.columns #=> ["id", "name", "age"]
rows.types #=> ["INTEGER", "TEXT", "INTEGER"]
rows.each { |row| puts row["name"] }
end
Execute (no result set)
conn.execute("INSERT INTO users (name) VALUES (?)", ["Alice"])
conn.changes #=> 1
conn.last_insert_rowid #=> 42
Batch Execution
conn.execute_batch("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT);\nCREATE TABLE posts (id INTEGER PRIMARY KEY, user_id INTEGER, title TEXT);\n")
Prepared Statements
stmt = conn.prepare("SELECT * FROM users WHERE name = ?")
stmt.bind(["Alice"])
rows = stmt.query
stmt.close
Transactions
conn.transaction do |tx|
tx.execute("UPDATE accounts SET balance = balance - 100 WHERE id = ?", [1])
tx.execute("UPDATE accounts SET balance = balance + 100 WHERE id = ?", [2])
# Commits on normal exit, rolls back on exception
end
# With behavior
conn.transaction(:immediate) do |tx|
tx.execute("INSERT INTO orders (item) VALUES (?)", ["widget"])
end
# Nested transactions (SAVEPOINT)
conn.transaction do |tx|
tx.execute("INSERT INTO users (name) VALUES (?)", ["Alice"])
tx.transaction do |tx2|
tx2.execute("INSERT INTO users (name) VALUES (?)", ["Bob"])
end
end
Embedded Replica Sync
db.sync # Manual sync
Fork Safety (Puma / Unicorn)
# puma.rb
on_worker_boot do
$db.discard! if $db
$db = Libsql::Database.open(...)
end
Type Mapping
| libSQL Type | Ruby Type | Notes |
|---|---|---|
| INTEGER | Integer |
Signed 64-bit |
| REAL | Float |
Double precision |
| TEXT | String |
UTF-8 encoded |
| BLOB | Libsql::Blob |
String subclass with ASCII-8BIT encoding |
| NULL | nil |
Development
Requirements: Ruby >= 3.4, Rust >= 1.74, and a C compiler.
bundle install # Install Ruby dependencies
rake compile # Compile the Rust extension
rake spec # Run tests
rake lint # Run all linters (RuboCop + Clippy)
rake fmt # Auto-format all code
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/speria-jp/libsql-ruby2.
License
The gem is available as open source under the terms of the MIT License.