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