1use diesel::dsl::{Asc, Desc};
28use diesel::query_dsl::methods::{OrderDsl, ThenOrderDsl};
29use diesel::ExpressionMethods;
30use std::fmt;
31
32#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
42pub enum QueryOrderDirection {
43 Ascending,
44 Descending,
45}
46
47impl Default for QueryOrderDirection {
48 fn default() -> Self {
49 Self::Ascending
50 }
51}
52
53impl fmt::Display for QueryOrderDirection {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 match self {
56 Self::Ascending => write!(f, "ASC"),
57 Self::Descending => write!(f, "DESC"),
58 }
59 }
60}
61
62impl QueryOrderDirection {
63 pub fn order_query<Expr, Q>(&self, query: Q, expr: Expr) -> OrderWithDirection<Q, Expr>
66 where
67 Expr: ExpressionMethods,
68 Q: OrderDsl<Asc<Expr>> + OrderDsl<Desc<Expr>, Output = <Q as OrderDsl<Asc<Expr>>>::Output>,
69 {
70 match self {
71 Self::Ascending => query.order(expr.asc()),
72 Self::Descending => query.order(expr.desc()),
73 }
74 }
75
76 pub fn order_multiple<Expr, Q>(
77 &self,
78 query: Q,
79 expr: Expr,
80 ) -> OrderMultipleWithDirection<Q, Expr>
81 where
82 Expr: OrderableTuple,
83 Q: OrderDsl<<Expr as OrderableTuple>::AscOutput>
84 + OrderDsl<
85 <Expr as OrderableTuple>::DescOutput,
86 Output = <Q as OrderDsl<<Expr as OrderableTuple>::AscOutput>>::Output,
87 >,
88 {
89 match self {
90 Self::Ascending => query.order(OrderableTuple::asc(expr)),
91 Self::Descending => query.order(OrderableTuple::desc(expr)),
92 }
93 }
94
95 pub fn then_order_by_query<Expr, Q>(
98 &self,
99 query: Q,
100 expr: Expr,
101 ) -> ThenOrderByWithDirection<Q, Expr>
102 where
103 Expr: ExpressionMethods,
104 Q: ThenOrderDsl<Asc<Expr>>
105 + ThenOrderDsl<Desc<Expr>, Output = <Q as ThenOrderDsl<Asc<Expr>>>::Output>,
106 {
107 match self {
108 Self::Ascending => query.then_order_by(expr.asc()),
109 Self::Descending => query.then_order_by(expr.desc()),
110 }
111 }
112}
113
114pub type OrderWithDirection<Q, Expr> = <Q as OrderDsl<Asc<Expr>>>::Output;
116pub type OrderMultipleWithDirection<Q, Expr> =
118 <Q as OrderDsl<<Expr as OrderableTuple>::AscOutput>>::Output;
119pub type ThenOrderByWithDirection<Q, Expr> = <Q as ThenOrderDsl<Asc<Expr>>>::Output;
121
122pub trait OrderWithDirectionDsl: Sized {
123 fn order_with_dir<Expr>(
126 self,
127 direction: QueryOrderDirection,
128 expr: Expr,
129 ) -> OrderWithDirection<Self, Expr>
130 where
131 Expr: ExpressionMethods,
132 Self: OrderDsl<Asc<Expr>>
133 + OrderDsl<Desc<Expr>, Output = <Self as OrderDsl<Asc<Expr>>>::Output>,
134 {
135 direction.order_query(self, expr)
136 }
137
138 fn order_by_with_dir<Expr>(
140 self,
141 order: QueryOrderDirection,
142 expr: Expr,
143 ) -> OrderWithDirection<Self, Expr>
144 where
145 Expr: ExpressionMethods,
146 Self: OrderDsl<Asc<Expr>>
147 + OrderDsl<Desc<Expr>, Output = <Self as OrderDsl<Asc<Expr>>>::Output>,
148 {
149 self.order_with_dir(order, expr)
150 }
151
152 fn order_multiple_with_dir<Expr>(
178 self,
179 direction: QueryOrderDirection,
180 expr: Expr,
181 ) -> OrderMultipleWithDirection<Self, Expr>
182 where
183 Expr: OrderableTuple,
184 Self: OrderDsl<<Expr as OrderableTuple>::AscOutput>
185 + OrderDsl<
186 <Expr as OrderableTuple>::DescOutput,
187 Output = <Self as OrderDsl<<Expr as OrderableTuple>::AscOutput>>::Output,
188 >,
189 {
190 direction.order_multiple(self, expr)
191 }
192
193 fn then_order_by_with_dir<Expr>(
196 self,
197 direction: QueryOrderDirection,
198 expr: Expr,
199 ) -> ThenOrderByWithDirection<Self, Expr>
200 where
201 Expr: ExpressionMethods,
202 Self: ThenOrderDsl<Asc<Expr>>
203 + ThenOrderDsl<Desc<Expr>, Output = <Self as ThenOrderDsl<Asc<Expr>>>::Output>,
204 {
205 direction.then_order_by_query(self, expr)
206 }
207}
208
209impl<Q> OrderWithDirectionDsl for Q {}
210
211pub trait OrderableTuple {
212 type AscOutput: diesel::Expression;
213 type DescOutput: diesel::Expression;
214 fn asc(self) -> Self::AscOutput;
215 fn desc(self) -> Self::DescOutput;
216}
217
218macro_rules! impl_orderabletuple {
219 ($($G:ident),+) => {
220 impl<$($G: ExpressionMethods,)*> OrderableTuple for ($($G,)*) {
221 type AscOutput = ($(Asc<$G>,)*);
222 type DescOutput = ($(Desc<$G>,)*);
223 fn asc(self) -> Self::AscOutput {
224 #[allow(non_snake_case)]
225 let ($($G,)*) = self;
226 ($($G.asc(),)*)
227 }
228 fn desc(self) -> Self::DescOutput {
229 #[allow(non_snake_case)]
230 let ($($G,)*) = self;
231 ($($G.desc(),)*)
232 }
233 }
234 }
235}
236
237impl_orderabletuple! {A1}
238impl_orderabletuple! {A1,A2}
239impl_orderabletuple! {A1,A2,A3}
240impl_orderabletuple! {A1,A2,A3,A4}
241impl_orderabletuple! {A1,A2,A3,A4,A5}
242impl_orderabletuple! {A1,A2,A3,A4,A5,A6}
243impl_orderabletuple! {A1,A2,A3,A4,A5,A6,A7}
244impl_orderabletuple! {A1,A2,A3,A4,A5,A6,A7,A8}
245impl_orderabletuple! {A1,A2,A3,A4,A5,A6,A7,A8,A9}
246impl_orderabletuple! {A1,A2,A3,A4,A5,A6,A7,A8,A9,A10}
247impl_orderabletuple! {A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11}
248impl_orderabletuple! {A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12}
249impl_orderabletuple! {A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13}
250impl_orderabletuple! {A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14}
251impl_orderabletuple! {A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15}