Skip to main content

icydb_core/db/query/
expr.rs

1use crate::db::query::{
2    plan::{OrderDirection, PlanError, validate::validate_order},
3    predicate::{self, normalize, normalize_enum_literals},
4};
5use crate::db::{
6    contracts::{Predicate, SchemaInfo, ValidateError},
7    query::plan::OrderSpec,
8};
9use thiserror::Error as ThisError;
10
11///
12/// FilterExpr
13/// Schema-agnostic filter expression for dynamic query input.
14/// Lowered into a validated predicate at the intent boundary.
15///
16
17#[derive(Clone, Debug)]
18pub struct FilterExpr(pub Predicate);
19
20impl FilterExpr {
21    /// Lower the filter expression into a validated predicate for the provided schema.
22    pub(crate) fn lower_with(&self, schema: &SchemaInfo) -> Result<Predicate, ValidateError> {
23        let normalized_enum_literals = normalize_enum_literals(schema, &self.0)?;
24        predicate::validate::reject_unsupported_query_features(&normalized_enum_literals)?;
25        predicate::validate(schema, &normalized_enum_literals)?;
26
27        Ok(normalize(&normalized_enum_literals))
28    }
29}
30
31///
32/// SortExpr
33/// Schema-agnostic sort expression for dynamic query input.
34/// Lowered into a validated order spec at the intent boundary.
35///
36
37#[derive(Clone, Debug)]
38pub struct SortExpr {
39    pub fields: Vec<(String, OrderDirection)>,
40}
41
42impl SortExpr {
43    /// Lower the sort expression into a validated order spec for the provided schema.
44    pub(crate) fn lower_with(&self, schema: &SchemaInfo) -> Result<OrderSpec, SortLowerError> {
45        let spec = OrderSpec {
46            fields: self.fields.clone(),
47        };
48
49        validate_order(schema, &spec)?;
50
51        Ok(spec)
52    }
53}
54
55///
56/// SortLowerError
57/// Errors returned when lowering sort expressions into order specs.
58///
59
60#[derive(Debug, ThisError)]
61pub(crate) enum SortLowerError {
62    #[error("{0}")]
63    Validate(#[from] ValidateError),
64
65    #[error("{0}")]
66    Plan(Box<PlanError>),
67}
68
69impl From<PlanError> for SortLowerError {
70    fn from(err: PlanError) -> Self {
71        Self::Plan(Box::new(err))
72    }
73}