diesel/pg/query_builder/
distinct_on.rs

1use crate::expression::SelectableExpression;
2use crate::pg::Pg;
3use crate::query_builder::order_clause::NoOrderClause;
4use crate::query_builder::{
5    AstPass, FromClause, QueryFragment, QueryId, SelectQuery, SelectStatement,
6};
7use crate::query_dsl::methods::DistinctOnDsl;
8use crate::query_dsl::order_dsl::ValidOrderingForDistinct;
9use crate::result::QueryResult;
10use crate::sql_types::SingleValue;
11use crate::QuerySource;
12use diesel::query_builder::order_clause::OrderClause;
13
14/// Represents `DISTINCT ON (...)`
15#[derive(Debug, Clone, Copy, QueryId)]
16#[cfg(feature = "postgres_backend")]
17pub struct DistinctOnClause<T>(pub(crate) T);
18
19impl<T> ValidOrderingForDistinct<DistinctOnClause<T>> for NoOrderClause {}
20impl<T> ValidOrderingForDistinct<DistinctOnClause<T>> for OrderClause<(T,)> {}
21impl<T> ValidOrderingForDistinct<DistinctOnClause<T>> for OrderClause<T> where T: crate::Expression {}
22
23impl<T> ValidOrderingForDistinct<DistinctOnClause<T>>
24    for OrderClause<crate::expression::operators::Asc<T>>
25where
26    T: crate::Expression,
27    T::SqlType: SingleValue,
28{
29}
30
31impl<T> ValidOrderingForDistinct<DistinctOnClause<T>>
32    for OrderClause<crate::expression::operators::Desc<T>>
33where
34    T: crate::Expression,
35    T::SqlType: SingleValue,
36{
37}
38
39macro_rules! valid_ordering {
40    // Special-case: for single tuple elements
41    // generate plain impls as well:
42    (
43        @optional_untuple:
44        [generics: $($T: ident)*]
45        [distinct: $D:ident]
46        [order: $O: ty,]
47    ) => {
48        // nothing if both a single tuple elements
49    };
50    (
51        @optional_untuple:
52        [generics: $($T: ident)*]
53        [distinct: $D:ident]
54        [order: $($O: ty,)*]
55    ) => {
56        impl<$($T,)*> ValidOrderingForDistinct<DistinctOnClause<$D>>
57            for OrderClause<($($O,)*)>
58        {}
59    };
60    (
61        @optional_untuple:
62        [generics: $($T: ident)*]
63        [distinct: $($D:ident)*]
64        [order: $O: ty,]
65    ) => {
66        impl<$($T,)*> ValidOrderingForDistinct<DistinctOnClause<($($D,)*)>>
67            for OrderClause<$O>
68        {}
69    };
70    (
71        @optional_untuple:
72        [generics: $($T: ident)*]
73        [distinct: $($D:ident)*]
74        [order: $($O: ty,)*]
75    ) => {};
76    // Special-case: rule out the all ident case if the
77    // corresponding flag is set
78    // We want to have these impls if
79    // the tuple sizes do **not** match
80    // therefore we set the flag below
81    (@impl_one:
82     [allow_plain = false]
83     $generics:tt
84     $distinct:tt
85     $other:tt
86     [$($T_:ident, )*]
87    ) => {
88        /* skip this one */
89    };
90    (@impl_one:
91     [allow_plain = $allow_plain: expr]
92     [generics: $($T:ident)*]
93     [distinct: $($D:ident)*]
94     [other: $($O:ident)*]
95     [$($Ty:ty, )*]
96    ) => {
97        impl<$($T,)*> ValidOrderingForDistinct<DistinctOnClause<($($D, )*)>>
98            for OrderClause<($($Ty, )* $($O,)*)>
99        {}
100        valid_ordering!(@optional_untuple: [generics: $($T)*] [distinct: $($D)*] [order: $($Ty,)* $($O,)*]);
101    };
102    (
103        @perm:
104        $allow_plain:tt
105        $generics:tt
106        $distinct:tt
107        $other:tt
108        [acc: $([$($acc:tt)*])*]
109        $T:ident
110        $($rest:tt)*
111    ) => {
112        valid_ordering! {
113            @perm:
114            $allow_plain
115            $generics
116            $distinct
117            $other
118                [acc:
119                 $(
120                     [$($acc)* crate::expression::operators::Asc<$T>, ]
121                     [$($acc)*     $T  , ]
122                     [$($acc)* crate::expression::operators::Desc<$T>, ]
123                 )*
124                ]
125                $($rest)*
126        }
127    };
128    (
129        @perm:
130        $allow_plain:tt
131        $generics:tt
132        $distinct:tt
133        $other:tt
134        [acc: $($Tys:tt)*]
135        /* nothing left */
136    ) => (
137        $(
138            valid_ordering! {@impl_one:
139                $allow_plain
140                $generics
141                $distinct
142                $other
143                $Tys
144            }
145        )*
146    );
147    (@skip_distinct_rev: [generics: $($G: ident)*] [other: $($O: ident)*] [acc: $($T: ident)*]) => {
148        valid_ordering!(@perm:
149                        [allow_plain = true]
150                        [generics: $($G)*]
151                        [distinct: $($T)*]
152                        [other: $($O)* ]
153                        [acc: []]
154                        $($T)*
155        );
156    };
157    (@skip_distinct_rev: [generics: $($G: ident)*] [other: $($O: ident)*] [acc: $($I: ident)*] $T: ident $($Ts: ident)*) => {
158        valid_ordering!(
159            @skip_distinct_rev:
160            [generics: $($G)*]
161            [other: $($O)*]
162            [acc: $T $($I)*]
163            $($Ts)*
164        );
165    };
166    (@skip_distinct:
167     [generics: $($G: ident)*]
168     [acc: $($O: ident)*]
169     $T: ident
170    ) => {};
171    (@skip_distinct:
172     [generics: $($G: ident)*]
173     [acc: $($O: ident)*]
174     $T:ident $($Ts: ident)*
175    ) => {
176        valid_ordering!(@skip_distinct_rev:
177            [generics: $($G)*]
178            [other: $($O)* $T]
179            [acc: ]
180            $($Ts)*
181        );
182        valid_ordering!(@skip_distinct: [generics: $($G)*] [acc: $($O)* $T] $($Ts)*);
183    };
184    (@skip_order_rev: [generics: $($G: ident)*] [acc: $($T: ident)*]) => {
185        valid_ordering!(@perm:
186            [allow_plain = true]
187            [generics: $($G)*]
188            [distinct: $($G)*]
189            [other: ]
190            [acc: []]
191            $($T)*
192        );
193    };
194    (@skip_order_rev: [generics: $($G: ident)*] [acc: $($I: ident)*] $T: ident $($Ts: ident)*) => {
195        valid_ordering!(
196            @skip_order_rev:
197            [generics: $($G)*]
198            [acc: $T $($I)*]
199            $($Ts)*
200        );
201    };
202    (@skip_order:
203     [generics: $($G: ident)*]
204     $T: ident
205    ) => {};
206    (@skip_order:
207     [generics: $($G: ident)*]
208     $T: ident $($Ts: ident)*
209    ) => {
210        valid_ordering!(@skip_order_rev: [generics: $($G)*] [acc: ] $($Ts)*);
211        valid_ordering!(@skip_order: [generics: $($G)*] $($Ts)*);
212    };
213    (@reverse_list: [generics: $($G: ident)*] [acc: $($I: ident)*]) => {
214        valid_ordering!(@skip_order: [generics: $($G)*] $($I)*);
215        valid_ordering!(@skip_distinct: [generics: $($G)*] [acc: ] $($I)*);
216    };
217    (@reverse_list: [generics: $($G: ident)*] [acc: $($I: ident)*] $T: ident $($Ts: ident)*) => {
218        valid_ordering!(@reverse_list: [generics: $($G)*] [acc: $T $($I)*] $($Ts)*);
219    };
220    ($(
221        $Tuple:tt {
222            $(($idx:tt) -> $T:ident, $ST:ident, $TT:ident,)+
223        }
224    )+) => {
225        $(
226            valid_ordering!(@perm:
227                [allow_plain = false]
228                [generics: $($T)*]
229                [distinct: $($T)*]
230                [other: ]
231                [acc: []]
232                $($T)*
233            );
234            valid_ordering!(@reverse_list: [generics: $($T)*] [acc: ] $($T)*);
235        )*
236    }
237}
238
239// we only generate these impl up to a tuple size of 5 as we generate n*n + 4 impls here
240// If we would generate these impls up to max_table_column_count tuple elements that
241// would be a really large number for 128 tuple elements (~64k trait impls)
242// It's fine to increase this number at some point in the future gradually
243diesel_derives::__diesel_for_each_tuple!(valid_ordering, 5);
244
245/// A decorator trait for `OrderClause`
246/// It helps to have bounds on either Col, Asc<Col> and Desc<Col>.
247pub trait OrderDecorator {
248    /// A column on a database table.
249    type Column;
250}
251
252impl<C> OrderDecorator for C
253where
254    C: crate::Column,
255{
256    type Column = C;
257}
258
259impl<C> OrderDecorator for crate::helper_types::Asc<C> {
260    type Column = C;
261}
262
263impl<C> OrderDecorator for crate::helper_types::Desc<C> {
264    type Column = C;
265}
266
267impl<T> QueryFragment<Pg> for DistinctOnClause<T>
268where
269    T: QueryFragment<Pg>,
270{
271    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> {
272        out.push_sql("DISTINCT ON (");
273        self.0.walk_ast(out.reborrow())?;
274        out.push_sql(") ");
275        Ok(())
276    }
277}
278
279impl<ST, F, S, D, W, O, LOf, G, H, Selection> DistinctOnDsl<Selection>
280    for SelectStatement<FromClause<F>, S, D, W, O, LOf, G, H>
281where
282    F: QuerySource,
283    Selection: SelectableExpression<F>,
284    Self: SelectQuery<SqlType = ST>,
285    O: ValidOrderingForDistinct<DistinctOnClause<Selection>>,
286    SelectStatement<FromClause<F>, S, DistinctOnClause<Selection>, W, O, LOf, G, H>:
287        SelectQuery<SqlType = ST>,
288{
289    type Output = SelectStatement<FromClause<F>, S, DistinctOnClause<Selection>, W, O, LOf, G, H>;
290
291    fn distinct_on(self, selection: Selection) -> Self::Output {
292        SelectStatement::new(
293            self.select,
294            self.from,
295            DistinctOnClause(selection),
296            self.where_clause,
297            self.order,
298            self.limit_offset,
299            self.group_by,
300            self.having,
301            self.locking,
302        )
303    }
304}