1#[derive(Debug, Clone)]
8pub enum SqlPlan {
9 ConstantResult {
13 columns: Vec<String>,
14 values: Vec<SqlValue>,
15 },
16
17 Scan {
19 collection: String,
20 alias: Option<String>,
21 engine: EngineType,
22 filters: Vec<Filter>,
23 projection: Vec<Projection>,
24 sort_keys: Vec<SortKey>,
25 limit: Option<usize>,
26 offset: usize,
27 distinct: bool,
28 window_functions: Vec<WindowSpec>,
29 },
30 PointGet {
31 collection: String,
32 alias: Option<String>,
33 engine: EngineType,
34 key_column: String,
35 key_value: SqlValue,
36 },
37 RangeScan {
38 collection: String,
39 field: String,
40 lower: Option<SqlValue>,
41 upper: Option<SqlValue>,
42 limit: usize,
43 },
44
45 Insert {
47 collection: String,
48 engine: EngineType,
49 rows: Vec<Vec<(String, SqlValue)>>,
50 column_defaults: Vec<(String, String)>,
53 },
54 KvInsert {
57 collection: String,
58 entries: Vec<(SqlValue, Vec<(String, SqlValue)>)>,
59 ttl_secs: u64,
61 },
62 Upsert {
64 collection: String,
65 engine: EngineType,
66 rows: Vec<Vec<(String, SqlValue)>>,
67 column_defaults: Vec<(String, String)>,
68 },
69 InsertSelect {
70 target: String,
71 source: Box<SqlPlan>,
72 limit: usize,
73 },
74 Update {
75 collection: String,
76 engine: EngineType,
77 assignments: Vec<(String, SqlExpr)>,
78 filters: Vec<Filter>,
79 target_keys: Vec<SqlValue>,
80 returning: bool,
81 },
82 Delete {
83 collection: String,
84 engine: EngineType,
85 filters: Vec<Filter>,
86 target_keys: Vec<SqlValue>,
87 },
88 Truncate {
89 collection: String,
90 restart_identity: bool,
91 },
92
93 Join {
95 left: Box<SqlPlan>,
96 right: Box<SqlPlan>,
97 on: Vec<(String, String)>,
98 join_type: JoinType,
99 condition: Option<SqlExpr>,
100 limit: usize,
101 projection: Vec<Projection>,
103 filters: Vec<Filter>,
105 },
106
107 Aggregate {
109 input: Box<SqlPlan>,
110 group_by: Vec<SqlExpr>,
111 aggregates: Vec<AggregateExpr>,
112 having: Vec<Filter>,
113 limit: usize,
114 },
115
116 TimeseriesScan {
118 collection: String,
119 time_range: (i64, i64),
120 bucket_interval_ms: i64,
121 group_by: Vec<String>,
122 aggregates: Vec<AggregateExpr>,
123 filters: Vec<Filter>,
124 projection: Vec<Projection>,
125 gap_fill: String,
126 limit: usize,
127 tiered: bool,
128 },
129 TimeseriesIngest {
130 collection: String,
131 rows: Vec<Vec<(String, SqlValue)>>,
132 },
133
134 VectorSearch {
136 collection: String,
137 field: String,
138 query_vector: Vec<f32>,
139 top_k: usize,
140 ef_search: usize,
141 filters: Vec<Filter>,
142 },
143 MultiVectorSearch {
144 collection: String,
145 query_vector: Vec<f32>,
146 top_k: usize,
147 ef_search: usize,
148 },
149 TextSearch {
150 collection: String,
151 query: String,
152 top_k: usize,
153 fuzzy: bool,
154 filters: Vec<Filter>,
155 },
156 HybridSearch {
157 collection: String,
158 query_vector: Vec<f32>,
159 query_text: String,
160 top_k: usize,
161 ef_search: usize,
162 vector_weight: f32,
163 fuzzy: bool,
164 },
165 SpatialScan {
166 collection: String,
167 field: String,
168 predicate: SpatialPredicate,
169 query_geometry: Vec<u8>,
170 distance_meters: f64,
171 attribute_filters: Vec<Filter>,
172 limit: usize,
173 projection: Vec<Projection>,
174 },
175
176 Union {
178 inputs: Vec<SqlPlan>,
179 distinct: bool,
180 },
181 Intersect {
182 left: Box<SqlPlan>,
183 right: Box<SqlPlan>,
184 all: bool,
185 },
186 Except {
187 left: Box<SqlPlan>,
188 right: Box<SqlPlan>,
189 all: bool,
190 },
191 RecursiveScan {
192 collection: String,
193 base_filters: Vec<Filter>,
194 recursive_filters: Vec<Filter>,
195 max_iterations: usize,
196 distinct: bool,
197 limit: usize,
198 },
199
200 Cte {
202 definitions: Vec<(String, SqlPlan)>,
204 outer: Box<SqlPlan>,
206 },
207}
208
209#[derive(Debug, Clone, Copy, PartialEq, Eq)]
211pub enum EngineType {
212 DocumentSchemaless,
213 DocumentStrict,
214 KeyValue,
215 Columnar,
216 Timeseries,
217 Spatial,
218}
219
220#[derive(Debug, Clone, Copy, PartialEq, Eq)]
222pub enum JoinType {
223 Inner,
224 Left,
225 Right,
226 Full,
227 Semi,
228 Anti,
229 Cross,
230}
231
232impl JoinType {
233 pub fn as_str(&self) -> &'static str {
234 match self {
235 Self::Inner => "inner",
236 Self::Left => "left",
237 Self::Right => "right",
238 Self::Full => "full",
239 Self::Semi => "semi",
240 Self::Anti => "anti",
241 Self::Cross => "cross",
242 }
243 }
244}
245
246#[derive(Debug, Clone, Copy, PartialEq, Eq)]
248pub enum SpatialPredicate {
249 DWithin,
250 Contains,
251 Intersects,
252 Within,
253}
254
255#[derive(Debug, Clone)]
257pub struct Filter {
258 pub expr: FilterExpr,
259}
260
261#[derive(Debug, Clone)]
263pub enum FilterExpr {
264 Comparison {
265 field: String,
266 op: CompareOp,
267 value: SqlValue,
268 },
269 Like {
270 field: String,
271 pattern: String,
272 },
273 InList {
274 field: String,
275 values: Vec<SqlValue>,
276 },
277 Between {
278 field: String,
279 low: SqlValue,
280 high: SqlValue,
281 },
282 IsNull {
283 field: String,
284 },
285 IsNotNull {
286 field: String,
287 },
288 And(Vec<Filter>),
289 Or(Vec<Filter>),
290 Not(Box<Filter>),
291 Expr(SqlExpr),
293}
294
295#[derive(Debug, Clone, Copy, PartialEq, Eq)]
297pub enum CompareOp {
298 Eq,
299 Ne,
300 Gt,
301 Ge,
302 Lt,
303 Le,
304}
305
306#[derive(Debug, Clone)]
308pub enum Projection {
309 Column(String),
311 Star,
313 QualifiedStar(String),
315 Computed { expr: SqlExpr, alias: String },
317}
318
319#[derive(Debug, Clone)]
321pub struct SortKey {
322 pub expr: SqlExpr,
323 pub ascending: bool,
324 pub nulls_first: bool,
325}
326
327#[derive(Debug, Clone)]
329pub struct AggregateExpr {
330 pub function: String,
331 pub args: Vec<SqlExpr>,
332 pub alias: String,
333 pub distinct: bool,
334}
335
336#[derive(Debug, Clone)]
338pub struct WindowSpec {
339 pub function: String,
340 pub args: Vec<SqlExpr>,
341 pub partition_by: Vec<SqlExpr>,
342 pub order_by: Vec<SortKey>,
343 pub alias: String,
344}
345
346#[derive(Debug, Clone, PartialEq)]
348pub enum SqlValue {
349 Int(i64),
350 Float(f64),
351 String(String),
352 Bool(bool),
353 Null,
354 Bytes(Vec<u8>),
355 Array(Vec<SqlValue>),
356}
357
358#[derive(Debug, Clone)]
360pub enum SqlExpr {
361 Column { table: Option<String>, name: String },
363 Literal(SqlValue),
365 BinaryOp {
367 left: Box<SqlExpr>,
368 op: BinaryOp,
369 right: Box<SqlExpr>,
370 },
371 UnaryOp { op: UnaryOp, expr: Box<SqlExpr> },
373 Function {
375 name: String,
376 args: Vec<SqlExpr>,
377 distinct: bool,
378 },
379 Case {
381 operand: Option<Box<SqlExpr>>,
382 when_then: Vec<(SqlExpr, SqlExpr)>,
383 else_expr: Option<Box<SqlExpr>>,
384 },
385 Cast { expr: Box<SqlExpr>, to_type: String },
387 Subquery(Box<SqlPlan>),
389 Wildcard,
391 IsNull { expr: Box<SqlExpr>, negated: bool },
393 InList {
395 expr: Box<SqlExpr>,
396 list: Vec<SqlExpr>,
397 negated: bool,
398 },
399 Between {
401 expr: Box<SqlExpr>,
402 low: Box<SqlExpr>,
403 high: Box<SqlExpr>,
404 negated: bool,
405 },
406 Like {
408 expr: Box<SqlExpr>,
409 pattern: Box<SqlExpr>,
410 negated: bool,
411 },
412 ArrayLiteral(Vec<SqlExpr>),
414}
415
416#[derive(Debug, Clone, Copy, PartialEq, Eq)]
418pub enum BinaryOp {
419 Add,
421 Sub,
422 Mul,
423 Div,
424 Mod,
425 Eq,
427 Ne,
428 Gt,
429 Ge,
430 Lt,
431 Le,
432 And,
434 Or,
435 Concat,
437}
438
439#[derive(Debug, Clone, Copy, PartialEq, Eq)]
441pub enum UnaryOp {
442 Neg,
443 Not,
444}
445
446#[derive(Debug, Clone, PartialEq, Eq)]
448pub enum SqlDataType {
449 Int64,
450 Float64,
451 String,
452 Bool,
453 Bytes,
454 Timestamp,
455 Decimal,
456 Uuid,
457 Vector(usize),
458 Geometry,
459}
460
461pub trait SqlCatalog {
468 fn get_collection(&self, name: &str) -> Option<CollectionInfo>;
469}
470
471#[derive(Debug, Clone)]
473pub struct CollectionInfo {
474 pub name: String,
475 pub engine: EngineType,
476 pub columns: Vec<ColumnInfo>,
477 pub primary_key: Option<String>,
478 pub has_auto_tier: bool,
479}
480
481#[derive(Debug, Clone)]
483pub struct ColumnInfo {
484 pub name: String,
485 pub data_type: SqlDataType,
486 pub nullable: bool,
487 pub is_primary_key: bool,
488 pub default: Option<String>,
490}