pub struct Sqlite;Expand description
SQLite: backtick-quoted names, ? placeholders, rows claimed by lease.
It builds the statements of the lease form (Lease), of the advisory lock form
(Advisory), and the insert. A writer locks the whole database, not rows, so it builds no
claim that holds rows for a handler: it does not implement RowLock, and a
SQLite table declares locked_until or advisory_lock. A lease claim is one
update that writes the lease, counts the attempt and returns the rows it took, as they were
before; one writer at a time keeps two claims apart. The rows of one claim come back in no
particular order. A dead letter into a table copies the row, then deletes it, in one
transaction. A claim of the service’s own opens its transaction with BEGIN IMMEDIATE
(begin_lease_claim), so it takes the write lock before it
selects. Every name is quoted, so a name keeps its case and may hold any character, and SQLite
keeps a name of any length. The quotes are backticks, which SQLite always reads as a name: a
statement that names a column the table lacks fails when it is prepared.
fetch is refused, so a claim of the service’s own brings a fetch of its
own.
SQLite keeps times as text, so the statements compare times as text: two times compare right when their text sorts as the times do.
SQLite has no locks a session holds, so in the advisory lock form the broker keeps the keys in
work in the process: lock and unlock are None, and
the claim selects up to Param::Limit claimable rows in claim order with their keys, the text
the key’s parts render, a column without a value read as empty text. The select cannot leave
out the keys in work, so the broker binds a limit that reaches past them. The take counts the
attempt and returns the row in one statement.
A table with FIFO groups needs no guard (fifo_guard is None): one
writer at a time keeps two claims apart, and a lease claim takes nothing while a row of the
group holds a lease.
SQLite runs every transaction serializable, so a table names no isolation level here: it names
a mode, and its transactions open with BEGIN DEFERRED, BEGIN IMMEDIATE or
BEGIN EXCLUSIVE (begin), or with BEGIN where it names none.
§Examples
A subscription asks SQLite for the statements of its table, as ruststream-sqlx does when the
subscription starts:
use ruststream_sqlx_dialect::{
Advisory, Column, Form, KeyPart, Sqlite, Statement, StatementError, TableSpec,
};
// The jobs table as `#[derive(Inbox)]` describes it, with `advisory_lock = "jobs-{job_id}"`.
const JOBS: TableSpec<'static> = TableSpec::new(
"jobs",
Column::new("job_id"),
Form::Advisory(&[KeyPart::Literal("jobs-"), KeyPart::Column("job_id")]),
);
// What a subscription to an advisory lock table prepares: the claim of candidates, and the
// lock on a key where the database keeps locks; without one the broker keeps the keys in work
// in the process.
fn advisory_statements(
dialect: &impl Advisory,
spec: &TableSpec<'_>,
) -> Result<(Statement, Option<Statement>), StatementError> {
Ok((dialect.advisory_claim(spec)?, dialect.lock()))
}
fn main() -> Result<(), StatementError> {
// SQLite keeps no locks a session holds, so the process keeps the keys in work.
let (_claim, lock) = advisory_statements(&Sqlite, &JOBS)?;
assert!(lock.is_none());
Ok(())
}A table in the row lock form finds no claim here, so a subscription to one does not compile:
use ruststream_sqlx_dialect::{
ClaimShape, Column, Form, RowLock, Sqlite, Statement, StatementError, TableSpec,
};
const JOBS: TableSpec<'static> = TableSpec::new("jobs", Column::new("job_id"), Form::RowLock);
// What a subscription to a row lock table asks of its dialect.
fn claims_its_rows(dialect: &impl RowLock) -> Result<Statement, StatementError> {
dialect.lock_claim(&JOBS, ClaimShape::Rows)
}
let claim = claims_its_rows(&Sqlite);Trait Implementations§
Source§impl Advisory for Sqlite
impl Advisory for Sqlite
Source§fn advisory_claim(
&self,
spec: &TableSpec<'_>,
) -> Result<Statement, StatementError>
fn advisory_claim( &self, spec: &TableSpec<'_>, ) -> Result<Statement, StatementError>
Param::Limit claimable rows of the
subscription’s group in claim order, two columns each, the id and the lock key as text
(named __lock). It takes no lock and writes nothing; where the database can tell, it
leaves out the rows whose key another session holds. Read moreSource§fn lock(&self) -> Option<Statement>
fn lock(&self) -> Option<Statement>
Param::Key for the session, without waiting: one
row whose first column is a 64-bit integer, nonzero when the lock was taken. None when the
process keeps the locks. Read moreSource§fn unlock(&self) -> Option<Statement>
fn unlock(&self) -> Option<Statement>
Param::Key: one row whose first column is a
64-bit integer, nonzero when the session held it. None when the process keeps the locks. Read moreSource§fn take(
&self,
spec: &TableSpec<'_>,
shape: ClaimShape,
) -> Result<Vec<Statement>, StatementError>
fn take( &self, spec: &TableSpec<'_>, shape: ClaimShape, ) -> Result<Vec<Statement>, StatementError>
shape, as it was before the count, only
while it is still claimable. The last returns the row, or none when the row is gone or no
longer claimable; a first statement, where there are two, counts the attempt and changes no row
in that case. Read moreimpl Copy for Sqlite
Source§impl Dialect for Sqlite
impl Dialect for Sqlite
Source§fn quote_into(&self, ident: &str, out: &mut String)
fn quote_into(&self, ident: &str, out: &mut String)
Source§fn placeholder_into(&self, _: NonZeroUsize, out: &mut String)
fn placeholder_into(&self, _: NonZeroUsize, out: &mut String)
Source§fn fetch(&self, _: &TableSpec<'_>) -> Result<Statement, StatementError>
fn fetch(&self, _: &TableSpec<'_>) -> Result<Statement, StatementError>
Source§fn ack(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>
fn ack(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>
processed_at when the
table has that column. Read moreSource§fn retry(
&self,
spec: &TableSpec<'_>,
) -> Result<Option<Statement>, StatementError>
fn retry( &self, spec: &TableSpec<'_>, ) -> Result<Option<Statement>, StatementError>
None when releasing
the row needs no statement. Read moreSource§fn retry_after(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>
fn retry_after(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>
Param::RetryAfter. Read moreSource§fn discard(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>
fn discard(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>
processed_at when the table
has that column. Read moreSource§fn dead_letter_group(
&self,
spec: &TableSpec<'_>,
) -> Result<Statement, StatementError>
fn dead_letter_group( &self, spec: &TableSpec<'_>, ) -> Result<Statement, StatementError>
Param::Destination. Read moreSource§fn dead_letter_table(
&self,
spec: &TableSpec<'_>,
target: TableName<'_>,
) -> Result<Vec<Statement>, StatementError>
fn dead_letter_table( &self, spec: &TableSpec<'_>, target: TableName<'_>, ) -> Result<Vec<Statement>, StatementError>
target, a table with the same
columns; they run in one transaction. Read moreSource§fn insert(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>
fn insert(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>
TableSpec::columns, each bound as Param::Column. Read moreSource§fn begin(
&self,
opening: Opening,
) -> Result<Option<&'static str>, StatementError>
fn begin( &self, opening: Opening, ) -> Result<Option<&'static str>, StatementError>
opening in place of BEGIN, or None when
BEGIN opens it. Read moreSource§fn server_version(&self) -> Option<&'static str>
fn server_version(&self) -> Option<&'static str>
None when the
dialect’s statements run on every version of its server. Read moreSource§fn check_server(
&self,
spec: &TableSpec<'_>,
version: &str,
) -> Result<(), StatementError>
fn check_server( &self, spec: &TableSpec<'_>, version: &str, ) -> Result<(), StatementError>
spec need; version is what the
server_version query returned. Read moreSource§fn savepoint(&self) -> &'static str
fn savepoint(&self) -> &'static str
Source§fn rollback_to_savepoint(&self) -> &'static str
fn rollback_to_savepoint(&self) -> &'static str
Source§fn fifo_guard(
&self,
spec: &TableSpec<'_>,
) -> Result<Option<Statement>, StatementError>
fn fifo_guard( &self, spec: &TableSpec<'_>, ) -> Result<Option<Statement>, StatementError>
None for a table without FIFO groups, or a dialect that
takes no group. Read moreimpl Eq for Sqlite
Source§impl Lease for Sqlite
impl Lease for Sqlite
Source§fn lease_claim(
&self,
spec: &TableSpec<'_>,
shape: ClaimShape,
) -> Result<Statement, StatementError>
fn lease_claim( &self, spec: &TableSpec<'_>, shape: ClaimShape, ) -> Result<Statement, StatementError>
Param::Limit rows of the
subscription’s group, in claim order, among the rows whose lease ended by
Param::LeaseNow. Read moreSource§fn extend(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>
fn extend(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>
Param::Lease) while the row still holds the delivery’s token
(Param::Held), so a handler that runs longer than one lease keeps
its row. Read moreSource§fn stamp(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>
fn stamp(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>
Param::Lease) and counts the attempt, while no lease holds the
row at Param::LeaseNow. Read moreSource§fn claim_counts_attempt(&self, spec: &TableSpec<'_>) -> bool
fn claim_counts_attempt(&self, spec: &TableSpec<'_>) -> bool
spec returns carry the attempt the claim counted. A
dialect whose claim returns the rows as they were before answers false; where it answers
true, a delivery reports one less than its row carries. Read moreimpl Opens<Deferred> for Sqlite
impl Opens<Exclusive> for Sqlite
impl Opens<Immediate> for Sqlite
Source§impl OutboxDialect for Sqlite
impl OutboxDialect for Sqlite
Source§fn outbox_fetch(
&self,
spec: &TableSpec<'_>,
) -> Result<Statement, StatementError>
fn outbox_fetch( &self, spec: &TableSpec<'_>, ) -> Result<Statement, StatementError>
Source§fn outbox_mark(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>
fn outbox_mark(&self, spec: &TableSpec<'_>) -> Result<Statement, StatementError>
Source§fn outbox_recover(
&self,
spec: &TableSpec<'_>,
) -> Result<Statement, StatementError>
fn outbox_recover( &self, spec: &TableSpec<'_>, ) -> Result<Statement, StatementError>
Param::Group binds, with every column: what the republish at
startup sends again. Read more