Skip to main content

qbrs_core/select/
selection.rs

1//! What a `.select(..)` list decodes to once a row comes back.
2
3use crate::expr::{Column, ColumnKey, ExprKind, Keyed, LabelKey, Labeled, SqlType};
4use crate::render::SelectItem;
5use std::marker::PhantomData;
6
7use crate::row::{Named, Row, RowCons, RowKey, RowNil};
8use crate::scope::{Find, Superset, Table, WrapNullable};
9
10/// Sealed for the reason `InsertRow` is: these traits pair a type-level
11/// claim (`Fields`/`Output`) with the runtime list of `SelectItem`s that is
12/// supposed to match it, and only the impls in this crate keep the two in
13/// step. A hand-written one could select a row that decodes transposed,
14/// which is the failure `row::SameShape` and column-keyed rows exist to stop.
15mod private {
16    /// Carries the trait's own parameters, for the reason `scope::proof`
17    /// explains: `Self` can be an honest `Column<C>` while the free `Idx`
18    /// is the caller's own type, so a seal on `Self` alone admits the
19    /// forgery. A private proof *type* is no better: projection reaches it.
20    pub trait Sealed<Scope, Idx> {}
21}
22
23/// `AllColumns`/`CteShape` are emitted in the schema's own crate, so their
24/// seal has to be nameable there. It is a separate trait, because sharing
25/// `private::Sealed` would hand out the one line that unseals `Selection`
26/// too, and a hand-written `Selection` is exactly what the seal is for.
27#[doc(hidden)]
28pub trait SelectableSealed {}
29
30impl<C, Scope, Idx> private::Sealed<Scope, Idx> for Column<C>
31where
32    C: crate::expr::ColumnKey,
33    Scope: Find<C::Table, Idx>,
34{
35}
36
37impl<K, Req, S: SqlType, Scope, Idx> private::Sealed<Scope, Idx> for Keyed<K, Req, S> where
38    Scope: Superset<Req, Idx>
39{
40}
41
42impl<K, Inner, Scope, Idx> private::Sealed<Scope, Idx> for Labeled<K, Inner> where
43    Inner: RowField<Scope, Idx>
44{
45}
46
47impl<T: AllColumns, Scope, Idx> private::Sealed<Scope, Idx> for All<T> where
48    T::Columns: ColumnList<Scope, Idx>
49{
50}
51
52/// What a single un-tupled selection decodes to: a bare native value, or
53/// its `Option`. Sealed by construction, since the impls come from the same
54/// `sql_leaf_type!` that declares the types. It is what gives a one-column
55/// set operation an `ORDER BY` with no position to state.
56pub trait SingleColumn {}
57
58/// One *field* of a resulting `Row`: the key its value is filed under, and
59/// the Rust type it decodes to. A selection list is a chain of
60/// `SelectionPart`s, one of which (`All`) carries many of these at once.
61///
62/// Parameterized by `Scope` so a bare column's `Value` is `Option<T>` when,
63/// and only when, that column's table is nullable in *this* query, via
64/// `scope::Find::Nullability` + `WrapNullable`. Nullability is therefore
65/// derived from join shape rather than asserted with a manual `.nullable()`.
66///
67/// Scope membership is proven as a side effect of this trait type-checking
68/// at all, through the `Find`/`Superset` bounds below, so callers need no
69/// separate check.
70#[diagnostic::on_unimplemented(
71    message = "`{Self}` can't be a field of this query's rows",
72    label = "a column, an aggregate, a window function, a `sql!` fragment, or a labelled one of those can be",
73    note = "an expression the builder inferred a type for (a comparison, an `is_null`, a `LIKE`) has to state what it decodes to with `.decodes_as::<..>()`, since that inference can contradict the join; a `sql!` fragment already states it"
74)]
75pub trait RowField<Scope, Idx>: RowKey + private::Sealed<Scope, Idx> {
76    type Value;
77    /// This field's SQL type: the marker `Value` has already resolved away
78    /// to a native Rust type. A single-column subquery (`Select::contains`)
79    /// needs this to compare its selected column against an outer
80    /// expression with `expr::Comparable`, which a native `Value` can't do.
81    type Sql: SqlType;
82    fn item(&self) -> SelectItem;
83}
84
85impl<C: ColumnKey, Scope, Idx> RowField<Scope, Idx> for Column<C>
86where
87    Scope: Find<C::Table, Idx>,
88    C::Sql: WrapNullable<<Scope as Find<C::Table, Idx>>::Nullability>,
89    <C::Sql as WrapNullable<<Scope as Find<C::Table, Idx>>::Nullability>>::Output: SqlType,
90{
91    type Value = <<C::Sql as WrapNullable<
92        <Scope as Find<C::Table, Idx>>::Nullability,
93    >>::Output as SqlType>::Native;
94    type Sql = <C::Sql as WrapNullable<<Scope as Find<C::Table, Idx>>::Nullability>>::Output;
95    fn item(&self) -> SelectItem {
96        SelectItem::bare(ExprKind::Column {
97            table: <C::Table as Table>::NAME,
98            name: C::NAME,
99        })
100    }
101}
102
103impl<K, Req, S: SqlType, Scope, Idx> RowField<Scope, Idx> for Keyed<K, Req, S>
104where
105    Scope: Superset<Req, Idx>,
106{
107    type Value = S::Native;
108    type Sql = S;
109    fn item(&self) -> SelectItem {
110        SelectItem::bare(self.kind.clone())
111    }
112}
113
114/// A label renames whatever it wraps and changes nothing else, so this is
115/// one impl rather than one per selectable: the inner value decides the
116/// scope check and the decoded type, the label decides the `AS` and the row
117/// key.
118impl<K: LabelKey, Inner: RowField<Scope, Idx>, Scope, Idx> RowField<Scope, Idx>
119    for Labeled<K, Inner>
120{
121    type Value = Inner::Value;
122    type Sql = Inner::Sql;
123    fn item(&self) -> SelectItem {
124        SelectItem::labeled(self.inner.item().kind, <K as Named>::NAME)
125    }
126}
127
128/// A whole `SELECT` list. A tuple decodes to a `row::Row` keyed by each
129/// element's `RowField::Key`; a single un-tupled element decodes to its bare
130/// value, since there is nothing to key it against.
131#[diagnostic::on_unimplemented(
132    message = "`{Self}` isn't a valid selection list here",
133    label = "a selection is a column, an aggregate, a window function, a `sql!` fragment, a labelled one of those, `<table>::All`, or a tuple of up to 32 of them",
134    note = "every element has to be in scope, so `.from(..)`/`.join(..)` the tables it names; an expression the builder inferred a type for also has to state its decoded type with `.decodes_as::<..>()`"
135)]
136pub trait Selection<Scope, Idx>: private::Sealed<Scope, Idx> {
137    type Output;
138    fn items(&self) -> Vec<SelectItem>;
139}
140
141macro_rules! scalar_selection {
142    (impl[$($generics:tt)*] $ty:ty) => {
143        impl<$($generics)*, Scope, Idx> Selection<Scope, Idx> for $ty
144        where
145            $ty: RowField<Scope, Idx>,
146        {
147                    type Output = <$ty as RowField<Scope, Idx>>::Value;
148            fn items(&self) -> Vec<SelectItem> {
149                vec![RowField::item(self)]
150            }
151        }
152    };
153}
154
155/// One element of a selection list. A column or an expression contributes
156/// one field; `All` contributes a whole table's worth, and a tuple whatever
157/// its own elements do. `Fields<Tail>` is what it puts in front of whatever
158/// the rest of the list contributes, so a list is assembled by nesting
159/// rather than by concatenating afterwards.
160///
161/// A tuple being one of these is what lets a selection be named once and
162/// used in several places: a `const` of columns goes into `select(..)` on
163/// its own and into a longer tuple beside an aggregate, with no macro to
164/// expand it at each call site.
165#[diagnostic::on_unimplemented(
166    message = "`{Self}` can't be part of a selection list",
167    label = "a column, an aggregate, a window function, a `sql!` fragment, a labelled one of those, `<table>::All`, or a tuple of those can be",
168    note = "an expression the builder inferred a type for (a comparison, an `is_null`, a `LIKE`) has to state what it decodes to with `.decodes_as::<..>()`, since that inference can contradict the join"
169)]
170pub trait SelectionPart<Scope, Idx>: private::Sealed<Scope, Idx> {
171    type Fields<Tail>;
172    fn push_items(&self, out: &mut Vec<SelectItem>);
173}
174
175macro_rules! field_part {
176    (impl[$($generics:tt)*] $ty:ty) => {
177        impl<$($generics)*, Scope, Idx> SelectionPart<Scope, Idx> for $ty
178        where
179            $ty: RowField<Scope, Idx>,
180        {
181                    type Fields<Tail> = RowCons<
182                <$ty as RowKey>::Key,
183                <$ty as RowField<Scope, Idx>>::Value,
184                Tail,
185            >;
186            fn push_items(&self, out: &mut Vec<SelectItem>) {
187                out.push(RowField::item(self));
188            }
189        }
190    };
191}
192/// Everything selectable on its own: as a whole list of one, and as one
193/// part of a longer list. Stated once, since a selectable that is one and
194/// not the other has never been a thing.
195macro_rules! selectable {
196    (impl[$($generics:tt)*] $ty:ty) => {
197        scalar_selection!(impl[$($generics)*] $ty);
198        field_part!(impl[$($generics)*] $ty);
199    };
200}
201selectable!(impl[C: ColumnKey] Column<C>);
202selectable!(impl[K, Req, S: SqlType] Keyed<K, Req, S>);
203selectable!(impl[K, Inner] Labeled<K, Inner>);
204
205/// Every column of one table, in declaration order, as in
206/// `select(users::All)`. The table's own `#[derive(Table)]` supplies the
207/// chain through `AllColumns`, so a selection list and the schema cannot
208/// drift apart, and a whole table counts as one element of a tuple however
209/// many columns it has.
210pub struct All<T>(PhantomData<fn() -> T>);
211
212impl<T> All<T> {
213    pub const fn new() -> Self {
214        All(PhantomData)
215    }
216}
217
218impl<T> Clone for All<T> {
219    fn clone(&self) -> Self {
220        *self
221    }
222}
223impl<T> Copy for All<T> {}
224
225impl<T> Default for All<T> {
226    fn default() -> Self {
227        All::new()
228    }
229}
230
231/// What `#[derive(Table)]` emits so `All<Table>` knows the table's columns
232/// and what each of them decodes to in a given scope.
233pub trait AllColumns: SelectableSealed {
234    /// The table's columns as a type-level list, `Cons<Column<C>, ..>`.
235    /// The row and the rendered items are both computed from it here, so a
236    /// hand-written impl can name a different set of columns but can never
237    /// make the two disagree. While this trait stated the row and pushed the
238    /// items separately, a schema's own crate could.
239    type Columns;
240}
241
242/// The list `AllColumns` names, walked once for the row's fields and once
243/// for the items. Implemented for `Nil` and `Cons<Column<C>, Tail>` only,
244/// and only here. It is sealed because this trait *is* the pairing
245/// `AllColumns` was split up to remove: it states the row and pushes the
246/// items separately, so a hand-written impl could transpose them. Nothing
247/// outside this crate implements it, so an ordinary private supertrait is
248/// enough; no `Proof` is needed.
249mod column_list {
250    pub trait Sealed {}
251    impl Sealed for crate::scope::Nil {}
252    impl<C: crate::expr::ColumnKey, Tail> Sealed for crate::scope::Cons<crate::expr::Column<C>, Tail> {}
253}
254
255pub trait ColumnList<Scope, Idx>: column_list::Sealed {
256    type Fields<Tail>;
257    fn push_items(out: &mut Vec<SelectItem>);
258}
259
260impl<Scope, Idx> ColumnList<Scope, Idx> for crate::scope::Nil {
261    type Fields<Tail> = Tail;
262    fn push_items(_out: &mut Vec<SelectItem>) {}
263}
264
265impl<C: ColumnKey, Tail, Scope, Idx> ColumnList<Scope, Idx> for crate::scope::Cons<Column<C>, Tail>
266where
267    Column<C>: RowField<Scope, Idx>,
268    Tail: ColumnList<Scope, Idx>,
269{
270    type Fields<T> = RowCons<C, <Column<C> as RowField<Scope, Idx>>::Value, Tail::Fields<T>>;
271    fn push_items(out: &mut Vec<SelectItem>) {
272        out.push(RowField::item(&Column::<C>::new()));
273        Tail::push_items(out);
274    }
275}
276
277impl<T: AllColumns, Scope, Idx> SelectionPart<Scope, Idx> for All<T>
278where
279    T::Columns: ColumnList<Scope, Idx>,
280{
281    type Fields<Tail> = <T::Columns as ColumnList<Scope, Idx>>::Fields<Tail>;
282    fn push_items(&self, out: &mut Vec<SelectItem>) {
283        <T::Columns as ColumnList<Scope, Idx>>::push_items(out);
284    }
285}
286
287impl<T: AllColumns, Scope, Idx> Selection<Scope, Idx> for All<T>
288where
289    T::Columns: ColumnList<Scope, Idx>,
290{
291    type Output = Row<<T::Columns as ColumnList<Scope, Idx>>::Fields<RowNil>>;
292    fn items(&self) -> Vec<SelectItem> {
293        let mut out = Vec::new();
294        <T::Columns as ColumnList<Scope, Idx>>::push_items(&mut out);
295        out
296    }
297}
298
299/// The fields a list contributes, nested in front of whatever follows it.
300/// `$tail` is `RowNil` for a whole selection and the rest of the outer list
301/// for a nested one, which is the only difference between the two.
302macro_rules! row_chain {
303    ($tail:ty; $n:ident $i:ident) => {
304        <$n as SelectionPart<Scope, $i>>::Fields<$tail>
305    };
306    ($tail:ty; $n:ident $i:ident, $($rest:tt)*) => {
307        <$n as SelectionPart<Scope, $i>>::Fields<row_chain!($tail; $($rest)*)>
308    };
309}
310
311macro_rules! tuple_selection {
312    ($($n:ident $i:ident),+) => {
313        impl<Scope, $($n,)+ $($i,)+> private::Sealed<Scope, ($($i,)+)> for ($($n,)+)
314        where
315            $($n: SelectionPart<Scope, $i>,)+
316        {
317        }
318
319        #[allow(non_snake_case)]
320        impl<Scope, $($n,)+ $($i,)+> Selection<Scope, ($($i,)+)> for ($($n,)+)
321        where
322            $($n: SelectionPart<Scope, $i>,)+
323        {
324                    type Output = Row<row_chain!(RowNil; $($n $i),+)>;
325            fn items(&self) -> Vec<SelectItem> {
326                let ($($n,)+) = self;
327                let mut out = Vec::new();
328                $(SelectionPart::push_items($n, &mut out);)+
329                out
330            }
331        }
332
333        #[allow(non_snake_case)]
334        impl<Scope, $($n,)+ $($i,)+> SelectionPart<Scope, ($($i,)+)> for ($($n,)+)
335        where
336            $($n: SelectionPart<Scope, $i>,)+
337        {
338            type Fields<Tail> = row_chain!(Tail; $($n $i),+);
339            fn push_items(&self, out: &mut Vec<SelectItem>) {
340                let ($($n,)+) = self;
341                $(SelectionPart::push_items($n, out);)+
342            }
343        }
344    };
345}
346tuple_selection!(A IA);
347tuple_selection!(A IA, B IB);
348tuple_selection!(A IA, B IB, C IC);
349tuple_selection!(A IA, B IB, C IC, D ID);
350tuple_selection!(A IA, B IB, C IC, D ID, E IE);
351tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF);
352tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG);
353tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH);
354tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II);
355tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ);
356tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK);
357tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL);
358tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM);
359tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN);
360tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO);
361tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO, P IP);
362tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO, P IP, Q IQ);
363tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO, P IP, Q IQ, R IR);
364tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO, P IP, Q IQ, R IR, S IS);
365tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO, P IP, Q IQ, R IR, S IS, T IT);
366tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO, P IP, Q IQ, R IR, S IS, T IT, U IU);
367tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO, P IP, Q IQ, R IR, S IS, T IT, U IU, V IV);
368tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO, P IP, Q IQ, R IR, S IS, T IT, U IU, V IV, W IW);
369tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO, P IP, Q IQ, R IR, S IS, T IT, U IU, V IV, W IW, X IX);
370tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO, P IP, Q IQ, R IR, S IS, T IT, U IU, V IV, W IW, X IX, Y IY);
371tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO, P IP, Q IQ, R IR, S IS, T IT, U IU, V IV, W IW, X IX, Y IY, Z IZ);
372tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO, P IP, Q IQ, R IR, S IS, T IT, U IU, V IV, W IW, X IX, Y IY, Z IZ, AA IAA);
373tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO, P IP, Q IQ, R IR, S IS, T IT, U IU, V IV, W IW, X IX, Y IY, Z IZ, AA IAA, BB IBB);
374tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO, P IP, Q IQ, R IR, S IS, T IT, U IU, V IV, W IW, X IX, Y IY, Z IZ, AA IAA, BB IBB, CC ICC);
375tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO, P IP, Q IQ, R IR, S IS, T IT, U IU, V IV, W IW, X IX, Y IY, Z IZ, AA IAA, BB IBB, CC ICC, DD IDD);
376tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO, P IP, Q IQ, R IR, S IS, T IT, U IU, V IV, W IW, X IX, Y IY, Z IZ, AA IAA, BB IBB, CC ICC, DD IDD, EE IEE);
377tuple_selection!(A IA, B IB, C IC, D ID, E IE, F IF, G IG, H IH, I II, J IJ, K IK, L IL, M IM, N IN, O IO, P IP, Q IQ, R IR, S IS, T IT, U IU, V IV, W IW, X IX, Y IY, Z IZ, AA IAA, BB IBB, CC ICC, DD IDD, EE IEE, FF IFF);