glite
glite: a SQLite driver for Gleam on the Erlang VM.
One connection is one actor that owns the SQLite handle and runs every
call on it, one at a time. Share a Connection between processes freely:
calls queue up, and a transaction runs as one call, so nothing else can
mix into it.
import glite
import glite/config
import glite/decode
pub fn main() {
let assert Ok(conn) = glite.connect(config.new("app.db"))
let assert Ok(Nil) =
glite.exec_script(conn, "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)")
let assert Ok(id) =
glite.query_one(
conn,
"INSERT INTO users (name) VALUES (?) RETURNING id",
[glite.text("Alice")],
{
use id <- decode.element(0, decode.int)
decode.success(id)
},
)
let assert Ok(Nil) = glite.disconnect(conn)
}
Types
What backup wrote.
pub type Backup {
Backup(path: String, bytes: Int)
}
Constructors
-
Backup(path: String, bytes: Int)
A connection to one SQLite database.
pub opaque type Connection
A message to a connection’s actor. Use it to name a supervised
connection: process.new_name("db") gives a Name(glite.Message).
pub type Message =
@internal Message
A query parameter.
pub type Param =
value.Value
Why a transaction did not commit.
pub type TransactionError(e) {
RolledBack(e)
Database(error.Error)
}
Constructors
-
RolledBack(e)The callback returned
Error(e); everything it did was rolled back. -
Database(error.Error)The database or the connection failed; nothing was committed.
How a transaction takes its locks.
pub type TransactionMode {
Immediate
Deferred
Exclusive
}
Constructors
-
ImmediateTake the write lock at BEGIN. Use this for any transaction that writes: it can’t fail halfway through because another connection wrote first.
-
DeferredTake locks as statements need them. Fine for read-only transactions.
-
ExclusiveTake the write lock at BEGIN and keep readers out (outside WAL mode).
Values
pub fn backup(
conn: Connection,
to path: String,
) -> Result(Backup, error.Error)
Write a consistent copy of the database to path with VACUUM INTO,
check the copy with PRAGMA integrity_check, and fsync it. path must
not exist yet. Writers wait while the copy is made.
pub fn blob(value: BitArray) -> value.Value
pub fn connect(
config: config.Config,
) -> Result(Connection, error.Error)
Open a database and start its actor, linked to the calling process. Every
setting in the config is checked after opening; if SQLite didn’t apply
one, such as WAL mode, this returns PragmaMismatch.
pub fn disconnect(conn: Connection) -> Result(Nil, error.Error)
Close the database and stop the actor. Closing a connection that is
already closed returns Ok(Nil). Stopping a supervised connection makes
its supervisor start a new one; stop the supervisor instead.
pub fn exec(
conn: Connection,
sql: String,
params: List(value.Value),
) -> Result(Int, error.Error)
Run one statement and return the number of rows it changed: always 0 for statements other than INSERT, UPDATE, DELETE and REPLACE.
The SQL must be one statement, with exactly as many parameters as it has placeholders.
pub fn exec_many(
conn: Connection,
sql: String,
params: List(List(value.Value)),
) -> Result(Int, error.Error)
Run one statement once per parameter list, all or nothing: if one run fails, the runs before it are rolled back. Returns the rows changed in total.
pub fn exec_script(
conn: Connection,
sql: String,
) -> Result(Nil, error.Error)
Run a script of several statements, without parameters, such as a schema migration.
pub fn float(value: Float) -> value.Value
pub fn int(value: Int) -> value.Value
pub fn named(name: process.Name(Message)) -> Connection
A connection to the supervised actor registered under name. Calls
return ConnectionClosed while no actor is registered.
pub fn null() -> value.Value
pub fn nullable(
value: option.Option(a),
to_param: fn(a) -> value.Value,
) -> value.Value
None becomes NULL; Some(x) becomes to_param(x).
pub fn query(
conn: Connection,
sql: String,
params: List(value.Value),
decoder: decode.RowDecoder(a),
) -> Result(List(a), error.Error)
Run a query and decode every row. More than max_rows rows is an error.
pub fn query_one(
conn: Connection,
sql: String,
params: List(value.Value),
decoder: decode.RowDecoder(a),
) -> Result(a, error.Error)
Run a query that returns exactly one row, and decode it. No rows, or more
than one, is a Decode error.
pub fn query_rows(
conn: Connection,
sql: String,
params: List(value.Value),
) -> Result(Rows, error.Error)
Run a query and return its column names and raw rows.
pub fn set_user_version(
conn: Connection,
version: Int,
) -> Result(Nil, error.Error)
Set the database’s user_version.
pub fn supervised(
config: config.Config,
name: process.Name(Message),
) -> supervision.ChildSpecification(Connection)
A child specification for a supervisor. The connection’s actor registers
under name; get a Connection for it with named. If the actor
crashes, the supervisor restarts it, which opens the database again.
let db_name = process.new_name("db")
let assert Ok(_) =
static_supervisor.new(static_supervisor.OneForOne)
|> static_supervisor.add(glite.supervised(config, db_name))
|> static_supervisor.start
let conn = glite.named(db_name)
pub fn text(value: String) -> value.Value
pub fn transaction(
conn: Connection,
mode: TransactionMode,
body: fn(tx.Tx) -> Result(a, e),
) -> Result(a, TransactionError(e))
Run body in a transaction: commit if it returns Ok, roll back if it
returns Error or panics. A panic is rolled back and then re-raised in
the calling process.
The body runs inside the connection’s actor, so no other caller’s
statements can mix into the transaction. Use the Tx it gets, not the
Connection: calling the connection from inside the body panics.
The whole transaction must finish within call_timeout_ms. If it
doesn’t, its running statement is interrupted, it is rolled back, and the
result is Database(Timeout(_)).
pub fn user_version(conn: Connection) -> Result(Int, error.Error)
The database’s user_version, for schema migrations.