Skip to main content

diesel/query_builder/
where_clause.rs

1use super::from_clause::AsQuerySource;
2use super::*;
3use crate::backend::DieselReserveSpecialization;
4use crate::expression::grouped::Grouped;
5use crate::expression::operators::{And, Or};
6use crate::expression::*;
7use crate::sql_types::BoolOrNullableBool;
8use alloc::sync::Arc;
9
10/// Add `Predicate` to the current `WHERE` clause, joining with `AND` if
11/// applicable.
12pub trait WhereAnd<Predicate> {
13    /// What is the type of the resulting `WHERE` clause?
14    type Output;
15
16    /// See the trait-level docs.
17    fn and(self, predicate: Predicate) -> Self::Output;
18}
19
20/// Add `Predicate` to the current `WHERE` clause, joining with `OR` if
21/// applicable.
22pub trait WhereOr<Predicate> {
23    /// What is the type of the resulting `WHERE` clause?
24    type Output;
25
26    /// See the trait-level docs.
27    fn or(self, predicate: Predicate) -> Self::Output;
28}
29
30/// Represents that a query has no `WHERE` clause.
31#[derive(#[automatically_derived]
impl ::core::fmt::Debug for NoWhereClause {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "NoWhereClause")
    }
}Debug, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for NoWhereClause { }
#[automatically_derived]
impl ::core::clone::Clone for NoWhereClause {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for NoWhereClause { }Copy, const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl diesel::query_builder::QueryId for NoWhereClause {
            type QueryId = NoWhereClause<>;
            const HAS_STATIC_QUERY_ID: bool = true;
            const IS_WINDOW_FUNCTION: bool = false;
        }
    };QueryId)]
