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, 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/// One `name AS (body)` binding, carried in by the `Cte` a query was
34/// entered through. Opaque outside this crate: `JoinSource::binding` is the
35/// only way to make one, and it takes the name and columns from the
36/// marker's `CteShape` rather than from anything a caller can vary.
37#[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
70/// An order-by key: a column/expression tagged with a direction. Built via
71/// `.asc()`/`.desc()` on any column or expression (see `OrderExt` below),
72/// so `.order_by(users::created_at.desc())` reads as one argument, not two.
73pub struct OrderKey<Req> {
74    kind: ExprKind,
75    dir: SortDir,
76    _marker: PhantomData<fn() -> Req>,
77}
78
79// Hand-written for the reason `Expr`'s is: `#[derive(Clone)]` would ask the
80// phantom `Req` to be `Clone`, which no scope list is.
81impl<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    /// The direction as a value, for a sort order that arrives at runtime
106    /// (`?dir=desc`) instead of an N-way match over `.asc()`/`.desc()`.
107    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
124/// Something a query can select from or join to. A schema table brings
125/// nothing with it; a `Cte` brings its `WITH` binding, so attaching that
126/// binding and putting the pseudo-table in scope stay one act. Every join
127/// kind, and `correlated`, work on both without being written twice.
128pub trait JoinSource<D>: join_source::Sealed {
129    /// The table this source contributes to the scope.
130    type Table: Table;
131    /// The `WITH` binding this source carries into the statement. It is
132    /// `None` for a schema table, which is already there.
133    #[doc(hidden)]
134    fn binding(self) -> Option<CteDef>;
135}
136
137mod join_source {
138    /// Sealed the way `dialect::Dialect` is: what a query can read from is
139    /// a closed set of two, a schema table and a bound CTE.
140    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/// Something a query can be ordered by: an `OrderKey` whose tables this
164/// scope contains, or a `SortKey` already discharged against it. `Condition`
165/// makes the same pair for `.filter`.
166#[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/// The same for `GROUP BY`: an expression this scope covers, or a
193/// `grouping(..)` already discharged against it.
194#[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
219/// A sort key whose scope requirement has already been discharged, so a
220/// runtime-length collection of them can be built and passed around, as in
221/// the `?sort=email,-placed_on` case. `select::sort_key` is to `.order_by_all`
222/// what `predicate` is to `.filter_all`.
223pub 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
239/// Discharges a sort key's scope requirement. `Scope` is inferred from the
240/// query the keys are eventually given to. Takes whatever `.order_by` takes,
241/// as `predicate` takes whatever `.filter` does, so a helper generic over
242/// `SortBy` can discharge without knowing which of the two it was handed.
243pub fn sort_key<Scope, Idxs, K: SortBy<Scope, Idxs>>(key: K) -> SortKey<Scope> {
244    key.into_sort_key()
245}
246
247/// A grouping key with its scope requirement discharged: `predicate`'s
248/// counterpart for `GROUP BY`.
249pub 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
263/// Discharges a grouping key's scope requirement, taking whatever
264/// `.group_by` takes, the same shape `predicate` and `sort_key` have.
265pub fn grouping<Scope, Idxs, K: GroupBy<Scope, Idxs>>(key: K) -> Grouping<Scope> {
266    key.into_grouping()
267}
268
269/// Something a query can be filtered by: an `Expr` whose tables this scope
270/// contains, or a `Predicate` already discharged against it. One `.filter`
271/// for both, so which one a condition happens to be doesn't change how it is
272/// applied.
273#[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    /// Discharged against this scope, which for an `Expr` is where its
280    /// `Superset` proof is spent and for a `Predicate` already happened.
281    #[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
304/// `EXISTS (<subquery>)`. Not an `Expr`, because unlike every other
305/// expression this one is dialect-pinned: the subquery it holds was
306/// capability-checked against its own dialect, and any CTE it binds is
307/// already rendered in that dialect. It is therefore a condition and only a
308/// condition: `.filter(..)` it, or `predicate(..)` it into a collection,
309/// onto a query of the same dialect. A `Predicate` carries `D` for this
310/// reason: discharging a condition gives up the tables it named, never the
311/// dialect it was built for.
312pub struct Exists<D, Req> {
313    kind: ExprKind,
314    _marker: PhantomData<fn() -> (D, Req)>,
315}
316
317// Hand-written for the reason `Expr`'s is: `#[derive(Clone)]` would ask the
318// phantom tags to be `Clone`.
319impl<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
337/// `lhs IN (<subquery>)` / `lhs NOT IN (<subquery>)`. Not an `Expr`, for the
338/// same reason `Exists` isn't: the subquery it holds was capability-checked
339/// against its own dialect. `.filter(..)` it, or `predicate(..)` it into a
340/// collection, onto a query of the same dialect.
341pub 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
364/// A condition whose scope requirement has already been discharged, so a
365/// runtime-length collection of them can be built and passed around. An
366/// `Expr` carries the tables it references in its type, which is what makes
367/// `vec![users_cond, orders_cond]` fail to unify; `predicate` trades that
368/// tag for a proof against one concrete scope.
369pub struct Predicate<D, Scope> {
370    kind: ExprKind,
371    _marker: PhantomData<fn() -> (D, Scope)>,
372}
373
374// Hand-written for the reason `Expr`'s is: `#[derive(Clone)]` would ask a
375// phantom `Scope` to be `Clone`.
376impl<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    /// True when any of them is. `expr::any_of` combines conditions that
387    /// reference the same tables; this one combines conditions whose scope
388    /// requirement is already discharged, which is what lets a search form
389    /// OR together conditions from different tables.
390    pub fn any_of(preds: impl IntoIterator<Item = Predicate<D, Scope>>) -> Self {
391        Predicate::combine(preds, false)
392    }
393
394    /// True when all of them are: the AND to `any_of`'s OR, so a group of
395    /// them can be nested inside one.
396    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
412/// Discharges a condition's scope requirement, so a runtime-length
413/// collection of them can be built and passed around. `Scope` and `D` are
414/// inferred from the query the resulting predicates are eventually given to.
415pub fn predicate<D, Scope, Idxs, C: Condition<D, Scope, Idxs>>(cond: C) -> Predicate<D, Scope> {
416    cond.into_predicate()
417}
418
419/// Holds just the `SELECT` list until `.from(..)` supplies the first table
420/// and therefore the query's initial `Scope`. Splitting this out, rather
421/// than requiring `Scope` be known at `.select(..)` time, is what lets the
422/// builder read in `SELECT -> FROM -> ...` order. Every selected column is
423/// still validated against the *final* scope, once, at the query's terminal
424/// method (`.to_sql(Postgres)`/`.load()`).
425pub 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    /// `SELECT <expr>` with no `FROM` at all (`now()`,
435    /// `current_setting('..')`, `pg_try_advisory_lock($1)`): a value the
436    /// database computes rather than a row it reads.
437    ///
438    /// The seed is the whole statement here, which is why this sits on it
439    /// rather than on `Select`: without a `FROM` there is no scope, so no
440    /// join, filter or ordering has anything to name. What makes it safe is
441    /// the empty scope itself: a selection is checked against `Nil`, so a
442    /// column reference has nowhere to resolve and does not compile.
443    ///
444    /// **Known limitations**: this shape is the statement and nothing else.
445    /// It cannot be `.prepare()`d (a bound value goes in a `sql!{}` slot
446    /// instead). It cannot be a `UNION` branch, a CTE body, or an `EXISTS`
447    /// subquery. It cannot be `.count()`ed either: a `SELECT` with
448    /// no `FROM` returns one row, so counting it answers nothing.
449    ///
450    /// The dialect is an argument for the reason `Select::to_sql`'s is.
451    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    /// `source` is a value, not a turbofish: a schema table's zero-sized
462    /// token (`users::Table`) or a `cte::with(..)` binding. A CTE brings its
463    /// `WITH` clause along, so it cannot be selected from unbound.
464    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/// Every clause of a `SELECT` except the selection list, which `Select`
479/// keeps typed and `DynSelect` keeps rendered. Held whole by both, so a new
480/// clause is added here once instead of being threaded through each of them
481/// and through rendering by hand.
482#[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    /// `SELECT count(*)` over this body with its paging dropped: a total
513    /// counts the rows that match, not the page being shown.
514    ///
515    /// A query whose rows aren't one per matching row is counted by
516    /// wrapping it, selection and all, since what a page of it would show is
517    /// what has to be counted. The rule is stated as what may be left
518    /// unwrapped (plain columns, no `GROUP BY`/`HAVING`/`DISTINCT`) rather
519    /// than as a list of what may not: an aggregate collapses the rows too,
520    /// and `sql!` can hold anything at all.
521    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    /// Attaches whatever `WITH` binding a join source carries before its
545    /// table is named in a FROM or JOIN clause.
546    fn bind<D, S: JoinSource<D>>(&mut self, source: S) {
547        self.ctes.extend(source.binding());
548    }
549}
550
551/// A `SELECT`. `Outer` is the scope this query was built *against*: `Nil`
552/// for a query of its own, and the outer query's scope for one started by
553/// `.correlated(..)`, which is what lets `EXISTS` report the outer tables it
554/// references. Defaulted, so a query that isn't a subquery never spells it.
555pub struct Select<D, Scope, Sel, Outer = Nil> {
556    body: SelectBody,
557    selection: Sel,
558    _marker: PhantomData<fn() -> (D, Scope, Outer)>,
559}
560
561// Cloning is what lets one built-up query serve both a count and a page.
562impl<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    /// Swaps the selection list, keeping every clause. With `Clone`, this is
582    /// how one built-up query serves both a count and a page.
583    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    /// AND-folded, and callable any number of times (conditionally, in a
592    /// loop, from a helper) without changing `Self`'s type, so the most
593    /// common kind of dynamic query needs no escape hatch.
594    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    /// AND-folds a runtime-length collection of already-discharged
600    /// conditions, the shape a search form has, where the conditions come
601    /// from different tables and so can't share one `Expr` type.
602    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    /// Appends a runtime-length collection of already-discharged sort keys,
616    /// the shape a `?sort=` parameter has, where the keys name different
617    /// tables and so can't share one `OrderKey` type.
618    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    /// `.order_by(..)`, but the key also has to be in this query's
626    /// selection. `Sel::Output` has to hold it, through the same `row::Field`
627    /// lookup `Row::get` and `SetOp::order_by_column` take, rather than the
628    /// key only being in scope. This is the exact rule `SELECT DISTINCT`
629    /// puts on a sort key (Postgres rejects one that isn't selected), so
630    /// pairing this with `.distinct()` leaves that rejected SQL unwritable.
631    ///
632    /// What gets rendered is the *selected* item the lookup landed on, for
633    /// the reason `SetOp::order_by_column` renders the ordinal rather than
634    /// the key it was handed: a key names a field, not an expression, and
635    /// two window functions over different frames share one. The index that
636    /// proves the lookup is the position that reads the item, so the check
637    /// and the rendered clause are one fact.
638    ///
639    /// **Known limitation**: `.reselect(..)` afterwards keeps the clause and
640    /// drops the guarantee. Swap the selection before sorting by it.
641    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    /// `.order_by_selected(..)` for a single un-tupled selection
655    /// (`select(users::email)`, not `select((users::email,))`): there is
656    /// exactly one selected column, so there is nothing to name. It has the
657    /// same shape `SetOp`'s single-column `.order_by(dir)` has, and the same
658    /// `.reselect(..)` caveat.
659    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    /// `SELECT DISTINCT`: one row per distinct selected tuple. The natural
670    /// answer to a one-to-many join that repeats its left side, and unlike a
671    /// `GROUP BY` of the whole selection it doesn't have to be restated when
672    /// the selection changes. Idempotent: a query is distinct or it isn't.
673    ///
674    /// **Known limitation**: Postgres requires a `SELECT DISTINCT`'s sort
675    /// keys to be in its selection, and nothing here enforces that for
676    /// plain `.order_by(..)`. Use `.order_by_selected(..)`/
677    /// `.order_by_selection(..)` instead, which check exactly this. `GROUP
678    /// BY` has a related but different gap: every non-aggregated selected
679    /// column has to appear in it, which is the selection-into-`GROUP BY`
680    /// direction rather than the `GROUP BY`-into-selection one
681    /// `row::Field` can check, so it stays unchecked. `count_sql` won't
682    /// show either problem, since a total drops the `ORDER BY`.
683    pub fn distinct(mut self) -> Self {
684        self.body.distinct = true;
685        self
686    }
687
688    /// Appends one grouping key; callable multiple times like `.filter()`
689    /// (each call adds a column to the `GROUP BY` list, it doesn't replace
690    /// it), for the same "dynamic composition without a type change" reason.
691    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    /// The same for a runtime-length collection of discharged grouping
697    /// keys, as `order_by_all` is to `order_by`.
698    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    /// A `WHERE`-shaped filter applied after grouping (aggregate
704    /// conditions), AND-folded across calls exactly like `.filter()`.
705    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    /// The same for a runtime-length collection of discharged conditions,
711    /// as `filter_all` is to `filter`.
712    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    /// The joined table is in scope for the `ON` condition, and so is
730    /// everything already joined. The scope the condition is discharged
731    /// against is the one the join produces, not the one it started from.
732    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    /// RIGHT JOIN retroactively flips every already-joined table to
767    /// nullable (`MapNullable`) before adding the new, guaranteed-present
768    /// table, mirroring Drizzle's `AppendToNullabilityMap` rule.
769    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
808/// The terminal methods, and so only for a query of its own: a subquery
809/// (`Outer != Nil`) references its outer query's tables, and rendering one
810/// on its own would name tables that aren't in its `FROM`. It reaches SQL
811/// through `exists`/`not_exists` instead.
812impl<D: Dialect, Scope, Sel> Select<D, Scope, Sel> {
813    /// The terminal step, and the *only* point each selected column's
814    /// scope-membership is checked. Membership is proven as a side effect of
815    /// `Sel: Selection<Scope, Idx>` type-checking at all.
816    ///
817    /// The dialect is an argument rather than a turbofish, so a query that
818    /// is rendered instead of executed says which SQL it wants in the one
819    /// place that decides. Everything before it infers, the way a table or a
820    /// column does.
821    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    /// How many rows this query would return, ignoring its
829    /// `ORDER BY`/`LIMIT`/`OFFSET`. A total is about what matches, not about
830    /// the page being shown. `reselect(count())` keeps them, which is what
831    /// makes it the wrong tool for a paginated total.
832    ///
833    /// A grouped query counts its *groups*, since that is what a page of it
834    /// would show, so the body becomes a subquery rather than having its
835    /// `GROUP BY` dropped or kept.
836    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    /// This query as an embeddable `Fragment`: an `EXISTS (..)` subquery, a
846    /// CTE body, or a set-operation branch. The only way to produce one, so
847    /// no caller has to remember that an embedded query renders with `?`
848    /// placeholders rather than `D`'s own style. `Outer = Nil` like the
849    /// other terminals: a correlated subquery names tables that aren't in
850    /// its own `FROM`, and reaches SQL through `EXISTS` instead.
851    pub(crate) fn fragment<Idx>(&self) -> Fragment
852    where
853        Sel: Selection<Scope, Idx>,
854    {
855        let mut sink = FragmentSink::new();
856        self.render_body_into::<Idx>(&mut sink);
857        sink.finish()
858    }
859
860    pub(crate) fn render_body_into<Idx>(&self, sink: &mut dyn crate::render::Sink)
861    where
862        Sel: Selection<Scope, Idx>,
863    {
864        self.body.render_into::<D>(&self.selection.items(), sink);
865    }
866
867    fn render_as<Idx>(&self) -> (String, Vec<Value>)
868    where
869        Sel: Selection<Scope, Idx>,
870    {
871        let mut sink = QuerySink::<D>::new();
872        self.body
873            .render_into::<D>(&self.selection.items(), &mut sink);
874        sink.finish()
875    }
876}
877
878impl SelectBody {
879    pub(crate) fn render_into<D: Dialect>(&self, selection: &[SelectItem], sink: &mut dyn Sink) {
880        let SelectBody {
881            ctes,
882            distinct,
883            from_table,
884            joins,
885            wheres,
886            order_by,
887            group_by,
888            having,
889            limit,
890            offset,
891        } = self;
892
893        if !ctes.is_empty() {
894            sink.text("WITH ");
895            for (i, cte) in ctes.iter().enumerate() {
896                if i > 0 {
897                    sink.text(", ");
898                }
899                crate::render::render_ident::<D>(sink, cte.name);
900                sink.text(" (");
901                for (i, col) in cte.column_names.iter().enumerate() {
902                    if i > 0 {
903                        sink.text(", ");
904                    }
905                    crate::render::render_ident::<D>(sink, col);
906                }
907                sink.text(") AS (");
908                cte.body.splice_into(sink);
909                sink.ch(')');
910            }
911            sink.ch(' ');
912        }
913        sink.text("SELECT ");
914        if *distinct {
915            sink.text("DISTINCT ");
916        }
917
918        render_select_list::<D>(selection, sink);
919
920        sink.text(" FROM ");
921        crate::render::render_ident::<D>(sink, from_table);
922
923        for j in joins {
924            sink.ch(' ');
925            sink.text(match j.kind {
926                JoinKind::Inner => "INNER JOIN",
927                JoinKind::Left => "LEFT JOIN",
928                JoinKind::Right => "RIGHT JOIN",
929                JoinKind::Full => "FULL JOIN",
930            });
931            sink.ch(' ');
932            crate::render::render_ident::<D>(sink, j.table);
933            sink.text(" ON ");
934            render_expr::<D>(&j.on, sink);
935        }
936
937        render_and_list::<D>(sink, " WHERE ", wheres);
938
939        render_expr_list::<D>(sink, " GROUP BY ", group_by);
940        render_and_list::<D>(sink, " HAVING ", having);
941        render_order_by::<D>(sink, " ORDER BY ", order_by);
942        render_limit_offset::<D>(sink, limit.as_ref(), offset.as_ref());
943    }
944}
945
946/// Starts a correlated subquery against a scope, rather than against a
947/// query. `UPDATE`/`DELETE`, whose scope is the one table they write,
948/// therefore reach the same `EXISTS` a `SELECT` does without conjuring a
949/// `Select` they don't otherwise need.
950pub(crate) fn correlated_with<D, Scope, S: JoinSource<D>, InnerSel>(
951    source: S,
952    selection: InnerSel,
953) -> Select<D, Cons<TableSlot<S::Table, NotNull>, Scope>, InnerSel, Scope> {
954    let mut body = SelectBody::new(<S::Table as Table>::NAME);
955    body.bind(source);
956    Select {
957        body,
958        selection,
959        _marker: PhantomData,
960    }
961}
962
963impl<D, Scope, Sel, Outer> Select<D, Scope, Sel, Outer> {
964    /// Starts a correlated subquery: a fresh `SELECT` whose scope is
965    /// `Cons<TableSlot<T, NotNull>, Scope>`: the new table, prepended onto
966    /// *this* (outer) query's entire scope. Because `Find`/`Superset` walk
967    /// the whole flat cons-list regardless of where it came from, the
968    /// subquery's `.filter()` can reference both its own new table's
969    /// columns and any outer column already in `Scope`, with no special
970    /// casing: growing the scope works the same whether the new table came
971    /// from a join or from a subquery's `FROM`.
972    ///
973    /// The result is an ordinary `Select`, carrying this query's scope as
974    /// its `Outer`, which is what `exists` reports. Every clause it takes is
975    /// the one `Select` already has.
976    pub fn correlated<S: JoinSource<D>, InnerSel>(
977        &self,
978        source: S,
979        selection: InnerSel,
980    ) -> Select<D, Cons<TableSlot<S::Table, NotNull>, Scope>, InnerSel, Scope> {
981        correlated_with(source, selection)
982    }
983}
984
985impl<D: Dialect, Scope, Sel, Outer: ScopeTables> Select<D, Scope, Sel, Outer> {
986    /// `EXISTS (<this query>)`, tagged with the outer tables it references
987    /// so it can only be filtered onto a query that has them in scope. Its
988    /// own column references were already checked against `Scope` when it
989    /// was built. On a query that isn't a subquery, `Outer` is `Nil` and
990    /// this is an uncorrelated `EXISTS`.
991    pub fn exists<Idx>(&self) -> Exists<D, Outer::Tables>
992    where
993        Sel: Selection<Scope, Idx>,
994    {
995        self.exists_kind::<Idx>(false)
996    }
997
998    pub fn not_exists<Idx>(&self) -> Exists<D, Outer::Tables>
999    where
1000        Sel: Selection<Scope, Idx>,
1001    {
1002        self.exists_kind::<Idx>(true)
1003    }
1004
1005    fn exists_kind<Idx>(&self, negated: bool) -> Exists<D, Outer::Tables>
1006    where
1007        Sel: Selection<Scope, Idx>,
1008    {
1009        Exists {
1010            kind: ExprKind::Exists {
1011                body: Box::new(self.body.clone()),
1012                selection: self.selection.items(),
1013                negated,
1014            },
1015            _marker: PhantomData,
1016        }
1017    }
1018
1019    /// `lhs IN (<this query>)`. This query selects exactly one column
1020    /// (`Sel: RowField`, so a bare column, aggregate, or labelled one of
1021    /// those, never a tuple), so its SQL type can be checked against `lhs`
1022    /// the same way `.eq(..)` checks two columns: `RowField::Sql` carries
1023    /// the marker a decoded `Selection::Output` has already resolved away.
1024    /// Tagged with the outer tables `lhs` and this query's own `Outer`
1025    /// reference, so it can only be filtered onto a query that has both in
1026    /// scope.
1027    ///
1028    /// **Known limitation**: membership only. A *scalar* subquery
1029    /// (`col = (SELECT max(x) ..)`) stays deferred. It would have to be an
1030    /// `Expr`, which carries no dialect to pin the subquery's capability
1031    /// check to.
1032    pub fn contains<Lhs, Idx>(
1033        &self,
1034        lhs: Lhs,
1035    ) -> InSubquery<D, <Outer::Tables as Concat<Lhs::Req>>::Output>
1036    where
1037        Lhs: IntoExpr,
1038        Lhs::Sql: Comparable<Sel::Sql>,
1039        Sel: RowField<Scope, Idx> + Selection<Scope, Idx>,
1040        Outer::Tables: Concat<Lhs::Req>,
1041    {
1042        self.in_subquery_kind::<Lhs, Idx>(lhs, false)
1043    }
1044
1045    pub fn not_contains<Lhs, Idx>(
1046        &self,
1047        lhs: Lhs,
1048    ) -> InSubquery<D, <Outer::Tables as Concat<Lhs::Req>>::Output>
1049    where
1050        Lhs: IntoExpr,
1051        Lhs::Sql: Comparable<Sel::Sql>,
1052        Sel: RowField<Scope, Idx> + Selection<Scope, Idx>,
1053        Outer::Tables: Concat<Lhs::Req>,
1054    {
1055        self.in_subquery_kind::<Lhs, Idx>(lhs, true)
1056    }
1057
1058    fn in_subquery_kind<Lhs, Idx>(
1059        &self,
1060        lhs: Lhs,
1061        negated: bool,
1062    ) -> InSubquery<D, <Outer::Tables as Concat<Lhs::Req>>::Output>
1063    where
1064        Lhs: IntoExpr,
1065        Lhs::Sql: Comparable<Sel::Sql>,
1066        Sel: RowField<Scope, Idx> + Selection<Scope, Idx>,
1067        Outer::Tables: Concat<Lhs::Req>,
1068    {
1069        InSubquery {
1070            kind: ExprKind::InSubquery {
1071                lhs: Box::new(lhs.into_expr().kind),
1072                body: Box::new(self.body.clone()),
1073                selection: self.selection.items(),
1074                negated,
1075            },
1076            _marker: PhantomData,
1077        }
1078    }
1079}
1080
1081/// A number of rows, which is what a `LIMIT` and an `OFFSET` each are: an
1082/// integer, or a `prepare!{}` placeholder for one, so a paginated endpoint
1083/// can prepare its query once and vary the page. A trait rather than
1084/// `Into<i64>` so a `usize` page size, the shape a paginated handler already
1085/// has, goes in without a cast. Every numeric impl lands in `0..=i64::MAX`:
1086/// a negative count is not a query any database will run, and a `usize` past
1087/// `i64::MAX` is not a page anyone is asking for.
1088#[diagnostic::on_unimplemented(
1089    message = "`{Self}` isn't a number of rows",
1090    label = "an integer, or a `prepare!{{}}` placeholder of type `Integer`/`BigInt`"
1091)]
1092pub trait IntoRowCount {
1093    fn into_row_count(self) -> RowCount;
1094}
1095
1096/// What a `LIMIT`/`OFFSET` clause holds. Opaque: the `IntoRowCount` impls
1097/// are the only way to make one.
1098#[derive(Debug, Clone)]
1099pub struct RowCount(RowCountKind);
1100
1101#[derive(Debug, Clone)]
1102enum RowCountKind {
1103    /// Written into the SQL text: a page size is not a value the plan
1104    /// should be reused across.
1105    Literal(i64),
1106    /// A bound parameter, which is what a `prepare!{}` placeholder is.
1107    Bound(ExprKind),
1108}
1109
1110macro_rules! into_row_count {
1111    ($($signed:ty),+ ; $($unsigned:ty),+) => {
1112        $(impl IntoRowCount for $signed {
1113            fn into_row_count(self) -> RowCount {
1114                RowCount(RowCountKind::Literal((self as i64).max(0)))
1115            }
1116        })+
1117        $(impl IntoRowCount for $unsigned {
1118            fn into_row_count(self) -> RowCount {
1119                RowCount(RowCountKind::Literal(i64::try_from(self).unwrap_or(i64::MAX)))
1120            }
1121        })+
1122    };
1123}
1124into_row_count!(i8, i16, i32, i64, isize ; u8, u16, u32, u64, usize);
1125
1126/// A `prepare!{}` placeholder, or any other scope-free `Expr` of an integer
1127/// type: bound rather than written, so one prepared query serves every page.
1128/// Only the two integer types, since a page is a number.
1129impl IntoRowCount for Expr<Nil, crate::expr::Integer> {
1130    fn into_row_count(self) -> RowCount {
1131        RowCount(RowCountKind::Bound(self.kind))
1132    }
1133}
1134
1135impl IntoRowCount for Expr<Nil, crate::expr::BigInt> {
1136    fn into_row_count(self) -> RowCount {
1137        RowCount(RowCountKind::Bound(self.kind))
1138    }
1139}
1140
1141/// `LIMIT`/`OFFSET`, with the filler a dialect needs when there's an offset
1142/// and no limit, since a bare `OFFSET` is Postgres-only.
1143pub(crate) fn render_limit_offset<D: Dialect>(
1144    sink: &mut dyn Sink,
1145    limit: Option<&RowCount>,
1146    offset: Option<&RowCount>,
1147) {
1148    match (limit, offset, D::OFFSET_WITHOUT_LIMIT) {
1149        (Some(l), _, _) => {
1150            sink.text(" LIMIT ");
1151            render_row_count::<D>(sink, l);
1152        }
1153        (None, Some(_), Some(filler)) => {
1154            sink.text(" LIMIT ");
1155            sink.text(filler);
1156        }
1157        _ => {}
1158    }
1159    if let Some(o) = offset {
1160        sink.text(" OFFSET ");
1161        render_row_count::<D>(sink, o);
1162    }
1163}
1164
1165fn render_row_count<D: Dialect>(sink: &mut dyn Sink, count: &RowCount) {
1166    match &count.0 {
1167        RowCountKind::Literal(n) => sink.text(&n.to_string()),
1168        RowCountKind::Bound(kind) => render_expr::<D>(kind, sink),
1169    }
1170}