ubiquisync_sql/db/error.rs
1/// An error from a SQL backend operation.
2#[derive(Debug, thiserror::Error)]
3pub enum DbError {
4 /// A backend error with no more specific variant; carries the backend's
5 /// own message.
6 #[error("sql error: {0}")]
7 Sql(String),
8 /// A UNIQUE / PRIMARY KEY conflict. A tracker that keys the op-log on
9 /// `(peer_id, entry_idx)` surfaces a re-ingested entry as this — failing the
10 /// batch so the whole apply rolls back rather than double-applying, not a
11 /// silent skip. Each backend must map its native constraint error to this
12 /// variant.
13 #[error("unique constraint violation")]
14 UniqueViolation,
15 /// A column held a value of a different type than the caller requested.
16 #[error("type mismatch at column {col}: expected {expected}")]
17 TypeMismatch {
18 /// Column index that was read.
19 col: usize,
20 /// The Rust type the caller asked for.
21 expected: &'static str,
22 },
23 /// A `u64` (e.g. a packed HLC timestamp) didn't fit the signed 64-bit
24 /// integer a SQL backend stores. On a write the value exceeded `i64::MAX`;
25 /// on a read the stored value was negative. Either way it can't round-trip
26 /// through a signed column — and the signed `MAX`/`GREATEST` merge guard
27 /// would misorder it — so we reject rather than silently wrap. The `i128`
28 /// holds the offending value losslessly in both directions.
29 #[error("integer value {0} out of range for signed 64-bit storage")]
30 IntegerOutOfRange(i128),
31 /// A column index past the end of the row was requested.
32 #[error("column index {0} out of bounds")]
33 ColumnOutOfBounds(usize),
34 /// A column was SQL NULL where the caller required a non-null value.
35 #[error("unexpected null at column {0}")]
36 UnexpectedNull(usize),
37}