Skip to main content

sea_orm/query/
select.rs

1use crate::{
2    ColumnTrait, EntityTrait, Iterable, Order, PrimaryKeyToColumn, QueryFilter, QueryOrder,
3    QuerySelect, QueryTrait,
4};
5use core::fmt::Debug;
6use core::marker::PhantomData;
7use sea_query::{FunctionCall, IntoColumnRef, SelectStatement, SimpleExpr};
8
9/// Defines a structure to perform select operations
10#[derive(Clone, Debug)]
11pub struct Select<E>
12where
13    E: EntityTrait,
14{
15    pub(crate) query: SelectStatement,
16    pub(crate) entity: PhantomData<E>,
17    pub(crate) linked_index: usize,
18}
19
20/// Defines a structure to perform a SELECT operation on two Models, with the second Model being optional
21#[derive(Clone, Debug)]
22pub struct SelectTwo<E, F>
23where
24    E: EntityTrait,
25    F: EntityTrait,
26{
27    pub(crate) query: SelectStatement,
28    pub(crate) entity: PhantomData<(E, F)>,
29}
30
31/// Defines a structure to perform a SELECT operation on many Models
32#[derive(Clone, Debug)]
33pub struct SelectTwoMany<E, F>
34where
35    E: EntityTrait,
36    F: EntityTrait,
37{
38    pub(crate) query: SelectStatement,
39    pub(crate) entity: PhantomData<(E, F)>,
40}
41
42/// Defines a structure to perform a SELECT operation on two Models
43#[derive(Clone, Debug)]
44pub struct SelectTwoRequired<E, F>
45where
46    E: EntityTrait,
47    F: EntityTrait,
48{
49    pub(crate) query: SelectStatement,
50    pub(crate) entity: PhantomData<(E, F)>,
51}
52
53/// Topology of multi-joins
54pub trait Topology {}
55
56/// A star topology
57#[derive(Debug, Clone)]
58pub struct TopologyStar;
59
60/// A chain topology
61#[derive(Debug, Clone)]
62pub struct TopologyChain;
63
64impl Topology for TopologyStar {}
65impl Topology for TopologyChain {}
66
67/// Perform a SELECT operation on three Models
68#[derive(Clone, Debug)]
69pub struct SelectThree<E, F, G, TOP>
70where
71    E: EntityTrait,
72    F: EntityTrait,
73    G: EntityTrait,
74    TOP: Topology,
75{
76    pub(crate) query: SelectStatement,
77    pub(crate) entity: PhantomData<(E, F, G, TOP)>,
78}
79
80/// Perform a SELECT operation on three Models with results consolidated
81#[derive(Clone, Debug)]
82pub struct SelectThreeMany<E, F, G, TOP>
83where
84    E: EntityTrait,
85    F: EntityTrait,
86    G: EntityTrait,
87    TOP: Topology,
88{
89    pub(crate) query: SelectStatement,
90    pub(crate) entity: PhantomData<(E, F, G, TOP)>,
91}
92
93/// Perform a SELECT operation on 4 Models
94#[derive(Clone, Debug)]
95pub struct SelectFour<E, F, G, H, TOP>
96where
97    E: EntityTrait,
98    F: EntityTrait,
99    G: EntityTrait,
100    H: EntityTrait,
101    TOP: Topology,
102{
103    pub(crate) query: SelectStatement,
104    pub(crate) entity: PhantomData<(E, F, G, H, TOP)>,
105}
106
107/// Perform a SELECT operation on 5 Models
108#[derive(Clone, Debug)]
109pub struct SelectFive<E, F, G, H, I, TOP>
110where
111    E: EntityTrait,
112    F: EntityTrait,
113    G: EntityTrait,
114    H: EntityTrait,
115    I: EntityTrait,
116    TOP: Topology,
117{
118    pub(crate) query: SelectStatement,
119    pub(crate) entity: PhantomData<(E, F, G, H, I, TOP)>,
120}
121
122/// Perform a SELECT operation on 6 Models
123#[derive(Clone, Debug)]
124pub struct SelectSix<E, F, G, H, I, J, TOP>
125where
126    E: EntityTrait,
127    F: EntityTrait,
128    G: EntityTrait,
129    H: EntityTrait,
130    I: EntityTrait,
131    J: EntityTrait,
132    TOP: Topology,
133{
134    pub(crate) query: SelectStatement,
135    pub(crate) entity: PhantomData<(E, F, G, H, I, J, TOP)>,
136}
137
138/// Performs a conversion to [SimpleExpr]
139pub trait IntoSimpleExpr {
140    /// Method to perform the conversion
141    fn into_simple_expr(self) -> SimpleExpr;
142}
143
144/// Extending [IntoSimpleExpr] to support casting ActiveEnum as TEXT in select expression
145pub trait ColumnAsExpr: IntoSimpleExpr {
146    /// Casting ActiveEnum as TEXT in select expression,
147    /// otherwise same as [IntoSimpleExpr::into_simple_expr]
148    fn into_column_as_expr(self) -> SimpleExpr;
149}
150
151macro_rules! impl_query_trait {
152    ( $trait: ident ) => {
153        impl<E> $trait for Select<E>
154        where
155            E: EntityTrait,
156        {
157            type QueryStatement = SelectStatement;
158
159            fn query(&mut self) -> &mut SelectStatement {
160                &mut self.query
161            }
162        }
163
164        impl<E, F> $trait for SelectTwo<E, F>
165        where
166            E: EntityTrait,
167            F: EntityTrait,
168        {
169            type QueryStatement = SelectStatement;
170
171            fn query(&mut self) -> &mut SelectStatement {
172                &mut self.query
173            }
174        }
175
176        impl<E, F> $trait for SelectTwoMany<E, F>
177        where
178            E: EntityTrait,
179            F: EntityTrait,
180        {
181            type QueryStatement = SelectStatement;
182
183            fn query(&mut self) -> &mut SelectStatement {
184                &mut self.query
185            }
186        }
187
188        impl<E, F> $trait for SelectTwoRequired<E, F>
189        where
190            E: EntityTrait,
191            F: EntityTrait,
192        {
193            type QueryStatement = SelectStatement;
194
195            fn query(&mut self) -> &mut SelectStatement {
196                &mut self.query
197            }
198        }
199    };
200}
201
202impl_query_trait!(QuerySelect);
203impl_query_trait!(QueryFilter);
204impl_query_trait!(QueryOrder);
205
206impl<C> ColumnAsExpr for C
207where
208    C: ColumnTrait,
209{
210    fn into_column_as_expr(self) -> SimpleExpr {
211        self.select_as(self.as_column_ref().into_column_ref().into())
212    }
213}
214
215impl ColumnAsExpr for SimpleExpr {
216    fn into_column_as_expr(self) -> SimpleExpr {
217        self.into_simple_expr()
218    }
219}
220
221impl<C> IntoSimpleExpr for C
222where
223    C: ColumnTrait,
224{
225    fn into_simple_expr(self) -> SimpleExpr {
226        SimpleExpr::Column(self.as_column_ref().into_column_ref())
227    }
228}
229
230impl IntoSimpleExpr for SimpleExpr {
231    fn into_simple_expr(self) -> SimpleExpr {
232        self
233    }
234}
235
236impl IntoSimpleExpr for FunctionCall {
237    fn into_simple_expr(self) -> SimpleExpr {
238        SimpleExpr::FunctionCall(self)
239    }
240}
241
242impl<E> Select<E>
243where
244    E: EntityTrait,
245{
246    pub(crate) fn new() -> Self {
247        Self {
248            query: SelectStatement::new(),
249            entity: PhantomData,
250            linked_index: 0,
251        }
252        .prepare_select()
253        .prepare_from()
254    }
255
256    fn prepare_select(mut self) -> Self {
257        self.query.exprs(self.column_list());
258        self
259    }
260
261    fn column_list(&self) -> Vec<SimpleExpr> {
262        E::Column::iter()
263            .map(|col| col.select_as(col.into_expr()))
264            .collect()
265    }
266
267    fn prepare_from(mut self) -> Self {
268        self.query.from(E::default().table_ref());
269        self
270    }
271
272    /// Apply order by primary key to the query statement
273    pub fn order_by_id_asc(self) -> Self {
274        self.order_by_id(Order::Asc)
275    }
276
277    /// Apply order by primary key to the query statement
278    pub fn order_by_id_desc(self) -> Self {
279        self.order_by_id(Order::Desc)
280    }
281
282    /// Apply order by primary key to the query statement
283    pub fn order_by_id(mut self, order: Order) -> Self {
284        for key in E::PrimaryKey::iter() {
285            let col = key.into_column();
286            self.query
287                .order_by_expr(col.into_simple_expr(), order.clone());
288        }
289        self
290    }
291}
292
293impl<E> QueryTrait for Select<E>
294where
295    E: EntityTrait,
296{
297    type QueryStatement = SelectStatement;
298    fn query(&mut self) -> &mut SelectStatement {
299        &mut self.query
300    }
301    fn as_query(&self) -> &SelectStatement {
302        &self.query
303    }
304    fn into_query(self) -> SelectStatement {
305        self.query
306    }
307}
308
309macro_rules! select_two {
310    ( $selector: ident ) => {
311        impl<E, F> QueryTrait for $selector<E, F>
312        where
313            E: EntityTrait,
314            F: EntityTrait,
315        {
316            type QueryStatement = SelectStatement;
317            fn query(&mut self) -> &mut SelectStatement {
318                &mut self.query
319            }
320            fn as_query(&self) -> &SelectStatement {
321                &self.query
322            }
323            fn into_query(self) -> SelectStatement {
324                self.query
325            }
326        }
327    };
328}
329
330select_two!(SelectTwo);
331select_two!(SelectTwoMany);
332select_two!(SelectTwoRequired);