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    /// `ON CONFLICT (...) DO UPDATE SET` assignments. Empty for plain
63    /// `UPSERT INTO ...`; populated when the caller is
64    /// `INSERT ... ON CONFLICT ... DO UPDATE SET`.
65    pub on_conflict_updates: Vec<(String, SqlExpr)>,
66}
67
68/// Parameters for planning an AGGREGATE operation.
69pub struct AggregateParams {
70    pub collection: String,
71    pub alias: Option<String>,
72    pub filters: Vec<Filter>,
73    pub group_by: Vec<SqlExpr>,
74    pub aggregates: Vec<AggregateExpr>,
75    pub having: Vec<Filter>,
76    pub limit: usize,
77    /// Timeseries-specific: bucket interval from time_bucket() call.
78    pub bucket_interval_ms: Option<i64>,
79    /// Timeseries-specific: non-time GROUP BY columns.
80    pub group_columns: Vec<String>,
81    /// Whether the collection has auto-tiering enabled.
82    pub has_auto_tier: bool,
83}
84
85/// Engine-specific planning rules.
86///
87/// Each engine type implements this trait to produce the correct `SqlPlan`
88/// variant for each operation, or return an error if the operation is not
89/// supported. This is the single source of truth for operation routing —
90/// no downstream code should ever check engine type to decide routing.
91pub trait EngineRules {
92    /// Plan an INSERT. Returns `Err` if the engine does not support inserts
93    /// (e.g. timeseries routes to `TimeseriesIngest` instead).
94    fn plan_insert(&self, params: InsertParams) -> Result<Vec<SqlPlan>>;
95    /// Plan an UPSERT (insert-or-merge). Returns `Err` for append-only or
96    /// columnar engines that don't support merge semantics.
97    fn plan_upsert(&self, params: UpsertParams) -> Result<Vec<SqlPlan>>;
98    /// Plan a table scan (SELECT without point-get optimization).
99    fn plan_scan(&self, params: ScanParams) -> Result<SqlPlan>;
100    /// Plan a point lookup by primary key. Returns `Err` for engines
101    /// that don't support O(1) key lookups (e.g. timeseries).
102    fn plan_point_get(&self, params: PointGetParams) -> Result<SqlPlan>;
103    /// Plan an UPDATE. Returns `Err` for append-only engines.
104    fn plan_update(&self, params: UpdateParams) -> Result<Vec<SqlPlan>>;
105    /// Plan a DELETE (point or bulk).
106    fn plan_delete(&self, params: DeleteParams) -> Result<Vec<SqlPlan>>;
107    /// Plan a GROUP BY / aggregate query.
108    fn plan_aggregate(&self, params: AggregateParams) -> Result<SqlPlan>;
109}
110
111/// Resolve the engine rules for a given engine type.
112///
113/// No catch-all — compiler enforces exhaustiveness.
114pub fn resolve_engine_rules(engine: EngineType) -> &'static dyn EngineRules {
115    match engine {
116        EngineType::DocumentSchemaless => &document_schemaless::SchemalessRules,
117        EngineType::DocumentStrict => &document_strict::StrictRules,
118        EngineType::KeyValue => &kv::KvRules,
119        EngineType::Columnar => &columnar::ColumnarRules,
120        EngineType::Timeseries => &timeseries::TimeseriesRules,
121        EngineType::Spatial => &spatial::SpatialRules,
122    }
123}