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
111 pub fn eq(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self {
112 self.filter(column, Operator::Eq, value)
113 }
114
115 pub fn ne(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self {
116 self.filter(column, Operator::Ne, value)
117 }
118
119 pub fn gt(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self {
120 self.filter(column, Operator::Gt, value)
121 }
122 pub fn gte(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self {
123 self.filter(column, Operator::Gte, value)
124 }
125
126 pub fn lt(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self {
128 self.filter(column, Operator::Lt, value)
129 }
130
131 pub fn lte(self, column: impl AsRef<str>, value: impl Into<Value>) -> Self {
132 self.filter(column, Operator::Lte, value)
133 }
134
135 pub fn is_null(self, column: impl AsRef<str>) -> Self {
136 self.filter(column, Operator::IsNull, Value::Null)
137 }
138
139 pub fn is_not_null(self, column: impl AsRef<str>) -> Self {
140 self.filter(column, Operator::IsNotNull, Value::Null)
141 }
142
143 pub fn like(self, column: impl AsRef<str>, pattern: impl Into<Value>) -> Self {
144 self.filter(column, Operator::Like, pattern)
145 }
146
147 pub fn ilike(self, column: impl AsRef<str>, pattern: impl Into<Value>) -> Self {
148 self.filter(column, Operator::ILike, pattern)
149 }
150
151 pub fn in_vals<I, V>(self, column: impl AsRef<str>, values: I) -> Self
152 where
153 I: IntoIterator<Item = V>,
154 V: Into<Value>,
155 {
156 let arr: Vec<Value> = values.into_iter().map(|v| v.into()).collect();
157 self.filter(column, Operator::In, Value::Array(arr))
158 }
159
160 pub fn order_by(mut self, column: impl AsRef<str>, order: SortOrder) -> Self {
161 self.cages.push(Cage {
162 kind: CageKind::Sort(order),
163 conditions: vec![Condition {
164 left: Expr::Named(column.as_ref().to_string()),
165 op: Operator::Eq,
166 value: Value::Null,
167 is_array_unnest: false,
168 }],
169 logical_op: LogicalOp::And,
170 });
171 self
172 }
173
174 pub fn order_desc(self, column: impl AsRef<str>) -> Self {
175 self.order_by(column, SortOrder::Desc)
176 }
177
178 pub fn order_asc(self, column: impl AsRef<str>) -> Self {
179 self.order_by(column, SortOrder::Asc)
180 }
181
182 pub fn offset(mut self, n: i64) -> Self {
183 self.cages.push(Cage {
184 kind: CageKind::Offset(n as usize),
185 conditions: vec![],
186 logical_op: LogicalOp::And,
187 });
188 self
189 }
190
191 pub fn group_by<I, S>(mut self, cols: I) -> Self
192 where
193 I: IntoIterator<Item = S>,
194 S: AsRef<str>,
195 {
196 let conditions: Vec<Condition> = cols
197 .into_iter()
198 .map(|c| Condition {
199 left: Expr::Named(c.as_ref().to_string()),
200 op: Operator::Eq,
201 value: Value::Null,
202 is_array_unnest: false,
203 })
204 .collect();
205
206 self.cages.push(Cage {
207 kind: CageKind::Partition,
208 conditions,
209 logical_op: LogicalOp::And,
210 });
211 self
212 }
213
214 pub fn distinct_on_all(mut self) -> Self {
215 self.distinct = true;
216 self
217 }
218
219 pub fn join(
220 mut self,
221 kind: JoinKind,
222 table: impl AsRef<str>,
223 left_col: impl AsRef<str>,
224 right_col: impl AsRef<str>,
225 ) -> Self {
226 self.joins.push(Join {
227 kind,
228 table: table.as_ref().to_string(),
229 on: Some(vec![Condition {
230 left: Expr::Named(left_col.as_ref().to_string()),
231 op: Operator::Eq,
232 value: Value::Column(right_col.as_ref().to_string()),
233 is_array_unnest: false,
234 }]),
235 on_true: false,
236 });
237 self
238 }
239
240 pub fn left_join(
241 self,
242 table: impl AsRef<str>,
243 left_col: impl AsRef<str>,
244 right_col: impl AsRef<str>,
245 ) -> Self {
246 self.join(JoinKind::Left, table, left_col, right_col)
247 }
248
249 pub fn inner_join(
250 self,
251 table: impl AsRef<str>,
252 left_col: impl AsRef<str>,
253 right_col: impl AsRef<str>,
254 ) -> Self {
255 self.join(JoinKind::Inner, table, left_col, right_col)
256 }
257
258 pub fn returning<I, S>(mut self, cols: I) -> Self
259 where
260 I: IntoIterator<Item = S>,
261 S: AsRef<str>,
262 {
263 self.returning = Some(
264 cols.into_iter()
265 .map(|c| Expr::Named(c.as_ref().to_string()))
266 .collect(),
267 );
268 self
269 }
270
271 pub fn returning_all(mut self) -> Self {
272 self.returning = Some(vec![Expr::Star]);
273 self
274 }
275
276 pub fn values<I, V>(mut self, vals: I) -> Self
277 where
278 I: IntoIterator<Item = V>,
279 V: Into<Value>,
280 {
281 self.cages.push(Cage {
282 kind: CageKind::Payload,
283 conditions: vals
284 .into_iter()
285 .enumerate()
286 .map(|(i, v)| Condition {
287 left: Expr::Named(format!("${}", i + 1)),
288 op: Operator::Eq,
289 value: v.into(),
290 is_array_unnest: false,
291 })
292 .collect(),
293 logical_op: LogicalOp::And,
294 });
295 self
296 }
297
298 pub fn set_value(mut self, column: impl AsRef<str>, value: impl Into<Value>) -> Self {
299 let payload_cage = self
300 .cages
301 .iter_mut()
302 .find(|c| matches!(c.kind, CageKind::Payload));
303
304 let condition = Condition {
305 left: Expr::Named(column.as_ref().to_string()),
306 op: Operator::Eq,
307 value: value.into(),
308 is_array_unnest: false,
309 };
310
311 if let Some(cage) = payload_cage {
312 cage.conditions.push(condition);
313 } else {
314 self.cages.push(Cage {
315 kind: CageKind::Payload,
316 conditions: vec![condition],
317 logical_op: LogicalOp::And,
318 });
319 }
320 self
321 }
322
323 pub fn set_opt<T>(self, column: impl AsRef<str>, value: Option<T>) -> Self
326 where
327 T: Into<Value>,
328 {
329 match value {
330 Some(v) => self.set_value(column, v),
331 None => self, }
333 }
334}