grafbase_sql_ast/ast/
row.rs

1use serde_json::Value;
2
3#[cfg(any(feature = "postgresql", feature = "mysql"))]
4use super::compare::JsonType;
5use crate::ast::{Comparable, Compare, Expression};
6use std::borrow::Cow;
7
8/// A collection of values surrounded by parentheses.
9#[derive(Debug, Default, PartialEq, Clone)]
10pub struct Row<'a> {
11    pub values: Vec<Expression<'a>>,
12}
13
14impl<'a> Row<'a> {
15    pub fn new() -> Self {
16        Row { values: Vec::new() }
17    }
18
19    pub fn with_capacity(capacity: usize) -> Self {
20        Row {
21            values: Vec::with_capacity(capacity),
22        }
23    }
24
25    pub fn pop(&mut self) -> Option<Expression<'a>> {
26        self.values.pop()
27    }
28
29    pub fn push<T>(&mut self, value: T)
30    where
31        T: Into<Expression<'a>>,
32    {
33        self.values.push(value.into());
34    }
35
36    pub fn is_empty(&self) -> bool {
37        self.values.is_empty()
38    }
39
40    pub fn len(&self) -> usize {
41        self.values.len()
42    }
43}
44
45impl<'a> IntoIterator for Row<'a> {
46    type Item = Expression<'a>;
47    type IntoIter = std::vec::IntoIter<Self::Item>;
48
49    fn into_iter(self) -> Self::IntoIter {
50        self.values.into_iter()
51    }
52}
53
54impl<'a, T> From<Vec<T>> for Row<'a>
55where
56    T: Into<Expression<'a>>,
57{
58    fn from(vector: Vec<T>) -> Row<'a> {
59        let mut row = Row::with_capacity(vector.len());
60
61        for v in vector.into_iter() {
62            row.push(v.into());
63        }
64
65        row
66    }
67}
68
69impl<'a, A> From<(A,)> for Row<'a>
70where
71    A: Into<Expression<'a>>,
72{
73    fn from((val,): (A,)) -> Self {
74        let mut row = Row::with_capacity(1);
75        row.push(val);
76        row
77    }
78}
79
80impl<'a, A, B> From<(A, B)> for Row<'a>
81where
82    A: Into<Expression<'a>>,
83    B: Into<Expression<'a>>,
84{
85    fn from(vals: (A, B)) -> Self {
86        let mut row = Row::with_capacity(2);
87
88        row.push(vals.0);
89        row.push(vals.1);
90
91        row
92    }
93}
94
95impl<'a, A, B, C> From<(A, B, C)> for Row<'a>
96where
97    A: Into<Expression<'a>>,
98    B: Into<Expression<'a>>,
99    C: Into<Expression<'a>>,
100{
101    fn from(vals: (A, B, C)) -> Self {
102        let mut row = Row::with_capacity(3);
103
104        row.push(vals.0);
105        row.push(vals.1);
106        row.push(vals.2);
107
108        row
109    }
110}
111
112impl<'a, A, B, C, D> From<(A, B, C, D)> for Row<'a>
113where
114    A: Into<Expression<'a>>,
115    B: Into<Expression<'a>>,
116    C: Into<Expression<'a>>,
117    D: Into<Expression<'a>>,
118{
119    fn from(vals: (A, B, C, D)) -> Self {
120        let mut row = Row::with_capacity(4);
121
122        row.push(vals.0);
123        row.push(vals.1);
124        row.push(vals.2);
125        row.push(vals.3);
126
127        row
128    }
129}
130
131impl<'a, A, B, C, D, E> From<(A, B, C, D, E)> for Row<'a>
132where
133    A: Into<Expression<'a>>,
134    B: Into<Expression<'a>>,
135    C: Into<Expression<'a>>,
136    D: Into<Expression<'a>>,
137    E: Into<Expression<'a>>,
138{
139    fn from(vals: (A, B, C, D, E)) -> Self {
140        let mut row = Row::with_capacity(5);
141
142        row.push(vals.0);
143        row.push(vals.1);
144        row.push(vals.2);
145        row.push(vals.3);
146        row.push(vals.4);
147
148        row
149    }
150}
151
152impl<'a> From<Value> for Row<'a> {
153    fn from(value: Value) -> Self {
154        match value {
155            Value::Array(values) => {
156                let mut row = Row::with_capacity(values.len());
157
158                for value in values {
159                    row.push(value);
160                }
161
162                row
163            }
164            value => {
165                let mut row = Row::with_capacity(1);
166                row.push(value);
167                row
168            }
169        }
170    }
171}
172
173impl<'a> Comparable<'a> for Row<'a> {
174    fn equals<T>(self, comparison: T) -> Compare<'a>
175    where
176        T: Into<Expression<'a>>,
177    {
178        let value: Expression<'a> = self.into();
179        value.equals(comparison)
180    }
181
182    fn not_equals<T>(self, comparison: T) -> Compare<'a>
183    where
184        T: Into<Expression<'a>>,
185    {
186        let value: Expression<'a> = self.into();
187        value.not_equals(comparison)
188    }
189
190    fn less_than<T>(self, comparison: T) -> Compare<'a>
191    where
192        T: Into<Expression<'a>>,
193    {
194        let value: Expression<'a> = self.into();
195        value.less_than(comparison)
196    }
197
198    fn less_than_or_equals<T>(self, comparison: T) -> Compare<'a>
199    where
200        T: Into<Expression<'a>>,
201    {
202        let value: Expression<'a> = self.into();
203        value.less_than_or_equals(comparison)
204    }
205
206    fn greater_than<T>(self, comparison: T) -> Compare<'a>
207    where
208        T: Into<Expression<'a>>,
209    {
210        let value: Expression<'a> = self.into();
211        value.greater_than(comparison)
212    }
213
214    fn greater_than_or_equals<T>(self, comparison: T) -> Compare<'a>
215    where
216        T: Into<Expression<'a>>,
217    {
218        let value: Expression<'a> = self.into();
219        value.greater_than_or_equals(comparison)
220    }
221
222    fn in_selection<T>(self, selection: T) -> Compare<'a>
223    where
224        T: Into<Expression<'a>>,
225    {
226        let value: Expression<'a> = self.into();
227        value.in_selection(selection)
228    }
229
230    fn not_in_selection<T>(self, selection: T) -> Compare<'a>
231    where
232        T: Into<Expression<'a>>,
233    {
234        let value: Expression<'a> = self.into();
235        value.not_in_selection(selection)
236    }
237
238    fn like<T>(self, pattern: T) -> Compare<'a>
239    where
240        T: Into<Expression<'a>>,
241    {
242        let value: Expression<'a> = self.into();
243        value.like(pattern)
244    }
245
246    fn not_like<T>(self, pattern: T) -> Compare<'a>
247    where
248        T: Into<Expression<'a>>,
249    {
250        let value: Expression<'a> = self.into();
251        value.not_like(pattern)
252    }
253
254    #[allow(clippy::wrong_self_convention)]
255    fn is_null(self) -> Compare<'a> {
256        let value: Expression<'a> = self.into();
257        value.is_null()
258    }
259
260    #[allow(clippy::wrong_self_convention)]
261    fn is_not_null(self) -> Compare<'a> {
262        let value: Expression<'a> = self.into();
263        value.is_not_null()
264    }
265
266    fn between<T, V>(self, left: T, right: V) -> Compare<'a>
267    where
268        T: Into<Expression<'a>>,
269        V: Into<Expression<'a>>,
270    {
271        let value: Expression<'a> = self.into();
272        value.between(left, right)
273    }
274
275    fn not_between<T, V>(self, left: T, right: V) -> Compare<'a>
276    where
277        T: Into<Expression<'a>>,
278        V: Into<Expression<'a>>,
279    {
280        let value: Expression<'a> = self.into();
281        value.not_between(left, right)
282    }
283
284    fn compare_raw<T, V>(self, raw_comparator: T, right: V) -> Compare<'a>
285    where
286        T: Into<Cow<'a, str>>,
287        V: Into<Expression<'a>>,
288    {
289        let value: Expression<'a> = self.into();
290        value.compare_raw(raw_comparator, right)
291    }
292
293    /// Tests if the array overlaps with another array.
294    #[cfg(any(feature = "postgresql", feature = "mysql"))]
295    fn array_overlaps<T>(self, item: T) -> Compare<'a>
296    where
297        T: Into<Expression<'a>>,
298    {
299        let value: Expression<'a> = self.into();
300
301        value.array_overlaps(item)
302    }
303
304    #[cfg(any(feature = "postgresql", feature = "mysql"))]
305    fn array_contains<T>(self, item: T) -> Compare<'a>
306    where
307        T: Into<Expression<'a>>,
308    {
309        let value: Expression<'a> = self.into();
310
311        value.array_contains(item)
312    }
313
314    #[cfg(any(feature = "postgresql", feature = "mysql"))]
315    fn array_contained<T>(self, item: T) -> Compare<'a>
316    where
317        T: Into<Expression<'a>>,
318    {
319        let value: Expression<'a> = self.into();
320
321        value.array_contained(item)
322    }
323
324    #[cfg(any(feature = "postgresql", feature = "mysql"))]
325    fn json_array_not_contains<T>(self, item: T) -> Compare<'a>
326    where
327        T: Into<Expression<'a>>,
328    {
329        let value: Expression<'a> = self.into();
330
331        value.json_array_not_contains(item)
332    }
333
334    #[cfg(any(feature = "postgresql", feature = "mysql"))]
335    fn json_array_begins_with<T>(self, item: T) -> Compare<'a>
336    where
337        T: Into<Expression<'a>>,
338    {
339        let value: Expression<'a> = self.into();
340
341        value.json_array_begins_with(item)
342    }
343
344    #[cfg(any(feature = "postgresql", feature = "mysql"))]
345    fn json_array_not_begins_with<T>(self, item: T) -> Compare<'a>
346    where
347        T: Into<Expression<'a>>,
348    {
349        let value: Expression<'a> = self.into();
350
351        value.json_array_not_begins_with(item)
352    }
353
354    #[cfg(any(feature = "postgresql", feature = "mysql"))]
355    fn json_array_ends_into<T>(self, item: T) -> Compare<'a>
356    where
357        T: Into<Expression<'a>>,
358    {
359        let value: Expression<'a> = self.into();
360
361        value.json_array_ends_into(item)
362    }
363
364    #[cfg(any(feature = "postgresql", feature = "mysql"))]
365    fn json_array_not_ends_into<T>(self, item: T) -> Compare<'a>
366    where
367        T: Into<Expression<'a>>,
368    {
369        let value: Expression<'a> = self.into();
370
371        value.json_array_not_ends_into(item)
372    }
373
374    #[cfg(any(feature = "postgresql", feature = "mysql"))]
375    fn json_type_equals<T>(self, json_type: T) -> Compare<'a>
376    where
377        T: Into<JsonType<'a>>,
378    {
379        let value: Expression<'a> = self.into();
380
381        value.json_type_equals(json_type)
382    }
383
384    #[cfg(any(feature = "postgresql", feature = "mysql"))]
385    fn json_type_not_equals<T>(self, json_type: T) -> Compare<'a>
386    where
387        T: Into<JsonType<'a>>,
388    {
389        let value: Expression<'a> = self.into();
390
391        value.json_type_not_equals(json_type)
392    }
393
394    #[cfg(feature = "postgresql")]
395    fn any(self) -> Compare<'a> {
396        let value: Expression<'a> = self.into();
397
398        value.any()
399    }
400
401    #[cfg(feature = "postgresql")]
402    fn all(self) -> Compare<'a> {
403        let value: Expression<'a> = self.into();
404
405        value.all()
406    }
407}