1use super::*;
2use crate::storage::query::sql_lowering::{filter_to_expr, projection_to_select_item};
3
4pub struct TableQueryBuilder {
5 query: TableQuery,
6}
7
8impl TableQueryBuilder {
9 pub fn new(table: &str) -> Self {
11 Self {
12 query: TableQuery::new(table),
13 }
14 }
15
16 pub fn alias(mut self, alias: &str) -> Self {
18 self.query.alias = Some(alias.to_string());
19 self
20 }
21
22 pub fn select(mut self, column: &str) -> Self {
24 let field = FieldRef::column(
25 self.query.alias.as_deref().unwrap_or(&self.query.table),
26 column,
27 );
28 self.query.select_items.push(SelectItem::Expr {
29 expr: Expr::col(field.clone()),
30 alias: None,
31 });
32 self.query.columns.push(Projection::from_field(field));
33 self
34 }
35
36 pub fn select_all(mut self) -> Self {
38 self.query.select_items = vec![SelectItem::Wildcard];
39 self.query.columns.clear();
40 self
41 }
42
43 pub fn filter(mut self, f: Filter) -> Self {
45 let f_expr = filter_to_expr(&f);
46 self.query.where_expr = Some(match self.query.where_expr.take() {
47 Some(existing) => Expr::binop(BinOp::And, existing, f_expr),
48 None => f_expr,
49 });
50 self.query.filter = Some(match self.query.filter.take() {
51 Some(existing) => existing.and(f),
52 None => f,
53 });
54 self
55 }
56
57 pub fn order_by(mut self, clause: OrderByClause) -> Self {
59 self.query.order_by.push(clause);
60 self
61 }
62
63 pub fn limit(mut self, n: u64) -> Self {
65 self.query.limit = Some(n);
66 self
67 }
68
69 pub fn offset(mut self, n: u64) -> Self {
71 self.query.offset = Some(n);
72 self
73 }
74
75 pub fn join_graph(self, pattern: GraphPattern, on: JoinCondition) -> JoinQueryBuilder {
77 JoinQueryBuilder {
78 left: QueryExpr::Table(self.query),
79 right: QueryExpr::Graph(GraphQuery::new(pattern)),
80 on,
81 join_type: JoinType::Inner,
82 filter: None,
83 order_by: Vec::new(),
84 limit: None,
85 offset: None,
86 return_items: Vec::new(),
87 return_: Vec::new(),
88 }
89 }
90
91 pub fn join_table(self, table: &str, on: JoinCondition) -> JoinQueryBuilder {
93 JoinQueryBuilder {
94 left: QueryExpr::Table(self.query),
95 right: QueryExpr::Table(TableQuery::new(table)),
96 on,
97 join_type: JoinType::Inner,
98 filter: None,
99 order_by: Vec::new(),
100 limit: None,
101 offset: None,
102 return_items: Vec::new(),
103 return_: Vec::new(),
104 }
105 }
106
107 pub fn join_vector(self, query: VectorQuery, on: JoinCondition) -> JoinQueryBuilder {
109 JoinQueryBuilder {
110 left: QueryExpr::Table(self.query),
111 right: QueryExpr::Vector(query),
112 on,
113 join_type: JoinType::Inner,
114 filter: None,
115 order_by: Vec::new(),
116 limit: None,
117 offset: None,
118 return_items: Vec::new(),
119 return_: Vec::new(),
120 }
121 }
122
123 pub fn join_path(self, query: PathQuery, on: JoinCondition) -> JoinQueryBuilder {
125 JoinQueryBuilder {
126 left: QueryExpr::Table(self.query),
127 right: QueryExpr::Path(query),
128 on,
129 join_type: JoinType::Inner,
130 filter: None,
131 order_by: Vec::new(),
132 limit: None,
133 offset: None,
134 return_items: Vec::new(),
135 return_: Vec::new(),
136 }
137 }
138
139 pub fn join_hybrid(self, query: HybridQuery, on: JoinCondition) -> JoinQueryBuilder {
141 JoinQueryBuilder {
142 left: QueryExpr::Table(self.query),
143 right: QueryExpr::Hybrid(query),
144 on,
145 join_type: JoinType::Inner,
146 filter: None,
147 order_by: Vec::new(),
148 limit: None,
149 offset: None,
150 return_items: Vec::new(),
151 return_: Vec::new(),
152 }
153 }
154
155 pub fn build(self) -> QueryExpr {
157 QueryExpr::Table(self.query)
158 }
159}
160
161pub struct GraphQueryBuilder {
163 query: GraphQuery,
164}
165
166impl GraphQueryBuilder {
167 pub fn new() -> Self {
169 Self {
170 query: GraphQuery::new(GraphPattern::new()),
171 }
172 }
173
174 pub fn node(mut self, pattern: NodePattern) -> Self {
176 self.query.pattern.nodes.push(pattern);
177 self
178 }
179
180 pub fn edge(mut self, pattern: EdgePattern) -> Self {
182 self.query.pattern.edges.push(pattern);
183 self
184 }
185
186 pub fn filter(mut self, f: Filter) -> Self {
188 self.query.filter = Some(match self.query.filter.take() {
189 Some(existing) => existing.and(f),
190 None => f,
191 });
192 self
193 }
194
195 pub fn alias(mut self, alias: &str) -> Self {
197 self.query.alias = Some(alias.to_string());
198 self
199 }
200
201 pub fn limit(mut self, n: u64) -> Self {
203 self.query.limit = Some(n);
204 self
205 }
206
207 pub fn return_field(mut self, field: FieldRef) -> Self {
209 self.query.return_.push(Projection::from_field(field));
210 self
211 }
212
213 pub fn build(self) -> QueryExpr {
215 QueryExpr::Graph(self.query)
216 }
217}
218
219impl Default for GraphQueryBuilder {
220 fn default() -> Self {
221 Self::new()
222 }
223}
224
225pub struct JoinQueryBuilder {
227 left: QueryExpr,
228 right: QueryExpr,
229 on: JoinCondition,
230 join_type: JoinType,
231 filter: Option<Filter>,
232 order_by: Vec<OrderByClause>,
233 limit: Option<u64>,
234 offset: Option<u64>,
235 return_items: Vec<SelectItem>,
236 return_: Vec<Projection>,
237}
238
239impl JoinQueryBuilder {
240 pub fn join_type(mut self, jt: JoinType) -> Self {
242 self.join_type = jt;
243 self
244 }
245
246 pub fn right_alias(mut self, alias: &str) -> Self {
248 let alias = alias.to_string();
249 match &mut self.right {
250 QueryExpr::Table(table) => table.alias = Some(alias.clone()),
251 QueryExpr::Graph(graph) => graph.alias = Some(alias.clone()),
252 QueryExpr::Path(path) => path.alias = Some(alias.clone()),
253 QueryExpr::Vector(vector) => vector.alias = Some(alias.clone()),
254 QueryExpr::Hybrid(hybrid) => hybrid.alias = Some(alias.clone()),
255 QueryExpr::Join(_)
256 | QueryExpr::Insert(_)
257 | QueryExpr::Update(_)
258 | QueryExpr::Delete(_)
259 | QueryExpr::CreateTable(_)
260 | QueryExpr::CreateCollection(_)
261 | QueryExpr::CreateVector(_)
262 | QueryExpr::DropTable(_)
263 | QueryExpr::DropGraph(_)
264 | QueryExpr::DropVector(_)
265 | QueryExpr::DropDocument(_)
266 | QueryExpr::DropKv(_)
267 | QueryExpr::DropCollection(_)
268 | QueryExpr::Truncate(_)
269 | QueryExpr::AlterTable(_)
270 | QueryExpr::GraphCommand(_)
271 | QueryExpr::SearchCommand(_)
272 | QueryExpr::CreateIndex(_)
273 | QueryExpr::DropIndex(_)
274 | QueryExpr::ProbabilisticCommand(_)
275 | QueryExpr::Ask(_)
276 | QueryExpr::SetConfig { .. }
277 | QueryExpr::ShowConfig { .. }
278 | QueryExpr::SetSecret { .. }
279 | QueryExpr::DeleteSecret { .. }
280 | QueryExpr::ShowSecrets { .. }
281 | QueryExpr::SetTenant(_)
282 | QueryExpr::ShowTenant
283 | QueryExpr::CreateTimeSeries(_)
284 | QueryExpr::DropTimeSeries(_)
285 | QueryExpr::CreateQueue(_)
286 | QueryExpr::AlterQueue(_)
287 | QueryExpr::DropQueue(_)
288 | QueryExpr::QueueSelect(_)
289 | QueryExpr::QueueCommand(_)
290 | QueryExpr::KvCommand(_)
291 | QueryExpr::ConfigCommand(_)
292 | QueryExpr::CreateTree(_)
293 | QueryExpr::DropTree(_)
294 | QueryExpr::TreeCommand(_)
295 | QueryExpr::ExplainAlter(_)
296 | QueryExpr::TransactionControl(_)
297 | QueryExpr::MaintenanceCommand(_)
298 | QueryExpr::CreateSchema(_)
299 | QueryExpr::DropSchema(_)
300 | QueryExpr::CreateSequence(_)
301 | QueryExpr::DropSequence(_)
302 | QueryExpr::CopyFrom(_)
303 | QueryExpr::CreateView(_)
304 | QueryExpr::DropView(_)
305 | QueryExpr::RefreshMaterializedView(_)
306 | QueryExpr::CreatePolicy(_)
307 | QueryExpr::DropPolicy(_)
308 | QueryExpr::CreateServer(_)
309 | QueryExpr::DropServer(_)
310 | QueryExpr::CreateForeignTable(_)
311 | QueryExpr::DropForeignTable(_)
312 | QueryExpr::Grant(_)
313 | QueryExpr::Revoke(_)
314 | QueryExpr::AlterUser(_)
315 | QueryExpr::CreateIamPolicy { .. }
316 | QueryExpr::DropIamPolicy { .. }
317 | QueryExpr::AttachPolicy { .. }
318 | QueryExpr::DetachPolicy { .. }
319 | QueryExpr::ShowPolicies { .. }
320 | QueryExpr::ShowEffectivePermissions { .. }
321 | QueryExpr::SimulatePolicy { .. }
322 | QueryExpr::CreateMigration(_)
323 | QueryExpr::ApplyMigration(_)
324 | QueryExpr::RollbackMigration(_)
325 | QueryExpr::ExplainMigration(_)
326 | QueryExpr::EventsBackfill(_)
327 | QueryExpr::EventsBackfillStatus { .. } => {}
328 }
329 self
330 }
331
332 pub fn filter(mut self, f: Filter) -> Self {
334 self.filter = Some(match self.filter.take() {
335 Some(existing) => existing.and(f),
336 None => f,
337 });
338 self
339 }
340
341 pub fn order_by(mut self, clause: OrderByClause) -> Self {
343 self.order_by.push(clause);
344 self
345 }
346
347 pub fn limit(mut self, n: u64) -> Self {
349 self.limit = Some(n);
350 self
351 }
352
353 pub fn offset(mut self, n: u64) -> Self {
355 self.offset = Some(n);
356 self
357 }
358
359 pub fn return_field(mut self, field: FieldRef) -> Self {
361 let projection = Projection::from_field(field);
362 if let Some(item) = projection_to_select_item(&projection) {
363 self.return_items.push(item);
364 }
365 self.return_.push(projection);
366 self
367 }
368
369 pub fn select(mut self, column: &str) -> Self {
371 let projection = Projection::from_field(FieldRef::column("", column));
372 if let Some(item) = projection_to_select_item(&projection) {
373 self.return_items.push(item);
374 }
375 self.return_.push(projection);
376 self
377 }
378
379 pub fn build(self) -> QueryExpr {
381 QueryExpr::Join(JoinQuery {
382 left: Box::new(self.left),
383 right: Box::new(self.right),
384 join_type: self.join_type,
385 on: self.on,
386 filter: self.filter,
387 order_by: self.order_by,
388 limit: self.limit,
389 offset: self.offset,
390 return_items: self.return_items,
391 return_: self.return_,
392 })
393 }
394}
395
396pub struct PathQueryBuilder {
398 query: PathQuery,
399}
400
401impl PathQueryBuilder {
402 pub fn new(from: NodeSelector, to: NodeSelector) -> Self {
404 Self {
405 query: PathQuery::new(from, to),
406 }
407 }
408
409 pub fn via_label(mut self, label: impl Into<String>) -> Self {
411 self.query.via.push(label.into());
412 self
413 }
414
415 pub fn max_length(mut self, n: u32) -> Self {
417 self.query.max_length = n;
418 self
419 }
420
421 pub fn filter(mut self, f: Filter) -> Self {
423 self.query.filter = Some(f);
424 self
425 }
426
427 pub fn alias(mut self, alias: &str) -> Self {
429 self.query.alias = Some(alias.to_string());
430 self
431 }
432
433 pub fn build(self) -> QueryExpr {
435 QueryExpr::Path(self.query)
436 }
437}
438
439#[derive(Debug, Clone)]
472pub struct CteDefinition {
473 pub name: String,
475 pub columns: Vec<String>,
477 pub query: Box<QueryExpr>,
479 pub recursive: bool,
481}
482
483impl CteDefinition {
484 pub fn new(name: &str, query: QueryExpr) -> Self {
486 Self {
487 name: name.to_string(),
488 columns: Vec::new(),
489 query: Box::new(query),
490 recursive: false,
491 }
492 }
493
494 pub fn recursive(name: &str, query: QueryExpr) -> Self {
496 Self {
497 name: name.to_string(),
498 columns: Vec::new(),
499 query: Box::new(query),
500 recursive: true,
501 }
502 }
503
504 pub fn with_columns(mut self, columns: Vec<String>) -> Self {
506 self.columns = columns;
507 self
508 }
509}
510
511#[derive(Debug, Clone, Default)]
513pub struct WithClause {
514 pub ctes: Vec<CteDefinition>,
516 pub has_recursive: bool,
518}
519
520impl WithClause {
521 pub fn new() -> Self {
523 Self::default()
524 }
525
526 pub fn add(mut self, cte: CteDefinition) -> Self {
528 if cte.recursive {
529 self.has_recursive = true;
530 }
531 self.ctes.push(cte);
532 self
533 }
534
535 pub fn is_empty(&self) -> bool {
537 self.ctes.is_empty()
538 }
539
540 pub fn get(&self, name: &str) -> Option<&CteDefinition> {
542 self.ctes.iter().find(|c| c.name == name)
543 }
544}
545
546#[derive(Debug, Clone)]
548pub struct QueryWithCte {
549 pub with_clause: Option<WithClause>,
551 pub query: QueryExpr,
553}
554
555impl QueryWithCte {
556 pub fn simple(query: QueryExpr) -> Self {
558 Self {
559 with_clause: None,
560 query,
561 }
562 }
563
564 pub fn with_ctes(with_clause: WithClause, query: QueryExpr) -> Self {
566 Self {
567 with_clause: Some(with_clause),
568 query,
569 }
570 }
571}
572
573pub struct CteQueryBuilder {
575 with_clause: WithClause,
576}
577
578impl CteQueryBuilder {
579 pub fn new() -> Self {
581 Self {
582 with_clause: WithClause::new(),
583 }
584 }
585
586 pub fn cte(mut self, name: &str, query: QueryExpr) -> Self {
588 self.with_clause = self.with_clause.add(CteDefinition::new(name, query));
589 self
590 }
591
592 pub fn recursive_cte(mut self, name: &str, query: QueryExpr) -> Self {
594 self.with_clause = self.with_clause.add(CteDefinition::recursive(name, query));
595 self
596 }
597
598 pub fn cte_with_columns(mut self, name: &str, columns: Vec<String>, query: QueryExpr) -> Self {
600 let cte = CteDefinition::new(name, query).with_columns(columns);
601 self.with_clause = self.with_clause.add(cte);
602 self
603 }
604
605 pub fn build(self, main_query: QueryExpr) -> QueryWithCte {
607 QueryWithCte::with_ctes(self.with_clause, main_query)
608 }
609}
610
611impl Default for CteQueryBuilder {
612 fn default() -> Self {
613 Self::new()
614 }
615}