diesel/query_builder/
where_clause.rs1use 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)]
74pub struct WhereClause<Expr>(Expr);
75
76impl<Expr: diesel::query_builder::QueryId> diesel::query_builder::QueryId for WhereClause<Expr> {
77 type QueryId = WhereClause<<Expr as diesel::query_builder::QueryId>::QueryId>;
78 const HAS_STATIC_QUERY_ID: bool =
79 <Expr as diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID && true;
80
81 const IS_WINDOW_FUNCTION: bool = const {
82 if Expr::IS_WINDOW_FUNCTION {
83 panic!("Using window functions in WHERE clauses is not supported");
84 }
85 false
86 };
87}
88
89impl<DB, Expr> QueryFragment<DB> for WhereClause<Expr>
90where
91 DB: Backend + DieselReserveSpecialization,
92 Expr: QueryFragment<DB>,
93{
94 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
95 out.push_sql(" WHERE ");
96 self.0.walk_ast(out.reborrow())?;
97 Ok(())
98 }
99}
100
101impl<Expr, Predicate> WhereAnd<Predicate> for WhereClause<Expr>
102where
103 Expr: Expression,
104 Expr::SqlType: BoolOrNullableBool,
105 Predicate: Expression,
106 Predicate::SqlType: BoolOrNullableBool,
107{
108 type Output = WhereClause<Grouped<And<Expr, Predicate>>>;
109
110 fn and(self, predicate: Predicate) -> Self::Output {
111 WhereClause(Grouped(And::new(self.0, predicate)))
112 }
113}
114
115impl<Expr, Predicate> WhereOr<Predicate> for WhereClause<Expr>
116where
117 Expr: Expression,
118 Expr::SqlType: BoolOrNullableBool,
119 Predicate: Expression,
120 Predicate::SqlType: BoolOrNullableBool,
121{
122 type Output = WhereClause<Grouped<Or<Expr, Predicate>>>;
123
124 fn or(self, predicate: Predicate) -> Self::Output {
125 WhereClause(Grouped(Or::new(self.0, predicate)))
126 }
127}
128
129impl<'a, DB, Predicate> From<WhereClause<Predicate>> for BoxedWhereClause<'a, DB>
130where
131 DB: Backend,
132 Predicate: QueryFragment<DB> + Send + 'a,
133{
134 fn from(where_clause: WhereClause<Predicate>) -> Self {
135 BoxedWhereClause::Where(Box::new(where_clause.0))
136 }
137}
138
139pub trait ValidWhereClause<QS> {}
142
143impl<QS> ValidWhereClause<QS> for NoWhereClause {}
144
145impl<QS, Expr> ValidWhereClause<QS> for WhereClause<Expr>
146where
147 Expr: AppearsOnTable<QS::QuerySource>,
148 QS: AsQuerySource,
149{
150}
151
152impl<Expr> ValidWhereClause<NoFromClause> for WhereClause<Expr> where
153 Expr: AppearsOnTable<NoFromClause>
154{
155}
156
157#[allow(missing_debug_implementations)] pub enum BoxedWhereClause<'a, DB> {
159 Where(Box<dyn QueryFragment<DB> + Send + 'a>),
160 None,
161}
162
163impl<DB> QueryFragment<DB> for BoxedWhereClause<'_, DB>
164where
165 DB: Backend + DieselReserveSpecialization,
166{
167 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
168 match *self {
169 BoxedWhereClause::Where(ref where_clause) => {
170 out.push_sql(" WHERE ");
171 where_clause.walk_ast(out)
172 }
173 BoxedWhereClause::None => Ok(()),
174 }
175 }
176}
177
178impl<DB> QueryId for BoxedWhereClause<'_, DB> {
179 type QueryId = ();
180
181 const HAS_STATIC_QUERY_ID: bool = false;
182}
183
184impl<'a, DB, Predicate> WhereAnd<Predicate> for BoxedWhereClause<'a, DB>
185where
186 DB: Backend + 'a,
187 Predicate: QueryFragment<DB> + Send + 'a,
188 Grouped<And<Box<dyn QueryFragment<DB> + Send + 'a>, Predicate>>: QueryFragment<DB>,
189{
190 type Output = Self;
191
192 fn and(self, predicate: Predicate) -> Self::Output {
193 use self::BoxedWhereClause::Where;
194
195 match self {
196 Where(where_clause) => Where(Box::new(Grouped(And::new(where_clause, predicate)))),
197 BoxedWhereClause::None => Where(Box::new(predicate)),
198 }
199 }
200}
201
202impl<'a, DB, Predicate> WhereOr<Predicate> for BoxedWhereClause<'a, DB>
203where
204 DB: Backend + 'a,
205 Predicate: QueryFragment<DB> + Send + 'a,
206 Grouped<Or<Box<dyn QueryFragment<DB> + Send + 'a>, Predicate>>: QueryFragment<DB>,
207{
208 type Output = Self;
209
210 fn or(self, predicate: Predicate) -> Self::Output {
211 use self::BoxedWhereClause::Where;
212
213 match self {
214 Where(where_clause) => Where(Box::new(Grouped(Or::new(where_clause, predicate)))),
215 BoxedWhereClause::None => Where(Box::new(predicate)),
216 }
217 }
218}