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]
impl ::core::clone::Clone for NoWhereClause {
    #[inline]
    fn clone(&self) -> NoWhereClause { *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) -> WhereClause<Expr> {
        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
174#[allow(missing_debug_implementations)] // We can't...
175pub enum BoxedWhereClause<'a, DB> {
176    Where(Box<dyn QueryFragment<DB> + Send + 'a>),
177    None,
178}
179
180impl<DB> QueryFragment<DB> for BoxedWhereClause<'_, DB>
181where
182    DB: Backend + DieselReserveSpecialization,
183{
184    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
185        match *self {
186            BoxedWhereClause::Where(ref where_clause) => {
187                out.push_sql(" WHERE ");
188                where_clause.walk_ast(out)
189            }
190            BoxedWhereClause::None => Ok(()),
191        }
192    }
193}
194
195impl<DB> QueryId for BoxedWhereClause<'_, DB> {
196    type QueryId = ();
197
198    const HAS_STATIC_QUERY_ID: bool = false;
199}
200
201impl<'a, DB, Predicate> WhereAnd<Predicate> for BoxedWhereClause<'a, DB>
202where
203    DB: Backend + 'a,
204    Predicate: QueryFragment<DB> + Send + 'a,
205    Grouped<And<Box<dyn QueryFragment<DB> + Send + 'a>, Predicate>>: QueryFragment<DB>,
206{
207    type Output = Self;
208
209    fn and(self, predicate: Predicate) -> Self::Output {
210        use self::BoxedWhereClause::Where;
211
212        match self {
213            Where(where_clause) => Where(Box::new(Grouped(And::new(where_clause, predicate)))),
214            BoxedWhereClause::None => Where(Box::new(predicate)),
215        }
216    }
217}
218
219impl<'a, DB, Predicate> WhereOr<Predicate> for BoxedWhereClause<'a, DB>
220where
221    DB: Backend + 'a,
222    Predicate: QueryFragment<DB> + Send + 'a,
223    Grouped<Or<Box<dyn QueryFragment<DB> + Send + 'a>, Predicate>>: QueryFragment<DB>,
224{
225    type Output = Self;
226
227    fn or(self, predicate: Predicate) -> Self::Output {
228        use self::BoxedWhereClause::Where;
229
230        match self {
231            Where(where_clause) => Where(Box::new(Grouped(Or::new(where_clause, predicate)))),
232            BoxedWhereClause::None => Where(Box::new(predicate)),
233        }
234    }
235}
236
237#[allow(missing_debug_implementations)] // We can't...
238pub enum BoxedCloneWhereClause<'a, DB> {
239    Where(Arc<dyn QueryFragment<DB> + Send + Sync + 'a>),
240    None,
241}
242
243impl<DB> Clone for BoxedCloneWhereClause<'_, DB> {
244    fn clone(&self) -> Self {
245        match self {
246            Self::Where(clause) => Self::Where(Arc::clone(clause)),
247            Self::None => Self::None,
248        }
249    }
250}
251
252impl<DB> QueryFragment<DB> for BoxedCloneWhereClause<'_, DB>
253where
254    DB: Backend + DieselReserveSpecialization,
255{
256    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
257        match *self {
258            BoxedCloneWhereClause::Where(ref where_clause) => {
259                out.push_sql(" WHERE ");
260                where_clause.walk_ast(out)
261            }
262            BoxedCloneWhereClause::None => Ok(()),
263        }
264    }
265}
266
267impl<DB> QueryId for BoxedCloneWhereClause<'_, DB> {
268    type QueryId = ();
269
270    const HAS_STATIC_QUERY_ID: bool = false;
271}
272
273impl<'a, DB, Predicate> WhereAnd<Predicate> for BoxedCloneWhereClause<'a, DB>
274where
275    DB: Backend + 'a,
276    Predicate: QueryFragment<DB> + Send + Sync + 'a,
277    Grouped<And<Arc<dyn QueryFragment<DB> + Send + Sync + 'a>, Predicate>>: QueryFragment<DB>,
278{
279    type Output = Self;
280
281    fn and(self, predicate: Predicate) -> Self::Output {
282        use self::BoxedCloneWhereClause::Where;
283
284        match self {
285            Where(where_clause) => Where(Arc::new(Grouped(And::new(where_clause, predicate)))),
286            BoxedCloneWhereClause::None => Where(Arc::new(predicate)),
287        }
288    }
289}
290
291impl<'a, DB, Predicate> WhereOr<Predicate> for BoxedCloneWhereClause<'a, DB>
292where
293    DB: Backend + 'a,
294    Predicate: QueryFragment<DB> + Send + Sync + 'a,
295    Grouped<Or<Arc<dyn QueryFragment<DB> + Send + Sync + 'a>, Predicate>>: QueryFragment<DB>,
296{
297    type Output = Self;
298
299    fn or(self, predicate: Predicate) -> Self::Output {
300        use self::BoxedCloneWhereClause::Where;
301
302        match self {
303            Where(where_clause) => Where(Arc::new(Grouped(Or::new(where_clause, predicate)))),
304            BoxedCloneWhereClause::None => Where(Arc::new(predicate)),
305        }
306    }
307}