chain_builder/query/
common.rs

1//! Common query functionality for WHERE clauses and other query parts
2
3use crate::query::QueryBuilder;
4use crate::types::Common;
5use serde_json::Value;
6
7/// Trait for common query operations
8pub trait QueryCommon {
9    /// Add a WITH clause
10    fn with(&mut self, alias: &str, chain_builder: crate::builder::ChainBuilder);
11
12    /// Add a recursive WITH clause
13    fn with_recursive(&mut self, alias: &str, chain_builder: crate::builder::ChainBuilder);
14
15    /// Add a UNION clause
16    fn union(&mut self, chain_builder: crate::builder::ChainBuilder);
17
18    /// Add a UNION ALL clause
19    fn union_all(&mut self, chain_builder: crate::builder::ChainBuilder);
20
21    /// Add a LIMIT clause
22    fn limit(&mut self, limit: usize);
23
24    /// Add an OFFSET clause
25    fn offset(&mut self, offset: usize);
26
27    /// Add a GROUP BY clause
28    fn group_by(&mut self, columns: Vec<String>);
29
30    /// Add a raw GROUP BY clause
31    fn group_by_raw(&mut self, sql: &str, binds: Option<Vec<Value>>);
32
33    /// Add an ORDER BY clause
34    fn order_by(&mut self, column: &str, order: &str);
35
36    /// Add a raw ORDER BY clause
37    fn order_by_raw(&mut self, sql: &str, binds: Option<Vec<Value>>);
38}
39
40impl QueryCommon for QueryBuilder {
41    fn with(&mut self, alias: &str, chain_builder: crate::builder::ChainBuilder) {
42        self.query_common
43            .push(Common::With(alias.to_string(), false, chain_builder));
44    }
45
46    fn with_recursive(&mut self, alias: &str, chain_builder: crate::builder::ChainBuilder) {
47        self.query_common
48            .push(Common::With(alias.to_string(), true, chain_builder));
49    }
50
51    fn union(&mut self, chain_builder: crate::builder::ChainBuilder) {
52        self.query_common.push(Common::Union(false, chain_builder));
53    }
54
55    fn union_all(&mut self, chain_builder: crate::builder::ChainBuilder) {
56        self.query_common.push(Common::Union(true, chain_builder));
57    }
58
59    fn limit(&mut self, limit: usize) {
60        self.query_common.push(Common::Limit(limit));
61    }
62
63    fn offset(&mut self, offset: usize) {
64        self.query_common.push(Common::Offset(offset));
65    }
66
67    fn group_by(&mut self, columns: Vec<String>) {
68        self.query_common.push(Common::GroupBy(columns));
69    }
70
71    fn group_by_raw(&mut self, sql: &str, binds: Option<Vec<Value>>) {
72        self.query_common
73            .push(Common::GroupByRaw(sql.to_string(), binds));
74    }
75
76    fn order_by(&mut self, column: &str, order: &str) {
77        self.query_common
78            .push(Common::OrderBy(column.to_string(), order.to_string()));
79    }
80
81    fn order_by_raw(&mut self, sql: &str, binds: Option<Vec<Value>>) {
82        self.query_common
83            .push(Common::OrderByRaw(sql.to_string(), binds));
84    }
85}
86
87/// Trait for HAVING clause operations
88pub trait HavingClauses {
89    /// Add a HAVING condition
90    fn having(&mut self, column: &str, operator: &str, value: Value);
91
92    /// Add a HAVING condition with raw SQL
93    fn having_raw(&mut self, sql: &str, binds: Option<Vec<Value>>);
94
95    /// Add a HAVING BETWEEN condition
96    fn having_between(&mut self, column: &str, values: [Value; 2]);
97
98    /// Add a HAVING IN condition
99    fn having_in(&mut self, column: &str, values: Vec<Value>);
100
101    /// Add a HAVING NOT IN condition
102    fn having_not_in(&mut self, column: &str, values: Vec<Value>);
103}
104
105impl HavingClauses for QueryBuilder {
106    fn having(&mut self, column: &str, operator: &str, value: Value) {
107        let sql = format!("{} {} ?", column, operator);
108        self.query_common
109            .push(Common::Having(sql, Some(vec![value])));
110    }
111
112    fn having_raw(&mut self, sql: &str, binds: Option<Vec<Value>>) {
113        self.query_common
114            .push(Common::Having(sql.to_string(), binds));
115    }
116
117    fn having_between(&mut self, column: &str, values: [Value; 2]) {
118        let sql = format!("{} BETWEEN ? AND ?", column);
119        self.query_common
120            .push(Common::Having(sql, Some(values.to_vec())));
121    }
122
123    fn having_in(&mut self, column: &str, values: Vec<Value>) {
124        let placeholders = vec!["?"; values.len()].join(", ");
125        let sql = format!("{} IN ({})", column, placeholders);
126        self.query_common.push(Common::Having(sql, Some(values)));
127    }
128
129    fn having_not_in(&mut self, column: &str, values: Vec<Value>) {
130        let placeholders = vec!["?"; values.len()].join(", ");
131        let sql = format!("{} NOT IN ({})", column, placeholders);
132        self.query_common.push(Common::Having(sql, Some(values)));
133    }
134}
135
136/// Trait for WHERE clause operations
137pub trait WhereClauses {
138    /// Add an equality condition
139    fn where_eq(&mut self, column: &str, value: Value);
140
141    /// Add a not equality condition
142    fn where_ne(&mut self, column: &str, value: Value);
143
144    /// Add an IN condition
145    fn where_in(&mut self, column: &str, values: Vec<Value>);
146
147    /// Add a NOT IN condition
148    fn where_not_in(&mut self, column: &str, values: Vec<Value>);
149
150    /// Add an IS NULL condition
151    fn where_null(&mut self, column: &str);
152
153    /// Add an IS NOT NULL condition
154    fn where_not_null(&mut self, column: &str);
155
156    /// Add a BETWEEN condition
157    fn where_between(&mut self, column: &str, values: [Value; 2]);
158
159    /// Add a NOT BETWEEN condition
160    fn where_not_between(&mut self, column: &str, values: [Value; 2]);
161
162    /// Add a LIKE condition
163    fn where_like(&mut self, column: &str, value: Value);
164
165    /// Add a NOT LIKE condition
166    fn where_not_like(&mut self, column: &str, value: Value);
167
168    /// Add a case-insensitive LIKE condition (ILIKE for Postgres, LOWER() for MySQL)
169    fn where_ilike(&mut self, column: &str, value: Value);
170
171    /// Add a greater than condition
172    fn where_gt(&mut self, column: &str, value: Value);
173
174    /// Add a greater than or equal condition
175    fn where_gte(&mut self, column: &str, value: Value);
176
177    /// Add a less than condition
178    fn where_lt(&mut self, column: &str, value: Value);
179
180    /// Add a less than or equal condition
181    fn where_lte(&mut self, column: &str, value: Value);
182
183    /// Add a column-to-column comparison
184    fn where_column(&mut self, lhs: &str, operator: &str, rhs: &str);
185
186    /// Add an EXISTS condition
187    fn where_exists(&mut self, query: impl FnOnce(&mut crate::builder::ChainBuilder));
188
189    /// Add a NOT EXISTS condition
190    fn where_not_exists(&mut self, query: impl FnOnce(&mut crate::builder::ChainBuilder));
191
192    /// Add a JSON contains condition (MySQL JSON_CONTAINS)
193    fn where_json_contains(&mut self, column: &str, value: Value);
194
195    /// Add a subquery condition
196    fn where_subquery(&mut self, query: impl FnOnce(&mut QueryBuilder));
197
198    /// Add an OR condition
199    fn or(&mut self) -> &mut QueryBuilder;
200
201    /// Add a raw WHERE condition
202    fn where_raw(&mut self, sql: &str, binds: Option<Vec<Value>>);
203}
204
205impl WhereClauses for QueryBuilder {
206    fn where_eq(&mut self, column: &str, value: Value) {
207        self.statement.push(crate::types::Statement::Value(
208            column.to_string(),
209            crate::query::Operator::Equal,
210            value,
211        ));
212    }
213
214    fn where_ne(&mut self, column: &str, value: Value) {
215        self.statement.push(crate::types::Statement::Value(
216            column.to_string(),
217            crate::query::Operator::NotEqual,
218            value,
219        ));
220    }
221
222    fn where_in(&mut self, column: &str, values: Vec<Value>) {
223        self.statement.push(crate::types::Statement::Value(
224            column.to_string(),
225            crate::query::Operator::In,
226            Value::Array(values),
227        ));
228    }
229
230    fn where_not_in(&mut self, column: &str, values: Vec<Value>) {
231        self.statement.push(crate::types::Statement::Value(
232            column.to_string(),
233            crate::query::Operator::NotIn,
234            Value::Array(values),
235        ));
236    }
237
238    fn where_null(&mut self, column: &str) {
239        self.statement.push(crate::types::Statement::Value(
240            column.to_string(),
241            crate::query::Operator::IsNull,
242            Value::Null,
243        ));
244    }
245
246    fn where_not_null(&mut self, column: &str) {
247        self.statement.push(crate::types::Statement::Value(
248            column.to_string(),
249            crate::query::Operator::IsNotNull,
250            Value::Null,
251        ));
252    }
253
254    fn where_between(&mut self, column: &str, values: [Value; 2]) {
255        self.statement.push(crate::types::Statement::Value(
256            column.to_string(),
257            crate::query::Operator::Between,
258            Value::Array(values.to_vec()),
259        ));
260    }
261
262    fn where_not_between(&mut self, column: &str, values: [Value; 2]) {
263        self.statement.push(crate::types::Statement::Value(
264            column.to_string(),
265            crate::query::Operator::NotBetween,
266            Value::Array(values.to_vec()),
267        ));
268    }
269
270    fn where_like(&mut self, column: &str, value: Value) {
271        self.statement.push(crate::types::Statement::Value(
272            column.to_string(),
273            crate::query::Operator::Like,
274            value,
275        ));
276    }
277
278    fn where_not_like(&mut self, column: &str, value: Value) {
279        self.statement.push(crate::types::Statement::Value(
280            column.to_string(),
281            crate::query::Operator::NotLike,
282            value,
283        ));
284    }
285
286    fn where_gt(&mut self, column: &str, value: Value) {
287        self.statement.push(crate::types::Statement::Value(
288            column.to_string(),
289            crate::query::Operator::GreaterThan,
290            value,
291        ));
292    }
293
294    fn where_gte(&mut self, column: &str, value: Value) {
295        self.statement.push(crate::types::Statement::Value(
296            column.to_string(),
297            crate::query::Operator::GreaterThanOrEqual,
298            value,
299        ));
300    }
301
302    fn where_lt(&mut self, column: &str, value: Value) {
303        self.statement.push(crate::types::Statement::Value(
304            column.to_string(),
305            crate::query::Operator::LessThan,
306            value,
307        ));
308    }
309
310    fn where_lte(&mut self, column: &str, value: Value) {
311        self.statement.push(crate::types::Statement::Value(
312            column.to_string(),
313            crate::query::Operator::LessThanOrEqual,
314            value,
315        ));
316    }
317
318    fn where_subquery(&mut self, query: impl FnOnce(&mut QueryBuilder)) {
319        let mut sub_query = QueryBuilder::default();
320        query(&mut sub_query);
321        self.statement
322            .push(crate::types::Statement::SubChain(Box::new(sub_query)));
323    }
324
325    fn or(&mut self) -> &mut QueryBuilder {
326        let or_query = QueryBuilder::default();
327        self.statement
328            .push(crate::types::Statement::OrChain(Box::new(or_query)));
329        self.statement.last_mut().unwrap().to_query_builder()
330    }
331
332    fn where_raw(&mut self, sql: &str, binds: Option<Vec<Value>>) {
333        self.statement
334            .push(crate::types::Statement::Raw((sql.to_string(), binds)));
335    }
336
337    fn where_ilike(&mut self, column: &str, value: Value) {
338        // For MySQL, use LOWER() function
339        let sql = format!("LOWER({}) LIKE LOWER(?)", column);
340        self.statement
341            .push(crate::types::Statement::Raw((sql, Some(vec![value]))));
342    }
343
344    fn where_column(&mut self, lhs: &str, operator: &str, rhs: &str) {
345        let sql = format!("{} {} {}", lhs, operator, rhs);
346        self.statement
347            .push(crate::types::Statement::Raw((sql, None)));
348    }
349
350    fn where_exists(&mut self, query: impl FnOnce(&mut crate::builder::ChainBuilder)) {
351        let mut sub_builder = crate::builder::ChainBuilder::new(crate::types::Client::Mysql);
352        query(&mut sub_builder);
353        let sql = format!("EXISTS ({})", sub_builder.to_sql().0);
354        self.statement
355            .push(crate::types::Statement::Raw((sql, None)));
356    }
357
358    fn where_not_exists(&mut self, query: impl FnOnce(&mut crate::builder::ChainBuilder)) {
359        let mut sub_builder = crate::builder::ChainBuilder::new(crate::types::Client::Mysql);
360        query(&mut sub_builder);
361        let sql = format!("NOT EXISTS ({})", sub_builder.to_sql().0);
362        self.statement
363            .push(crate::types::Statement::Raw((sql, None)));
364    }
365
366    fn where_json_contains(&mut self, column: &str, value: Value) {
367        let sql = format!("JSON_CONTAINS({}, ?)", column);
368        self.statement
369            .push(crate::types::Statement::Raw((sql, Some(vec![value]))));
370    }
371}