Skip to main content

icydb_core/db/query/
expr.rs

1//! Module: query::expr
2//! Responsibility: schema-agnostic filter/sort expression wrappers and lowering.
3//! Does not own: planner route selection or executor evaluation.
4//! Boundary: intent boundary lowers these to validated predicate/order forms.
5
6use crate::db::query::plan::{OrderDirection, PlanError, validate::validate_order};
7use crate::db::{
8    predicate::{Predicate, normalize, normalize_enum_literals},
9    query::plan::OrderSpec,
10    schema::{SchemaInfo, ValidateError, reject_unsupported_query_features, validate},
11};
12use thiserror::Error as ThisError;
13
14///
15/// FilterExpr
16/// Schema-agnostic filter expression for dynamic query input.
17/// Lowered into a validated predicate at the intent boundary.
18///
19
20#[derive(Clone, Debug)]
21pub struct FilterExpr(pub Predicate);
22
23impl FilterExpr {
24    /// Lower the filter expression into a validated predicate for the provided schema.
25    pub(crate) fn lower_with(&self, schema: &SchemaInfo) -> Result<Predicate, ValidateError> {
26        // Phase 1: normalize enum literals using schema enum metadata.
27        let normalized_enum_literals = normalize_enum_literals(schema, &self.0)?;
28
29        // Phase 2: reject unsupported query features and validate against schema.
30        reject_unsupported_query_features(&normalized_enum_literals)?;
31        validate(schema, &normalized_enum_literals)?;
32
33        // Phase 3: normalize structural predicate shape for deterministic planning.
34        Ok(normalize(&normalized_enum_literals))
35    }
36}
37
38///
39/// SortExpr
40/// Schema-agnostic sort expression for dynamic query input.
41/// Lowered into a validated order spec at the intent boundary.
42///
43
44#[derive(Clone, Debug)]
45pub struct SortExpr {
46    fields: Vec<(String, OrderDirection)>,
47}
48
49impl SortExpr {
50    /// Construct one schema-agnostic sort expression.
51    #[must_use]
52    pub const fn new(fields: Vec<(String, OrderDirection)>) -> Self {
53        Self { fields }
54    }
55
56    /// Borrow the declared sort fields in declaration order.
57    #[must_use]
58    pub fn fields(&self) -> &[(String, OrderDirection)] {
59        &self.fields
60    }
61
62    /// Lower the sort expression into a validated order spec for the provided schema.
63    pub(crate) fn lower_with(&self, schema: &SchemaInfo) -> Result<OrderSpec, SortLowerError> {
64        let spec = OrderSpec {
65            fields: self.fields.clone(),
66        };
67
68        validate_order(schema, &spec)?;
69
70        Ok(spec)
71    }
72}
73
74///
75/// SortLowerError
76/// Errors returned when lowering sort expressions into order specs.
77///
78
79#[derive(Debug, ThisError)]
80pub(crate) enum SortLowerError {
81    #[error("{0}")]
82    Validate(#[from] ValidateError),
83
84    #[error("{0}")]
85    Plan(Box<PlanError>),
86}
87
88impl From<PlanError> for SortLowerError {
89    fn from(err: PlanError) -> Self {
90        Self::Plan(Box::new(err))
91    }
92}