1use std::marker::PhantomData;
6
7use crate::cte::Cte;
8use crate::dialect::{Dialect, SupportsFullOuterJoin, SupportsRightJoin};
9use crate::expr::{BoolLike, Comparable, Expr, ExprKind, IntoExpr, Value};
10use crate::render::{
11 Fragment, FragmentSink, QuerySink, SelectItem, Sink, render_and_list, render_expr,
12 render_expr_list, render_order_by, render_select_list,
13};
14use crate::row::{Field as RowFieldLookup, LookupKey, Row};
15use crate::scope::{
16 BaseTable, Concat, Cons, MapNullable, MaybeNull, Nil, NotNull, Position, ScopeTables, Superset,
17 Table, TableSlot,
18};
19
20mod dyn_select;
21mod prepared;
22mod selection;
23mod set_op;
24
25pub use crate::expr::SortDir;
26pub use dyn_select::{CannotFilterAfterErase, DynSelect};
27pub use prepared::{Prepared, PreparedParams, Total, UnresolvedPlaceholder};
28pub use selection::{
29 All, AllColumns, ColumnList, RowField, SelectableSealed, Selection, SelectionPart, SingleColumn,
30};
31pub use set_op::SetOp;
32
33#[doc(hidden)]
38#[derive(Debug, Clone)]
39pub struct CteDef {
40 name: &'static str,
41 column_names: Vec<&'static str>,
42 body: Fragment,
43}
44
45impl CteDef {
46 pub(crate) fn new(name: &'static str, column_names: Vec<&'static str>, body: Fragment) -> Self {
47 CteDef {
48 name,
49 column_names,
50 body,
51 }
52 }
53}
54
55#[derive(Debug, Clone)]
56enum JoinKind {
57 Inner,
58 Left,
59 Right,
60 Full,
61}
62
63#[derive(Debug, Clone)]
64struct JoinClause {
65 kind: JoinKind,
66 table: &'static str,
67 on: ExprKind,
68}
69
70pub struct OrderKey<Req> {
74 kind: ExprKind,
75 dir: SortDir,
76 _marker: PhantomData<fn() -> Req>,
77}
78
79impl<Req> Clone for OrderKey<Req> {
82 fn clone(&self) -> Self {
83 OrderKey {
84 kind: self.kind.clone(),
85 dir: self.dir,
86 _marker: PhantomData,
87 }
88 }
89}
90
91impl<Req> OrderKey<Req> {
92 pub(crate) fn into_parts(self) -> (ExprKind, SortDir) {
93 (self.kind, self.dir)
94 }
95}
96
97pub trait OrderExt: IntoExpr + Sized {
98 fn asc(self) -> OrderKey<Self::Req> {
99 OrderKey {
100 kind: self.into_expr().kind,
101 dir: SortDir::Asc,
102 _marker: PhantomData,
103 }
104 }
105 fn sort(self, dir: SortDir) -> OrderKey<Self::Req> {
108 OrderKey {
109 kind: self.into_expr().kind,
110 dir,
111 _marker: PhantomData,
112 }
113 }
114 fn desc(self) -> OrderKey<Self::Req> {
115 OrderKey {
116 kind: self.into_expr().kind,
117 dir: SortDir::Desc,
118 _marker: PhantomData,
119 }
120 }
121}
122impl<T: IntoExpr> OrderExt for T {}
123
124pub trait JoinSource<D>: join_source::Sealed {
129 type Table: Table;
131 #[doc(hidden)]
134 fn binding(self) -> Option<CteDef>;
135}
136
137mod join_source {
138 pub trait Sealed {}
141 impl<T: super::BaseTable> Sealed for T {}
142 impl<D, Marker> Sealed for crate::cte::Cte<D, Marker> {}
143}
144
145impl<D, T: BaseTable> JoinSource<D> for T {
146 type Table = T;
147 fn binding(self) -> Option<CteDef> {
148 None
149 }
150}
151
152impl<D, Marker: crate::cte::CteShape> JoinSource<D> for Cte<D, Marker> {
153 type Table = Marker;
154 fn binding(self) -> Option<CteDef> {
155 Some(CteDef::new(
156 <Marker as Table>::NAME,
157 <Marker::Row as crate::row::ColumnNames>::names(),
158 self.into_body(),
159 ))
160 }
161}
162
163#[diagnostic::on_unimplemented(
167 message = "`{Self}` isn't a sort key",
168 label = "a column or expression with `.asc()`/`.desc()`/`.sort(dir)` on it, or a `sort_key(..)`",
169 note = "a `SortKey` also has to have been discharged against *this* scope — a scope lists its tables most-recently-joined first, so two that look alike can still differ in order"
170)]
171pub trait SortBy<Scope, Idxs> {
172 #[doc(hidden)]
173 fn into_sort_key(self) -> SortKey<Scope>;
174}
175
176impl<Scope: Superset<Req, Idxs>, Req, Idxs> SortBy<Scope, Idxs> for OrderKey<Req> {
177 fn into_sort_key(self) -> SortKey<Scope> {
178 SortKey {
179 kind: self.kind,
180 dir: self.dir,
181 _marker: PhantomData,
182 }
183 }
184}
185
186impl<Scope> SortBy<Scope, ()> for SortKey<Scope> {
187 fn into_sort_key(self) -> SortKey<Scope> {
188 self
189 }
190}
191
192#[diagnostic::on_unimplemented(
195 message = "`{Self}` isn't a grouping key",
196 label = "a column or expression, or a `grouping(..)`",
197 note = "a `Grouping` also has to have been discharged against *this* scope — a scope lists its tables most-recently-joined first, so two that look alike can still differ in order"
198)]
199pub trait GroupBy<Scope, Idxs> {
200 #[doc(hidden)]
201 fn into_grouping(self) -> Grouping<Scope>;
202}
203
204impl<Scope: Superset<Req, Idxs>, Req, Idxs, T: IntoExpr<Req = Req>> GroupBy<Scope, Idxs> for T {
205 fn into_grouping(self) -> Grouping<Scope> {
206 Grouping {
207 kind: self.into_expr().kind,
208 _marker: PhantomData,
209 }
210 }
211}
212
213impl<Scope> GroupBy<Scope, ()> for Grouping<Scope> {
214 fn into_grouping(self) -> Grouping<Scope> {
215 self
216 }
217}
218
219pub struct SortKey<Scope> {
224 kind: ExprKind,
225 dir: SortDir,
226 _marker: PhantomData<fn() -> Scope>,
227}
228
229impl<Scope> Clone for SortKey<Scope> {
230 fn clone(&self) -> Self {
231 SortKey {
232 kind: self.kind.clone(),
233 dir: self.dir,
234 _marker: PhantomData,
235 }
236 }
237}
238
239pub fn sort_key<Scope, Idxs, K: SortBy<Scope, Idxs>>(key: K) -> SortKey<Scope> {
244 key.into_sort_key()
245}
246
247pub struct Grouping<Scope> {
250 kind: ExprKind,
251 _marker: PhantomData<fn() -> Scope>,
252}
253
254impl<Scope> Clone for Grouping<Scope> {
255 fn clone(&self) -> Self {
256 Grouping {
257 kind: self.kind.clone(),
258 _marker: PhantomData,
259 }
260 }
261}
262
263pub fn grouping<Scope, Idxs, K: GroupBy<Scope, Idxs>>(key: K) -> Grouping<Scope> {
266 key.into_grouping()
267}
268
269#[diagnostic::on_unimplemented(
274 message = "`{Self}` isn't a condition",
275 label = "a comparison (`.eq(..)`, `.gt(..)`, `.is_null()`), an `any_of`/`all_of` of them, a `sql!` fragment of type `Bool`, a `predicate(..)`, or an `EXISTS`/`.contains(..)` of a subquery in *this* dialect",
276 note = "a `Predicate` also has to have been discharged against *this* scope — a scope lists its tables most-recently-joined first, so two that look alike can still differ in order"
277)]
278pub trait Condition<D, Scope, Idxs> {
279 #[doc(hidden)]
282 fn into_predicate(self) -> Predicate<D, Scope>;
283}
284
285impl<D, Scope: Superset<Req, Idxs>, Req, Idxs, T: IntoExpr<Req = Req>> Condition<D, Scope, Idxs>
286 for T
287where
288 T::Sql: BoolLike,
289{
290 fn into_predicate(self) -> Predicate<D, Scope> {
291 Predicate {
292 kind: self.into_expr().kind,
293 _marker: PhantomData,
294 }
295 }
296}
297
298impl<D, Scope> Condition<D, Scope, ()> for Predicate<D, Scope> {
299 fn into_predicate(self) -> Predicate<D, Scope> {
300 self
301 }
302}
303
304pub struct Exists<D, Req> {
313 kind: ExprKind,
314 _marker: PhantomData<fn() -> (D, Req)>,
315}
316
317impl<D, Req> Clone for Exists<D, Req> {
320 fn clone(&self) -> Self {
321 Exists {
322 kind: self.kind.clone(),
323 _marker: PhantomData,
324 }
325 }
326}
327
328impl<D, Scope: Superset<Req, Idxs>, Req, Idxs> Condition<D, Scope, Idxs> for Exists<D, Req> {
329 fn into_predicate(self) -> Predicate<D, Scope> {
330 Predicate {
331 kind: self.kind,
332 _marker: PhantomData,
333 }
334 }
335}
336
337pub struct InSubquery<D, Req> {
342 kind: ExprKind,
343 _marker: PhantomData<fn() -> (D, Req)>,
344}
345
346impl<D, Req> Clone for InSubquery<D, Req> {
347 fn clone(&self) -> Self {
348 InSubquery {
349 kind: self.kind.clone(),
350 _marker: PhantomData,
351 }
352 }
353}
354
355impl<D, Scope: Superset<Req, Idxs>, Req, Idxs> Condition<D, Scope, Idxs> for InSubquery<D, Req> {
356 fn into_predicate(self) -> Predicate<D, Scope> {
357 Predicate {
358 kind: self.kind,
359 _marker: PhantomData,
360 }
361 }
362}
363
364pub struct Predicate<D, Scope> {
370 kind: ExprKind,
371 _marker: PhantomData<fn() -> (D, Scope)>,
372}
373
374impl<D, Scope> Clone for Predicate<D, Scope> {
377 fn clone(&self) -> Self {
378 Predicate {
379 kind: self.kind.clone(),
380 _marker: PhantomData,
381 }
382 }
383}
384
385impl<D, Scope> Predicate<D, Scope> {
386 pub fn any_of(preds: impl IntoIterator<Item = Predicate<D, Scope>>) -> Self {
391 Predicate::combine(preds, false)
392 }
393
394 pub fn all_of(preds: impl IntoIterator<Item = Predicate<D, Scope>>) -> Self {
397 Predicate::combine(preds, true)
398 }
399
400 fn combine(preds: impl IntoIterator<Item = Predicate<D, Scope>>, all: bool) -> Self {
401 Predicate {
402 kind: crate::expr::fold_conditions(preds.into_iter().map(Predicate::into_kind), all),
403 _marker: PhantomData,
404 }
405 }
406
407 pub(crate) fn into_kind(self) -> ExprKind {
408 self.kind
409 }
410}
411
412pub fn predicate<D, Scope, Idxs, C: Condition<D, Scope, Idxs>>(cond: C) -> Predicate<D, Scope> {
416 cond.into_predicate()
417}
418
419pub struct SelectSeed<Sel> {
426 selection: Sel,
427}
428
429pub fn select<Sel>(selection: Sel) -> SelectSeed<Sel> {
430 SelectSeed { selection }
431}
432
433impl<Sel> SelectSeed<Sel> {
434 pub fn to_sql<D: Dialect, Idx>(&self, _dialect: D) -> (String, Vec<Value>)
452 where
453 Sel: Selection<Nil, Idx>,
454 {
455 let mut sink = QuerySink::<D>::new();
456 sink.text("SELECT ");
457 render_select_list::<D>(&self.selection.items(), &mut sink);
458 sink.finish()
459 }
460
461 pub fn from<D, S: JoinSource<D>>(
465 self,
466 source: S,
467 ) -> Select<D, Cons<TableSlot<S::Table, NotNull>, Nil>, Sel> {
468 let mut body = SelectBody::new(<S::Table as Table>::NAME);
469 body.bind(source);
470 Select {
471 body,
472 selection: self.selection,
473 _marker: PhantomData,
474 }
475 }
476}
477
478#[derive(Debug, Clone)]
483pub(crate) struct SelectBody {
484 ctes: Vec<CteDef>,
485 distinct: bool,
486 from_table: &'static str,
487 joins: Vec<JoinClause>,
488 wheres: Vec<ExprKind>,
489 order_by: Vec<(ExprKind, SortDir)>,
490 group_by: Vec<ExprKind>,
491 having: Vec<ExprKind>,
492 limit: Option<RowCount>,
493 offset: Option<RowCount>,
494}
495
496impl SelectBody {
497 fn new(from_table: &'static str) -> Self {
498 SelectBody {
499 ctes: Vec::new(),
500 distinct: false,
501 from_table,
502 joins: Vec::new(),
503 wheres: Vec::new(),
504 order_by: Vec::new(),
505 group_by: Vec::new(),
506 having: Vec::new(),
507 limit: None,
508 offset: None,
509 }
510 }
511
512 fn count_sql<D: Dialect>(&self, selection: &[SelectItem]) -> (String, Vec<Value>) {
522 let mut body = self.clone();
523 body.order_by.clear();
524 body.limit = None;
525 body.offset = None;
526 let one_row_each = body.group_by.is_empty()
527 && body.having.is_empty()
528 && !body.distinct
529 && selection
530 .iter()
531 .all(|item| matches!(item.kind, ExprKind::Column { .. }));
532
533 let mut sink = QuerySink::<D>::new();
534 if one_row_each {
535 body.render_into::<D>(&[crate::expr::count_item()], &mut sink);
536 return sink.finish();
537 }
538 crate::render::render_count_wrapped::<D>(&mut sink, |sink| {
539 body.render_into::<D>(selection, sink)
540 });
541 sink.finish()
542 }
543
544 fn bind<D, S: JoinSource<D>>(&mut self, source: S) {
547 self.ctes.extend(source.binding());
548 }
549}
550
551pub struct Select<D, Scope, Sel, Outer = Nil> {
556 body: SelectBody,
557 selection: Sel,
558 _marker: PhantomData<fn() -> (D, Scope, Outer)>,
559}
560
561impl<D, Scope, Sel: Clone, Outer> Clone for Select<D, Scope, Sel, Outer> {
563 fn clone(&self) -> Self {
564 Select {
565 body: self.body.clone(),
566 selection: self.selection.clone(),
567 _marker: PhantomData,
568 }
569 }
570}
571
572impl<D, Scope, Sel, Outer> Select<D, Scope, Sel, Outer> {
573 fn retype<NewScope>(self) -> Select<D, NewScope, Sel, Outer> {
574 Select {
575 body: self.body,
576 selection: self.selection,
577 _marker: PhantomData,
578 }
579 }
580
581 pub fn reselect<NewSel>(self, selection: NewSel) -> Select<D, Scope, NewSel, Outer> {
584 Select {
585 body: self.body,
586 selection,
587 _marker: PhantomData,
588 }
589 }
590
591 pub fn filter<C: Condition<D, Scope, Idxs>, Idxs>(mut self, cond: C) -> Self {
595 self.body.wheres.push(cond.into_predicate().into_kind());
596 self
597 }
598
599 pub fn filter_all(mut self, conds: impl IntoIterator<Item = Predicate<D, Scope>>) -> Self {
603 self.body
604 .wheres
605 .extend(conds.into_iter().map(Predicate::into_kind));
606 self
607 }
608
609 pub fn order_by<K: SortBy<Scope, Idxs>, Idxs>(mut self, key: K) -> Self {
610 let key = key.into_sort_key();
611 self.body.order_by.push((key.kind, key.dir));
612 self
613 }
614
615 pub fn order_by_all(mut self, keys: impl IntoIterator<Item = SortKey<Scope>>) -> Self {
619 self.body
620 .order_by
621 .extend(keys.into_iter().map(|k| (k.kind, k.dir)));
622 self
623 }
624
625 pub fn order_by_selected<K, SelIdx, Idx, L>(mut self, _key: K, dir: SortDir) -> Self
642 where
643 K: LookupKey,
644 Sel: Selection<Scope, SelIdx, Output = Row<L>>,
645 L: RowFieldLookup<K::Key, Idx>,
646 Idx: Position,
647 {
648 let mut items = self.selection.items();
649 let item = items.remove(<Idx as Position>::POSITION as usize - 1);
650 self.body.order_by.push((item.kind, dir));
651 self
652 }
653
654 pub fn order_by_selection<SelIdx>(mut self, dir: SortDir) -> Self
660 where
661 Sel: Selection<Scope, SelIdx>,
662 Sel::Output: SingleColumn,
663 {
664 let item = self.selection.items().remove(0);
665 self.body.order_by.push((item.kind, dir));
666 self
667 }
668
669 pub fn distinct(mut self) -> Self {
684 self.body.distinct = true;
685 self
686 }
687
688 pub fn group_by<K: GroupBy<Scope, Idxs>, Idxs>(mut self, key: K) -> Self {
692 self.body.group_by.push(key.into_grouping().kind);
693 self
694 }
695
696 pub fn group_by_all(mut self, keys: impl IntoIterator<Item = Grouping<Scope>>) -> Self {
699 self.body.group_by.extend(keys.into_iter().map(|g| g.kind));
700 self
701 }
702
703 pub fn having<C: Condition<D, Scope, Idxs>, Idxs>(mut self, cond: C) -> Self {
706 self.body.having.push(cond.into_predicate().into_kind());
707 self
708 }
709
710 pub fn having_all(mut self, conds: impl IntoIterator<Item = Predicate<D, Scope>>) -> Self {
713 self.body
714 .having
715 .extend(conds.into_iter().map(Predicate::into_kind));
716 self
717 }
718
719 pub fn limit(mut self, n: impl IntoRowCount) -> Self {
720 self.body.limit = Some(n.into_row_count());
721 self
722 }
723
724 pub fn offset(mut self, n: impl IntoRowCount) -> Self {
725 self.body.offset = Some(n.into_row_count());
726 self
727 }
728
729 pub fn inner_join<S: JoinSource<D>, C, Idxs>(
733 mut self,
734 source: S,
735 on: C,
736 ) -> Select<D, Cons<TableSlot<S::Table, NotNull>, Scope>, Sel, Outer>
737 where
738 C: Condition<D, Cons<TableSlot<S::Table, NotNull>, Scope>, Idxs>,
739 {
740 self.body.bind(source);
741 self.body.joins.push(JoinClause {
742 kind: JoinKind::Inner,
743 table: <S::Table as Table>::NAME,
744 on: on.into_predicate().into_kind(),
745 });
746 self.retype()
747 }
748
749 pub fn left_join<S: JoinSource<D>, C, Idxs>(
750 mut self,
751 source: S,
752 on: C,
753 ) -> Select<D, Cons<TableSlot<S::Table, MaybeNull>, Scope>, Sel, Outer>
754 where
755 C: Condition<D, Cons<TableSlot<S::Table, MaybeNull>, Scope>, Idxs>,
756 {
757 self.body.bind(source);
758 self.body.joins.push(JoinClause {
759 kind: JoinKind::Left,
760 table: <S::Table as Table>::NAME,
761 on: on.into_predicate().into_kind(),
762 });
763 self.retype()
764 }
765
766 pub fn right_join<S: JoinSource<D>, C, Idxs>(
770 mut self,
771 source: S,
772 on: C,
773 ) -> Select<D, Cons<TableSlot<S::Table, NotNull>, Scope::Output>, Sel, Outer>
774 where
775 D: SupportsRightJoin,
776 Scope: MapNullable,
777 C: Condition<D, Cons<TableSlot<S::Table, NotNull>, Scope::Output>, Idxs>,
778 {
779 self.body.bind(source);
780 self.body.joins.push(JoinClause {
781 kind: JoinKind::Right,
782 table: <S::Table as Table>::NAME,
783 on: on.into_predicate().into_kind(),
784 });
785 self.retype()
786 }
787
788 pub fn full_join<S: JoinSource<D>, C, Idxs>(
789 mut self,
790 source: S,
791 on: C,
792 ) -> Select<D, Cons<TableSlot<S::Table, MaybeNull>, Scope::Output>, Sel, Outer>
793 where
794 D: SupportsFullOuterJoin,
795 Scope: MapNullable,
796 C: Condition<D, Cons<TableSlot<S::Table, MaybeNull>, Scope::Output>, Idxs>,
797 {
798 self.body.bind(source);
799 self.body.joins.push(JoinClause {
800 kind: JoinKind::Full,
801 table: <S::Table as Table>::NAME,
802 on: on.into_predicate().into_kind(),
803 });
804 self.retype()
805 }
806}
807
808impl<D: Dialect, Scope, Sel> Select<D, Scope, Sel> {
813 pub fn to_sql<Idx>(&self, _dialect: D) -> (String, Vec<Value>)
822 where
823 Sel: Selection<Scope, Idx>,
824 {
825 self.render_as::<Idx>()
826 }
827
828 pub fn count_sql<Idx>(&self, _dialect: D) -> (String, Vec<Value>)
837 where
838 Sel: Selection<Scope, Idx>,
839 {
840 self.body.count_sql::<D>(&self.selection.items())
841 }
842}
843
844impl<D: Dialect, Scope, Sel> Select<D, Scope, Sel> {
845 pub(crate) fn fragment<Idx>(&self) -> Fragment
852 where
853 Sel: Selection<Scope, Idx>,
854 {
855 let mut sink = FragmentSink::new();
856 self.body
857 .render_into::<D>(&self.selection.items(), &mut sink);
858 sink.finish()
859 }
860
861 fn render_as<Idx>(&self) -> (String, Vec<Value>)
862 where
863 Sel: Selection<Scope, Idx>,
864 {
865 let mut sink = QuerySink::<D>::new();
866 self.body
867 .render_into::<D>(&self.selection.items(), &mut sink);
868 sink.finish()
869 }
870}
871
872impl SelectBody {
873 pub(crate) fn render_into<D: Dialect>(&self, selection: &[SelectItem], sink: &mut dyn Sink) {
874 let SelectBody {
875 ctes,
876 distinct,
877 from_table,
878 joins,
879 wheres,
880 order_by,
881 group_by,
882 having,
883 limit,
884 offset,
885 } = self;
886
887 if !ctes.is_empty() {
888 sink.text("WITH ");
889 for (i, cte) in ctes.iter().enumerate() {
890 if i > 0 {
891 sink.text(", ");
892 }
893 crate::render::render_ident::<D>(sink, cte.name);
894 sink.text(" (");
895 for (i, col) in cte.column_names.iter().enumerate() {
896 if i > 0 {
897 sink.text(", ");
898 }
899 crate::render::render_ident::<D>(sink, col);
900 }
901 sink.text(") AS (");
902 cte.body.splice_into(sink);
903 sink.ch(')');
904 }
905 sink.ch(' ');
906 }
907 sink.text("SELECT ");
908 if *distinct {
909 sink.text("DISTINCT ");
910 }
911
912 render_select_list::<D>(selection, sink);
913
914 sink.text(" FROM ");
915 crate::render::render_ident::<D>(sink, from_table);
916
917 for j in joins {
918 sink.ch(' ');
919 sink.text(match j.kind {
920 JoinKind::Inner => "INNER JOIN",
921 JoinKind::Left => "LEFT JOIN",
922 JoinKind::Right => "RIGHT JOIN",
923 JoinKind::Full => "FULL JOIN",
924 });
925 sink.ch(' ');
926 crate::render::render_ident::<D>(sink, j.table);
927 sink.text(" ON ");
928 render_expr::<D>(&j.on, sink);
929 }
930
931 render_and_list::<D>(sink, " WHERE ", wheres);
932
933 render_expr_list::<D>(sink, " GROUP BY ", group_by);
934 render_and_list::<D>(sink, " HAVING ", having);
935 render_order_by::<D>(sink, " ORDER BY ", order_by);
936 render_limit_offset::<D>(sink, limit.as_ref(), offset.as_ref());
937 }
938}
939
940pub(crate) fn correlated_with<D, Scope, S: JoinSource<D>, InnerSel>(
945 source: S,
946 selection: InnerSel,
947) -> Select<D, Cons<TableSlot<S::Table, NotNull>, Scope>, InnerSel, Scope> {
948 let mut body = SelectBody::new(<S::Table as Table>::NAME);
949 body.bind(source);
950 Select {
951 body,
952 selection,
953 _marker: PhantomData,
954 }
955}
956
957impl<D, Scope, Sel, Outer> Select<D, Scope, Sel, Outer> {
958 pub fn correlated<S: JoinSource<D>, InnerSel>(
971 &self,
972 source: S,
973 selection: InnerSel,
974 ) -> Select<D, Cons<TableSlot<S::Table, NotNull>, Scope>, InnerSel, Scope> {
975 correlated_with(source, selection)
976 }
977}
978
979impl<D: Dialect, Scope, Sel, Outer: ScopeTables> Select<D, Scope, Sel, Outer> {
980 pub fn exists<Idx>(&self) -> Exists<D, Outer::Tables>
986 where
987 Sel: Selection<Scope, Idx>,
988 {
989 self.exists_kind::<Idx>(false)
990 }
991
992 pub fn not_exists<Idx>(&self) -> Exists<D, Outer::Tables>
993 where
994 Sel: Selection<Scope, Idx>,
995 {
996 self.exists_kind::<Idx>(true)
997 }
998
999 fn exists_kind<Idx>(&self, negated: bool) -> Exists<D, Outer::Tables>
1000 where
1001 Sel: Selection<Scope, Idx>,
1002 {
1003 Exists {
1004 kind: ExprKind::Exists {
1005 body: Box::new(self.body.clone()),
1006 selection: self.selection.items(),
1007 negated,
1008 },
1009 _marker: PhantomData,
1010 }
1011 }
1012
1013 pub fn contains<Lhs, Idx>(
1027 &self,
1028 lhs: Lhs,
1029 ) -> InSubquery<D, <Outer::Tables as Concat<Lhs::Req>>::Output>
1030 where
1031 Lhs: IntoExpr,
1032 Lhs::Sql: Comparable<Sel::Sql>,
1033 Sel: RowField<Scope, Idx> + Selection<Scope, Idx>,
1034 Outer::Tables: Concat<Lhs::Req>,
1035 {
1036 self.in_subquery_kind::<Lhs, Idx>(lhs, false)
1037 }
1038
1039 pub fn not_contains<Lhs, Idx>(
1040 &self,
1041 lhs: Lhs,
1042 ) -> InSubquery<D, <Outer::Tables as Concat<Lhs::Req>>::Output>
1043 where
1044 Lhs: IntoExpr,
1045 Lhs::Sql: Comparable<Sel::Sql>,
1046 Sel: RowField<Scope, Idx> + Selection<Scope, Idx>,
1047 Outer::Tables: Concat<Lhs::Req>,
1048 {
1049 self.in_subquery_kind::<Lhs, Idx>(lhs, true)
1050 }
1051
1052 fn in_subquery_kind<Lhs, Idx>(
1053 &self,
1054 lhs: Lhs,
1055 negated: bool,
1056 ) -> InSubquery<D, <Outer::Tables as Concat<Lhs::Req>>::Output>
1057 where
1058 Lhs: IntoExpr,
1059 Lhs::Sql: Comparable<Sel::Sql>,
1060 Sel: RowField<Scope, Idx> + Selection<Scope, Idx>,
1061 Outer::Tables: Concat<Lhs::Req>,
1062 {
1063 InSubquery {
1064 kind: ExprKind::InSubquery {
1065 lhs: Box::new(lhs.into_expr().kind),
1066 body: Box::new(self.body.clone()),
1067 selection: self.selection.items(),
1068 negated,
1069 },
1070 _marker: PhantomData,
1071 }
1072 }
1073}
1074
1075#[diagnostic::on_unimplemented(
1083 message = "`{Self}` isn't a number of rows",
1084 label = "an integer, or a `prepare!{{}}` placeholder of type `Integer`/`BigInt`"
1085)]
1086pub trait IntoRowCount {
1087 fn into_row_count(self) -> RowCount;
1088}
1089
1090#[derive(Debug, Clone)]
1093pub struct RowCount(RowCountKind);
1094
1095#[derive(Debug, Clone)]
1096enum RowCountKind {
1097 Literal(i64),
1100 Bound(ExprKind),
1102}
1103
1104macro_rules! into_row_count {
1105 ($($signed:ty),+ ; $($unsigned:ty),+) => {
1106 $(impl IntoRowCount for $signed {
1107 fn into_row_count(self) -> RowCount {
1108 RowCount(RowCountKind::Literal((self as i64).max(0)))
1109 }
1110 })+
1111 $(impl IntoRowCount for $unsigned {
1112 fn into_row_count(self) -> RowCount {
1113 RowCount(RowCountKind::Literal(i64::try_from(self).unwrap_or(i64::MAX)))
1114 }
1115 })+
1116 };
1117}
1118into_row_count!(i8, i16, i32, i64, isize ; u8, u16, u32, u64, usize);
1119
1120impl IntoRowCount for Expr<Nil, crate::expr::Integer> {
1124 fn into_row_count(self) -> RowCount {
1125 RowCount(RowCountKind::Bound(self.kind))
1126 }
1127}
1128
1129impl IntoRowCount for Expr<Nil, crate::expr::BigInt> {
1130 fn into_row_count(self) -> RowCount {
1131 RowCount(RowCountKind::Bound(self.kind))
1132 }
1133}
1134
1135pub(crate) fn render_limit_offset<D: Dialect>(
1138 sink: &mut dyn Sink,
1139 limit: Option<&RowCount>,
1140 offset: Option<&RowCount>,
1141) {
1142 match (limit, offset, D::OFFSET_WITHOUT_LIMIT) {
1143 (Some(l), _, _) => {
1144 sink.text(" LIMIT ");
1145 render_row_count::<D>(sink, l);
1146 }
1147 (None, Some(_), Some(filler)) => {
1148 sink.text(" LIMIT ");
1149 sink.text(filler);
1150 }
1151 _ => {}
1152 }
1153 if let Some(o) = offset {
1154 sink.text(" OFFSET ");
1155 render_row_count::<D>(sink, o);
1156 }
1157}
1158
1159fn render_row_count<D: Dialect>(sink: &mut dyn Sink, count: &RowCount) {
1160 match &count.0 {
1161 RowCountKind::Literal(n) => sink.text(&n.to_string()),
1162 RowCountKind::Bound(kind) => render_expr::<D>(kind, sink),
1163 }
1164}