Skip to main content

nodedb_sql/types/
query.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! Query structure types: projections, sort keys, aggregates, windows, engine/join/spatial enums.
4
5use crate::types_expr::SqlExpr;
6
7/// Database engine type for a collection.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum EngineType {
10    DocumentSchemaless,
11    DocumentStrict,
12    KeyValue,
13    Columnar,
14    Timeseries,
15    Spatial,
16    /// ND sparse array engine — `CREATE ARRAY ...`. Routes through
17    /// `ArrayRules` for SQL-level validation, but most table-shaped
18    /// operations are unsupported on this engine (DML happens via
19    /// dedicated `INSERT INTO ARRAY` / `DELETE FROM ARRAY` syntax).
20    Array,
21    /// A continuous aggregate read as a relation. Read-only: routes through
22    /// `ContinuousAggregateRules`, which refuses every write.
23    ContinuousAggregate,
24}
25
26/// SQL join type.
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum JoinType {
29    Inner,
30    Left,
31    Right,
32    Full,
33    Semi,
34    Anti,
35    Cross,
36}
37
38impl JoinType {
39    pub fn as_str(&self) -> &'static str {
40        match self {
41            Self::Inner => "inner",
42            Self::Left => "left",
43            Self::Right => "right",
44            Self::Full => "full",
45            Self::Semi => "semi",
46            Self::Anti => "anti",
47            Self::Cross => "cross",
48        }
49    }
50}
51
52/// Spatial predicate types.
53#[derive(Debug, Clone, Copy, PartialEq, Eq)]
54pub enum SpatialPredicate {
55    DWithin,
56    Contains,
57    Intersects,
58    Within,
59}
60
61/// Projection item in SELECT.
62#[derive(Debug, Clone)]
63pub enum Projection {
64    /// Simple column reference: `SELECT name`
65    Column(String),
66    /// All columns: `SELECT *`
67    Star,
68    /// Qualified star: `SELECT t.*`
69    QualifiedStar(String),
70    /// Computed expression: `SELECT price * qty AS total`
71    Computed { expr: SqlExpr, alias: String },
72    /// Expression the Control Plane evaluates per output row after the Data
73    /// Plane returns the rows (a sequence accessor, possibly inside a larger
74    /// expression). The Data Plane projects the base columns the expression
75    /// references; the response stage evaluates `expr`, writes `alias`, and
76    /// drops those base columns.
77    CpComputed { expr: SqlExpr, alias: String },
78}
79
80/// Sort key for ORDER BY.
81#[derive(Debug, Clone)]
82pub struct SortKey {
83    pub expr: SqlExpr,
84    pub ascending: bool,
85    pub nulls_first: bool,
86}
87
88/// Aggregate expression: `COUNT(*)`, `SUM(amount)`, etc.
89#[derive(Debug, Clone)]
90pub struct AggregateExpr {
91    pub function: String,
92    pub args: Vec<SqlExpr>,
93    pub alias: String,
94    pub distinct: bool,
95    /// For the synthetic `GROUPING(col)` pseudo-aggregate: the index of `col`
96    /// in the canonical group-by key list. The executor uses this index to read
97    /// the grouping-set bitmask and return 0 (present) or 1 (NULL-filled).
98    /// `None` for all ordinary aggregate functions.
99    pub grouping_col_index: Option<usize>,
100    /// Lowercase source text of a `FILTER (WHERE ...)` predicate. The
101    /// planner folds the predicate into `args` as
102    /// `CASE WHEN <predicate> THEN <arg> END`, so a row the predicate does
103    /// not admit feeds NULL, which every aggregate skips. The text is part
104    /// of the output key only.
105    pub filter_text: Option<String>,
106    /// Lowercase source text of a computed argument (`v * 2`). `None` for a
107    /// column or wildcard argument. Part of the aggregate's output key, so
108    /// two computed aggregates of one function get distinct keys.
109    pub arg_text: Option<String>,
110}
111
112/// Records SELECT-list interleaving of GROUP BY keys and aggregate
113/// expressions so the output-schema builder emits columns in the user's
114/// SELECT order instead of a hardcoded group-keys-first order.
115/// `GroupKey(i)` indexes `Aggregate::group_by[i]`; `Aggregate(j)` indexes
116/// `Aggregate::aggregates[j]`. Empty = no projection was in scope when the
117/// plan was built (engine-rules base plan); output_schema falls back to
118/// group-keys-first, matching pre-fix behavior.
119#[derive(Debug, Clone, PartialEq, Eq)]
120pub enum AggOutputSlot {
121    GroupKey(usize),
122    Aggregate(usize),
123}
124
125/// Window function specification.
126#[derive(Debug, Clone)]
127pub struct WindowSpec {
128    pub function: String,
129    pub args: Vec<SqlExpr>,
130    pub partition_by: Vec<SqlExpr>,
131    pub order_by: Vec<SortKey>,
132    pub alias: String,
133    /// Frame specification (`ROWS`/`RANGE` BETWEEN ... AND ...).
134    /// Defaults to `RANGE UNBOUNDED PRECEDING TO CURRENT ROW`
135    /// when the SQL omits a frame clause.
136    pub frame: nodedb_query::WindowFrame,
137}