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 order_by(mut self, column: impl AsRef<str>, order: SortOrder) -> Self {
111 self.cages.push(Cage {
112 kind: CageKind::Sort(order),
113 conditions: vec![Condition {
114 left: Expr::Named(column.as_ref().to_string()),
115 op: Operator::Eq,
116 value: Value::Null,
117 is_array_unnest: false,
118 }],
119 logical_op: LogicalOp::And,
120 });
121 self
122 }
123
124 pub fn order_desc(self, column: impl AsRef<str>) -> Self {
125 self.order_by(column, SortOrder::Desc)
126 }
127
128 pub fn order_asc(self, column: impl AsRef<str>) -> Self {
129 self.order_by(column, SortOrder::Asc)
130 }
131
132 pub fn offset(mut self, n: i64) -> Self {
133 self.cages.push(Cage {
134 kind: CageKind::Offset(n as usize),
135 conditions: vec![],
136 logical_op: LogicalOp::And,
137 });
138 self
139 }
140
141 pub fn group_by<I, S>(mut self, cols: I) -> Self
142 where
143 I: IntoIterator<Item = S>,
144 S: AsRef<str>,
145 {
146 let conditions: Vec<Condition> = cols
147 .into_iter()
148 .map(|c| Condition {
149 left: Expr::Named(c.as_ref().to_string()),
150 op: Operator::Eq,
151 value: Value::Null,
152 is_array_unnest: false,
153 })
154 .collect();
155
156 self.cages.push(Cage {
157 kind: CageKind::Partition,
158 conditions,
159 logical_op: LogicalOp::And,
160 });
161 self
162 }
163
164 pub fn distinct_on_all(mut self) -> Self {
165 self.distinct = true;
166 self
167 }
168
169 pub fn join(
170 mut self,
171 kind: JoinKind,
172 table: impl AsRef<str>,
173 left_col: impl AsRef<str>,
174 right_col: impl AsRef<str>,
175 ) -> Self {
176 self.joins.push(Join {
177 kind,
178 table: table.as_ref().to_string(),
179 on: Some(vec![Condition {
180 left: Expr::Named(left_col.as_ref().to_string()),
181 op: Operator::Eq,
182 value: Value::Column(right_col.as_ref().to_string()),
183 is_array_unnest: false,
184 }]),
185 on_true: false,
186 });
187 self
188 }
189
190 pub fn left_join(
191 self,
192 table: impl AsRef<str>,
193 left_col: impl AsRef<str>,
194 right_col: impl AsRef<str>,
195 ) -> Self {
196 self.join(JoinKind::Left, table, left_col, right_col)
197 }
198
199 pub fn inner_join(
200 self,
201 table: impl AsRef<str>,
202 left_col: impl AsRef<str>,
203 right_col: impl AsRef<str>,
204 ) -> Self {
205 self.join(JoinKind::Inner, table, left_col, right_col)
206 }
207
208 pub fn returning<I, S>(mut self, cols: I) -> Self
209 where
210 I: IntoIterator<Item = S>,
211 S: AsRef<str>,
212 {
213 self.returning = Some(
214 cols.into_iter()
215 .map(|c| Expr::Named(c.as_ref().to_string()))
216 .collect(),
217 );
218 self
219 }
220
221 pub fn returning_all(mut self) -> Self {
222 self.returning = Some(vec![Expr::Star]);
223 self
224 }
225
226 pub fn values<I, V>(mut self, vals: I) -> Self
227 where
228 I: IntoIterator<Item = V>,
229 V: Into<Value>,
230 {
231 self.cages.push(Cage {
232 kind: CageKind::Payload,
233 conditions: vals
234 .into_iter()
235 .enumerate()
236 .map(|(i, v)| Condition {
237 left: Expr::Named(format!("${}", i + 1)),
238 op: Operator::Eq,
239 value: v.into(),
240 is_array_unnest: false,
241 })
242 .collect(),
243 logical_op: LogicalOp::And,
244 });
245 self
246 }
247
248 pub fn set_value(mut self, column: impl AsRef<str>, value: impl Into<Value>) -> Self {
249 let payload_cage = self
250 .cages
251 .iter_mut()
252 .find(|c| matches!(c.kind, CageKind::Payload));
253
254 let condition = Condition {
255 left: Expr::Named(column.as_ref().to_string()),
256 op: Operator::Eq,
257 value: value.into(),
258 is_array_unnest: false,
259 };
260
261 if let Some(cage) = payload_cage {
262 cage.conditions.push(condition);
263 } else {
264 self.cages.push(Cage {
265 kind: CageKind::Payload,
266 conditions: vec![condition],
267 logical_op: LogicalOp::And,
268 });
269 }
270 self
271 }
272}