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}