1use super::common::{FieldRef, OrderByDef, SchemaRef};
2use super::conditions::Conditions;
3use super::custom::CustomTableSource;
4use super::expr::Expr;
5
6#[derive(Debug, Clone, Default)]
12pub struct QueryStmt {
13 pub ctes: Option<Vec<CteDef>>,
14 pub columns: Vec<SelectColumn>,
15 pub distinct: Option<DistinctDef>,
16 pub from: Option<Vec<FromItem>>,
18 pub joins: Option<Vec<JoinDef>>,
19 pub where_clause: Option<Conditions>,
20 pub group_by: Option<Vec<GroupByItem>>,
21 pub having: Option<Conditions>,
22 pub window: Option<Vec<WindowNameDef>>,
23 pub order_by: Option<Vec<OrderByDef>>,
24 pub limit: Option<LimitDef>,
25 pub lock: Option<Vec<SelectLockDef>>,
27}
28
29#[derive(Debug, Clone)]
35pub enum SelectColumn {
36 Star(Option<String>),
38
39 Expr { expr: Expr, alias: Option<String> },
41
42 Field {
44 field: FieldRef,
45 alias: Option<String>,
46 },
47}
48
49impl SelectColumn {
50 pub fn all() -> Self {
52 SelectColumn::Star(None)
53 }
54
55 pub fn all_from(table: impl Into<String>) -> Self {
57 SelectColumn::Star(Some(table.into()))
58 }
59
60 pub fn field(table: &str, name: &str) -> Self {
62 SelectColumn::Field {
63 field: FieldRef::new(table, name),
64 alias: None,
65 }
66 }
67
68 pub fn expr(expr: Expr) -> Self {
70 SelectColumn::Expr { expr, alias: None }
71 }
72
73 pub fn aliased(expr: Expr, alias: impl Into<String>) -> Self {
75 SelectColumn::Expr {
76 expr,
77 alias: Some(alias.into()),
78 }
79 }
80
81 pub fn field_aliased(table: &str, name: &str, alias: impl Into<String>) -> Self {
83 SelectColumn::Field {
84 field: FieldRef::new(table, name),
85 alias: Some(alias.into()),
86 }
87 }
88}
89
90#[derive(Debug, Clone)]
96pub enum DistinctDef {
97 Distinct,
99 DistinctOn(Vec<Expr>),
101}
102
103#[derive(Debug, Clone)]
109pub struct FromItem {
110 pub source: TableSource,
111 pub only: bool,
113 pub sample: Option<TableSampleDef>,
115 pub index_hint: Option<SqliteIndexHint>,
117}
118
119impl FromItem {
120 pub fn table(schema_ref: SchemaRef) -> Self {
121 Self {
122 source: TableSource::Table(schema_ref),
123 only: false,
124 sample: None,
125 index_hint: None,
126 }
127 }
128
129 pub fn lateral(inner: FromItem) -> Self {
130 Self {
131 source: TableSource::Lateral(Box::new(inner)),
132 only: false,
133 sample: None,
134 index_hint: None,
135 }
136 }
137
138 pub fn function(name: impl Into<String>, args: Vec<Expr>, alias: impl Into<String>) -> Self {
139 Self {
140 source: TableSource::Function {
141 name: name.into(),
142 args,
143 alias: Some(alias.into()),
144 },
145 only: false,
146 sample: None,
147 index_hint: None,
148 }
149 }
150
151 pub fn values(rows: Vec<Vec<Expr>>, alias: impl Into<String>) -> Self {
152 Self {
153 source: TableSource::Values {
154 rows,
155 alias: alias.into(),
156 column_aliases: None,
157 },
158 only: false,
159 sample: None,
160 index_hint: None,
161 }
162 }
163
164 pub fn subquery(query: QueryStmt, alias: String) -> Self {
165 Self {
166 source: TableSource::SubQuery(SubQueryDef {
167 query: Box::new(query),
168 alias,
169 }),
170 only: false,
171 sample: None,
172 index_hint: None,
173 }
174 }
175}
176
177#[derive(Debug, Clone)]
179pub enum TableSource {
180 Table(SchemaRef),
182 SubQuery(SubQueryDef),
184 SetOp(Box<SetOpDef>),
186 Lateral(Box<FromItem>),
188 Function {
190 name: String,
191 args: Vec<Expr>,
192 alias: Option<String>,
193 },
194 Values {
196 rows: Vec<Vec<Expr>>,
197 alias: String,
198 column_aliases: Option<Vec<String>>,
199 },
200 Custom(Box<dyn CustomTableSource>),
202}
203
204#[derive(Debug, Clone)]
210pub struct TableSampleDef {
211 pub method: SampleMethod,
213 pub percentage: f64,
215 pub seed: Option<i64>,
217}
218
219#[derive(Debug, Clone, Copy, PartialEq, Eq)]
221pub enum SampleMethod {
222 Bernoulli,
224 System,
226 Block,
228}
229
230#[derive(Debug, Clone)]
236pub enum SqliteIndexHint {
237 IndexedBy(String),
239 NotIndexed,
241}
242
243#[derive(Debug, Clone)]
249pub struct JoinDef {
250 pub source: FromItem,
251 pub condition: Option<JoinCondition>,
252 pub join_type: JoinType,
253 pub natural: bool,
254}
255
256impl JoinDef {
257 pub fn inner(source: FromItem, on: Conditions) -> Self {
258 Self {
259 source,
260 condition: Some(JoinCondition::On(on)),
261 join_type: JoinType::Inner,
262 natural: false,
263 }
264 }
265
266 pub fn left(source: FromItem, on: Conditions) -> Self {
267 Self {
268 source,
269 condition: Some(JoinCondition::On(on)),
270 join_type: JoinType::Left,
271 natural: false,
272 }
273 }
274
275 pub fn right(source: FromItem, on: Conditions) -> Self {
276 Self {
277 source,
278 condition: Some(JoinCondition::On(on)),
279 join_type: JoinType::Right,
280 natural: false,
281 }
282 }
283
284 pub fn full(source: FromItem, on: Conditions) -> Self {
285 Self {
286 source,
287 condition: Some(JoinCondition::On(on)),
288 join_type: JoinType::Full,
289 natural: false,
290 }
291 }
292
293 pub fn cross(source: FromItem) -> Self {
294 Self {
295 source,
296 condition: None,
297 join_type: JoinType::Cross,
298 natural: false,
299 }
300 }
301
302 pub fn using(join_type: JoinType, source: FromItem, columns: Vec<String>) -> Self {
303 Self {
304 source,
305 condition: Some(JoinCondition::Using(columns)),
306 join_type,
307 natural: false,
308 }
309 }
310
311 pub fn natural(mut self) -> Self {
312 self.natural = true;
313 self
314 }
315}
316
317#[derive(Debug, Clone)]
319pub enum JoinCondition {
320 On(Conditions),
322 Using(Vec<String>),
324}
325
326#[derive(Debug, Clone, Copy, PartialEq, Eq)]
328pub enum JoinType {
329 Inner,
330 Left,
331 Right,
332 Full,
333 Cross,
334 CrossApply,
336 OuterApply,
338}
339
340#[derive(Debug, Clone)]
346pub struct SubQueryDef {
347 pub query: Box<QueryStmt>,
348 pub alias: String,
349}
350
351#[derive(Debug, Clone)]
357pub struct SetOpDef {
358 pub left: Box<QueryStmt>,
359 pub right: Box<QueryStmt>,
360 pub operation: SetOperationType,
361}
362
363impl SetOpDef {
364 pub fn union(left: QueryStmt, right: QueryStmt) -> Self {
365 Self {
366 left: Box::new(left),
367 right: Box::new(right),
368 operation: SetOperationType::Union,
369 }
370 }
371
372 pub fn union_all(left: QueryStmt, right: QueryStmt) -> Self {
373 Self {
374 left: Box::new(left),
375 right: Box::new(right),
376 operation: SetOperationType::UnionAll,
377 }
378 }
379
380 pub fn intersect(left: QueryStmt, right: QueryStmt) -> Self {
381 Self {
382 left: Box::new(left),
383 right: Box::new(right),
384 operation: SetOperationType::Intersect,
385 }
386 }
387
388 pub fn except(left: QueryStmt, right: QueryStmt) -> Self {
389 Self {
390 left: Box::new(left),
391 right: Box::new(right),
392 operation: SetOperationType::Except,
393 }
394 }
395}
396
397#[derive(Debug, Clone, Copy, PartialEq, Eq)]
399pub enum SetOperationType {
400 Union,
401 UnionAll,
402 Intersect,
403 IntersectAll,
404 Except,
405 ExceptAll,
406}
407
408#[derive(Debug, Clone)]
414pub enum GroupByItem {
415 Expr(Expr),
417 Rollup(Vec<Expr>),
419 Cube(Vec<Expr>),
421 GroupingSets(Vec<Vec<Expr>>),
423}
424
425#[derive(Debug, Clone)]
431pub struct WindowNameDef {
432 pub name: String,
433 pub base_window: Option<String>,
435 pub partition_by: Option<Vec<Expr>>,
436 pub order_by: Option<Vec<OrderByDef>>,
437 pub frame: Option<super::expr::WindowFrameDef>,
438}
439
440#[derive(Debug, Clone)]
446pub struct LimitDef {
447 pub kind: LimitKind,
448 pub offset: Option<u64>,
449}
450
451impl LimitDef {
452 pub fn limit(count: u64) -> Self {
453 Self {
454 kind: LimitKind::Limit(count),
455 offset: None,
456 }
457 }
458
459 pub fn limit_offset(count: u64, offset: u64) -> Self {
460 Self {
461 kind: LimitKind::Limit(count),
462 offset: Some(offset),
463 }
464 }
465
466 pub fn fetch_first(count: u64) -> Self {
467 Self {
468 kind: LimitKind::FetchFirst {
469 count,
470 with_ties: false,
471 percent: false,
472 },
473 offset: None,
474 }
475 }
476
477 pub fn fetch_first_with_ties(count: u64) -> Self {
478 Self {
479 kind: LimitKind::FetchFirst {
480 count,
481 with_ties: true,
482 percent: false,
483 },
484 offset: None,
485 }
486 }
487
488 pub fn top(count: u64) -> Self {
489 Self {
490 kind: LimitKind::Top {
491 count,
492 with_ties: false,
493 percent: false,
494 },
495 offset: None,
496 }
497 }
498
499 pub fn offset(mut self, offset: u64) -> Self {
500 self.offset = Some(offset);
501 self
502 }
503}
504
505#[derive(Debug, Clone)]
507pub enum LimitKind {
508 Limit(u64),
510 FetchFirst {
512 count: u64,
513 with_ties: bool,
514 percent: bool,
516 },
517 Top {
519 count: u64,
520 with_ties: bool,
521 percent: bool,
522 },
523}
524
525#[derive(Debug, Clone)]
531pub struct CteDef {
532 pub name: String,
533 pub query: Box<QueryStmt>,
534 pub recursive: bool,
535 pub column_names: Option<Vec<String>>,
537 pub materialized: Option<CteMaterialized>,
539}
540
541impl CteDef {
542 pub fn new(name: impl Into<String>, query: QueryStmt) -> Self {
543 Self {
544 name: name.into(),
545 query: Box::new(query),
546 recursive: false,
547 column_names: None,
548 materialized: None,
549 }
550 }
551
552 pub fn recursive(name: impl Into<String>, query: QueryStmt) -> Self {
553 Self {
554 name: name.into(),
555 query: Box::new(query),
556 recursive: true,
557 column_names: None,
558 materialized: None,
559 }
560 }
561
562 pub fn columns(mut self, cols: Vec<&str>) -> Self {
563 self.column_names = Some(cols.into_iter().map(String::from).collect());
564 self
565 }
566
567 pub fn materialized(mut self) -> Self {
568 self.materialized = Some(CteMaterialized::Materialized);
569 self
570 }
571
572 pub fn not_materialized(mut self) -> Self {
573 self.materialized = Some(CteMaterialized::NotMaterialized);
574 self
575 }
576}
577
578#[derive(Debug, Clone, Copy, PartialEq, Eq)]
580pub enum CteMaterialized {
581 Materialized,
582 NotMaterialized,
583}
584
585#[derive(Debug, Clone)]
591pub struct SelectLockDef {
592 pub strength: LockStrength,
593 pub of: Option<Vec<SchemaRef>>,
594 pub nowait: bool,
595 pub skip_locked: bool,
596 pub wait: Option<u64>,
598}
599
600#[derive(Debug, Clone, Copy, PartialEq, Eq)]
602pub enum LockStrength {
603 Update,
604 NoKeyUpdate,
606 Share,
607 KeyShare,
609}