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;
8
9pub trait WhereAnd<Predicate> {
12 type Output;
14
15 fn and(self, predicate: Predicate) -> Self::Output;
17}
18
19pub trait WhereOr<Predicate> {
22 type Output;
24
25 fn or(self, predicate: Predicate) -> Self::Output;
27}
28
29#[derive(Debug, Clone, Copy, QueryId)]
31pub struct NoWhereClause;
32
33impl<DB> QueryFragment<DB> for NoWhereClause
34where
35 DB: Backend + DieselReserveSpecialization,
36{
37 fn walk_ast<'b>(&'b self, _: AstPass<'_, 'b, DB>) -> QueryResult<()> {
38 Ok(())
39 }
40}
41
42impl<Predicate> WhereAnd<Predicate> for NoWhereClause
43where
44 Predicate: Expression,
45 Predicate::SqlType: BoolOrNullableBool,
46{
47 type Output = WhereClause<Predicate>;
48
49 fn and(self, predicate: Predicate) -> Self::Output {
50 WhereClause(predicate)
51 }
52}
53
54impl<Predicate> WhereOr<Predicate> for NoWhereClause
55where
56 Predicate: Expression,
57 Predicate::SqlType: BoolOrNullableBool,
58{
59 type Output = WhereClause<Predicate>;
60
61 fn or(self, predicate: Predicate) -> Self::Output {
62 WhereClause(predicate)
63 }
64}
65
66impl<DB> From<NoWhereClause> for BoxedWhereClause<'_, DB> {
67 fn from(_: NoWhereClause) -> Self {
68 BoxedWhereClause::None
69 }
70}
71
72#[derive(Debug, Clone, Copy, QueryId)]
74pub struct WhereClause<Expr>(Expr);
75
76impl<DB, Expr> QueryFragment<DB> for WhereClause<Expr>
77where
78 DB: Backend + DieselReserveSpecialization,
79 Expr: QueryFragment<DB>,
80{
81 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
82 out.push_sql(" WHERE ");
83 self.0.walk_ast(out.reborrow())?;
84 Ok(())
85 }
86}
87
88impl<Expr, Predicate> WhereAnd<Predicate> for WhereClause<Expr>
89where
90 Expr: Expression,
91 Expr::SqlType: BoolOrNullableBool,
92 Predicate: Expression,
93 Predicate::SqlType: BoolOrNullableBool,
94{
95 type Output = WhereClause<Grouped<And<Expr, Predicate>>>;
96
97 fn and(self, predicate: Predicate) -> Self::Output {
98 WhereClause(Grouped(And::new(self.0, predicate)))
99 }
100}
101
102impl<Expr, Predicate> WhereOr<Predicate> for WhereClause<Expr>
103where
104 Expr: Expression,
105 Expr::SqlType: BoolOrNullableBool,
106 Predicate: Expression,
107 Predicate::SqlType: BoolOrNullableBool,
108{
109 type Output = WhereClause<Grouped<Or<Expr, Predicate>>>;
110
111 fn or(self, predicate: Predicate) -> Self::Output {
112 WhereClause(Grouped(Or::new(self.0, predicate)))
113 }
114}
115
116impl<'a, DB, Predicate> From<WhereClause<Predicate>> for BoxedWhereClause<'a, DB>
117where
118 DB: Backend,
119 Predicate: QueryFragment<DB> + Send + 'a,
120{
121 fn from(where_clause: WhereClause<Predicate>) -> Self {
122 BoxedWhereClause::Where(Box::new(where_clause.0))
123 }
124}
125
126pub trait ValidWhereClause<QS> {}
129
130impl<QS> ValidWhereClause<QS> for NoWhereClause {}
131
132impl<QS, Expr> ValidWhereClause<QS> for WhereClause<Expr>
133where
134 Expr: AppearsOnTable<QS::QuerySource>,
135 QS: AsQuerySource,
136{
137}
138
139impl<Expr> ValidWhereClause<NoFromClause> for WhereClause<Expr> where
140 Expr: AppearsOnTable<NoFromClause>
141{
142}
143
144#[allow(missing_debug_implementations)] pub enum BoxedWhereClause<'a, DB> {
146 Where(Box<dyn QueryFragment<DB> + Send + 'a>),
147 None,
148}
149
150impl<DB> QueryFragment<DB> for BoxedWhereClause<'_, DB>
151where
152 DB: Backend + DieselReserveSpecialization,
153{
154 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
155 match *self {
156 BoxedWhereClause::Where(ref where_clause) => {
157 out.push_sql(" WHERE ");
158 where_clause.walk_ast(out)
159 }
160 BoxedWhereClause::None => Ok(()),
161 }
162 }
163}
164
165impl<DB> QueryId for BoxedWhereClause<'_, DB> {
166 type QueryId = ();
167
168 const HAS_STATIC_QUERY_ID: bool = false;
169}
170
171impl<'a, DB, Predicate> WhereAnd<Predicate> for BoxedWhereClause<'a, DB>
172where
173 DB: Backend + 'a,
174 Predicate: QueryFragment<DB> + Send + 'a,
175 Grouped<And<Box<dyn QueryFragment<DB> + Send + 'a>, Predicate>>: QueryFragment<DB>,
176{
177 type Output = Self;
178
179 fn and(self, predicate: Predicate) -> Self::Output {
180 use self::BoxedWhereClause::Where;
181
182 match self {
183 Where(where_clause) => Where(Box::new(Grouped(And::new(where_clause, predicate)))),
184 BoxedWhereClause::None => Where(Box::new(predicate)),
185 }
186 }
187}
188
189impl<'a, DB, Predicate> WhereOr<Predicate> for BoxedWhereClause<'a, DB>
190where
191 DB: Backend + 'a,
192 Predicate: QueryFragment<DB> + Send + 'a,
193 Grouped<Or<Box<dyn QueryFragment<DB> + Send + 'a>, Predicate>>: QueryFragment<DB>,
194{
195 type Output = Self;
196
197 fn or(self, predicate: Predicate) -> Self::Output {
198 use self::BoxedWhereClause::Where;
199
200 match self {
201 Where(where_clause) => Where(Box::new(Grouped(Or::new(where_clause, predicate)))),
202 BoxedWhereClause::None => Where(Box::new(predicate)),
203 }
204 }
205}