Skip to main content

nodedb_sql/engine_rules/
spatial.rs

1//! Engine rules for spatial columnar collections.
2
3use crate::engine_rules::*;
4use crate::error::Result;
5use crate::types::*;
6
7pub struct SpatialRules;
8
9impl EngineRules for SpatialRules {
10    fn plan_insert(&self, p: InsertParams) -> Result<Vec<SqlPlan>> {
11        Ok(vec![SqlPlan::Insert {
12            collection: p.collection,
13            engine: EngineType::Spatial,
14            rows: p.rows,
15            column_defaults: p.column_defaults,
16            if_absent: p.if_absent,
17        }])
18    }
19
20    /// Spatial extends columnar and inherits the same upsert semantics:
21    /// duplicate PK tombstones the prior row; the new row (or merged form
22    /// when `on_conflict_updates` is non-empty) is appended.
23    fn plan_upsert(&self, p: UpsertParams) -> Result<Vec<SqlPlan>> {
24        Ok(vec![SqlPlan::Upsert {
25            collection: p.collection,
26            engine: EngineType::Spatial,
27            rows: p.rows,
28            column_defaults: p.column_defaults,
29            on_conflict_updates: p.on_conflict_updates,
30        }])
31    }
32
33    fn plan_scan(&self, p: ScanParams) -> Result<SqlPlan> {
34        // Plain scan on spatial collection — no spatial predicate involved.
35        // Spatial predicates (ST_DWithin, ST_Contains, etc.) are detected
36        // in select.rs and routed to SpatialScan directly, bypassing this.
37        Ok(SqlPlan::Scan {
38            collection: p.collection,
39            alias: p.alias,
40            engine: EngineType::Spatial,
41            filters: p.filters,
42            projection: p.projection,
43            sort_keys: p.sort_keys,
44            limit: p.limit,
45            offset: p.offset,
46            distinct: p.distinct,
47            window_functions: p.window_functions,
48        })
49    }
50
51    fn plan_point_get(&self, p: PointGetParams) -> Result<SqlPlan> {
52        Ok(SqlPlan::PointGet {
53            collection: p.collection,
54            alias: p.alias,
55            engine: EngineType::Spatial,
56            key_column: p.key_column,
57            key_value: p.key_value,
58        })
59    }
60
61    fn plan_update(&self, p: UpdateParams) -> Result<Vec<SqlPlan>> {
62        Ok(vec![SqlPlan::Update {
63            collection: p.collection,
64            engine: EngineType::Spatial,
65            assignments: p.assignments,
66            filters: p.filters,
67            target_keys: p.target_keys,
68            returning: p.returning,
69        }])
70    }
71
72    fn plan_delete(&self, p: DeleteParams) -> Result<Vec<SqlPlan>> {
73        Ok(vec![SqlPlan::Delete {
74            collection: p.collection,
75            engine: EngineType::Spatial,
76            filters: p.filters,
77            target_keys: p.target_keys,
78        }])
79    }
80
81    fn plan_aggregate(&self, p: AggregateParams) -> Result<SqlPlan> {
82        let base_scan = SqlPlan::Scan {
83            collection: p.collection,
84            alias: p.alias,
85            engine: EngineType::Spatial,
86            filters: p.filters,
87            projection: Vec::new(),
88            sort_keys: Vec::new(),
89            limit: None,
90            offset: 0,
91            distinct: false,
92            window_functions: Vec::new(),
93        };
94        Ok(SqlPlan::Aggregate {
95            input: Box::new(base_scan),
96            group_by: p.group_by,
97            aggregates: p.aggregates,
98            having: p.having,
99            limit: p.limit,
100        })
101    }
102}