32pub struct NoWhereClause;
33
34impl<DB> QueryFragment<DB> for NoWhereClause
35where
36    DB: Backend + DieselReserveSpecialization,
37{
38    fn walk_ast<'b>(&'b self, _: AstPass<'_, 'b, DB>) -> QueryResult<()> {
39        Ok(())
40    }
41}
42
43impl<Predicate> WhereAnd<Predicate> for NoWhereClause
44where
45    Predicate: Expression,
46    Predicate::SqlType: BoolOrNullableBool,
47{
48    type Output = WhereClause<Predicate>;
49
50    fn and(self, predicate: Predicate) -> Self::Output {
51        WhereClause(predicate)
52    }
53}
54
55impl<Predicate> WhereOr<Predicate> for NoWhereClause
56where
57    Predicate: Expression,
58    Predicate::SqlType: BoolOrNullableBool,
59{
60    type Output = WhereClause<Predicate>;
61
62    fn or(self, predicate: Predicate) -> Self::Output {
63        WhereClause(predicate)
64    }
65}
66
67impl<DB> From<NoWhereClause> for BoxedWhereClause<'_, DB> {
68    fn from(_: NoWhereClause) -> Self {
69        BoxedWhereClause::None
70    }
71}
72
73impl<DB> From<NoWhereClause> for BoxedCloneWhereClause<'_, DB> {
74    fn from(_: NoWhereClause) -> Self {
75        BoxedCloneWhereClause::None
76    }
77}
78
79/// The `WHERE` clause of a query.
80#[derive(#[automatically_derived]
impl<Expr: ::core::fmt::Debug> ::core::fmt::Debug for WhereClause<Expr> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f, "WhereClause",
            &&self.0)
    }
}Debug, #[automatically_derived]
impl<Expr: ::core::clone::Clone> ::core::clone::Clone for WhereClause<Expr> {
    #[inline]
    fn clone(&self) -> Self {
        WhereClause(::core::clone::Clone::clone(&self.0))
    }
}Clone, #[automatically_derived]
impl<Expr: ::core::marker::Copy> ::core::marker::Copy for WhereClause<Expr> {
}Copy)]
81pub struct WhereClause<Expr>(Expr);
82
83impl<Expr: diesel::query_builder::QueryId> diesel::query_builder::QueryId for WhereClause<Expr> {
84    type QueryId = WhereClause<<Expr as diesel::query_builder::QueryId>::QueryId>;
85    const HAS_STATIC_QUERY_ID: bool =
86        <Expr as diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID && true;
87
88    const IS_WINDOW_FUNCTION: bool = const {
89        if Expr::IS_WINDOW_FUNCTION {
90            {
    ::core::panicking::panic_fmt(format_args!("Using window functions in WHERE clauses is not supported"));
};panic!("Using window functions in WHERE clauses is not supported");
91        }
92        false
93    };
94}
95
96impl<DB, Expr> QueryFragment<DB> for WhereClause<Expr>
97where
98    DB: Backend + DieselReserveSpecialization,
99    Expr: QueryFragment<DB>,
100{
101    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
102        out.push_sql(" WHERE ");
103        self.0.walk_ast(out.reborrow())?;
104        Ok(())
105    }
106}
107
108impl<Expr, Predicate> WhereAnd<Predicate> for WhereClause<Expr>
109where
110    Expr: Expression,
111    Expr::SqlType: BoolOrNullableBool,
112    Predicate: Expression,
113    Predicate::SqlType: BoolOrNullableBool,
114{
115    type Output = WhereClause<Grouped<And<Expr, Predicate>>>;
116
117    fn and(self, predicate: Predicate) -> Self::Output {
118        WhereClause(Grouped(And::new(self.0, predicate)))
119    }
120}
121
122impl<Expr, Predicate> WhereOr<Predicate> for WhereClause<Expr>
123where
124    Expr: Expression,
125    Expr::SqlType: BoolOrNullableBool,
126    Predicate: Expression,
127    Predicate::SqlType: BoolOrNullableBool,
128{
129    type Output = WhereClause<Grouped<Or<Expr, Predicate>>>;
130
131    fn or(self, predicate: Predicate) -> Self::Output {
132        WhereClause(Grouped(Or::new(self.0, predicate)))
133    }
134}
135
136impl<'a, DB, Predicate> From<WhereClause<Predicate>> for BoxedWhereClause<'a, DB>
137where
138    DB: Backend,
139    Predicate: QueryFragment<DB> + Send + 'a,
140{
141    fn from(where_clause: WhereClause<Predicate>) -> Self {
142        BoxedWhereClause::Where(Box::new(where_clause.0))
143    }
144}
145
146impl<'a, DB, Predicate> From<WhereClause<Predicate>> for BoxedCloneWhereClause<'a, DB>
147where
148    DB: Backend,
149    Predicate: QueryFragment<DB> + Send + Sync + 'a,
150{
151    fn from(where_clause: WhereClause<Predicate>) -> Self {
152        BoxedCloneWhereClause::Where(Arc::new(where_clause.0))
153    }
154}
155
156/// Marker trait indicating that a `WHERE` clause is valid for a given query
157/// source.
158pub trait ValidWhereClause<QS> {}
159
160impl<QS> ValidWhereClause<QS> for NoWhereClause {}
161
162impl<QS, Expr> ValidWhereClause<QS> for WhereClause<Expr>
163where
164    Expr: AppearsOnTable<QS::QuerySource>,
165    QS: AsQuerySource,
166{
167}
168
169impl<Expr> ValidWhereClause<NoFromClause> for WhereClause<Expr> where
170    Expr: AppearsOnTable<NoFromClause>
171{
172}
173
174impl<GB> ValidGrouping<GB> for NoWhereClause {
175    type IsAggregate = is_aggregate::Never;
176}
177
178impl<GB, Expr: ValidGrouping<GB>> ValidGrouping<GB> for WhereClause<Expr> {
179    type IsAggregate = Expr::IsAggregate;
180}
181
182#[allow(missing_debug_implementations)] // We can't...
183pub enum BoxedWhereClause<'a, DB> {
184    Where(Box<dyn QueryFragment<DB> + Send + 'a>),
185    None,
186}
187
188impl<DB> QueryFragment<DB> for BoxedWhereClause<'_, DB>
189where
190    DB: Backend + DieselReserveSpecialization,
191{
192    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
193        match *self {
194            BoxedWhereClause::Where(ref where_clause) => {
195                out.push_sql(" WHERE ");
196                where_clause.walk_ast(out)
197            }
198            BoxedWhereClause::None => Ok(()),
199        }
200    }
201}
202
203impl<DB> QueryId for BoxedWhereClause<'_, DB> {
204    type QueryId = ();
205
206    const HAS_STATIC_QUERY_ID: bool = false;
207}
208
209impl<'a, DB, Predicate> WhereAnd<Predicate> for BoxedWhereClause<'a, DB>
210where
211    DB: Backend + 'a,
212    Predicate: QueryFragment<DB> + Send + 'a,
213    Grouped<And<Box<dyn QueryFragment<DB> + Send + 'a>, Predicate>>: QueryFragment<DB>,
214{
215    type Output = Self;
216
217    fn and(self, predicate: Predicate) -> Self::Output {
218        use self::BoxedWhereClause::Where;
219
220        match self {
221            Where(where_clause) => Where(Box::new(Grouped(And::new(where_clause, predicate)))),
222            BoxedWhereClause::None => Where(Box::new(predicate)),
223        }
224    }
225}
226
227impl<'a, DB, Predicate> WhereOr<Predicate> for BoxedWhereClause<'a, DB>
228where
229    DB: Backend + 'a,
230    Predicate: QueryFragment<DB> + Send + 'a,
231    Grouped<Or<Box<dyn QueryFragment<DB> + Send + 'a>, Predicate>>: QueryFragment<DB>,
232{
233    type Output = Self;
234
235    fn or(self, predicate: Predicate) -> Self::Output {
236        use self::BoxedWhereClause::Where;
237
238        match self {
239            Where(where_clause) => Where(Box::new(Grouped(Or::new(where_clause, predicate)))),
240            BoxedWhereClause::None => Where(Box::new(predicate)),
241        }
242    }
243}
244
245#[allow(missing_debug_implementations)] // We can't...
246pub enum BoxedCloneWhereClause<'a, DB> {
247    Where(Arc<dyn QueryFragment<DB> + Send + Sync + 'a>),
248    None,
249}
250
251impl<DB> Clone for BoxedCloneWhereClause<'_, DB> {
252    fn clone(&self) -> Self {
253        match self {
254            Self::Where(clause) => Self::Where(Arc::clone(clause)),
255            Self::None => Self::None,
256        }
257    }
258}
259
260impl<DB> QueryFragment<DB> for BoxedCloneWhereClause<'_, DB>
261where
262    DB: Backend + DieselReserveSpecialization,
263{
264    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
265        match *self {
266            BoxedCloneWhereClause::Where(ref where_clause) => {
267                out.push_sql(" WHERE ");
268                where_clause.walk_ast(out)
269            }
270            BoxedCloneWhereClause::None => Ok(()),
271        }
272    }
273}
274
275impl<DB> QueryId for BoxedCloneWhereClause<'_, DB> {
276    type QueryId = ();
277
278    const HAS_STATIC_QUERY_ID: bool = false;
279}
280
281impl<'a, DB, Predicate> WhereAnd<Predicate> for BoxedCloneWhereClause<'a, DB>
282where
283    DB: Backend + 'a,
284    Predicate: QueryFragment<DB> + Send + Sync + 'a,
285    Grouped<And<Arc<dyn QueryFragment<DB> + Send + Sync + 'a>, Predicate>>: QueryFragment<DB>,
286{
287    type Output = Self;
288
289    fn and(self, predicate: Predicate) -> Self::Output {
290        use self::BoxedCloneWhereClause::Where;
291
292        match self {
293            Where(where_clause) => Where(Arc::new(Grouped(And::new(where_clause, predicate)))),
294            BoxedCloneWhereClause::None => Where(Arc::new(predicate)),
295        }
296    }
297}
298
299impl<'a, DB, Predicate> WhereOr<Predicate> for BoxedCloneWhereClause<'a, DB>
300where
301    DB: Backend + 'a,
302    Predicate: QueryFragment<DB> + Send + Sync + 'a,
303    Grouped<Or<Arc<dyn QueryFragment<DB> + Send + Sync + 'a>, Predicate>>: QueryFragment<DB>,
304{
305    type Output = Self;
306
307    fn or(self, predicate: Predicate) -> Self::Output {
308        use self::BoxedCloneWhereClause::Where;
309
310        match self {
311            Where(where_clause) => Where(Arc::new(Grouped(Or::new(where_clause, predicate)))),
312            BoxedCloneWhereClause::None => Where(Arc::new(predicate)),
313        }
314    }
315}