Skip to main content

nodedb_sql/engine_rules/
mod.rs

1pub mod columnar;
2pub mod document_schemaless;
3pub mod document_strict;
4pub mod kv;
5pub mod spatial;
6pub mod timeseries;
7
8use crate::error::Result;
9use crate::types::*;
10
11/// Parameters for planning an INSERT operation.
12pub struct InsertParams {
13    pub collection: String,
14    pub columns: Vec<String>,
15    pub rows: Vec<Vec<(String, SqlValue)>>,
16    pub column_defaults: Vec<(String, String)>,
17}
18
19/// Parameters for planning a SCAN operation.
20pub struct ScanParams {
21    pub collection: String,
22    pub alias: Option<String>,
23    pub filters: Vec<Filter>,
24    pub projection: Vec<Projection>,
25    pub sort_keys: Vec<SortKey>,
26    pub limit: Option<usize>,
27    pub offset: usize,
28    pub distinct: bool,
29    pub window_functions: Vec<WindowSpec>,
30}
31
32/// Parameters for planning a POINT GET operation.
33pub struct PointGetParams {
34    pub collection: String,
35    pub alias: Option<String>,
36    pub key_column: String,
37    pub key_value: SqlValue,
38}
39
40/// Parameters for planning an UPDATE operation.
41pub struct UpdateParams {
42    pub collection: String,
43    pub assignments: Vec<(String, SqlExpr)>,
44    pub filters: Vec<Filter>,
45    pub target_keys: Vec<SqlValue>,
46    pub returning: bool,
47}
48
49/// Parameters for planning a DELETE operation.
50pub struct DeleteParams {
51    pub collection: String,
52    pub filters: Vec<Filter>,
53    pub target_keys: Vec<SqlValue>,
54}
55
56/// Parameters for planning an UPSERT operation.
57pub struct UpsertParams {
58    pub collection: String,
59    pub columns: Vec<String>,
60    pub rows: Vec<Vec<(String, SqlValue)>>,
61    pub column_defaults: Vec<(String, String)>,
62}
63
64/// Parameters for planning an AGGREGATE operation.
65pub struct AggregateParams {
66    pub collection: String,
67    pub alias: Option<String>,
68    pub filters: Vec<Filter>,
69    pub group_by: Vec<SqlExpr>,
70    pub aggregates: Vec<AggregateExpr>,
71    pub having: Vec<Filter>,
72    pub limit: usize,
73    /// Timeseries-specific: bucket interval from time_bucket() call.
74    pub bucket_interval_ms: Option<i64>,
75    /// Timeseries-specific: non-time GROUP BY columns.
76    pub group_columns: Vec<String>,
77    /// Whether the collection has auto-tiering enabled.
78    pub has_auto_tier: bool,
79}
80
81/// Engine-specific planning rules.
82///
83/// Each engine type implements this trait to produce the correct `SqlPlan`
84/// variant for each operation, or return an error if the operation is not
85/// supported. This is the single source of truth for operation routing —
86/// no downstream code should ever check engine type to decide routing.
87pub trait EngineRules {
88    /// Plan an INSERT. Returns `Err` if the engine does not support inserts
89    /// (e.g. timeseries routes to `TimeseriesIngest` instead).
90    fn plan_insert(&self, params: InsertParams) -> Result<Vec<SqlPlan>>;
91    /// Plan an UPSERT (insert-or-merge). Returns `Err` for append-only or
92    /// columnar engines that don't support merge semantics.
93    fn plan_upsert(&self, params: UpsertParams) -> Result<Vec<SqlPlan>>;
94    /// Plan a table scan (SELECT without point-get optimization).
95    fn plan_scan(&self, params: ScanParams) -> Result<SqlPlan>;
96    /// Plan a point lookup by primary key. Returns `Err` for engines
97    /// that don't support O(1) key lookups (e.g. timeseries).
98    fn plan_point_get(&self, params: PointGetParams) -> Result<SqlPlan>;
99    /// Plan an UPDATE. Returns `Err` for append-only engines.
100    fn plan_update(&self, params: UpdateParams) -> Result<Vec<SqlPlan>>;
101    /// Plan a DELETE (point or bulk).
102    fn plan_delete(&self, params: DeleteParams) -> Result<Vec<SqlPlan>>;
103    /// Plan a GROUP BY / aggregate query.
104    fn plan_aggregate(&self, params: AggregateParams) -> Result<SqlPlan>;
105}
106
107/// Resolve the engine rules for a given engine type.
108///
109/// No catch-all — compiler enforces exhaustiveness.
110pub fn resolve_engine_rules(engine: EngineType) -> &'static dyn EngineRules {
111    match engine {
112        EngineType::DocumentSchemaless => &document_schemaless::SchemalessRules,
113        EngineType::DocumentStrict => &document_strict::StrictRules,
114        EngineType::KeyValue => &kv::KvRules,
115        EngineType::Columnar => &columnar::ColumnarRules,
116        EngineType::Timeseries => &timeseries::TimeseriesRules,
117        EngineType::Spatial => &spatial::SpatialRules,
118    }
119}