Skip to main content

diesel/query_builder/select_statement/
mod.rs

1//! Within this module, types commonly use the following abbreviations:
2//!
3//! F: From Clause
4//! S: Select Clause
5//! D: Distinct Clause
6//! W: Where Clause
7//! O: Order By Clause
8//! L: Limit Clause
9//! Of: Offset Clause
10//! G: Group By Clause
11//! H: Having clause
12//! LC: For Update Clause
13
14pub(crate) mod boxed;
15pub(crate) mod boxed_clone;
16mod dsl_impls;
17pub use self::boxed::BoxedSelectStatement;#[diesel_derives::__diesel_public_if(
18    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
19)]
20pub(crate) use self::boxed::BoxedSelectStatement;
21pub use self::boxed_clone::BoxedCloneSelectStatement;#[diesel_derives::__diesel_public_if(
22    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"
23)]
24pub(crate) use self::boxed_clone::BoxedCloneSelectStatement;
25
26use super::NoFromClause;
27use super::distinct_clause::NoDistinctClause;
28use super::from_clause::AsQuerySource;
29use super::from_clause::FromClause;
30use super::group_by_clause::*;
31use super::limit_clause::NoLimitClause;
32use super::locking_clause::NoLockingClause;
33use super::offset_clause::NoOffsetClause;
34use super::order_clause::NoOrderClause;
35use super::select_clause::*;
36use super::where_clause::*;
37use super::{AstPass, Query, QueryFragment};
38use crate::backend::{Backend, sql_dialect};
39use crate::expression::subselect::{SubselectGroupBy, ValidSubselect, ValidSubselectGrouping};
40use crate::expression::*;
41use crate::query_builder::having_clause::NoHavingClause;
42use crate::query_builder::limit_offset_clause::LimitOffsetClause;
43use crate::query_builder::{QueryId, SelectQuery};
44use crate::query_dsl::order_dsl::ValidOrderingForDistinct;
45use crate::query_source::joins::{AppendSelection, Inner, Join};
46use crate::query_source::*;
47use crate::result::QueryResult;
48
49/// This type represents a select query
50///
51/// Using this type directly is only meaningful for custom backends
52/// that need to provide a custom [`QueryFragment`] implementation
53#[doc = " This type represents a select query"]
#[doc = ""]
#[doc = " Using this type directly is only meaningful for custom backends"]
#[doc = " that need to provide a custom [`QueryFragment`] implementation"]
#[must_use =
"Queries are only executed when calling `load`, `get_result` or similar."]
#[non_exhaustive]
pub struct SelectStatement<From, Select = DefaultSelectClause<From>, Distinct
    = NoDistinctClause, Where = NoWhereClause, Order = NoOrderClause,
    LimitOffset = LimitOffsetClause<NoLimitClause, NoOffsetClause>, GroupBy =
    NoGroupByClause, Having = NoHavingClause, Locking = NoLockingClause> {
    #[doc = " The select clause of the query"]
    pub select: Select,
    #[doc = " The from clause of the query"]
    pub from: From,
    #[doc = " The distinct clause of the query"]
    pub distinct: Distinct,
    #[doc = " The where clause of the query"]
    pub where_clause: Where,
    #[doc = " The order clause of the query"]
    pub order: Order,
    #[doc = " The combined limit/offset clause of the query"]
    pub limit_offset: LimitOffset,
    #[doc = " The group by clause of the query"]
    pub group_by: GroupBy,
    #[doc = " The having clause of the query"]
    pub having: Having,
    #[doc = " The locking clause of the query"]
    pub locking: Locking,
}#[diesel_derives::__diesel_public_if(
54    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
55    public_fields(
56        select,
57        from,
58        distinct,
59        where_clause,
60        order,
61        limit_offset,
62        group_by,
63        having,
64        locking
65    )
66)]
67#[derive(#[automatically_derived]
impl<From: ::core::fmt::Debug, Select: ::core::fmt::Debug,
    Distinct: ::core::fmt::Debug, Where: ::core::fmt::Debug,
    Order: ::core::fmt::Debug, LimitOffset: ::core::fmt::Debug,
    GroupBy: ::core::fmt::Debug, Having: ::core::fmt::Debug,
    Locking: ::core::fmt::Debug> ::core::fmt::Debug for
    SelectStatement<From, Select, Distinct, Where, Order, LimitOffset,
    GroupBy, Having, Locking> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            &["select", "from", "distinct", "where_clause", "order",
                        "limit_offset", "group_by", "having", "locking"];
        let values: &[&dyn ::core::fmt::Debug] =
            &[&self.select, &self.from, &self.distinct, &self.where_clause,
                        &self.order, &self.limit_offset, &self.group_by,
                        &self.having, &&self.locking];
        ::core::fmt::Formatter::debug_struct_fields_finish(f,
            "SelectStatement", names, values)
    }
}Debug, #[automatically_derived]
impl<From: ::core::clone::Clone, Select: ::core::clone::Clone,
    Distinct: ::core::clone::Clone, Where: ::core::clone::Clone,
    Order: ::core::clone::Clone, LimitOffset: ::core::clone::Clone,
    GroupBy: ::core::clone::Clone, Having: ::core::clone::Clone,
    Locking: ::core::clone::Clone> ::core::clone::Clone for
    SelectStatement<From, Select, Distinct, Where, Order, LimitOffset,
    GroupBy, Having, Locking> {
    #[inline]
    fn clone(&self) -> Self {
        Self {
            select: ::core::clone::Clone::clone(&self.select),
            from: ::core::clone::Clone::clone(&self.from),
            distinct: ::core::clone::Clone::clone(&self.distinct),
            where_clause: ::core::clone::Clone::clone(&self.where_clause),
            order: ::core::clone::Clone::clone(&self.order),
            limit_offset: ::core::clone::Clone::clone(&self.limit_offset),
            group_by: ::core::clone::Clone::clone(&self.group_by),
            having: ::core::clone::Clone::clone(&self.having),
            locking: ::core::clone::Clone::clone(&self.locking),
        }
    }
}Clone, #[automatically_derived]
impl<From: ::core::marker::Copy, Select: ::core::marker::Copy,
    Distinct: ::core::marker::Copy, Where: ::core::marker::Copy,
    Order: ::core::marker::Copy, LimitOffset: ::core::marker::Copy,
    GroupBy: ::core::marker::Copy, Having: ::core::marker::Copy,
    Locking: ::core::marker::Copy> ::core::marker::Copy for
    SelectStatement<From, Select, Distinct, Where, Order, LimitOffset,
    GroupBy, Having, Locking> {
}Copy, const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl<From: diesel::query_builder::QueryId,
            Select: diesel::query_builder::QueryId,
            Distinct: diesel::query_builder::QueryId,
            Where: diesel::query_builder::QueryId,
            Order: diesel::query_builder::QueryId,
            LimitOffset: diesel::query_builder::QueryId,
            GroupBy: diesel::query_builder::QueryId,
            Having: diesel::query_builder::QueryId,
            Locking: diesel::query_builder::QueryId>
            diesel::query_builder::QueryId for
            SelectStatement<From, Select, Distinct, Where, Order, LimitOffset,
            GroupBy, Having, Locking> {
            type QueryId =
                SelectStatement<<From as
                diesel::query_builder::QueryId>::QueryId,
                <Select as diesel::query_builder::QueryId>::QueryId,
                <Distinct as diesel::query_builder::QueryId>::QueryId,
                <Where as diesel::query_builder::QueryId>::QueryId,
                <Order as diesel::query_builder::QueryId>::QueryId,
                <LimitOffset as diesel::query_builder::QueryId>::QueryId,
                <GroupBy as diesel::query_builder::QueryId>::QueryId,
                <Having as diesel::query_builder::QueryId>::QueryId,
                <Locking as diesel::query_builder::QueryId>::QueryId>;
            const HAS_STATIC_QUERY_ID: bool =
                <From as diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID
                                                    &&
                                                    <Select as
                                                        diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID &&
                                                <Distinct as
                                                    diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID &&
                                            <Where as
                                                diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID &&
                                        <Order as
                                            diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID &&
                                    <LimitOffset as
                                        diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID &&
                                <GroupBy as
                                    diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID &&
                            <Having as
                                diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID &&
                        <Locking as
                            diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID &&
                    true;
            const IS_WINDOW_FUNCTION: bool =
                <From as diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION
                                                    ||
                                                    <Select as
                                                        diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION ||
                                                <Distinct as
                                                    diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION ||
                                            <Where as
                                                diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION ||
                                        <Order as
                                            diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION ||
                                    <LimitOffset as
                                        diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION ||
                                <GroupBy as
                                    diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION ||
                            <Having as
                                diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION ||
                        <Locking as
                            diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION ||
                    false;
        }
    };QueryId)]
