pub enum SQLRiteError {
NotImplemented(String),
General(String),
Internal(String),
UnknownCommand(String),
SqlError(ParserError),
Io(Error),
Busy(String),
BusySnapshot(String),
}Expand description
SQLRiteError is an enum with all the standardized errors available for returning
Variants§
NotImplemented(String)
General(String)
Internal(String)
UnknownCommand(String)
SqlError(ParserError)
Io(Error)
Busy(String)
Phase 11.4 — BEGIN CONCURRENT commit hit a write-write
conflict. Some other transaction committed a newer version
of a row in this transaction’s write-set after this
transaction’s begin_ts. Caller should ROLLBACK (already
implicitly performed) and retry the transaction with a
fresh begin_ts.
BusySnapshot(String)
Phase 11.4 — same shape as SQLRiteError::Busy but
surfaces the snapshot-isolation specific case: a row in
the read-set changed under us. Distinguished from Busy
so SDKs can map it to a per-language exception that the
caller’s retry helper recognizes (mirrors Turso /
libSQL’s BUSY vs BUSY_SNAPSHOT split). v0 only emits
Busy from the write-write validation loop; the
read-anomaly variant is reserved for the snapshot-read
integration that follows.
Implementations§
Source§impl SQLRiteError
impl SQLRiteError
Sourcepub fn is_retryable(&self) -> bool
pub fn is_retryable(&self) -> bool
Phase 11.4 — true for Busy and BusySnapshot. SDK retry
helpers branch on this rather than matching the variants
individually so adding a third “retryable” variant later
doesn’t break callers.
Examples found in repository?
21fn main() -> Result<()> {
22 let mut a = Connection::open_in_memory()?;
23 a.execute("PRAGMA journal_mode = mvcc")?;
24 a.execute(
25 "CREATE TABLE accounts (
26 id INTEGER PRIMARY KEY,
27 holder TEXT NOT NULL,
28 balance INTEGER NOT NULL
29 )",
30 )?;
31 a.execute("INSERT INTO accounts (id, holder, balance) VALUES (1, 'alice', 100)")?;
32 a.execute("INSERT INTO accounts (id, holder, balance) VALUES (2, 'bob', 100)")?;
33
34 // Sibling handle on the same Arc<Mutex<Database>>. In real apps
35 // you'd hand this to a worker thread; we keep it on the main
36 // thread to keep the demo readable.
37 let mut b = a.connect();
38
39 println!("=== Disjoint-row commits both succeed ===");
40 a.execute("BEGIN CONCURRENT")?;
41 b.execute("BEGIN CONCURRENT")?;
42 a.execute("UPDATE accounts SET balance = balance + 10 WHERE id = 1")?;
43 b.execute("UPDATE accounts SET balance = balance + 20 WHERE id = 2")?;
44 a.execute("COMMIT")?;
45 b.execute("COMMIT")?; // write-sets don't intersect — no conflict.
46 print_balances(&mut a)?;
47
48 println!("\n=== Same-row commits: A wins, B retries ===");
49 // Interleave BEGINs so A.begin_ts < B.begin_ts and both see the
50 // same pre-update value.
51 a.execute("BEGIN CONCURRENT")?;
52 b.execute("BEGIN CONCURRENT")?;
53 a.execute("UPDATE accounts SET balance = balance + 5 WHERE id = 1")?;
54 b.execute("UPDATE accounts SET balance = balance + 50 WHERE id = 1")?;
55 a.execute("COMMIT")?;
56 // B's commit sees a version newer than its own `begin_ts` → Busy.
57 // The transaction is already dropped on the failed COMMIT;
58 // there's no ROLLBACK to run. Start a fresh BEGIN CONCURRENT.
59 match b.execute("COMMIT") {
60 Err(e) if e.is_retryable() => {
61 eprintln!(" B lost the race: {e}");
62 b.execute("BEGIN CONCURRENT")?;
63 b.execute("UPDATE accounts SET balance = balance + 50 WHERE id = 1")?;
64 b.execute("COMMIT")?;
65 }
66 other => {
67 other?;
68 }
69 }
70 print_balances(&mut a)?;
71
72 Ok(())
73}Trait Implementations§
Source§impl Debug for SQLRiteError
impl Debug for SQLRiteError
Source§impl Display for SQLRiteError
impl Display for SQLRiteError
Source§impl Error for SQLRiteError
impl Error for SQLRiteError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()