Skip to main content

turso_orm/
error.rs

1//! The ORM error type, modeled by [`DbErr`].
2//!
3//! Every fallible operation in the crate returns [`DbErr`]. The driver's own
4//! error is wrapped transparently in [`DbErr::Driver`] so that callers keep
5//! access to its classification (busy, constraint kind, decode failure)
6//! through the helpers on [`DbErr`]; the remaining variants cover the
7//! situations the ORM layer detects itself, such as a `NotSet` primary key or
8//! an `UPDATE` that matched nothing.
9//!
10//! The enum is `#[non_exhaustive]` so that new ORM-level failure modes can be
11//! added without breaking matches downstream.
12
13use turso_orm_driver::{ConstraintKind, Error as DriverError, ErrorKind};
14
15/// The error returned by every fallible operation of the ORM.
16#[derive(Debug, thiserror::Error)]
17#[non_exhaustive]
18pub enum DbErr {
19    /// An error reported by the driver or the engine.
20    #[error(transparent)]
21    Driver(#[from] DriverError),
22    /// A row was expected but none was found.
23    #[error("record not found: {0}")]
24    RecordNotFound(String),
25    /// An `INSERT` inserted nothing, for example under `ON CONFLICT DO NOTHING`.
26    #[error("record not inserted")]
27    RecordNotInserted,
28    /// An `UPDATE` matched no row.
29    #[error("record not updated")]
30    RecordNotUpdated,
31    /// A required attribute of an active model is `NotSet`.
32    #[error("attribute not set: {0}")]
33    AttrNotSet(String),
34    /// A primary key value is missing from an active model.
35    #[error("primary key not set")]
36    PrimaryKeyNotSet,
37    /// A value had the wrong type for the target column or field.
38    #[error("type error: {0}")]
39    Type(String),
40    /// A JSON conversion failed.
41    #[error("json error: {0}")]
42    Json(String),
43    /// A migration failed.
44    #[error("migration error: {0}")]
45    Migration(String),
46    /// A free-form error raised by user code or hooks.
47    #[error("{0}")]
48    Custom(String),
49}
50
51impl DbErr {
52    /// The classification of the underlying driver error, if any.
53    ///
54    /// ORM-level variants carry no driver classification and yield `None`.
55    pub fn kind(&self) -> Option<ErrorKind> {
56        match self {
57            DbErr::Driver(e) => Some(e.kind()),
58            _ => None,
59        }
60    }
61
62    /// The violated constraint, when this wraps a constraint error.
63    pub fn constraint(&self) -> Option<ConstraintKind> {
64        match self {
65            DbErr::Driver(e) => e.constraint(),
66            _ => None,
67        }
68    }
69
70    /// Whether the error is transient lock contention worth retrying.
71    pub fn is_busy(&self) -> bool {
72        matches!(self, DbErr::Driver(e) if e.is_busy())
73    }
74
75    /// Whether the error is a unique-key violation.
76    pub fn is_unique_violation(&self) -> bool {
77        self.constraint() == Some(ConstraintKind::Unique)
78    }
79
80    /// Whether the error is a foreign-key violation.
81    pub fn is_foreign_key_violation(&self) -> bool {
82        self.constraint() == Some(ConstraintKind::ForeignKey)
83    }
84}
85
86/// The result alias used throughout the crate, defaulting to [`DbErr`].
87pub type Result<T, E = DbErr> = std::result::Result<T, E>;