Skip to main content

icydb_core/db/executor/
mod.rs

1mod context;
2mod delete;
3mod load;
4mod plan;
5mod save;
6pub(crate) mod trace;
7mod unique;
8mod upsert;
9
10pub(crate) use context::*;
11pub use delete::DeleteExecutor;
12pub use load::LoadExecutor;
13pub use save::SaveExecutor;
14pub(crate) use unique::resolve_unique_pk;
15pub use upsert::{UniqueIndexHandle, UpsertExecutor, UpsertResult};
16
17use crate::{
18    db::store::DataKey,
19    error::{ErrorClass, ErrorOrigin, InternalError},
20};
21use thiserror::Error as ThisError;
22
23#[cfg(test)]
24mod tests;
25
26///
27/// ExecutorError
28///
29
30#[derive(Debug, ThisError)]
31pub enum ExecutorError {
32    #[error("corruption detected ({origin}): {message}")]
33    Corruption {
34        origin: ErrorOrigin,
35        message: String,
36    },
37
38    #[error("index constraint violation: {0} ({1})")]
39    IndexViolation(String, String),
40
41    #[error("index not found: {0} ({1})")]
42    IndexNotFound(String, String),
43
44    #[error("index not unique: {0} ({1})")]
45    IndexNotUnique(String, String),
46
47    #[error("index key missing: {0} ({1})")]
48    IndexKeyMissing(String, String),
49
50    #[error("data key exists: {0}")]
51    KeyExists(DataKey),
52
53    #[error("primary key type mismatch: expected {0}, got {1}")]
54    KeyTypeMismatch(String, String),
55
56    #[error("primary key out of range for {0}: {1}")]
57    KeyOutOfRange(String, String),
58}
59
60impl ExecutorError {
61    #[must_use]
62    /// Build an index-violation error with a formatted path/field list.
63    pub(crate) fn index_violation(path: &str, index_fields: &[&str]) -> Self {
64        Self::IndexViolation(path.to_string(), index_fields.join(", "))
65    }
66
67    pub(crate) const fn class(&self) -> ErrorClass {
68        match self {
69            Self::KeyExists(_) | Self::IndexViolation(_, _) => ErrorClass::Conflict,
70            Self::IndexNotFound(_, _)
71            | Self::IndexNotUnique(_, _)
72            | Self::IndexKeyMissing(_, _)
73            | Self::KeyTypeMismatch(_, _)
74            | Self::KeyOutOfRange(_, _) => ErrorClass::Unsupported,
75            Self::Corruption { .. } => ErrorClass::Corruption,
76        }
77    }
78
79    pub(crate) const fn origin(&self) -> ErrorOrigin {
80        match self {
81            Self::KeyExists(_) => ErrorOrigin::Store,
82            Self::IndexViolation(_, _)
83            | Self::IndexNotFound(_, _)
84            | Self::IndexNotUnique(_, _)
85            | Self::IndexKeyMissing(_, _) => ErrorOrigin::Index,
86            Self::Corruption { origin, .. } => *origin,
87            Self::KeyTypeMismatch(_, _) | Self::KeyOutOfRange(_, _) => ErrorOrigin::Executor,
88        }
89    }
90
91    pub(crate) fn corruption(origin: ErrorOrigin, message: impl Into<String>) -> Self {
92        Self::Corruption {
93            origin,
94            message: message.into(),
95        }
96    }
97}
98
99impl From<ExecutorError> for InternalError {
100    fn from(err: ExecutorError) -> Self {
101        Self::new(err.class(), err.origin(), err.to_string())
102    }
103}