68#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
69pub struct SelectStatement<
70    From,
71    Select = DefaultSelectClause<From>,
72    Distinct = NoDistinctClause,
73    Where = NoWhereClause,
74    Order = NoOrderClause,
75    LimitOffset = LimitOffsetClause<NoLimitClause, NoOffsetClause>,
76    GroupBy = NoGroupByClause,
77    Having = NoHavingClause,
78    Locking = NoLockingClause,
79> {
80    /// The select clause of the query
81    pub(crate) select: Select,
82    /// The from clause of the query
83    pub(crate) from: From,
84    /// The distinct clause of the query
85    pub(crate) distinct: Distinct,
86    /// The where clause of the query
87    pub(crate) where_clause: Where,
88    /// The order clause of the query
89    pub(crate) order: Order,
90    /// The combined limit/offset clause of the query
91    pub(crate) limit_offset: LimitOffset,
92    /// The group by clause of the query
93    pub(crate) group_by: GroupBy,
94    /// The having clause of the query
95    pub(crate) having: Having,
96    /// The locking clause of the query
97    pub(crate) locking: Locking,
98}
99
100/// Semi-Private trait for containing get-functions for all `SelectStatement` fields
101//
102// This is used by `#[derive(MultiConnection)]`
103pub trait SelectStatementAccessor {
104    /// The type of the select clause
105    type Select;
106    /// The type of the from clause
107    type From;
108    /// The type of the distinct clause
109    type Distinct;
110    /// The type of the where clause
111    type Where;
112    /// The type of the order clause
113    type Order;
114    /// The type of the limit offset clause
115    type LimitOffset;
116    /// The type of the group by clause
117    type GroupBy;
118    /// The type of the having clause
119    type Having;
120    /// The type of the locking clause
121    type Locking;
122
123    /// Access the select clause
124    fn select_clause(&self) -> &Self::Select;
125    /// Access the from clause
126    #[allow(clippy::wrong_self_convention)] // obviously wrong, as `from` refers to the clause name
127    fn from_clause(&self) -> &Self::From;
128    /// Access the distinct clause
129    fn distinct_clause(&self) -> &Self::Distinct;
130    /// Access the where clause
131    fn where_clause(&self) -> &Self::Where;
132    /// Access the order clause
133    fn order_clause(&self) -> &Self::Order;
134    /// Access the limit_offset clause
135    fn limit_offset_clause(&self) -> &Self::LimitOffset;
136    /// Access the group by clause
137    fn group_by_clause(&self) -> &Self::GroupBy;
138    /// Access the having clause
139    fn having_clause(&self) -> &Self::Having;
140    /// Access the locking clause
141    fn locking_clause(&self) -> &Self::Locking;
142}
143
144impl<F, S, D, W, O, LOf, G, H, LC> SelectStatementAccessor
145    for SelectStatement<F, S, D, W, O, LOf, G, H, LC>
146{
147    type Select = S;
148    type From = F;
149    type Distinct = D;
150    type Where = W;
151    type Order = O;
152    type LimitOffset = LOf;
153    type GroupBy = G;
154    type Having = H;
155    type Locking = LC;
156
157    fn select_clause(&self) -> &Self::Select {
158        &self.select
159    }
160
161    fn from_clause(&self) -> &Self::From {
162        &self.from
163    }
164
165    fn distinct_clause(&self) -> &Self::Distinct {
166        &self.distinct
167    }
168
169    fn where_clause(&self) -> &Self::Where {
170        &self.where_clause
171    }
172
173    fn order_clause(&self) -> &Self::Order {
174        &self.order
175    }
176
177    fn limit_offset_clause(&self) -> &Self::LimitOffset {
178        &self.limit_offset
179    }
180
181    fn group_by_clause(&self) -> &Self::GroupBy {
182        &self.group_by
183    }
184
185    fn having_clause(&self) -> &Self::Having {
186        &self.having
187    }
188
189    fn locking_clause(&self) -> &Self::Locking {
190        &self.locking
191    }
192}
193
194impl<F, S, D, W, O, LOf, G, H, LC> SelectStatement<F, S, D, W, O, LOf, G, H, LC> {
195    #[allow(clippy::too_many_arguments)]
196    pub(crate) fn new(
197        select: S,
198        from: F,
199        distinct: D,
200        where_clause: W,
201        order: O,
202        limit_offset: LOf,
203        group_by: G,
204        having: H,
205        locking: LC,
206    ) -> Self {
207        SelectStatement {
208            select,
209            from,
210            distinct,
211            where_clause,
212            order,
213            limit_offset,
214            group_by,
215            having,
216            locking,
217        }
218    }
219
220    /// The statement with its order clause mapped through `f` and every other clause kept.
221    pub(crate) fn map_order<NewO>(
222        self,
223        f: impl FnOnce(O) -> NewO,
224    ) -> SelectStatement<F, S, D, W, NewO, LOf, G, H, LC> {
225        SelectStatement::new(
226            self.select,
227            self.from,
228            self.distinct,
229            self.where_clause,
230            f(self.order),
231            self.limit_offset,
232            self.group_by,
233            self.having,
234            self.locking,
235        )
236    }
237}
238
239impl<F: QuerySource> SelectStatement<FromClause<F>> {
240    // This is used by the `table!` macro
241    #[doc(hidden)]
242    pub fn simple(from: F) -> Self {
243        let from = FromClause::new(from);
244        SelectStatement::new(
245            DefaultSelectClause::new(&from),
246            from,
247            NoDistinctClause,
248            NoWhereClause,
249            NoOrderClause,
250            LimitOffsetClause {
251                limit_clause: NoLimitClause,
252                offset_clause: NoOffsetClause,
253            },
254            NoGroupByClause,
255            NoHavingClause,
256            NoLockingClause,
257        )
258    }
259}
260
261impl<F, S, D, W, O, LOf, G, H, LC> Query for SelectStatement<F, S, D, W, O, LOf, G, H, LC>
262where
263    G: ValidGroupByClause,
264    S: SelectClauseExpression<F>,
265    S::Selection: ValidGrouping<G::Expressions>,
266    W: ValidWhereClause<F>,
267{
268    type SqlType = S::SelectClauseSqlType;
269}
270
271impl<F, S, D, W, O, LOf, G, H, LC> SelectQuery for SelectStatement<F, S, D, W, O, LOf, G, H, LC>
272where
273    S: SelectClauseExpression<F>,
274    O: ValidOrderingForDistinct<D>,
275{
276    type SqlType = S::SelectClauseSqlType;
277}
278
279impl<F, S, D, W, O, LOf, G, H, LC, DB> QueryFragment<DB>
280    for SelectStatement<F, S, D, W, O, LOf, G, H, LC>
281where
282    DB: Backend,
283    Self: QueryFragment<DB, DB::SelectStatementSyntax>,
284{
285    fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
286        <Self as QueryFragment<DB, DB::SelectStatementSyntax>>::walk_ast(self, pass)
287    }
288}
289
290impl<F, S, D, W, O, LOf, G, H, LC, DB>
291    QueryFragment<DB, sql_dialect::select_statement_syntax::AnsiSqlSelectStatement>
292    for SelectStatement<F, S, D, W, O, LOf, G, H, LC>
293where
294    DB: Backend<
295        SelectStatementSyntax = sql_dialect::select_statement_syntax::AnsiSqlSelectStatement,
296    >,
297    S: QueryFragment<DB>,
298    F: QueryFragment<DB>,
299    D: QueryFragment<DB>,
300    W: QueryFragment<DB>,
301    O: QueryFragment<DB>,
302    LOf: QueryFragment<DB>,
303    G: QueryFragment<DB>,
304    H: QueryFragment<DB>,
305    LC: QueryFragment<DB>,
306{
307    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
308        out.push_sql("SELECT ");
309        self.distinct.walk_ast(out.reborrow())?;
310        self.select.walk_ast(out.reborrow())?;
311        self.from.walk_ast(out.reborrow())?;
312        self.where_clause.walk_ast(out.reborrow())?;
313        self.group_by.walk_ast(out.reborrow())?;
314        self.having.walk_ast(out.reborrow())?;
315        self.order.walk_ast(out.reborrow())?;
316        self.limit_offset.walk_ast(out.reborrow())?;
317        self.locking.walk_ast(out.reborrow())?;
318        Ok(())
319    }
320}
321
322impl<S, F, D, W, O, LOf, G, H, LC, QS> ValidSubselect<QS>
323    for SelectStatement<FromClause<F>, S, D, W, O, LOf, G, H, LC>
324where
325    Self: SelectQuery,
326    F: QuerySource,
327    QS: QuerySource,
328    Join<F, QS, Inner>: QuerySource,
329    W: ValidWhereClause<FromClause<Join<F, QS, Inner>>>,
330{
331}
332
333impl<S, D, W, O, LOf, G, H, LC> ValidSubselect<NoFromClause>
334    for SelectStatement<NoFromClause, S, D, W, O, LOf, G, H, LC>
335where
336    Self: SelectQuery,
337    W: ValidWhereClause<NoFromClause>,
338{
339}
340
341impl<S, F, D, W, O, LOf, G, H, LC> ValidSubselect<NoFromClause>
342    for SelectStatement<FromClause<F>, S, D, W, O, LOf, G, H, LC>
343where
344    Self: SelectQuery,
345    F: QuerySource,
346    W: ValidWhereClause<FromClause<F>>,
347{
348}
349
350impl<S, D, W, O, LOf, G, H, LC, QS> ValidSubselect<QS>
351    for SelectStatement<NoFromClause, S, D, W, O, LOf, G, H, LC>
352where
353    Self: SelectQuery,
354    QS: QuerySource,
355    W: ValidWhereClause<NoFromClause>,
356{
357}
358
359// SQL lets every clause of a subselect reference the outer query, but diesel only
360// accepts outer columns in the `WHERE` clause, so that is the only clause to check
361impl<F, S, D, W, O, LOf, G, H, LC, GB> ValidSubselectGrouping<GB>
362    for SelectStatement<F, S, D, W, O, LOf, G, H, LC>
363where
364    W: ValidGrouping<SubselectGroupBy<GB, F>>,
365{
366    type IsAggregate = W::IsAggregate;
367}
368
369/// Allow `SelectStatement<From>` to act as if it were `From` as long as
370/// no other query methods have been called on it
371impl<From, T> AppearsInFromClause<T> for SelectStatement<From>
372where
373    From: AsQuerySource,
374    From::QuerySource: AppearsInFromClause<T> + QuerySource,
375{
376    type Count = <From::QuerySource as AppearsInFromClause<T>>::Count;
377}
378
379impl<From> QuerySource for SelectStatement<From>
380where
381    From: AsQuerySource,
382    <From::QuerySource as QuerySource>::DefaultSelection: SelectableExpression<Self>,
383{
384    type FromClause = <From::QuerySource as QuerySource>::FromClause;
385    type DefaultSelection = <From::QuerySource as QuerySource>::DefaultSelection;
386
387    fn from_clause(&self) -> <From::QuerySource as QuerySource>::FromClause {
388        self.from.as_query_source().from_clause()
389    }
390
391    fn default_selection(&self) -> Self::DefaultSelection {
392        self.from.as_query_source().default_selection()
393    }
394}
395
396impl<From, Selection> AppendSelection<Selection> for SelectStatement<From>
397where
398    From: AsQuerySource,
399    From::QuerySource: AppendSelection<Selection>,
400{
401    type Output = <From::QuerySource as AppendSelection<Selection>>::Output;
402
403    fn append_selection(&self, selection: Selection) -> Self::Output {
404        self.from.as_query_source().append_selection(selection)
405    }
406}