1use crate::ast::{
6 Cage, CageKind, Condition, Expr, Join, JoinKind, LogicalOp, Operator, Qail, SortOrder,
7 Value,
8};
9
10impl Qail {
11 pub fn limit(mut self, n: i64) -> Self {
12 self.cages.push(Cage {
13 kind: CageKind::Limit(n as usize),
14 conditions: vec![],
15 logical_op: LogicalOp::And,
16 });
17 self
18 }
19
20 #[deprecated(since = "0.11.0", note = "Use .order_asc(column) instead")]
21 pub fn sort_asc(mut self, column: &str) -> Self {
22 self.cages.push(Cage {
23 kind: CageKind::Sort(SortOrder::Asc),
24 conditions: vec![Condition {
25 left: Expr::Named(column.to_string()),
26 op: Operator::Eq,
27 value: Value::Null,
28 is_array_unnest: false,
29 }],
30 logical_op: LogicalOp::And,
31 });
32 self
33 }
34
35 pub fn select_all(mut self) -> Self {
36 self.columns.push(Expr::Star);
37 self
38 }
39
40 pub fn columns<I, S>(mut self, cols: I) -> Self
41 where
42 I: IntoIterator<Item = S>,
43 S: AsRef<str>,
44 {
45 self.columns.extend(
46 cols.into_iter()
47 .map(|c| Expr::Named(c.as_ref().to_string())),
48 );
49 self
50 }
51
52 pub fn column(mut self, col: impl AsRef<str>) -> Self {
53 self.columns.push(Expr::Named(col.as_ref().to_string()));
54 self
55 }
56
57 pub fn filter(
58 mut self,
59 column: impl AsRef<str>,
60 op: Operator,
61 value: impl Into<Value>,
62 ) -> Self {
63 let filter_cage = self
64 .cages
65 .iter_mut()
66 .find(|c| matches!(c.kind, CageKind::Filter));
67
68 let condition = Condition {
69 left: Expr::Named(column.as_ref().to_string()),
70 op,
71 value: value.into(),
72 is_array_unnest: false,
73 };
74
75 if let Some(cage) = filter_cage {
76 cage.conditions.push(condition);
77 } else {
78 self.cages.push(Cage {
79 kind: CageKind::Filter,
80 conditions: vec![condition],
81 logical_op: LogicalOp::And,
82 });
83 }
84 self
85 }
86
87 pub fn or_filter(
88 mut self,
89 column: impl AsRef<str>,
90 op: Operator,
91 value: impl Into<Value>,
92 ) -> Self {
93 self.cages.push(Cage {
94 kind: CageKind::Filter,
95 conditions: vec![Condition {
96 left: Expr::Named(column.as_ref().to_string()),
97 op,
98 value: value.into(),
99 is_array_unnest: false,
100 }],
101 logical_op: LogicalOp::Or,
102 });
103 self
104 }
105
106 pub fn where_eq(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self {
107 self.filter(column, Operator::Eq, value)
108 }
109
110 pub fn eq(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self {
116 self.filter(column, Operator::Eq, value)
117 }
118
119 pub fn ne(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self {
121 self.filter(column, Operator::Ne, value)
122 }
123
124 pub fn gt(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self {
126 self.filter(column, Operator::Gt, value)
127 }
128
129 pub fn gte(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self {
131 self.filter(column, Operator::Gte, value)
132 }
133
134 pub fn lt(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self {
136 self.filter(column, Operator::Lt, value)
137 }
138
139 pub fn lte(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self {
141 self.filter(column, Operator::Lte, value)
142 }
143
144 pub fn is_null(self, column: impl AsRef<str>) -> Self {
146 self.filter(column, Operator::IsNull, Value::Null)
147 }
148
149 pub fn is_not_null(self, column: impl AsRef<str>) -> Self {
151 self.filter(column, Operator::IsNotNull, Value::Null)
152 }
153
154 pub fn like(self, column: impl AsRef<str>, pattern: impl Into<Value>) -> Self {
156 self.filter(column, Operator::Like, pattern)
157 }
158
159 pub fn ilike(self, column: impl AsRef<str>, pattern: impl Into<Value>) -> Self {
161 self.filter(column, Operator::ILike, pattern)
162 }
163
164 pub fn in_vals<I, V>(self, column: impl AsRef<str>, values: I) -> Self
166 where
167 I: IntoIterator<Item = V>,
168 V: Into<Value>,
169 {
170 let arr: Vec<Value> = values.into_iter().map(|v| v.into()).collect();
171 self.filter(column, Operator::In, Value::Array(arr))
172 }
173
174 pub fn order_by(mut self, column: impl AsRef<str>, order: SortOrder) -> Self {
175 self.cages.push(Cage {
176 kind: CageKind::Sort(order),
177 conditions: vec![Condition {
178 left: Expr::Named(column.as_ref().to_string()),
179 op: Operator::Eq,
180 value: Value::Null,
181 is_array_unnest: false,
182 }],
183 logical_op: LogicalOp::And,
184 });
185 self
186 }
187
188 pub fn order_desc(self, column: impl AsRef<str>) -> Self {
189 self.order_by(column, SortOrder::Desc)
190 }
191
192 pub fn order_asc(self, column: impl AsRef<str>) -> Self {
193 self.order_by(column, SortOrder::Asc)
194 }
195
196 pub fn offset(mut self, n: i64) -> Self {
197 self.cages.push(Cage {
198 kind: CageKind::Offset(n as usize),
199 conditions: vec![],
200 logical_op: LogicalOp::And,
201 });
202 self
203 }
204
205 pub fn group_by<I, S>(mut self, cols: I) -> Self
206 where
207 I: IntoIterator<Item = S>,
208 S: AsRef<str>,
209 {
210 let conditions: Vec<Condition> = cols
211 .into_iter()
212 .map(|c| Condition {
213 left: Expr::Named(c.as_ref().to_string()),
214 op: Operator::Eq,
215 value: Value::Null,
216 is_array_unnest: false,
217 })
218 .collect();
219
220 self.cages.push(Cage {
221 kind: CageKind::Partition,
222 conditions,
223 logical_op: LogicalOp::And,
224 });
225 self
226 }
227
228 pub fn distinct_on_all(mut self) -> Self {
229 self.distinct = true;
230 self
231 }
232
233 pub fn join(
234 mut self,
235 kind: JoinKind,
236 table: impl AsRef<str>,
237 left_col: impl AsRef<str>,
238 right_col: impl AsRef<str>,
239 ) -> Self {
240 self.joins.push(Join {
241 kind,
242 table: table.as_ref().to_string(),
243 on: Some(vec![Condition {
244 left: Expr::Named(left_col.as_ref().to_string()),
245 op: Operator::Eq,
246 value: Value::Column(right_col.as_ref().to_string()),
247 is_array_unnest: false,
248 }]),
249 on_true: false,
250 });
251 self
252 }
253
254 pub fn left_join(
255 self,
256 table: impl AsRef<str>,
257 left_col: impl AsRef<str>,
258 right_col: impl AsRef<str>,
259 ) -> Self {
260 self.join(JoinKind::Left, table, left_col, right_col)
261 }
262
263 pub fn inner_join(
264 self,
265 table: impl AsRef<str>,
266 left_col: impl AsRef<str>,
267 right_col: impl AsRef<str>,
268 ) -> Self {
269 self.join(JoinKind::Inner, table, left_col, right_col)
270 }
271
272 pub fn returning<I, S>(mut self, cols: I) -> Self
273 where
274 I: IntoIterator<Item = S>,
275 S: AsRef<str>,
276 {
277 self.returning = Some(
278 cols.into_iter()
279 .map(|c| Expr::Named(c.as_ref().to_string()))
280 .collect(),
281 );
282 self
283 }
284
285 pub fn returning_all(mut self) -> Self {
286 self.returning = Some(vec![Expr::Star]);
287 self
288 }
289
290 pub fn values<I, V>(mut self, vals: I) -> Self
291 where
292 I: IntoIterator<Item = V>,
293 V: Into<Value>,
294 {
295 self.cages.push(Cage {
296 kind: CageKind::Payload,
297 conditions: vals
298 .into_iter()
299 .enumerate()
300 .map(|(i, v)| Condition {
301 left: Expr::Named(format!("${}", i + 1)),
302 op: Operator::Eq,
303 value: v.into(),
304 is_array_unnest: false,
305 })
306 .collect(),
307 logical_op: LogicalOp::And,
308 });
309 self
310 }
311
312 pub fn set_value(mut self, column: impl AsRef<str>, value: impl Into<Value>) -> Self {
313 let payload_cage = self
314 .cages
315 .iter_mut()
316 .find(|c| matches!(c.kind, CageKind::Payload));
317
318 let condition = Condition {
319 left: Expr::Named(column.as_ref().to_string()),
320 op: Operator::Eq,
321 value: value.into(),
322 is_array_unnest: false,
323 };
324
325 if let Some(cage) = payload_cage {
326 cage.conditions.push(condition);
327 } else {
328 self.cages.push(Cage {
329 kind: CageKind::Payload,
330 conditions: vec![condition],
331 logical_op: LogicalOp::And,
332 });
333 }
334 self
335 }
336
337 pub fn set_opt<T>(self, column: impl AsRef<str>, value: Option<T>) -> Self
340 where
341 T: Into<Value>,
342 {
343 match value {
344 Some(v) => self.set_value(column, v),
345 None => self, }
347 }
348}