1use core::ops::{BitAnd, BitOr, Not};
18
19use crate::sql::{SQL, SQLChunk, Token};
20use crate::traits::{SQLParam, ToSQL};
21use crate::types::Bool;
22
23use super::{AggregateKind, Expr, NonNull, Nullability, SQLExpr, Scalar};
24
25pub fn not<'a, V, E>(expr: E) -> SQLExpr<'a, V, Bool, NonNull, Scalar>
33where
34 V: SQLParam + 'a,
35 E: ToSQL<'a, V>,
36{
37 let expr_sql = expr.to_sql();
38 let needs_paren = expr_sql.chunks.len() > 1
39 || (expr_sql.chunks.len() == 1
40 && !matches!(expr_sql.chunks[0], SQLChunk::Raw(_) | SQLChunk::Ident(_)));
41
42 let sql = if needs_paren {
43 SQL::from_iter([Token::NOT, Token::LPAREN])
44 .append(expr_sql)
45 .push(Token::RPAREN)
46 } else {
47 SQL::from(Token::NOT).append(expr_sql)
48 };
49 SQLExpr::new(sql)
50}
51
52pub fn and<'a, V, I, E>(conditions: I) -> SQLExpr<'a, V, Bool, NonNull, Scalar>
61where
62 V: SQLParam + 'a,
63 I: IntoIterator<Item = E>,
64 E: ToSQL<'a, V>,
65{
66 let mut iter = conditions.into_iter();
67
68 let sql = match iter.next() {
69 None => SQL::empty(),
70 Some(first) => {
71 let first_sql = first.to_sql();
72 let Some(second) = iter.next() else {
73 return SQLExpr::new(first_sql);
74 };
75 let all_conditions = core::iter::once(first_sql)
76 .chain(core::iter::once(second.to_sql()))
77 .chain(iter.map(|c| c.to_sql()));
78 SQL::from(Token::LPAREN)
79 .append(SQL::join(all_conditions, Token::AND))
80 .push(Token::RPAREN)
81 }
82 };
83 SQLExpr::new(sql)
84}
85
86pub fn and2<'a, V, L, R>(left: L, right: R) -> SQLExpr<'a, V, Bool, NonNull, Scalar>
88where
89 V: SQLParam + 'a,
90 L: ToSQL<'a, V>,
91 R: ToSQL<'a, V>,
92{
93 SQLExpr::new(
94 SQL::from(Token::LPAREN)
95 .append(left.to_sql())
96 .push(Token::AND)
97 .append(right.to_sql())
98 .push(Token::RPAREN),
99 )
100}
101
102pub fn or<'a, V, I, E>(conditions: I) -> SQLExpr<'a, V, Bool, NonNull, Scalar>
111where
112 V: SQLParam + 'a,
113 I: IntoIterator<Item = E>,
114 E: ToSQL<'a, V>,
115{
116 let mut iter = conditions.into_iter();
117
118 let sql = match iter.next() {
119 None => SQL::empty(),
120 Some(first) => {
121 let first_sql = first.to_sql();
122 let Some(second) = iter.next() else {
123 return SQLExpr::new(first_sql);
124 };
125 let all_conditions = core::iter::once(first_sql)
126 .chain(core::iter::once(second.to_sql()))
127 .chain(iter.map(|c| c.to_sql()));
128 SQL::from(Token::LPAREN)
129 .append(SQL::join(all_conditions, Token::OR))
130 .push(Token::RPAREN)
131 }
132 };
133 SQLExpr::new(sql)
134}
135
136pub fn or2<'a, V, L, R>(left: L, right: R) -> SQLExpr<'a, V, Bool, NonNull, Scalar>
138where
139 V: SQLParam + 'a,
140 L: ToSQL<'a, V>,
141 R: ToSQL<'a, V>,
142{
143 SQLExpr::new(
144 SQL::from(Token::LPAREN)
145 .append(left.to_sql())
146 .push(Token::OR)
147 .append(right.to_sql())
148 .push(Token::RPAREN),
149 )
150}
151
152impl<'a, V, N, A> Not for SQLExpr<'a, V, Bool, N, A>
165where
166 V: SQLParam + 'a,
167 N: Nullability,
168 A: AggregateKind,
169{
170 type Output = SQLExpr<'a, V, Bool, NonNull, Scalar>;
171
172 fn not(self) -> Self::Output {
173 not(self)
174 }
175}
176
177impl<'a, V, N, A, Rhs> BitAnd<Rhs> for SQLExpr<'a, V, Bool, N, A>
186where
187 V: SQLParam + 'a,
188 N: Nullability,
189 A: AggregateKind,
190 Rhs: Expr<'a, V>,
191{
192 type Output = SQLExpr<'a, V, Bool, NonNull, Scalar>;
193
194 fn bitand(self, rhs: Rhs) -> Self::Output {
195 and2(self, rhs)
196 }
197}
198
199impl<'a, V, N, A, Rhs> BitOr<Rhs> for SQLExpr<'a, V, Bool, N, A>
208where
209 V: SQLParam + 'a,
210 N: Nullability,
211 A: AggregateKind,
212 Rhs: Expr<'a, V>,
213{
214 type Output = SQLExpr<'a, V, Bool, NonNull, Scalar>;
215
216 fn bitor(self, rhs: Rhs) -> Self::Output {
217 or2(self, rhs)
218 }
219}