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::ValidSubselect;
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)
        ->
            SelectStatement<From, Select, Distinct, Where, Order, LimitOffset,
            GroupBy, Having, Locking> {
        SelectStatement {
            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
221impl<F: QuerySource> SelectStatement<FromClause<F>> {
222    // This is used by the `table!` macro
223    #[doc(hidden)]
224    pub fn simple(from: F) -> Self {
225        let from = FromClause::new(from);
226        SelectStatement::new(
227            DefaultSelectClause::new(&from),
228            from,
229            NoDistinctClause,
230            NoWhereClause,
231            NoOrderClause,
232            LimitOffsetClause {
233                limit_clause: NoLimitClause,
234                offset_clause: NoOffsetClause,
235            },
236            NoGroupByClause,
237            NoHavingClause,
238            NoLockingClause,
239        )
240    }
241}
242
243impl<F, S, D, W, O, LOf, G, H, LC> Query for SelectStatement<F, S, D, W, O, LOf, G, H, LC>
244where
245    G: ValidGroupByClause,
246    S: SelectClauseExpression<F>,
247    S::Selection: ValidGrouping<G::Expressions>,
248    W: ValidWhereClause<F>,
249{
250    type SqlType = S::SelectClauseSqlType;
251}
252
253impl<F, S, D, W, O, LOf, G, H, LC> SelectQuery for SelectStatement<F, S, D, W, O, LOf, G, H, LC>
254where
255    S: SelectClauseExpression<F>,
256    O: ValidOrderingForDistinct<D>,
257{
258    type SqlType = S::SelectClauseSqlType;
259}
260
261impl<F, S, D, W, O, LOf, G, H, LC, DB> QueryFragment<DB>
262    for SelectStatement<F, S, D, W, O, LOf, G, H, LC>
263where
264    DB: Backend,
265    Self: QueryFragment<DB, DB::SelectStatementSyntax>,
266{
267    fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
268        <Self as QueryFragment<DB, DB::SelectStatementSyntax>>::walk_ast(self, pass)
269    }
270}
271
272impl<F, S, D, W, O, LOf, G, H, LC, DB>
273    QueryFragment<DB, sql_dialect::select_statement_syntax::AnsiSqlSelectStatement>
274    for SelectStatement<F, S, D, W, O, LOf, G, H, LC>
275where
276    DB: Backend<
277        SelectStatementSyntax = sql_dialect::select_statement_syntax::AnsiSqlSelectStatement,
278    >,
279    S: QueryFragment<DB>,
280    F: QueryFragment<DB>,
281    D: QueryFragment<DB>,
282    W: QueryFragment<DB>,
283    O: QueryFragment<DB>,
284    LOf: QueryFragment<DB>,
285    G: QueryFragment<DB>,
286    H: QueryFragment<DB>,
287    LC: QueryFragment<DB>,
288{
289    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
290        out.push_sql("SELECT ");
291        self.distinct.walk_ast(out.reborrow())?;
292        self.select.walk_ast(out.reborrow())?;
293        self.from.walk_ast(out.reborrow())?;
294        self.where_clause.walk_ast(out.reborrow())?;
295        self.group_by.walk_ast(out.reborrow())?;
296        self.having.walk_ast(out.reborrow())?;
297        self.order.walk_ast(out.reborrow())?;
298        self.limit_offset.walk_ast(out.reborrow())?;
299        self.locking.walk_ast(out.reborrow())?;
300        Ok(())
301    }
302}
303
304impl<S, F, D, W, O, LOf, G, H, LC, QS> ValidSubselect<QS>
305    for SelectStatement<FromClause<F>, S, D, W, O, LOf, G, H, LC>
306where
307    Self: SelectQuery,
308    F: QuerySource,
309    QS: QuerySource,
310    Join<F, QS, Inner>: QuerySource,
311    W: ValidWhereClause<FromClause<Join<F, QS, Inner>>>,
312{
313}
314
315impl<S, D, W, O, LOf, G, H, LC> ValidSubselect<NoFromClause>
316    for SelectStatement<NoFromClause, S, D, W, O, LOf, G, H, LC>
317where
318    Self: SelectQuery,
319    W: ValidWhereClause<NoFromClause>,
320{
321}
322
323impl<S, F, D, W, O, LOf, G, H, LC> ValidSubselect<NoFromClause>
324    for SelectStatement<FromClause<F>, S, D, W, O, LOf, G, H, LC>
325where
326    Self: SelectQuery,
327    F: QuerySource,
328    W: ValidWhereClause<FromClause<F>>,
329{
330}
331
332impl<S, D, W, O, LOf, G, H, LC, QS> ValidSubselect<QS>
333    for SelectStatement<NoFromClause, S, D, W, O, LOf, G, H, LC>
334where
335    Self: SelectQuery,
336    QS: QuerySource,
337    W: ValidWhereClause<NoFromClause>,
338{
339}
340
341/// Allow `SelectStatement<From>` to act as if it were `From` as long as
342/// no other query methods have been called on it
343impl<From, T> AppearsInFromClause<T> for SelectStatement<From>
344where
345    From: AsQuerySource,
346    From::QuerySource: AppearsInFromClause<T> + QuerySource,
347{
348    type Count = <From::QuerySource as AppearsInFromClause<T>>::Count;
349}
350
351impl<From> QuerySource for SelectStatement<From>
352where
353    From: AsQuerySource,
354    <From::QuerySource as QuerySource>::DefaultSelection: SelectableExpression<Self>,
355{
356    type FromClause = <From::QuerySource as QuerySource>::FromClause;
357    type DefaultSelection = <From::QuerySource as QuerySource>::DefaultSelection;
358
359    fn from_clause(&self) -> <From::QuerySource as QuerySource>::FromClause {
360        self.from.as_query_source().from_clause()
361    }
362
363    fn default_selection(&self) -> Self::DefaultSelection {
364        self.from.as_query_source().default_selection()
365    }
366}
367
368impl<From, Selection> AppendSelection<Selection> for SelectStatement<From>
369where
370    From: AsQuerySource,
371    From::QuerySource: AppendSelection<Selection>,
372{
373    type Output = <From::QuerySource as AppendSelection<Selection>>::Output;
374
375    fn append_selection(&self, selection: Selection) -> Self::Output {
376        self.from.as_query_source().append_selection(selection)
377    }
378}