Skip to main content

qbrs_core/select/
mod.rs

1//! The `SELECT` builder: `select(..).from(..).join(..).filter(..)
2//! .order_by(..).limit(..)`, in SQL keyword order, with tables passed as
3//! arguments rather than by turbofish.
4
5use std::marker::PhantomData;
6
7use crate::cte::Cte;
8use crate::dialect::{Dialect, SupportsFullOuterJoin, SupportsRightJoin};
9use crate::expr::{BoolLike, 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::scope::{
15    BaseTable, Cons, MapNullable, MaybeNull, Nil, NotNull, ScopeTables, Superset, Table, TableSlot,
16};
17
18mod dyn_select;
19mod prepared;
20mod selection;
21mod set_op;
22
23pub use crate::expr::SortDir;
24pub use dyn_select::{CannotFilterAfterErase, DynSelect};
25pub use prepared::{Prepared, PreparedParams, Total, UnresolvedPlaceholder};
26pub use selection::{
27    All, AllColumns, ColumnList, RowField, SelectableSealed, Selection, SelectionPart, SingleColumn,
28};
29pub use set_op::SetOp;
30
31/// One `name AS (body)` binding, carried in by the `Cte` a query was
32/// entered through. Opaque outside this crate: `JoinSource::binding` is the
33/// only way to make one, and it takes the name and columns from the
34/// marker's `CteShape` rather than from anything a caller can vary.
35#[doc(hidden)]
36#[derive(Debug, Clone)]
37pub struct CteDef {
38    name: &'static str,
39    column_names: Vec<&'static str>,
40    body: Fragment,
41}
42
43impl CteDef {
44    pub(crate) fn new(name: &'static str, column_names: Vec<&'static str>, body: Fragment) -> Self {
45        CteDef {
46            name,
47            column_names,
48            body,
49        }
50    }
51}
52
53#[derive(Debug, Clone)]
54enum JoinKind {
55    Inner,
56    Left,
57    Right,
58    Full,
59}
60
61#[derive(Debug, Clone)]
62struct JoinClause {
63    kind: JoinKind,
64    table: &'static str,
65    on: ExprKind,
66}
67
68/// An order-by key: a column/expression tagged with a direction. Built via
69/// `.asc()`/`.desc()` on any column or expression (see `OrderExt` below),
70/// so `.order_by(users::created_at.desc())` reads as one argument, not two.
71pub struct OrderKey<Req> {
72    kind: ExprKind,
73    dir: SortDir,
74    _marker: PhantomData<fn() -> Req>,
75}
76
77// Hand-written for the reason `Expr`'s is: `#[derive(Clone)]` would ask the
78// phantom `Req` to be `Clone`, which no scope list is.
79impl<Req> Clone for OrderKey<Req> {
80    fn clone(&self) -> Self {
81        OrderKey {
82            kind: self.kind.clone(),
83            dir: self.dir,
84            _marker: PhantomData,
85        }
86    }
87}
88
89impl<Req> OrderKey<Req> {
90    pub(crate) fn into_parts(self) -> (ExprKind, SortDir) {
91        (self.kind, self.dir)
92    }
93}
94
95pub trait OrderExt: IntoExpr + Sized {
96    fn asc(self) -> OrderKey<Self::Req> {
97        OrderKey {
98            kind: self.into_expr().kind,
99            dir: SortDir::Asc,
100            _marker: PhantomData,
101        }
102    }
103    /// The direction as a value, for a sort order that arrives at runtime —
104    /// `?dir=desc` — instead of an N-way match over `.asc()`/`.desc()`.
105    fn sort(self, dir: SortDir) -> OrderKey<Self::Req> {
106        OrderKey {
107            kind: self.into_expr().kind,
108            dir,
109            _marker: PhantomData,
110        }
111    }
112    fn desc(self) -> OrderKey<Self::Req> {
113        OrderKey {
114            kind: self.into_expr().kind,
115            dir: SortDir::Desc,
116            _marker: PhantomData,
117        }
118    }
119}
120impl<T: IntoExpr> OrderExt for T {}
121
122/// Something a query can select from or join to. A schema table brings
123/// nothing with it; a `Cte` brings its `WITH` binding, so attaching that
124/// binding and putting the pseudo-table in scope stay one act — while every
125/// join kind, and `correlated`, work on both without being written twice.
126pub trait JoinSource<D>: join_source::Sealed {
127    /// The table this source contributes to the scope.
128    type Table: Table;
129    /// The `WITH` binding this source carries into the statement — `None`
130    /// for a schema table, which is already there.
131    #[doc(hidden)]
132    fn binding(self) -> Option<CteDef>;
133}
134
135mod join_source {
136    /// Sealed the way `dialect::Dialect` is: what a query can read from is
137    /// a closed set of two, a schema table and a bound CTE.
138    pub trait Sealed {}
139    impl<T: super::BaseTable> Sealed for T {}
140    impl<D, Marker> Sealed for crate::cte::Cte<D, Marker> {}
141}
142
143impl<D, T: BaseTable> JoinSource<D> for T {
144    type Table = T;
145    fn binding(self) -> Option<CteDef> {
146        None
147    }
148}
149
150impl<D, Marker: crate::cte::CteShape> JoinSource<D> for Cte<D, Marker> {
151    type Table = Marker;
152    fn binding(self) -> Option<CteDef> {
153        Some(CteDef::new(
154            <Marker as Table>::NAME,
155            <Marker::Row as crate::row::ColumnNames>::names(),
156            self.into_body(),
157        ))
158    }
159}
160
161/// Something a query can be ordered by: an `OrderKey` whose tables this
162/// scope contains, or a `SortKey` already discharged against it — the same
163/// pair `Condition` makes for `.filter`.
164#[diagnostic::on_unimplemented(
165    message = "`{Self}` isn't a sort key",
166    label = "a column or expression with `.asc()`/`.desc()`/`.sort(dir)` on it, or a `sort_key(..)`",
167    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"
168)]
169pub trait SortBy<Scope, Idxs> {
170    #[doc(hidden)]
171    fn into_sort_key(self) -> SortKey<Scope>;
172}
173
174impl<Scope: Superset<Req, Idxs>, Req, Idxs> SortBy<Scope, Idxs> for OrderKey<Req> {
175    fn into_sort_key(self) -> SortKey<Scope> {
176        SortKey {
177            kind: self.kind,
178            dir: self.dir,
179            _marker: PhantomData,
180        }
181    }
182}
183
184impl<Scope> SortBy<Scope, ()> for SortKey<Scope> {
185    fn into_sort_key(self) -> SortKey<Scope> {
186        self
187    }
188}
189
190/// The same for `GROUP BY`: an expression this scope covers, or a
191/// `grouping(..)` already discharged against it.
192#[diagnostic::on_unimplemented(
193    message = "`{Self}` isn't a grouping key",
194    label = "a column or expression, or a `grouping(..)`",
195    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"
196)]
197pub trait GroupBy<Scope, Idxs> {
198    #[doc(hidden)]
199    fn into_grouping(self) -> Grouping<Scope>;
200}
201
202impl<Scope: Superset<Req, Idxs>, Req, Idxs, T: IntoExpr<Req = Req>> GroupBy<Scope, Idxs> for T {
203    fn into_grouping(self) -> Grouping<Scope> {
204        Grouping {
205            kind: self.into_expr().kind,
206            _marker: PhantomData,
207        }
208    }
209}
210
211impl<Scope> GroupBy<Scope, ()> for Grouping<Scope> {
212    fn into_grouping(self) -> Grouping<Scope> {
213        self
214    }
215}
216
217/// A sort key whose scope requirement has already been discharged, so a
218/// runtime-length collection of them can be built and passed around — the
219/// `?sort=email,-placed_on` case. `select::sort_key` is to `.order_by_all`
220/// what `predicate` is to `.filter_all`.
221pub struct SortKey<Scope> {
222    kind: ExprKind,
223    dir: SortDir,
224    _marker: PhantomData<fn() -> Scope>,
225}
226
227impl<Scope> Clone for SortKey<Scope> {
228    fn clone(&self) -> Self {
229        SortKey {
230            kind: self.kind.clone(),
231            dir: self.dir,
232            _marker: PhantomData,
233        }
234    }
235}
236
237/// Discharges a sort key's scope requirement. `Scope` is inferred from the
238/// query the keys are eventually given to. Takes whatever `.order_by` takes,
239/// as `predicate` takes whatever `.filter` does — so a helper generic over
240/// `SortBy` can discharge without knowing which of the two it was handed.
241pub fn sort_key<Scope, Idxs, K: SortBy<Scope, Idxs>>(key: K) -> SortKey<Scope> {
242    key.into_sort_key()
243}
244
245/// A grouping key with its scope requirement discharged — `predicate`'s
246/// counterpart for `GROUP BY`.
247pub struct Grouping<Scope> {
248    kind: ExprKind,
249    _marker: PhantomData<fn() -> Scope>,
250}
251
252impl<Scope> Clone for Grouping<Scope> {
253    fn clone(&self) -> Self {
254        Grouping {
255            kind: self.kind.clone(),
256            _marker: PhantomData,
257        }
258    }
259}
260
261/// Discharges a grouping key's scope requirement, taking whatever
262/// `.group_by` takes — the same shape `predicate` and `sort_key` have.
263pub fn grouping<Scope, Idxs, K: GroupBy<Scope, Idxs>>(key: K) -> Grouping<Scope> {
264    key.into_grouping()
265}
266
267/// Something a query can be filtered by: an `Expr` whose tables this scope
268/// contains, or a `Predicate` already discharged against it. One `.filter`
269/// for both, so which one a condition happens to be doesn't change how it is
270/// applied.
271#[diagnostic::on_unimplemented(
272    message = "`{Self}` isn't a condition",
273    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` of a subquery in *this* dialect",
274    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"
275)]
276pub trait Condition<D, Scope, Idxs> {
277    /// Discharged against this scope, which for an `Expr` is where its
278    /// `Superset` proof is spent and for a `Predicate` already happened.
279    #[doc(hidden)]
280    fn into_predicate(self) -> Predicate<D, Scope>;
281}
282
283impl<D, Scope: Superset<Req, Idxs>, Req, Idxs, T: IntoExpr<Req = Req>> Condition<D, Scope, Idxs>
284    for T
285where
286    T::Sql: BoolLike,
287{
288    fn into_predicate(self) -> Predicate<D, Scope> {
289        Predicate {
290            kind: self.into_expr().kind,
291            _marker: PhantomData,
292        }
293    }
294}
295
296impl<D, Scope> Condition<D, Scope, ()> for Predicate<D, Scope> {
297    fn into_predicate(self) -> Predicate<D, Scope> {
298        self
299    }
300}
301
302/// `EXISTS (<subquery>)`. Not an `Expr`, because unlike every other
303/// expression this one is dialect-pinned: the subquery it holds was
304/// capability-checked against its own dialect, and any CTE it binds is
305/// already rendered in that dialect. It is therefore a condition and only a
306/// condition — `.filter(..)` it, or `predicate(..)` it into a collection,
307/// onto a query of the same dialect. A `Predicate` carries `D` for this
308/// reason: discharging a condition gives up the tables it named, never the
309/// dialect it was built for.
310pub struct Exists<D, Req> {
311    kind: ExprKind,
312    _marker: PhantomData<fn() -> (D, Req)>,
313}
314
315// Hand-written for the reason `Expr`'s is: `#[derive(Clone)]` would ask the
316// phantom tags to be `Clone`.
317impl<D, Req> Clone for Exists<D, Req> {
318    fn clone(&self) -> Self {
319        Exists {
320            kind: self.kind.clone(),
321            _marker: PhantomData,
322        }
323    }
324}
325
326impl<D, Scope: Superset<Req, Idxs>, Req, Idxs> Condition<D, Scope, Idxs> for Exists<D, Req> {
327    fn into_predicate(self) -> Predicate<D, Scope> {
328        Predicate {
329            kind: self.kind,
330            _marker: PhantomData,
331        }
332    }
333}
334
335/// A condition whose scope requirement has already been discharged, so a
336/// runtime-length collection of them can be built and passed around. An
337/// `Expr` carries the tables it references in its type, which is what makes
338/// `vec![users_cond, orders_cond]` fail to unify; `predicate` trades that
339/// tag for a proof against one concrete scope.
340pub struct Predicate<D, Scope> {
341    kind: ExprKind,
342    _marker: PhantomData<fn() -> (D, Scope)>,
343}
344
345// Hand-written for the reason `Expr`'s is: `#[derive(Clone)]` would ask a
346// phantom `Scope` to be `Clone`.
347impl<D, Scope> Clone for Predicate<D, Scope> {
348    fn clone(&self) -> Self {
349        Predicate {
350            kind: self.kind.clone(),
351            _marker: PhantomData,
352        }
353    }
354}
355
356impl<D, Scope> Predicate<D, Scope> {
357    /// True when any of them is. `expr::any_of` combines conditions that
358    /// reference the same tables; this one combines conditions whose scope
359    /// requirement is already discharged, which is what lets a search form
360    /// OR together conditions from different tables.
361    pub fn any_of(preds: impl IntoIterator<Item = Predicate<D, Scope>>) -> Self {
362        Predicate::combine(preds, false)
363    }
364
365    /// True when all of them are — the AND to `any_of`'s OR, so a group of
366    /// them can be nested inside one.
367    pub fn all_of(preds: impl IntoIterator<Item = Predicate<D, Scope>>) -> Self {
368        Predicate::combine(preds, true)
369    }
370
371    fn combine(preds: impl IntoIterator<Item = Predicate<D, Scope>>, all: bool) -> Self {
372        Predicate {
373            kind: crate::expr::fold_conditions(preds.into_iter().map(Predicate::into_kind), all),
374            _marker: PhantomData,
375        }
376    }
377
378    pub(crate) fn into_kind(self) -> ExprKind {
379        self.kind
380    }
381}
382
383/// Discharges a condition's scope requirement, so a runtime-length
384/// collection of them can be built and passed around. `Scope` and `D` are
385/// inferred from the query the resulting predicates are eventually given to.
386pub fn predicate<D, Scope, Idxs, C: Condition<D, Scope, Idxs>>(cond: C) -> Predicate<D, Scope> {
387    cond.into_predicate()
388}
389
390/// Holds just the `SELECT` list until `.from(..)` supplies the first table
391/// and therefore the query's initial `Scope`. Splitting this out (rather
392/// than requiring `Scope` be known at `.select(..)` time) is what lets the
393/// builder read in `SELECT -> FROM -> ...` order while still validating
394/// every selected column against the *final* scope only once, at the
395/// query's terminal method (`.to_sql(Postgres)`/`.load()`).
396pub struct SelectSeed<Sel> {
397    selection: Sel,
398}
399
400pub fn select<Sel>(selection: Sel) -> SelectSeed<Sel> {
401    SelectSeed { selection }
402}
403
404impl<Sel> SelectSeed<Sel> {
405    /// `source` is a value, not a turbofish — a schema table's zero-sized
406    /// token (`users::Table`) or a `cte::with(..)` binding. A CTE brings its
407    /// `WITH` clause along, so it cannot be selected from unbound.
408    pub fn from<D, S: JoinSource<D>>(
409        self,
410        source: S,
411    ) -> Select<D, Cons<TableSlot<S::Table, NotNull>, Nil>, Sel> {
412        let mut body = SelectBody::new(<S::Table as Table>::NAME);
413        body.bind(source);
414        Select {
415            body,
416            selection: self.selection,
417            _marker: PhantomData,
418        }
419    }
420}
421
422/// Every clause of a `SELECT` except the selection list, which `Select`
423/// keeps typed and `DynSelect` keeps rendered. Held whole by both, so a new
424/// clause is added here once instead of being threaded through each of them
425/// and through rendering by hand.
426#[derive(Debug, Clone)]
427pub(crate) struct SelectBody {
428    ctes: Vec<CteDef>,
429    distinct: bool,
430    from_table: &'static str,
431    joins: Vec<JoinClause>,
432    wheres: Vec<ExprKind>,
433    order_by: Vec<(ExprKind, SortDir)>,
434    group_by: Vec<ExprKind>,
435    having: Vec<ExprKind>,
436    limit: Option<RowCount>,
437    offset: Option<RowCount>,
438}
439
440impl SelectBody {
441    fn new(from_table: &'static str) -> Self {
442        SelectBody {
443            ctes: Vec::new(),
444            distinct: false,
445            from_table,
446            joins: Vec::new(),
447            wheres: Vec::new(),
448            order_by: Vec::new(),
449            group_by: Vec::new(),
450            having: Vec::new(),
451            limit: None,
452            offset: None,
453        }
454    }
455
456    /// `SELECT count(*)` over this body with its paging dropped: a total
457    /// counts the rows that match, not the page being shown.
458    ///
459    /// A query whose rows aren't one per matching row is counted by
460    /// wrapping it, selection and all, since what a page of it would show is
461    /// what has to be counted. Stated as what may be left unwrapped — plain
462    /// columns, no `GROUP BY`/`HAVING`/`DISTINCT` — rather than as a list of
463    /// what may not: an aggregate collapses the rows too, and `sql!` can
464    /// hold anything at all.
465    fn count_sql<D: Dialect>(&self, selection: &[SelectItem]) -> (String, Vec<Value>) {
466        let mut body = self.clone();
467        body.order_by.clear();
468        body.limit = None;
469        body.offset = None;
470        let one_row_each = body.group_by.is_empty()
471            && body.having.is_empty()
472            && !body.distinct
473            && selection
474                .iter()
475                .all(|item| matches!(item.kind, ExprKind::Column { .. }));
476
477        let mut sink = QuerySink::<D>::new();
478        if one_row_each {
479            body.render_into::<D>(&[crate::expr::count_item()], &mut sink);
480            return sink.finish();
481        }
482        crate::render::render_count_wrapped::<D>(&mut sink, |sink| {
483            body.render_into::<D>(selection, sink)
484        });
485        sink.finish()
486    }
487
488    /// Attaches whatever `WITH` binding a join source carries before its
489    /// table is named in a FROM or JOIN clause.
490    fn bind<D, S: JoinSource<D>>(&mut self, source: S) {
491        self.ctes.extend(source.binding());
492    }
493}
494
495/// A `SELECT`. `Outer` is the scope this query was built *against* — `Nil`
496/// for a query of its own, and the outer query's scope for one started by
497/// `.correlated(..)`, which is what lets `EXISTS` report the outer tables it
498/// references. Defaulted, so a query that isn't a subquery never spells it.
499pub struct Select<D, Scope, Sel, Outer = Nil> {
500    body: SelectBody,
501    selection: Sel,
502    _marker: PhantomData<fn() -> (D, Scope, Outer)>,
503}
504
505// Cloning is what lets one built-up query serve both a count and a page.
506impl<D, Scope, Sel: Clone, Outer> Clone for Select<D, Scope, Sel, Outer> {
507    fn clone(&self) -> Self {
508        Select {
509            body: self.body.clone(),
510            selection: self.selection.clone(),
511            _marker: PhantomData,
512        }
513    }
514}
515
516impl<D, Scope, Sel, Outer> Select<D, Scope, Sel, Outer> {
517    fn retype<NewScope>(self) -> Select<D, NewScope, Sel, Outer> {
518        Select {
519            body: self.body,
520            selection: self.selection,
521            _marker: PhantomData,
522        }
523    }
524
525    /// Swaps the selection list, keeping every clause. With `Clone`, this is
526    /// how one built-up query serves both a count and a page.
527    pub fn reselect<NewSel>(self, selection: NewSel) -> Select<D, Scope, NewSel, Outer> {
528        Select {
529            body: self.body,
530            selection,
531            _marker: PhantomData,
532        }
533    }
534
535    /// AND-folded, and callable any number of times — conditionally, in a
536    /// loop, from a helper — without changing `Self`'s type, so the most
537    /// common kind of dynamic query needs no escape hatch.
538    pub fn filter<C: Condition<D, Scope, Idxs>, Idxs>(mut self, cond: C) -> Self {
539        self.body.wheres.push(cond.into_predicate().into_kind());
540        self
541    }
542
543    /// AND-folds a runtime-length collection of already-discharged
544    /// conditions — the shape a search form has, where the conditions come
545    /// from different tables and so can't share one `Expr` type.
546    pub fn filter_all(mut self, conds: impl IntoIterator<Item = Predicate<D, Scope>>) -> Self {
547        self.body
548            .wheres
549            .extend(conds.into_iter().map(Predicate::into_kind));
550        self
551    }
552
553    pub fn order_by<K: SortBy<Scope, Idxs>, Idxs>(mut self, key: K) -> Self {
554        let key = key.into_sort_key();
555        self.body.order_by.push((key.kind, key.dir));
556        self
557    }
558
559    /// Appends a runtime-length collection of already-discharged sort keys
560    /// — the shape a `?sort=` parameter has, where the keys name different
561    /// tables and so can't share one `OrderKey` type.
562    pub fn order_by_all(mut self, keys: impl IntoIterator<Item = SortKey<Scope>>) -> Self {
563        self.body
564            .order_by
565            .extend(keys.into_iter().map(|k| (k.kind, k.dir)));
566        self
567    }
568
569    /// `SELECT DISTINCT`: one row per distinct selected tuple. The natural
570    /// answer to a one-to-many join that repeats its left side, and unlike a
571    /// `GROUP BY` of the whole selection it doesn't have to be restated when
572    /// the selection changes. Idempotent — a query is distinct or it isn't.
573    ///
574    /// **Known limitation**: Postgres requires a `SELECT DISTINCT`'s sort
575    /// keys to be in its selection, and nothing here relates the two — the
576    /// same gap `GROUP BY` has. Sorting a distinct query by a column it
577    /// doesn't select renders SQL the database rejects, and `count_sql`
578    /// won't show it, since a total drops the `ORDER BY`. Relating them
579    /// would mean carrying "is distinct" in `Select`'s type and taking sort
580    /// keys by identity (`SetOp::order_by_column`'s shape) — a type
581    /// parameter through every builder signature for one clause.
582    pub fn distinct(mut self) -> Self {
583        self.body.distinct = true;
584        self
585    }
586
587    /// Appends one grouping key; callable multiple times like `.filter()`
588    /// (each call adds a column to the `GROUP BY` list, it doesn't replace
589    /// it), for the same "dynamic composition without a type change" reason.
590    pub fn group_by<K: GroupBy<Scope, Idxs>, Idxs>(mut self, key: K) -> Self {
591        self.body.group_by.push(key.into_grouping().kind);
592        self
593    }
594
595    /// The same for a runtime-length collection of discharged grouping
596    /// keys, as `order_by_all` is to `order_by`.
597    pub fn group_by_all(mut self, keys: impl IntoIterator<Item = Grouping<Scope>>) -> Self {
598        self.body.group_by.extend(keys.into_iter().map(|g| g.kind));
599        self
600    }
601
602    /// A `WHERE`-shaped filter applied after grouping (aggregate
603    /// conditions) — AND-folded across calls exactly like `.filter()`.
604    pub fn having<C: Condition<D, Scope, Idxs>, Idxs>(mut self, cond: C) -> Self {
605        self.body.having.push(cond.into_predicate().into_kind());
606        self
607    }
608
609    /// The same for a runtime-length collection of discharged conditions,
610    /// as `filter_all` is to `filter`.
611    pub fn having_all(mut self, conds: impl IntoIterator<Item = Predicate<D, Scope>>) -> Self {
612        self.body
613            .having
614            .extend(conds.into_iter().map(Predicate::into_kind));
615        self
616    }
617
618    pub fn limit(mut self, n: impl IntoRowCount) -> Self {
619        self.body.limit = Some(n.into_row_count());
620        self
621    }
622
623    pub fn offset(mut self, n: impl IntoRowCount) -> Self {
624        self.body.offset = Some(n.into_row_count());
625        self
626    }
627
628    /// The joined table is in scope for the `ON` condition, and so is
629    /// everything already joined — the scope the condition is discharged
630    /// against is the one the join produces, not the one it started from.
631    pub fn inner_join<S: JoinSource<D>, C, Idxs>(
632        mut self,
633        source: S,
634        on: C,
635    ) -> Select<D, Cons<TableSlot<S::Table, NotNull>, Scope>, Sel, Outer>
636    where
637        C: Condition<D, Cons<TableSlot<S::Table, NotNull>, Scope>, Idxs>,
638    {
639        self.body.bind(source);
640        self.body.joins.push(JoinClause {
641            kind: JoinKind::Inner,
642            table: <S::Table as Table>::NAME,
643            on: on.into_predicate().into_kind(),
644        });
645        self.retype()
646    }
647
648    pub fn left_join<S: JoinSource<D>, C, Idxs>(
649        mut self,
650        source: S,
651        on: C,
652    ) -> Select<D, Cons<TableSlot<S::Table, MaybeNull>, Scope>, Sel, Outer>
653    where
654        C: Condition<D, Cons<TableSlot<S::Table, MaybeNull>, Scope>, Idxs>,
655    {
656        self.body.bind(source);
657        self.body.joins.push(JoinClause {
658            kind: JoinKind::Left,
659            table: <S::Table as Table>::NAME,
660            on: on.into_predicate().into_kind(),
661        });
662        self.retype()
663    }
664
665    /// RIGHT JOIN retroactively flips every already-joined table to
666    /// nullable (`MapNullable`) before adding the new, guaranteed-present
667    /// table, mirroring Drizzle's `AppendToNullabilityMap` rule.
668    pub fn right_join<S: JoinSource<D>, C, Idxs>(
669        mut self,
670        source: S,
671        on: C,
672    ) -> Select<D, Cons<TableSlot<S::Table, NotNull>, Scope::Output>, Sel, Outer>
673    where
674        D: SupportsRightJoin,
675        Scope: MapNullable,
676        C: Condition<D, Cons<TableSlot<S::Table, NotNull>, Scope::Output>, Idxs>,
677    {
678        self.body.bind(source);
679        self.body.joins.push(JoinClause {
680            kind: JoinKind::Right,
681            table: <S::Table as Table>::NAME,
682            on: on.into_predicate().into_kind(),
683        });
684        self.retype()
685    }
686
687    pub fn full_join<S: JoinSource<D>, C, Idxs>(
688        mut self,
689        source: S,
690        on: C,
691    ) -> Select<D, Cons<TableSlot<S::Table, MaybeNull>, Scope::Output>, Sel, Outer>
692    where
693        D: SupportsFullOuterJoin,
694        Scope: MapNullable,
695        C: Condition<D, Cons<TableSlot<S::Table, MaybeNull>, Scope::Output>, Idxs>,
696    {
697        self.body.bind(source);
698        self.body.joins.push(JoinClause {
699            kind: JoinKind::Full,
700            table: <S::Table as Table>::NAME,
701            on: on.into_predicate().into_kind(),
702        });
703        self.retype()
704    }
705}
706
707/// The terminal methods, and so only for a query of its own: a subquery
708/// (`Outer != Nil`) references its outer query's tables, and rendering one
709/// on its own would name tables that aren't in its `FROM`. It reaches SQL
710/// through `exists`/`not_exists` instead.
711impl<D: Dialect, Scope, Sel> Select<D, Scope, Sel> {
712    /// The terminal step, and the *only* point each selected column's
713    /// scope-membership is checked — proven as a side effect of
714    /// `Sel: Selection<Scope, Idx>` type-checking at all.
715    ///
716    /// The dialect is an argument rather than a turbofish, so a query that
717    /// is rendered instead of executed says which SQL it wants in the one
718    /// place that decides — and everything before it infers, the way a
719    /// table or a column does.
720    pub fn to_sql<Idx>(&self, _dialect: D) -> (String, Vec<Value>)
721    where
722        Sel: Selection<Scope, Idx>,
723    {
724        self.render_as::<Idx>()
725    }
726
727    /// How many rows this query would return, ignoring its
728    /// `ORDER BY`/`LIMIT`/`OFFSET` — a total is about what matches, not about
729    /// the page being shown. `reselect(count())` keeps them, which is what
730    /// makes it the wrong tool for a paginated total.
731    ///
732    /// A grouped query counts its *groups*, since that is what a page of it
733    /// would show, so the body becomes a subquery rather than having its
734    /// `GROUP BY` dropped or kept.
735    pub fn count_sql<Idx>(&self, _dialect: D) -> (String, Vec<Value>)
736    where
737        Sel: Selection<Scope, Idx>,
738    {
739        self.body.count_sql::<D>(&self.selection.items())
740    }
741}
742
743impl<D: Dialect, Scope, Sel> Select<D, Scope, Sel> {
744    /// This query as an embeddable `Fragment`: an `EXISTS (..)` subquery, a
745    /// CTE body, or a set-operation branch. The only way to produce one, so
746    /// no caller has to remember that an embedded query renders with `?`
747    /// placeholders rather than `D`'s own style. `Outer = Nil` like the
748    /// other terminals: a correlated subquery names tables that aren't in
749    /// its own `FROM`, and reaches SQL through `EXISTS` instead.
750    pub(crate) fn fragment<Idx>(&self) -> Fragment
751    where
752        Sel: Selection<Scope, Idx>,
753    {
754        let mut sink = FragmentSink::new();
755        self.body
756            .render_into::<D>(&self.selection.items(), &mut sink);
757        sink.finish()
758    }
759
760    fn render_as<Idx>(&self) -> (String, Vec<Value>)
761    where
762        Sel: Selection<Scope, Idx>,
763    {
764        let mut sink = QuerySink::<D>::new();
765        self.body
766            .render_into::<D>(&self.selection.items(), &mut sink);
767        sink.finish()
768    }
769}
770
771impl SelectBody {
772    pub(crate) fn render_into<D: Dialect>(&self, selection: &[SelectItem], sink: &mut dyn Sink) {
773        let SelectBody {
774            ctes,
775            distinct,
776            from_table,
777            joins,
778            wheres,
779            order_by,
780            group_by,
781            having,
782            limit,
783            offset,
784        } = self;
785
786        if !ctes.is_empty() {
787            sink.text("WITH ");
788            for (i, cte) in ctes.iter().enumerate() {
789                if i > 0 {
790                    sink.text(", ");
791                }
792                crate::render::render_ident::<D>(sink, cte.name);
793                sink.text(" (");
794                for (i, col) in cte.column_names.iter().enumerate() {
795                    if i > 0 {
796                        sink.text(", ");
797                    }
798                    crate::render::render_ident::<D>(sink, col);
799                }
800                sink.text(") AS (");
801                cte.body.splice_into(sink);
802                sink.ch(')');
803            }
804            sink.ch(' ');
805        }
806        sink.text("SELECT ");
807        if *distinct {
808            sink.text("DISTINCT ");
809        }
810
811        render_select_list::<D>(selection, sink);
812
813        sink.text(" FROM ");
814        crate::render::render_ident::<D>(sink, from_table);
815
816        for j in joins {
817            sink.ch(' ');
818            sink.text(match j.kind {
819                JoinKind::Inner => "INNER JOIN",
820                JoinKind::Left => "LEFT JOIN",
821                JoinKind::Right => "RIGHT JOIN",
822                JoinKind::Full => "FULL JOIN",
823            });
824            sink.ch(' ');
825            crate::render::render_ident::<D>(sink, j.table);
826            sink.text(" ON ");
827            render_expr::<D>(&j.on, sink);
828        }
829
830        render_and_list::<D>(sink, " WHERE ", wheres);
831
832        render_expr_list::<D>(sink, " GROUP BY ", group_by);
833        render_and_list::<D>(sink, " HAVING ", having);
834        render_order_by::<D>(sink, " ORDER BY ", order_by);
835        render_limit_offset::<D>(sink, limit.as_ref(), offset.as_ref());
836    }
837}
838
839/// Starts a correlated subquery against a scope, rather than against a
840/// query — so `UPDATE`/`DELETE`, whose scope is the one table they write,
841/// reach the same `EXISTS` a `SELECT` does without conjuring a `Select`
842/// they don't otherwise need.
843pub(crate) fn correlated_with<D, Scope, S: JoinSource<D>, InnerSel>(
844    source: S,
845    selection: InnerSel,
846) -> Select<D, Cons<TableSlot<S::Table, NotNull>, Scope>, InnerSel, Scope> {
847    let mut body = SelectBody::new(<S::Table as Table>::NAME);
848    body.bind(source);
849    Select {
850        body,
851        selection,
852        _marker: PhantomData,
853    }
854}
855
856impl<D, Scope, Sel, Outer> Select<D, Scope, Sel, Outer> {
857    /// Starts a correlated subquery: a fresh `SELECT` whose scope is
858    /// `Cons<TableSlot<T, NotNull>, Scope>` — the new table, prepended onto
859    /// *this* (outer) query's entire scope. Because `Find`/`Superset` walk
860    /// the whole flat cons-list regardless of where it came from, the
861    /// subquery's `.filter()` can reference both its own new table's
862    /// columns and any outer column already in `Scope`, with no special
863    /// casing: growing the scope works the same whether the new table came
864    /// from a join or from a subquery's `FROM`.
865    ///
866    /// The result is an ordinary `Select` — every clause it takes is the
867    /// one `Select` already has — carrying this query's scope as its
868    /// `Outer`, which is what `exists` reports.
869    pub fn correlated<S: JoinSource<D>, InnerSel>(
870        &self,
871        source: S,
872        selection: InnerSel,
873    ) -> Select<D, Cons<TableSlot<S::Table, NotNull>, Scope>, InnerSel, Scope> {
874        correlated_with(source, selection)
875    }
876}
877
878impl<D: Dialect, Scope, Sel, Outer: ScopeTables> Select<D, Scope, Sel, Outer> {
879    /// `EXISTS (<this query>)`, tagged with the outer tables it references
880    /// so it can only be filtered onto a query that has them in scope. Its
881    /// own column references were already checked against `Scope` when it
882    /// was built. On a query that isn't a subquery, `Outer` is `Nil` and
883    /// this is an uncorrelated `EXISTS`.
884    pub fn exists<Idx>(&self) -> Exists<D, Outer::Tables>
885    where
886        Sel: Selection<Scope, Idx>,
887    {
888        self.exists_kind::<Idx>(false)
889    }
890
891    pub fn not_exists<Idx>(&self) -> Exists<D, Outer::Tables>
892    where
893        Sel: Selection<Scope, Idx>,
894    {
895        self.exists_kind::<Idx>(true)
896    }
897
898    fn exists_kind<Idx>(&self, negated: bool) -> Exists<D, Outer::Tables>
899    where
900        Sel: Selection<Scope, Idx>,
901    {
902        Exists {
903            kind: ExprKind::Exists {
904                body: Box::new(self.body.clone()),
905                selection: self.selection.items(),
906                negated,
907            },
908            _marker: PhantomData,
909        }
910    }
911}
912
913/// A number of rows — what a `LIMIT` and an `OFFSET` each are: an integer,
914/// or a `prepare!{}` placeholder for one, so a paginated endpoint can
915/// prepare its query once and vary the page. A trait rather than
916/// `Into<i64>` so a `usize` page size — the shape a paginated handler
917/// already has — goes in without a cast. Every numeric impl lands in
918/// `0..=i64::MAX`: a negative count is not a query any database will run,
919/// and a `usize` past `i64::MAX` is not a page anyone is asking for.
920#[diagnostic::on_unimplemented(
921    message = "`{Self}` isn't a number of rows",
922    label = "an integer, or a `prepare!{{}}` placeholder of type `Integer`/`BigInt`"
923)]
924pub trait IntoRowCount {
925    fn into_row_count(self) -> RowCount;
926}
927
928/// What a `LIMIT`/`OFFSET` clause holds. Opaque: the `IntoRowCount` impls
929/// are the only way to make one.
930#[derive(Debug, Clone)]
931pub struct RowCount(RowCountKind);
932
933#[derive(Debug, Clone)]
934enum RowCountKind {
935    /// Written into the SQL text: a page size is not a value the plan
936    /// should be reused across.
937    Literal(i64),
938    /// A bound parameter, which is what a `prepare!{}` placeholder is.
939    Bound(ExprKind),
940}
941
942macro_rules! into_row_count {
943    ($($signed:ty),+ ; $($unsigned:ty),+) => {
944        $(impl IntoRowCount for $signed {
945            fn into_row_count(self) -> RowCount {
946                RowCount(RowCountKind::Literal((self as i64).max(0)))
947            }
948        })+
949        $(impl IntoRowCount for $unsigned {
950            fn into_row_count(self) -> RowCount {
951                RowCount(RowCountKind::Literal(i64::try_from(self).unwrap_or(i64::MAX)))
952            }
953        })+
954    };
955}
956into_row_count!(i8, i16, i32, i64, isize ; u8, u16, u32, u64, usize);
957
958/// A `prepare!{}` placeholder, or any other scope-free `Expr` of an integer type:
959/// bound rather than written, so one prepared query serves every page. Only
960/// the two integer types — a page is a number.
961impl IntoRowCount for Expr<Nil, crate::expr::Integer> {
962    fn into_row_count(self) -> RowCount {
963        RowCount(RowCountKind::Bound(self.kind))
964    }
965}
966
967impl IntoRowCount for Expr<Nil, crate::expr::BigInt> {
968    fn into_row_count(self) -> RowCount {
969        RowCount(RowCountKind::Bound(self.kind))
970    }
971}
972
973/// `LIMIT`/`OFFSET`, with the filler a dialect needs when there's an offset
974/// and no limit — a bare `OFFSET` is Postgres-only.
975pub(crate) fn render_limit_offset<D: Dialect>(
976    sink: &mut dyn Sink,
977    limit: Option<&RowCount>,
978    offset: Option<&RowCount>,
979) {
980    match (limit, offset, D::OFFSET_WITHOUT_LIMIT) {
981        (Some(l), _, _) => {
982            sink.text(" LIMIT ");
983            render_row_count::<D>(sink, l);
984        }
985        (None, Some(_), Some(filler)) => {
986            sink.text(" LIMIT ");
987            sink.text(filler);
988        }
989        _ => {}
990    }
991    if let Some(o) = offset {
992        sink.text(" OFFSET ");
993        render_row_count::<D>(sink, o);
994    }
995}
996
997fn render_row_count<D: Dialect>(sink: &mut dyn Sink, count: &RowCount) {
998    match &count.0 {
999        RowCountKind::Literal(n) => sink.text(&n.to_string()),
1000        RowCountKind::Bound(kind) => render_expr::<D>(kind, sink),
1001    }
1002}