diesel/query_source/aliasing/
field_alias_mapper.rs

1use super::{Alias, AliasSource, AliasedField};
2
3use crate::expression;
4use crate::query_source::{Column, Table, TableNotEqual};
5
6/// Serves to map `Self` to `Alias<S>`
7///
8/// Any column `Self` that belongs to `S::Table` will be transformed into `AliasedField<S, Self>`
9///
10/// Any column `Self` that does not belong to `S::Table` will be left untouched.
11///
12/// This also works with tuples and some expressions.
13// This first part is implemented by the `table!` macro.
14// The second part is useful to implement the joins, and may be useful to an end-user for
15// ergonomics.
16pub trait FieldAliasMapper<S> {
17    /// Output type when mapping `C` to `Alias<S>`
18    ///
19    /// If `C: Column<Table = S::Table>`, `Out = AliasedField<S, C>`  
20    /// Otherwise, `Out = C`
21    type Out;
22
23    /// Does the mapping
24    fn map(self, alias: &Alias<S>) -> Self::Out;
25}
26
27#[doc(hidden)]
28/// Allows implementing `FieldAliasMapper` in external crates without running into conflicting impl
29/// errors due to https://github.com/rust-lang/rust/issues/20400
30///
31/// We will always have `Self = S::Table` and `CT = C::Table`
32pub trait FieldAliasMapperAssociatedTypesDisjointnessTrick<CT, S, C> {
33    type Out;
34    fn map(column: C, alias: &Alias<S>) -> Self::Out;
35}
36impl<S, C> FieldAliasMapper<S> for C
37where
38    S: AliasSource,
39    C: Column,
40    S::Target: FieldAliasMapperAssociatedTypesDisjointnessTrick<C::Table, S, C>,
41{
42    type Out = <S::Target as FieldAliasMapperAssociatedTypesDisjointnessTrick<C::Table, S, C>>::Out;
43
44    fn map(self, alias: &Alias<S>) -> Self::Out {
45        <S::Target as FieldAliasMapperAssociatedTypesDisjointnessTrick<C::Table, S, C>>::map(
46            self, alias,
47        )
48    }
49}
50
51impl<TS, TC, S, C> FieldAliasMapperAssociatedTypesDisjointnessTrick<TC, S, C> for TS
52where
53    S: AliasSource<Target = TS>,
54    C: Column<Table = TC>,
55    TC: Table,
56    TS: TableNotEqual<TC>,
57{
58    type Out = C;
59
60    fn map(column: C, _alias: &Alias<S>) -> Self::Out {
61        // left untouched because the tables are different
62        column
63    }
64}
65
66macro_rules! field_alias_mapper {
67    ($(
68        $Tuple:tt {
69            $(($idx:tt) -> $T:ident, $ST:ident, $TT:ident,)+
70        }
71    )+) => {
72        $(
73            impl<_S, $($T,)*> FieldAliasMapper<_S> for ($($T,)*)
74            where
75                _S: AliasSource,
76                $($T: FieldAliasMapper<_S>,)*
77            {
78                type Out = ($(<$T as FieldAliasMapper<_S>>::Out,)*);
79
80                fn map(self, alias: &Alias<_S>) -> Self::Out {
81                    (
82                        $(self.$idx.map(alias),)*
83                    )
84                }
85            }
86        )*
87    }
88}
89
90impl<_S, T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
    T31> FieldAliasMapper<_S> for
    (T, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16,
    T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31)
    where _S: AliasSource, T: FieldAliasMapper<_S>, T1: FieldAliasMapper<_S>,
    T2: FieldAliasMapper<_S>, T3: FieldAliasMapper<_S>,
    T4: FieldAliasMapper<_S>, T5: FieldAliasMapper<_S>,
    T6: FieldAliasMapper<_S>, T7: FieldAliasMapper<_S>,
    T8: FieldAliasMapper<_S>, T9: FieldAliasMapper<_S>,
    T10: FieldAliasMapper<_S>, T11: FieldAliasMapper<_S>,
    T12: FieldAliasMapper<_S>, T13: FieldAliasMapper<_S>,
    T14: FieldAliasMapper<_S>, T15: FieldAliasMapper<_S>,
    T16: FieldAliasMapper<_S>, T17: FieldAliasMapper<_S>,
    T18: FieldAliasMapper<_S>, T19: FieldAliasMapper<_S>,
    T20: FieldAliasMapper<_S>, T21: FieldAliasMapper<_S>,
    T22: FieldAliasMapper<_S>, T23: FieldAliasMapper<_S>,
    T24: FieldAliasMapper<_S>, T25: FieldAliasMapper<_S>,
    T26: FieldAliasMapper<_S>, T27: FieldAliasMapper<_S>,
    T28: FieldAliasMapper<_S>, T29: FieldAliasMapper<_S>,
    T30: FieldAliasMapper<_S>, T31: FieldAliasMapper<_S> {
    type Out =
        (<T as FieldAliasMapper<_S>>::Out, <T1 as FieldAliasMapper<_S>>::Out,
        <T2 as FieldAliasMapper<_S>>::Out, <T3 as FieldAliasMapper<_S>>::Out,
        <T4 as FieldAliasMapper<_S>>::Out, <T5 as FieldAliasMapper<_S>>::Out,
        <T6 as FieldAliasMapper<_S>>::Out, <T7 as FieldAliasMapper<_S>>::Out,
        <T8 as FieldAliasMapper<_S>>::Out, <T9 as FieldAliasMapper<_S>>::Out,
        <T10 as FieldAliasMapper<_S>>::Out,
        <T11 as FieldAliasMapper<_S>>::Out,
        <T12 as FieldAliasMapper<_S>>::Out,
        <T13 as FieldAliasMapper<_S>>::Out,
        <T14 as FieldAliasMapper<_S>>::Out,
        <T15 as FieldAliasMapper<_S>>::Out,
        <T16 as FieldAliasMapper<_S>>::Out,
        <T17 as FieldAliasMapper<_S>>::Out,
        <T18 as FieldAliasMapper<_S>>::Out,
        <T19 as FieldAliasMapper<_S>>::Out,
        <T20 as FieldAliasMapper<_S>>::Out,
        <T21 as FieldAliasMapper<_S>>::Out,
        <T22 as FieldAliasMapper<_S>>::Out,
        <T23 as FieldAliasMapper<_S>>::Out,
        <T24 as FieldAliasMapper<_S>>::Out,
        <T25 as FieldAliasMapper<_S>>::Out,
        <T26 as FieldAliasMapper<_S>>::Out,
        <T27 as FieldAliasMapper<_S>>::Out,
        <T28 as FieldAliasMapper<_S>>::Out,
        <T29 as FieldAliasMapper<_S>>::Out,
        <T30 as FieldAliasMapper<_S>>::Out,
        <T31 as FieldAliasMapper<_S>>::Out);
    fn map(self, alias: &Alias<_S>) -> Self::Out {
        (self.0.map(alias), self.1.map(alias), self.2.map(alias),
            self.3.map(alias), self.4.map(alias), self.5.map(alias),
            self.6.map(alias), self.7.map(alias), self.8.map(alias),
            self.9.map(alias), self.10.map(alias), self.11.map(alias),
            self.12.map(alias), self.13.map(alias), self.14.map(alias),
            self.15.map(alias), self.16.map(alias), self.17.map(alias),
            self.18.map(alias), self.19.map(alias), self.20.map(alias),
            self.21.map(alias), self.22.map(alias), self.23.map(alias),
            self.24.map(alias), self.25.map(alias), self.26.map(alias),
            self.27.map(alias), self.28.map(alias), self.29.map(alias),
            self.30.map(alias), self.31.map(alias))
    }
}diesel_derives::__diesel_for_each_tuple!(field_alias_mapper);
91
92// The following `FieldAliasMapper` impls are useful for the generic join implementations.
93// More may be added.
94impl<SPrev, SNew, F> FieldAliasMapper<SNew> for AliasedField<SPrev, F>
95where
96    SNew: AliasSource,
97{
98    type Out = Self;
99
100    fn map(self, _alias: &Alias<SNew>) -> Self::Out {
101        // left untouched because it has already been aliased
102        self
103    }
104}
105
106impl<S, F> FieldAliasMapper<S> for expression::nullable::Nullable<F>
107where
108    F: FieldAliasMapper<S>,
109{
110    type Out = expression::nullable::Nullable<<F as FieldAliasMapper<S>>::Out>;
111
112    fn map(self, alias: &Alias<S>) -> Self::Out {
113        expression::nullable::Nullable::new(self.0.map(alias))
114    }
115}
116
117impl<S, F> FieldAliasMapper<S> for expression::grouped::Grouped<F>
118where
119    F: FieldAliasMapper<S>,
120{
121    type Out = expression::grouped::Grouped<<F as FieldAliasMapper<S>>::Out>;
122
123    fn map(self, alias: &Alias<S>) -> Self::Out {
124        expression::grouped::Grouped(self.0.map(alias))
125    }
126}