1use crate::{
6 expr::{Condition, ConditionHolder, IntoCondition, SimpleExpr},
7 types::{
8 ColumnRef, DynIden, IntoColumnRef, IntoIden, IntoTableRef, JoinExpr, JoinType, Order,
9 OrderExpr, TableRef, WindowStatement,
10 },
11 value::{IntoValue, Value, Values},
12};
13
14use super::traits::{QueryBuilderTrait, QueryStatementBuilder, QueryStatementWriter};
15
16#[derive(Debug, Clone, Default)]
34pub struct SelectStatement {
35 pub(crate) raw_sql: Option<String>,
36 pub(crate) ctes: Vec<CommonTableExpr>,
37 pub(crate) distinct: Option<SelectDistinct>,
38 pub(crate) selects: Vec<SelectExpr>,
39 pub(crate) from: Vec<TableRef>,
40 pub(crate) join: Vec<JoinExpr>,
41 pub(crate) r#where: ConditionHolder,
42 pub(crate) groups: Vec<SimpleExpr>,
43 pub(crate) having: ConditionHolder,
44 pub(crate) unions: Vec<(UnionType, SelectStatement)>,
45 pub(crate) orders: Vec<OrderExpr>,
46 pub(crate) limit: Option<Value>,
47 pub(crate) offset: Option<Value>,
48 pub(crate) lock: Option<LockClause>,
49 pub(crate) windows: Vec<(DynIden, WindowStatement)>,
50}
51
52#[derive(Debug, Clone)]
56pub struct CommonTableExpr {
57 pub(crate) name: DynIden,
59 pub(crate) query: Box<SelectStatement>,
61 pub(crate) recursive: bool,
63}
64
65#[derive(Debug, Clone)]
67#[non_exhaustive]
68pub enum SelectDistinct {
69 All,
71 Distinct,
73 DistinctRow,
75 DistinctOn(Vec<ColumnRef>),
77}
78
79#[derive(Debug, Clone)]
81pub struct SelectExpr {
82 pub expr: SimpleExpr,
84 pub alias: Option<DynIden>,
86}
87
88#[derive(Debug, Clone, Copy, PartialEq, Eq)]
90#[non_exhaustive]
91pub enum LockType {
92 Update,
94 NoKeyUpdate,
96 Share,
98 KeyShare,
100}
101
102#[derive(Debug, Clone, Copy, PartialEq, Eq)]
104#[non_exhaustive]
105pub enum LockBehavior {
106 Nowait,
108 SkipLocked,
110}
111
112#[allow(dead_code)]
115#[derive(Debug, Clone)]
116pub struct LockClause {
117 pub(crate) r#type: LockType,
118 pub(crate) tables: Vec<TableRef>,
119 pub(crate) behavior: Option<LockBehavior>,
120}
121
122#[derive(Debug, Clone, Copy, PartialEq, Eq)]
124#[non_exhaustive]
125pub enum UnionType {
126 Intersect,
128 Distinct,
130 Except,
132 All,
134}
135
136impl<T> From<T> for SelectExpr
137where
138 T: Into<SimpleExpr>,
139{
140 fn from(expr: T) -> Self {
141 SelectExpr {
142 expr: expr.into(),
143 alias: None,
144 }
145 }
146}
147
148impl SelectStatement {
149 pub fn new() -> Self {
151 Self::default()
152 }
153
154 pub fn raw(sql: impl Into<String>) -> Self {
156 Self {
157 raw_sql: Some(sql.into()),
158 ..Self::default()
159 }
160 }
161
162 pub fn take(&mut self) -> Self {
164 Self {
165 raw_sql: self.raw_sql.take(),
166 ctes: std::mem::take(&mut self.ctes),
167 distinct: self.distinct.take(),
168 selects: std::mem::take(&mut self.selects),
169 from: std::mem::take(&mut self.from),
170 join: std::mem::take(&mut self.join),
171 r#where: std::mem::replace(&mut self.r#where, ConditionHolder::new()),
172 groups: std::mem::take(&mut self.groups),
173 having: std::mem::replace(&mut self.having, ConditionHolder::new()),
174 unions: std::mem::take(&mut self.unions),
175 orders: std::mem::take(&mut self.orders),
176 limit: self.limit.take(),
177 offset: self.offset.take(),
178 lock: self.lock.take(),
179 windows: std::mem::take(&mut self.windows),
180 }
181 }
182
183 pub fn clear_from(&mut self) -> &mut Self {
185 self.from.clear();
186 self
187 }
188
189 pub fn column<C>(&mut self, col: C) -> &mut Self
204 where
205 C: IntoColumnRef,
206 {
207 self.selects.push(SelectExpr {
208 expr: SimpleExpr::Column(col.into_column_ref()),
209 alias: None,
210 });
211 self
212 }
213
214 pub fn columns<I, C>(&mut self, cols: I) -> &mut Self
226 where
227 I: IntoIterator<Item = C>,
228 C: IntoColumnRef,
229 {
230 for col in cols {
231 self.column(col);
232 }
233 self
234 }
235
236 pub fn expr<E>(&mut self, expr: E) -> &mut Self
248 where
249 E: Into<SimpleExpr>,
250 {
251 self.selects.push(SelectExpr {
252 expr: expr.into(),
253 alias: None,
254 });
255 self
256 }
257
258 pub fn expr_as<E, A>(&mut self, expr: E, alias: A) -> &mut Self
270 where
271 E: Into<SimpleExpr>,
272 A: IntoIden,
273 {
274 self.selects.push(SelectExpr {
275 expr: expr.into(),
276 alias: Some(alias.into_iden()),
277 });
278 self
279 }
280
281 pub fn from<T>(&mut self, tbl: T) -> &mut Self
295 where
296 T: IntoTableRef,
297 {
298 self.from.push(tbl.into_table_ref());
299 self
300 }
301
302 pub fn from_as<T, A>(&mut self, tbl: T, alias: A) -> &mut Self
306 where
307 T: IntoIden,
308 A: IntoIden,
309 {
310 self.from
311 .push(TableRef::TableAlias(tbl.into_iden(), alias.into_iden()));
312 self
313 }
314
315 pub fn from_subquery(&mut self, query: SelectStatement, alias: impl IntoIden) -> &mut Self {
319 self.from
320 .push(TableRef::SubQuery(Box::new(query), alias.into_iden()));
321 self
322 }
323
324 pub fn clear_selects(&mut self) -> &mut Self {
326 self.selects.clear();
327 self
328 }
329
330 pub fn join<T, C>(&mut self, join: JoinType, tbl: T, condition: C) -> &mut Self
348 where
349 T: IntoTableRef,
350 C: IntoCondition,
351 {
352 self.join.push(JoinExpr {
353 join,
354 table: tbl.into_table_ref(),
355 on: Some(crate::types::JoinOn::Condition(condition.into_condition())),
356 });
357 self
358 }
359
360 pub fn left_join<T, C>(&mut self, tbl: T, condition: C) -> &mut Self
375 where
376 T: IntoTableRef,
377 C: IntoCondition,
378 {
379 self.join(JoinType::LeftJoin, tbl, condition)
380 }
381
382 pub fn right_join<T, C>(&mut self, tbl: T, condition: C) -> &mut Self
384 where
385 T: IntoTableRef,
386 C: IntoCondition,
387 {
388 self.join(JoinType::RightJoin, tbl, condition)
389 }
390
391 pub fn full_outer_join<T, C>(&mut self, tbl: T, condition: C) -> &mut Self
393 where
394 T: IntoTableRef,
395 C: IntoCondition,
396 {
397 self.join(JoinType::FullOuterJoin, tbl, condition)
398 }
399
400 pub fn inner_join<T, C>(&mut self, tbl: T, condition: C) -> &mut Self
402 where
403 T: IntoTableRef,
404 C: IntoCondition,
405 {
406 self.join(JoinType::InnerJoin, tbl, condition)
407 }
408
409 pub fn cross_join<T>(&mut self, tbl: T) -> &mut Self
411 where
412 T: IntoTableRef,
413 {
414 self.join.push(JoinExpr {
415 join: JoinType::CrossJoin,
416 table: tbl.into_table_ref(),
417 on: None,
418 });
419 self
420 }
421
422 pub fn and_where<C>(&mut self, condition: C) -> &mut Self
436 where
437 C: IntoCondition,
438 {
439 self.r#where.add_and(condition);
440 self
441 }
442
443 pub fn cond_where(&mut self, condition: Condition) -> &mut Self {
445 self.r#where.add_and(condition);
446 self
447 }
448
449 pub fn group_by<C>(&mut self, col: C) -> &mut Self
465 where
466 C: IntoColumnRef,
467 {
468 self.groups.push(SimpleExpr::Column(col.into_column_ref()));
469 self
470 }
471
472 pub fn group_by_col<C>(&mut self, col: C) -> &mut Self
474 where
475 C: IntoColumnRef,
476 {
477 self.group_by(col)
478 }
479
480 pub fn group_by_columns<I, C>(&mut self, cols: I) -> &mut Self
482 where
483 I: IntoIterator<Item = C>,
484 C: IntoColumnRef,
485 {
486 for col in cols {
487 self.group_by(col);
488 }
489 self
490 }
491
492 pub fn and_having<C>(&mut self, condition: C) -> &mut Self
509 where
510 C: IntoCondition,
511 {
512 self.having.add_and(condition);
513 self
514 }
515
516 pub fn cond_having(&mut self, condition: Condition) -> &mut Self {
518 self.having.add_and(condition);
519 self
520 }
521
522 pub fn order_by<C>(&mut self, col: C, order: Order) -> &mut Self
537 where
538 C: IntoColumnRef,
539 {
540 use crate::types::OrderExprKind;
541 self.orders.push(OrderExpr {
542 expr: OrderExprKind::Expr(Box::new(SimpleExpr::Column(col.into_column_ref()))),
543 order,
544 nulls: None,
545 });
546 self
547 }
548
549 pub fn order_by_expr<E>(&mut self, expr: E, order: Order) -> &mut Self
551 where
552 E: Into<SimpleExpr>,
553 {
554 use crate::types::OrderExprKind;
555 self.orders.push(OrderExpr {
556 expr: OrderExprKind::Expr(Box::new(expr.into())),
557 order,
558 nulls: None,
559 });
560 self
561 }
562
563 pub fn limit<V>(&mut self, limit: V) -> &mut Self
577 where
578 V: IntoValue,
579 {
580 self.limit = Some(limit.into_value());
581 self
582 }
583
584 pub fn offset<V>(&mut self, offset: V) -> &mut Self
597 where
598 V: IntoValue,
599 {
600 self.offset = Some(offset.into_value());
601 self
602 }
603
604 pub fn distinct(&mut self) -> &mut Self {
619 self.distinct = Some(SelectDistinct::Distinct);
620 self
621 }
622
623 pub fn distinct_on<I, C>(&mut self, cols: I) -> &mut Self
625 where
626 I: IntoIterator<Item = C>,
627 C: IntoColumnRef,
628 {
629 let cols: Vec<ColumnRef> = cols.into_iter().map(|c| c.into_column_ref()).collect();
630 self.distinct = Some(SelectDistinct::DistinctOn(cols));
631 self
632 }
633
634 pub fn clear_distinct(&mut self) -> &mut Self {
636 self.distinct = None;
637 self
638 }
639
640 pub fn union(&mut self, query: SelectStatement) -> &mut Self {
644 self.unions.push((UnionType::Distinct, query));
645 self
646 }
647
648 pub fn union_all(&mut self, query: SelectStatement) -> &mut Self {
650 self.unions.push((UnionType::All, query));
651 self
652 }
653
654 pub fn intersect(&mut self, query: SelectStatement) -> &mut Self {
656 self.unions.push((UnionType::Intersect, query));
657 self
658 }
659
660 pub fn except(&mut self, query: SelectStatement) -> &mut Self {
662 self.unions.push((UnionType::Except, query));
663 self
664 }
665
666 pub fn with_cte<N>(&mut self, name: N, query: SelectStatement) -> &mut Self
687 where
688 N: IntoIden,
689 {
690 self.ctes.push(CommonTableExpr {
691 name: name.into_iden(),
692 query: Box::new(query),
693 recursive: false,
694 });
695 self
696 }
697
698 pub fn with_recursive_cte<N>(&mut self, name: N, query: SelectStatement) -> &mut Self
731 where
732 N: IntoIden,
733 {
734 self.ctes.push(CommonTableExpr {
735 name: name.into_iden(),
736 query: Box::new(query),
737 recursive: true,
738 });
739 self
740 }
741
742 pub fn window_as<T>(&mut self, name: T, window: WindowStatement) -> &mut Self
771 where
772 T: IntoIden,
773 {
774 self.windows.push((name.into_iden(), window));
775 self
776 }
777
778 pub fn lock(&mut self, lock_type: LockType) -> &mut Self {
782 self.lock = Some(LockClause {
783 r#type: lock_type,
784 tables: Vec::new(),
785 behavior: None,
786 });
787 self
788 }
789
790 pub fn lock_exclusive(&mut self) -> &mut Self {
792 self.lock(LockType::Update)
793 }
794
795 pub fn lock_shared(&mut self) -> &mut Self {
797 self.lock(LockType::Share)
798 }
799
800 pub fn apply_if<T, F>(&mut self, val: Option<T>, func: F) -> &mut Self
804 where
805 F: FnOnce(&mut Self, T),
806 {
807 if let Some(val) = val {
808 func(self, val);
809 }
810 self
811 }
812
813 pub fn conditions<T, F>(&mut self, b: bool, if_true: T, if_false: F) -> &mut Self
815 where
816 T: FnOnce(&mut Self),
817 F: FnOnce(&mut Self),
818 {
819 if b {
820 if_true(self)
821 } else {
822 if_false(self)
823 }
824 self
825 }
826}
827
828impl QueryStatementBuilder for SelectStatement {
829 fn build_any(&self, query_builder: &dyn QueryBuilderTrait) -> (String, Values) {
830 use crate::backend::{
831 MySqlQueryBuilder, PostgresQueryBuilder, QueryBuilder, SqliteQueryBuilder,
832 };
833 use std::any::Any;
834
835 let any_builder = query_builder as &dyn Any;
836
837 if let Some(pg) = any_builder.downcast_ref::<PostgresQueryBuilder>() {
838 return pg.build_select(self);
839 }
840
841 if let Some(mysql) = any_builder.downcast_ref::<MySqlQueryBuilder>() {
842 return mysql.build_select(self);
843 }
844
845 if let Some(sqlite) = any_builder.downcast_ref::<SqliteQueryBuilder>() {
846 return sqlite.build_select(self);
847 }
848
849 panic!(
850 "Unsupported query builder type. Use PostgresQueryBuilder, MySqlQueryBuilder, or SqliteQueryBuilder."
851 );
852 }
853}
854
855impl QueryStatementWriter for SelectStatement {}