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 pub set_op: Option<Box<SetOpDef>>,
30}
31
32#[derive(Debug, Clone)]
38pub enum SelectColumn {
39 Star(Option<String>),
41
42 Expr { expr: Expr, alias: Option<String> },
44
45 Field {
47 field: FieldRef,
48 alias: Option<String>,
49 },
50}
51
52impl SelectColumn {
53 pub fn all() -> Self {
55 SelectColumn::Star(None)
56 }
57
58 pub fn all_from(table: impl Into<String>) -> Self {
60 SelectColumn::Star(Some(table.into()))
61 }
62
63 pub fn field(table: &str, name: &str) -> Self {
65 SelectColumn::Field {
66 field: FieldRef::new(table, name),
67 alias: None,
68 }
69 }
70
71 pub fn expr(expr: Expr) -> Self {
73 SelectColumn::Expr { expr, alias: None }
74 }
75
76 pub fn aliased(expr: Expr, alias: impl Into<String>) -> Self {
78 SelectColumn::Expr {
79 expr,
80 alias: Some(alias.into()),
81 }
82 }
83
84 pub fn field_aliased(table: &str, name: &str, alias: impl Into<String>) -> Self {
86 SelectColumn::Field {
87 field: FieldRef::new(table, name),
88 alias: Some(alias.into()),
89 }
90 }
91}
92
93#[derive(Debug, Clone)]
99pub enum DistinctDef {
100 Distinct,
102 DistinctOn(Vec<Expr>),
104}
105
106#[derive(Debug, Clone)]
112pub struct FromItem {
113 pub source: TableSource,
114 pub only: bool,
116 pub sample: Option<TableSampleDef>,
118 pub index_hint: Option<SqliteIndexHint>,
120}
121
122impl FromItem {
123 pub fn table(schema_ref: SchemaRef) -> Self {
124 Self {
125 source: TableSource::Table(schema_ref),
126 only: false,
127 sample: None,
128 index_hint: None,
129 }
130 }
131
132 pub fn lateral(inner: FromItem) -> Self {
133 Self {
134 source: TableSource::Lateral(Box::new(inner)),
135 only: false,
136 sample: None,
137 index_hint: None,
138 }
139 }
140
141 pub fn function(name: impl Into<String>, args: Vec<Expr>, alias: impl Into<String>) -> Self {
142 Self {
143 source: TableSource::Function {
144 name: name.into(),
145 args,
146 alias: Some(alias.into()),
147 },
148 only: false,
149 sample: None,
150 index_hint: None,
151 }
152 }
153
154 pub fn values(rows: Vec<Vec<Expr>>, alias: impl Into<String>) -> Self {
155 Self {
156 source: TableSource::Values {
157 rows,
158 alias: alias.into(),
159 column_aliases: None,
160 },
161 only: false,
162 sample: None,
163 index_hint: None,
164 }
165 }
166
167 pub fn subquery(query: QueryStmt, alias: String) -> Self {
168 Self {
169 source: TableSource::SubQuery(SubQueryDef {
170 query: Box::new(query),
171 alias,
172 }),
173 only: false,
174 sample: None,
175 index_hint: None,
176 }
177 }
178}
179
180#[derive(Debug, Clone)]
182pub enum TableSource {
183 Table(SchemaRef),
185 SubQuery(SubQueryDef),
187 SetOp(Box<SetOpDef>),
189 Lateral(Box<FromItem>),
191 Function {
193 name: String,
194 args: Vec<Expr>,
195 alias: Option<String>,
196 },
197 Values {
199 rows: Vec<Vec<Expr>>,
200 alias: String,
201 column_aliases: Option<Vec<String>>,
202 },
203 Custom(Box<dyn CustomTableSource>),
205}
206
207#[derive(Debug, Clone)]
213pub struct TableSampleDef {
214 pub method: SampleMethod,
216 pub percentage: f64,
218 pub seed: Option<i64>,
220}
221
222#[derive(Debug, Clone, Copy, PartialEq, Eq)]
224pub enum SampleMethod {
225 Bernoulli,
227 System,
229 Block,
231}
232
233#[derive(Debug, Clone)]
239pub enum SqliteIndexHint {
240 IndexedBy(String),
242 NotIndexed,
244}
245
246#[derive(Debug, Clone)]
252pub struct JoinDef {
253 pub source: FromItem,
254 pub condition: Option<JoinCondition>,
255 pub join_type: JoinType,
256 pub natural: bool,
257}
258
259impl JoinDef {
260 pub fn inner(source: FromItem, on: Conditions) -> Self {
261 Self {
262 source,
263 condition: Some(JoinCondition::On(on)),
264 join_type: JoinType::Inner,
265 natural: false,
266 }
267 }
268
269 pub fn left(source: FromItem, on: Conditions) -> Self {
270 Self {
271 source,
272 condition: Some(JoinCondition::On(on)),
273 join_type: JoinType::Left,
274 natural: false,
275 }
276 }
277
278 pub fn right(source: FromItem, on: Conditions) -> Self {
279 Self {
280 source,
281 condition: Some(JoinCondition::On(on)),
282 join_type: JoinType::Right,
283 natural: false,
284 }
285 }
286
287 pub fn full(source: FromItem, on: Conditions) -> Self {
288 Self {
289 source,
290 condition: Some(JoinCondition::On(on)),
291 join_type: JoinType::Full,
292 natural: false,
293 }
294 }
295
296 pub fn cross(source: FromItem) -> Self {
297 Self {
298 source,
299 condition: None,
300 join_type: JoinType::Cross,
301 natural: false,
302 }
303 }
304
305 pub fn using(join_type: JoinType, source: FromItem, columns: Vec<String>) -> Self {
306 Self {
307 source,
308 condition: Some(JoinCondition::Using(columns)),
309 join_type,
310 natural: false,
311 }
312 }
313
314 pub fn natural(mut self) -> Self {
315 self.natural = true;
316 self
317 }
318}
319
320#[derive(Debug, Clone)]
322pub enum JoinCondition {
323 On(Conditions),
325 Using(Vec<String>),
327}
328
329#[derive(Debug, Clone, Copy, PartialEq, Eq)]
331pub enum JoinType {
332 Inner,
333 Left,
334 Right,
335 Full,
336 Cross,
337 CrossApply,
339 OuterApply,
341}
342
343#[derive(Debug, Clone)]
349pub struct SubQueryDef {
350 pub query: Box<QueryStmt>,
351 pub alias: String,
352}
353
354#[derive(Debug, Clone)]
360pub struct SetOpDef {
361 pub left: Box<QueryStmt>,
362 pub right: Box<QueryStmt>,
363 pub operation: SetOperationType,
364}
365
366impl SetOpDef {
367 pub fn union(left: QueryStmt, right: QueryStmt) -> Self {
368 Self {
369 left: Box::new(left),
370 right: Box::new(right),
371 operation: SetOperationType::Union,
372 }
373 }
374
375 pub fn union_all(left: QueryStmt, right: QueryStmt) -> Self {
376 Self {
377 left: Box::new(left),
378 right: Box::new(right),
379 operation: SetOperationType::UnionAll,
380 }
381 }
382
383 pub fn intersect(left: QueryStmt, right: QueryStmt) -> Self {
384 Self {
385 left: Box::new(left),
386 right: Box::new(right),
387 operation: SetOperationType::Intersect,
388 }
389 }
390
391 pub fn except(left: QueryStmt, right: QueryStmt) -> Self {
392 Self {
393 left: Box::new(left),
394 right: Box::new(right),
395 operation: SetOperationType::Except,
396 }
397 }
398}
399
400#[derive(Debug, Clone, Copy, PartialEq, Eq)]
402pub enum SetOperationType {
403 Union,
404 UnionAll,
405 Intersect,
406 IntersectAll,
407 Except,
408 ExceptAll,
409}
410
411#[derive(Debug, Clone)]
417pub enum GroupByItem {
418 Expr(Expr),
420 Rollup(Vec<Expr>),
422 Cube(Vec<Expr>),
424 GroupingSets(Vec<Vec<Expr>>),
426}
427
428#[derive(Debug, Clone)]
434pub struct WindowNameDef {
435 pub name: String,
436 pub base_window: Option<String>,
438 pub partition_by: Option<Vec<Expr>>,
439 pub order_by: Option<Vec<OrderByDef>>,
440 pub frame: Option<super::expr::WindowFrameDef>,
441}
442
443#[derive(Debug, Clone)]
449pub struct LimitDef {
450 pub kind: LimitKind,
451 pub offset: Option<u64>,
452}
453
454impl LimitDef {
455 pub fn limit(count: u64) -> Self {
456 Self {
457 kind: LimitKind::Limit(count),
458 offset: None,
459 }
460 }
461
462 pub fn limit_offset(count: u64, offset: u64) -> Self {
463 Self {
464 kind: LimitKind::Limit(count),
465 offset: Some(offset),
466 }
467 }
468
469 pub fn fetch_first(count: u64) -> Self {
470 Self {
471 kind: LimitKind::FetchFirst {
472 count,
473 with_ties: false,
474 percent: false,
475 },
476 offset: None,
477 }
478 }
479
480 pub fn fetch_first_with_ties(count: u64) -> Self {
481 Self {
482 kind: LimitKind::FetchFirst {
483 count,
484 with_ties: true,
485 percent: false,
486 },
487 offset: None,
488 }
489 }
490
491 pub fn top(count: u64) -> Self {
492 Self {
493 kind: LimitKind::Top {
494 count,
495 with_ties: false,
496 percent: false,
497 },
498 offset: None,
499 }
500 }
501
502 pub fn offset(mut self, offset: u64) -> Self {
503 self.offset = Some(offset);
504 self
505 }
506}
507
508#[derive(Debug, Clone)]
510pub enum LimitKind {
511 Limit(u64),
513 FetchFirst {
515 count: u64,
516 with_ties: bool,
517 percent: bool,
519 },
520 Top {
522 count: u64,
523 with_ties: bool,
524 percent: bool,
525 },
526}
527
528#[derive(Debug, Clone)]
534pub struct CteDef {
535 pub name: String,
536 pub query: Box<QueryStmt>,
537 pub recursive: bool,
538 pub column_names: Option<Vec<String>>,
540 pub materialized: Option<CteMaterialized>,
542}
543
544impl CteDef {
545 pub fn new(name: impl Into<String>, query: QueryStmt) -> Self {
546 Self {
547 name: name.into(),
548 query: Box::new(query),
549 recursive: false,
550 column_names: None,
551 materialized: None,
552 }
553 }
554
555 pub fn recursive(name: impl Into<String>, query: QueryStmt) -> Self {
556 Self {
557 name: name.into(),
558 query: Box::new(query),
559 recursive: true,
560 column_names: None,
561 materialized: None,
562 }
563 }
564
565 pub fn columns(mut self, cols: Vec<&str>) -> Self {
566 self.column_names = Some(cols.into_iter().map(String::from).collect());
567 self
568 }
569
570 pub fn materialized(mut self) -> Self {
571 self.materialized = Some(CteMaterialized::Materialized);
572 self
573 }
574
575 pub fn not_materialized(mut self) -> Self {
576 self.materialized = Some(CteMaterialized::NotMaterialized);
577 self
578 }
579}
580
581#[derive(Debug, Clone, Copy, PartialEq, Eq)]
583pub enum CteMaterialized {
584 Materialized,
585 NotMaterialized,
586}
587
588#[derive(Debug, Clone)]
594pub struct SelectLockDef {
595 pub strength: LockStrength,
596 pub of: Option<Vec<SchemaRef>>,
597 pub nowait: bool,
598 pub skip_locked: bool,
599 pub wait: Option<u64>,
601}
602
603#[derive(Debug, Clone, Copy, PartialEq, Eq)]
605pub enum LockStrength {
606 Update,
607 NoKeyUpdate,
609 Share,
610 KeyShare,
612}