1use crate::ast::{
6 CTEDef, Cage, CageKind, Condition, Expr, Join, JoinKind, LockMode, LogicalOp, Operator,
7 OverridingKind, Qail, SampleMethod, SortOrder, Value,
8};
9
10impl Qail {
11 pub fn column_expr(mut self, expr: Expr) -> Self {
13 self.columns.push(expr);
14 self
15 }
16
17 pub fn columns_expr<I>(mut self, exprs: I) -> Self
19 where
20 I: IntoIterator<Item = Expr>,
21 {
22 self.columns.extend(exprs);
23 self
24 }
25
26 pub fn distinct_on<I, S>(mut self, cols: I) -> Self
28 where
29 I: IntoIterator<Item = S>,
30 S: AsRef<str>,
31 {
32 self.distinct_on = cols
33 .into_iter()
34 .map(|c| Expr::Named(c.as_ref().to_string()))
35 .collect();
36 self
37 }
38
39 pub fn distinct_on_expr<I>(mut self, exprs: I) -> Self
41 where
42 I: IntoIterator<Item = Expr>,
43 {
44 self.distinct_on = exprs.into_iter().collect();
45 self
46 }
47
48 pub fn filter_cond(mut self, condition: Condition) -> Self {
50 let filter_cage = self
51 .cages
52 .iter_mut()
53 .find(|c| matches!(c.kind, CageKind::Filter) && c.logical_op == LogicalOp::And);
54
55 if let Some(cage) = filter_cage {
56 cage.conditions.push(condition);
57 } else {
58 self.cages.push(Cage {
59 kind: CageKind::Filter,
60 conditions: vec![condition],
61 logical_op: LogicalOp::And,
62 });
63 }
64 self
65 }
66
67 pub fn having_cond(mut self, condition: Condition) -> Self {
69 self.having.push(condition);
70 self
71 }
72
73 pub fn having_conds(mut self, conditions: impl IntoIterator<Item = Condition>) -> Self {
75 self.having.extend(conditions);
76 self
77 }
78
79 pub fn with_ctes(mut self, ctes: Vec<CTEDef>) -> Self {
81 self.ctes = ctes;
82 self
83 }
84
85 pub fn update_from<I, S>(mut self, tables: I) -> Self
87 where
88 I: IntoIterator<Item = S>,
89 S: AsRef<str>,
90 {
91 self.from_tables
92 .extend(tables.into_iter().map(|s| s.as_ref().to_string()));
93 self
94 }
95
96 pub fn delete_using<I, S>(mut self, tables: I) -> Self
98 where
99 I: IntoIterator<Item = S>,
100 S: AsRef<str>,
101 {
102 self.using_tables
103 .extend(tables.into_iter().map(|s| s.as_ref().to_string()));
104 self
105 }
106
107 pub fn for_update(mut self) -> Self {
109 self.lock_mode = Some(LockMode::Update);
110 self
111 }
112
113 pub fn for_update_skip_locked(mut self) -> Self {
116 self.lock_mode = Some(LockMode::Update);
117 self.skip_locked = true;
118 self
119 }
120
121 pub fn for_no_key_update(mut self) -> Self {
123 self.lock_mode = Some(LockMode::NoKeyUpdate);
124 self
125 }
126
127 pub fn for_share(mut self) -> Self {
129 self.lock_mode = Some(LockMode::Share);
130 self
131 }
132
133 pub fn for_key_share(mut self) -> Self {
135 self.lock_mode = Some(LockMode::KeyShare);
136 self
137 }
138
139 pub fn fetch_first(mut self, count: u64) -> Self {
141 self.fetch = Some((count, false));
142 self
143 }
144
145 pub fn fetch_with_ties(mut self, count: u64) -> Self {
147 self.fetch = Some((count, true));
148 self
149 }
150
151 pub fn default_values(mut self) -> Self {
153 self.default_values = true;
154 self
155 }
156
157 pub fn overriding_system_value(mut self) -> Self {
159 self.overriding = Some(OverridingKind::SystemValue);
160 self
161 }
162
163 pub fn overriding_user_value(mut self) -> Self {
165 self.overriding = Some(OverridingKind::UserValue);
166 self
167 }
168
169 pub fn tablesample_bernoulli(mut self, percent: f64) -> Self {
171 self.sample = Some((SampleMethod::Bernoulli, percent, None));
172 self
173 }
174
175 pub fn tablesample_system(mut self, percent: f64) -> Self {
177 self.sample = Some((SampleMethod::System, percent, None));
178 self
179 }
180
181 pub fn repeatable(mut self, seed: u64) -> Self {
183 if let Some((method, percent, _)) = self.sample {
184 self.sample = Some((method, percent, Some(seed)));
185 }
186 self
187 }
188
189 pub fn only(mut self) -> Self {
191 self.only_table = true;
192 self
193 }
194
195 pub fn left_join_as(
197 mut self,
198 table: impl AsRef<str>,
199 alias: impl AsRef<str>,
200 left_col: impl AsRef<str>,
201 right_col: impl AsRef<str>,
202 ) -> Self {
203 self.joins.push(Join {
204 kind: JoinKind::Left,
205 table: format!("{} {}", table.as_ref(), alias.as_ref()),
206 on: Some(vec![Condition {
207 left: Expr::Named(left_col.as_ref().to_string()),
208 op: Operator::Eq,
209 value: Value::Column(right_col.as_ref().to_string()),
210 is_array_unnest: false,
211 }]),
212 on_true: false,
213 });
214 self
215 }
216
217 pub fn inner_join_as(
219 mut self,
220 table: impl AsRef<str>,
221 alias: impl AsRef<str>,
222 left_col: impl AsRef<str>,
223 right_col: impl AsRef<str>,
224 ) -> Self {
225 self.joins.push(Join {
226 kind: JoinKind::Inner,
227 table: format!("{} {}", table.as_ref(), alias.as_ref()),
228 on: Some(vec![Condition {
229 left: Expr::Named(left_col.as_ref().to_string()),
230 op: Operator::Eq,
231 value: Value::Column(right_col.as_ref().to_string()),
232 is_array_unnest: false,
233 }]),
234 on_true: false,
235 });
236 self
237 }
238
239 pub fn join_conds(
258 mut self,
259 kind: JoinKind,
260 table: impl AsRef<str>,
261 conditions: Vec<Condition>,
262 ) -> Self {
263 self.joins.push(Join {
264 kind,
265 table: table.as_ref().to_string(),
266 on: Some(conditions),
267 on_true: false,
268 });
269 self
270 }
271
272 pub fn left_join_conds(self, table: impl AsRef<str>, conditions: Vec<Condition>) -> Self {
274 self.join_conds(JoinKind::Left, table, conditions)
275 }
276
277 pub fn inner_join_conds(self, table: impl AsRef<str>, conditions: Vec<Condition>) -> Self {
279 self.join_conds(JoinKind::Inner, table, conditions)
280 }
281
282 pub fn table_alias(mut self, alias: impl AsRef<str>) -> Self {
284 self.table = format!("{} {}", self.table, alias.as_ref());
285 self
286 }
287
288 pub fn order_by_expr(mut self, expr: Expr, order: SortOrder) -> Self {
290 self.cages.push(Cage {
291 kind: CageKind::Sort(order),
292 conditions: vec![Condition {
293 left: expr,
294 op: Operator::Eq,
295 value: Value::Null,
296 is_array_unnest: false,
297 }],
298 logical_op: LogicalOp::And,
299 });
300 self
301 }
302
303 pub fn group_by_expr<I>(mut self, exprs: I) -> Self
305 where
306 I: IntoIterator<Item = Expr>,
307 {
308 let conditions: Vec<Condition> = exprs
309 .into_iter()
310 .map(|e| Condition {
311 left: e,
312 op: Operator::Eq,
313 value: Value::Null,
314 is_array_unnest: false,
315 })
316 .collect();
317
318 self.cages.push(Cage {
319 kind: CageKind::Partition,
320 conditions,
321 logical_op: LogicalOp::And,
322 });
323 self
324 }
325}