Skip to main content

icydb_core/db/executor/
mod.rs

1pub(super) mod aggregate;
2mod context;
3mod cursor;
4mod delete;
5mod executable_plan;
6mod execution_plan;
7mod kernel;
8pub(super) mod load;
9mod mutation;
10mod physical_path;
11mod plan_metrics;
12pub(super) mod route;
13mod stream;
14#[cfg(test)]
15mod tests;
16mod window;
17
18pub(in crate::db) use crate::db::lowering::{LoweredIndexPrefixSpec, LoweredIndexRangeSpec};
19pub(super) use context::*;
20pub(in crate::db) use cursor::{
21    PlannedCursor, decode_pk_cursor_boundary, decode_typed_primary_key_cursor_slot, prepare_cursor,
22    revalidate_cursor, validate_index_range_anchor,
23    validate_index_range_boundary_anchor_consistency,
24};
25pub(super) use delete::DeleteExecutor;
26pub(in crate::db) use executable_plan::ExecutablePlan;
27pub(in crate::db::executor) use execution_plan::ExecutionPlan;
28pub(in crate::db::executor) use kernel::{
29    ExecutionKernel, IndexPredicateCompileMode, PlanRow, PostAccessStats,
30};
31pub(super) use load::LoadExecutor;
32pub use load::{ExecutionAccessPathVariant, ExecutionOptimization, ExecutionTrace};
33pub(super) use mutation::save::SaveExecutor;
34pub(super) use stream::access::*;
35pub(super) use stream::key::{
36    BudgetedOrderedKeyStream, KeyOrderComparator, OrderedKeyStream, OrderedKeyStreamBox,
37    VecOrderedKeyStream,
38};
39pub(in crate::db) use window::compute_page_window;
40
41// Design notes:
42// - SchemaInfo is the planner-visible schema (relational attributes). Executors may see
43//   additional tuple payload not represented in SchemaInfo.
44// - Unsupported or opaque values are treated as incomparable; executor validation may
45//   skip type checks for these values.
46// - ORDER BY is stable; incomparable values preserve input order.
47// - Corruption indicates invalid persisted bytes or store mismatches; invariant violations
48//   indicate executor/planner contract breaches.
49
50use crate::{
51    db::{
52        data::DataKey,
53        plan::AccessPlannedQuery,
54        query::{
55            fluent::{delete::FluentDeleteQuery, load::FluentLoadQuery},
56            intent::{PlannedQuery, Query, QueryError},
57            predicate::PredicateFieldSlots,
58        },
59    },
60    error::{ErrorClass, ErrorOrigin, InternalError},
61    traits::EntityKind,
62};
63use thiserror::Error as ThisError;
64
65pub(super) fn compile_predicate_slots<E: EntityKind>(
66    plan: &AccessPlannedQuery<E::Key>,
67) -> Option<PredicateFieldSlots> {
68    plan.predicate
69        .as_ref()
70        .map(PredicateFieldSlots::resolve::<E>)
71}
72
73impl<E: EntityKind> From<PlannedQuery<E>> for ExecutablePlan<E> {
74    fn from(value: PlannedQuery<E>) -> Self {
75        Self::new(value.into_inner())
76    }
77}
78
79impl<E: EntityKind> Query<E> {
80    /// Compile this logical planned query into executor runtime state.
81    pub fn plan(&self) -> Result<ExecutablePlan<E>, QueryError> {
82        self.planned().map(ExecutablePlan::from)
83    }
84}
85
86impl<E: EntityKind> FluentLoadQuery<'_, E> {
87    /// Compile this fluent load intent into executor runtime state.
88    pub fn plan(&self) -> Result<ExecutablePlan<E>, QueryError> {
89        self.planned().map(ExecutablePlan::from)
90    }
91}
92
93impl<E: EntityKind> FluentDeleteQuery<'_, E> {
94    /// Compile this fluent delete intent into executor runtime state.
95    pub fn plan(&self) -> Result<ExecutablePlan<E>, QueryError> {
96        self.planned().map(ExecutablePlan::from)
97    }
98}
99
100///
101/// ExecutorError
102///
103
104#[derive(Debug, ThisError)]
105pub(crate) enum ExecutorError {
106    #[error("corruption detected ({origin}): {message}")]
107    Corruption {
108        origin: ErrorOrigin,
109        message: String,
110    },
111
112    #[error("data key exists: {0}")]
113    KeyExists(DataKey),
114}
115
116impl ExecutorError {
117    pub(crate) const fn class(&self) -> ErrorClass {
118        match self {
119            Self::KeyExists(_) => ErrorClass::Conflict,
120            Self::Corruption { .. } => ErrorClass::Corruption,
121        }
122    }
123
124    pub(crate) const fn origin(&self) -> ErrorOrigin {
125        match self {
126            Self::KeyExists(_) => ErrorOrigin::Store,
127            Self::Corruption { origin, .. } => *origin,
128        }
129    }
130
131    pub(crate) fn corruption(origin: ErrorOrigin, message: impl Into<String>) -> Self {
132        Self::Corruption {
133            origin,
134            message: message.into(),
135        }
136    }
137
138    // Construct a store-origin corruption error with canonical taxonomy.
139    pub(crate) fn store_corruption(message: impl Into<String>) -> Self {
140        Self::corruption(ErrorOrigin::Store, message)
141    }
142
143    // Construct a serialize-origin corruption error with canonical taxonomy.
144    pub(crate) fn serialize_corruption(message: impl Into<String>) -> Self {
145        Self::corruption(ErrorOrigin::Serialize, message)
146    }
147
148    // Construct a store-origin corruption error from displayable source context.
149    pub(crate) fn store_corruption_from(source: impl std::fmt::Display) -> Self {
150        Self::store_corruption(source.to_string())
151    }
152}
153
154impl From<ExecutorError> for InternalError {
155    fn from(err: ExecutorError) -> Self {
156        Self::classified(err.class(), err.origin(), err.to_string())
157    }
158}