Skip to main content

nodedb_sql/engine_rules/
columnar.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! Engine rules for plain columnar collections.
4
5use crate::engine_rules::*;
6use crate::error::{Result, SqlError};
7use crate::types::*;
8
9pub struct ColumnarRules;
10
11impl EngineRules for ColumnarRules {
12    fn plan_insert(&self, p: InsertParams) -> Result<Vec<SqlPlan>> {
13        Ok(vec![SqlPlan::Insert {
14            collection: p.collection,
15            engine: EngineType::Columnar,
16            rows: p.rows,
17            column_defaults: p.column_defaults,
18            if_absent: p.if_absent,
19            column_schema: p.column_schema,
20            primary_key: p.primary_key,
21        }])
22    }
23
24    /// `UPSERT` / `INSERT ... ON CONFLICT (pk) DO UPDATE` on columnar.
25    /// Duplicate PK tombstones the prior row via the segment's delete
26    /// bitmap; the new row (or its merged form, when `on_conflict_updates`
27    /// is non-empty) is appended. Sort-key semantics are unchanged.
28    fn plan_upsert(&self, p: UpsertParams) -> Result<Vec<SqlPlan>> {
29        Ok(vec![SqlPlan::Upsert {
30            collection: p.collection,
31            engine: EngineType::Columnar,
32            rows: p.rows,
33            column_defaults: p.column_defaults,
34            on_conflict_updates: p.on_conflict_updates,
35            column_schema: p.column_schema,
36            primary_key: p.primary_key,
37        }])
38    }
39
40    fn plan_scan(&self, p: ScanParams) -> Result<SqlPlan> {
41        if p.temporal.is_temporal() && !p.bitemporal {
42            return Err(SqlError::Unsupported {
43                detail: format!(
44                    "FOR SYSTEM_TIME / FOR VALID_TIME requires a bitemporal \
45                     collection; '{}' was not created WITH bitemporal = true",
46                    p.collection
47                ),
48            });
49        }
50        Ok(SqlPlan::Scan {
51            collection: p.collection,
52            alias: p.alias,
53            engine: EngineType::Columnar,
54            filters: p.filters,
55            projection: p.projection,
56            sort_keys: p.sort_keys,
57            limit: p.limit,
58            offset: p.offset,
59            distinct: p.distinct,
60            window_functions: p.window_functions,
61            temporal: p.temporal,
62        })
63    }
64
65    fn plan_point_get(&self, p: PointGetParams) -> Result<SqlPlan> {
66        Ok(SqlPlan::PointGet {
67            collection: p.collection,
68            alias: p.alias,
69            engine: EngineType::Columnar,
70            key_column: p.key_column,
71            key_value: p.key_value,
72            projection: p.projection,
73        })
74    }
75
76    fn plan_update(&self, p: UpdateParams) -> Result<Vec<SqlPlan>> {
77        Ok(vec![SqlPlan::Update {
78            collection: p.collection,
79            engine: EngineType::Columnar,
80            assignments: p.assignments,
81            filters: p.filters,
82            target_keys: p.target_keys,
83            returning: p.returning,
84        }])
85    }
86
87    fn plan_update_from(&self, p: UpdateFromParams) -> Result<Vec<SqlPlan>> {
88        Ok(vec![SqlPlan::UpdateFrom {
89            collection: p.collection,
90            engine: EngineType::Columnar,
91            source: p.source,
92            target_join_col: p.target_join_col,
93            source_join_col: p.source_join_col,
94            assignments: p.assignments,
95            target_filters: p.target_filters,
96            returning: p.returning,
97        }])
98    }
99
100    fn plan_delete(&self, p: DeleteParams) -> Result<Vec<SqlPlan>> {
101        Ok(vec![SqlPlan::Delete {
102            collection: p.collection,
103            engine: EngineType::Columnar,
104            filters: p.filters,
105            target_keys: p.target_keys,
106        }])
107    }
108
109    fn plan_aggregate(&self, p: AggregateParams) -> Result<SqlPlan> {
110        if p.temporal.is_temporal() && !p.bitemporal {
111            return Err(SqlError::Unsupported {
112                detail: format!(
113                    "FOR SYSTEM_TIME / FOR VALID_TIME requires a bitemporal \
114                     collection; '{}' was not created WITH bitemporal = true",
115                    p.collection
116                ),
117            });
118        }
119        let base_scan = SqlPlan::Scan {
120            collection: p.collection,
121            alias: p.alias,
122            engine: EngineType::Columnar,
123            filters: p.filters,
124            projection: Vec::new(),
125            sort_keys: Vec::new(),
126            limit: None,
127            offset: 0,
128            distinct: false,
129            window_functions: Vec::new(),
130            temporal: p.temporal,
131        };
132        Ok(SqlPlan::Aggregate {
133            input: Box::new(base_scan),
134            group_by: p.group_by,
135            group_by_aliases: Vec::new(),
136            output_order: Vec::new(),
137            aggregates: p.aggregates,
138            having: p.having,
139            limit: p.limit,
140            grouping_sets: None,
141            sort_keys: Vec::new(),
142        })
143    }
144
145    fn plan_merge(&self, p: MergeParams) -> Result<Vec<SqlPlan>> {
146        Err(SqlError::Unsupported {
147            detail: format!(
148                "MERGE is not supported on columnar collection '{}'",
149                p.collection
150            ),
151        })
152    }
153}