sea_orm/query/
select.rs

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