Skip to main content

icydb_core/db/query/plan/
executable.rs

1use crate::{
2    db::query::plan::{ExplainPlan, LogicalPlan, PlanFingerprint},
3    error::{ErrorClass, ErrorOrigin, InternalError},
4    traits::EntityKind,
5};
6use std::marker::PhantomData;
7
8///
9/// ExecutablePlan
10///
11/// Executor-ready plan bound to a specific entity type.
12///
13
14pub struct ExecutablePlan<E: EntityKind> {
15    plan: LogicalPlan,
16    _marker: PhantomData<E>,
17}
18
19impl<E: EntityKind> ExecutablePlan<E> {
20    pub(crate) const fn new(plan: LogicalPlan) -> Self {
21        Self {
22            plan,
23            _marker: PhantomData,
24        }
25    }
26
27    /// Explain this plan without executing it.
28    #[must_use]
29    pub fn explain(&self) -> ExplainPlan {
30        self.plan.explain()
31    }
32
33    /// Compute a stable fingerprint for this plan.
34    #[must_use]
35    pub fn fingerprint(&self) -> PlanFingerprint {
36        self.plan.fingerprint()
37    }
38
39    pub(crate) const fn access(&self) -> &crate::db::query::plan::AccessPlan {
40        &self.plan.access
41    }
42
43    pub(crate) fn into_inner(self) -> LogicalPlan {
44        self.plan
45    }
46
47    /// Erase the entity type while preserving the validated plan and entity path.
48    #[must_use]
49    pub fn erase(self) -> ExecutablePlanErased {
50        ExecutablePlanErased {
51            plan: self.plan,
52            entity_path: E::PATH,
53        }
54    }
55}
56
57/// Opaque, entity-tagged plan used for dynamic dispatch.
58#[doc(hidden)]
59pub struct ExecutablePlanErased {
60    plan: LogicalPlan,
61    entity_path: &'static str,
62}
63
64impl ExecutablePlanErased {
65    #[doc(hidden)]
66    pub fn into_typed<E: EntityKind>(self) -> Result<ExecutablePlan<E>, InternalError> {
67        if self.entity_path != E::PATH {
68            return Err(InternalError::new(
69                ErrorClass::Unsupported,
70                ErrorOrigin::Query,
71                format!(
72                    "plan entity mismatch: expected {}, found {}",
73                    E::PATH,
74                    self.entity_path
75                ),
76            ));
77        }
78
79        Ok(ExecutablePlan::new(self.plan))
80    }
81}