partiql_value/
tuple.rs

1use itertools::Itertools;
2
3use std::cmp::Ordering;
4
5use std::fmt::{Debug, Formatter};
6use std::hash::{Hash, Hasher};
7use std::iter::{zip, Zip};
8use std::vec;
9
10use crate::sort::NullSortedValue;
11use crate::{BindingsName, EqualityValue, NullableEq, Value};
12#[cfg(feature = "serde")]
13use serde::{Deserialize, Serialize};
14
15#[derive(Default, Eq, Clone)]
16#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
17pub struct Tuple {
18    attrs: Vec<String>,
19    vals: Vec<Value>,
20}
21
22impl Tuple {
23    #[must_use]
24    pub fn new() -> Self {
25        Tuple {
26            attrs: vec![],
27            vals: vec![],
28        }
29    }
30
31    #[inline]
32    pub fn insert(&mut self, attr: &str, val: Value) {
33        self.attrs.push(attr.to_string());
34        self.vals.push(val);
35    }
36
37    #[inline]
38    #[must_use]
39    pub fn len(&self) -> usize {
40        self.attrs.len()
41    }
42
43    #[inline]
44    #[must_use]
45    pub fn is_empty(&self) -> bool {
46        self.len() == 0
47    }
48
49    #[inline]
50    /// Creates a `Tuple` containing all the attributes and values provided by `self` and `other`
51    /// removing duplicate attributes. Assumes that `self` contains unique attributes and `other`
52    /// contains unique attributes. In the case of duplicate attributes between `self` and `other`,
53    /// the result `Tuple` will contain the attribute provided by `other`. See section 3.4 of the
54    /// spec for details: https://partiql.org/assets/PartiQL-Specification.pdf#subsection.3.4.
55    #[must_use]
56    pub fn tuple_concat(&self, other: &Tuple) -> Self {
57        other
58            .pairs()
59            .chain(self.pairs())
60            .unique_by(|(a, _)| *a)
61            .map(|(a, v)| (a, v.clone()))
62            .collect()
63    }
64
65    #[inline]
66    #[must_use]
67    pub fn get(&self, attr: &BindingsName<'_>) -> Option<&Value> {
68        self.find_value(attr).map(|i| &self.vals[i])
69    }
70
71    #[inline]
72    #[must_use]
73    pub fn take_val(self, attr: &BindingsName<'_>) -> Option<Value> {
74        self.find_value(attr)
75            .and_then(|i| self.vals.into_iter().nth(i))
76    }
77
78    #[inline(always)]
79    fn find_value(&self, attr: &BindingsName<'_>) -> Option<usize> {
80        let matcher = attr.matcher();
81        self.attrs.iter().position(|a| matcher.matches(a))
82    }
83
84    #[inline]
85    pub fn remove(&mut self, attr: &BindingsName<'_>) -> Option<Value> {
86        match self.find_value(attr) {
87            Some(i) => {
88                self.attrs.remove(i);
89                Some(self.vals.remove(i))
90            }
91            _ => None,
92        }
93    }
94
95    #[inline]
96    #[must_use]
97    pub fn pairs(&self) -> PairsIter<'_> {
98        PairsIter(zip(self.attrs.iter(), self.vals.iter()))
99    }
100
101    #[inline]
102    #[must_use]
103    pub fn into_pairs(self) -> PairsIntoIter {
104        PairsIntoIter(zip(self.attrs, self.vals))
105    }
106
107    #[inline]
108    pub fn values(&self) -> impl Iterator<Item = &Value> + Clone {
109        self.vals.iter()
110    }
111
112    #[inline]
113    pub fn into_values(self) -> impl Iterator<Item = Value> {
114        self.vals.into_iter()
115    }
116}
117
118#[derive(Debug, Clone)]
119pub struct PairsIter<'a>(Zip<std::slice::Iter<'a, String>, std::slice::Iter<'a, Value>>);
120
121impl<'a> Iterator for PairsIter<'a> {
122    type Item = (&'a String, &'a Value);
123
124    #[inline]
125    fn next(&mut self) -> Option<Self::Item> {
126        self.0.next()
127    }
128
129    #[inline]
130    fn size_hint(&self) -> (usize, Option<usize>) {
131        self.0.size_hint()
132    }
133}
134
135#[derive(Debug, Clone)]
136pub struct PairsIntoIter(Zip<std::vec::IntoIter<String>, std::vec::IntoIter<Value>>);
137
138impl Iterator for PairsIntoIter {
139    type Item = (String, Value);
140
141    #[inline]
142    fn next(&mut self) -> Option<Self::Item> {
143        self.0.next()
144    }
145
146    #[inline]
147    fn size_hint(&self) -> (usize, Option<usize>) {
148        self.0.size_hint()
149    }
150}
151
152impl<const N: usize, T> From<[(&str, T); N]> for Tuple
153where
154    T: Into<Value>,
155{
156    #[inline]
157    fn from(arr: [(&str, T); N]) -> Self {
158        arr.into_iter()
159            .fold(Tuple::new(), |mut acc: Tuple, (attr, val)| {
160                acc.insert(attr, val.into());
161                acc
162            })
163    }
164}
165
166impl<S, T> FromIterator<(S, T)> for Tuple
167where
168    S: Into<String>,
169    T: Into<Value>,
170{
171    #[inline]
172    fn from_iter<I: IntoIterator<Item = (S, T)>>(iter: I) -> Tuple {
173        let iterator = iter.into_iter();
174        let (lower, _) = iterator.size_hint();
175        let mut attrs = Vec::with_capacity(lower);
176        let mut vals = Vec::with_capacity(lower);
177        for (k, v) in iterator {
178            attrs.push(k.into());
179            vals.push(v.into());
180        }
181        Tuple { attrs, vals }
182    }
183}
184
185impl<S, T> Extend<(S, T)> for Tuple
186where
187    S: AsRef<str>,
188    T: Into<Value>,
189{
190    fn extend<I: IntoIterator<Item = (S, T)>>(&mut self, iter: I) {
191        for (k, v) in iter {
192            self.insert(k.as_ref(), v.into());
193        }
194    }
195}
196
197impl Iterator for Tuple {
198    type Item = (String, Value);
199
200    #[inline]
201    fn next(&mut self) -> Option<Self::Item> {
202        match (self.attrs.pop(), self.vals.pop()) {
203            (Some(attr), Some(val)) => Some((attr, val)),
204            _ => None,
205        }
206    }
207
208    #[inline]
209    fn size_hint(&self) -> (usize, Option<usize>) {
210        (self.attrs.len(), Some(self.attrs.len()))
211    }
212}
213
214impl PartialEq for Tuple {
215    fn eq(&self, other: &Self) -> bool {
216        let wrap = EqualityValue::<true, false, _>;
217        NullableEq::eq(&wrap(self), &wrap(other)) == Value::Boolean(true)
218    }
219}
220
221impl<const NULLS_EQUAL: bool, const NAN_EQUAL: bool> NullableEq
222    for EqualityValue<'_, NULLS_EQUAL, NAN_EQUAL, Tuple>
223{
224    #[inline(always)]
225    fn eq(&self, other: &Self) -> Value {
226        if self.0.vals.len() != other.0.vals.len() {
227            return Value::Boolean(false);
228        }
229        for ((ls, lv), (rs, rv)) in self.0.pairs().sorted().zip(other.0.pairs().sorted()) {
230            if ls != rs {
231                return Value::Boolean(false);
232            }
233            let wrap = EqualityValue::<{ NULLS_EQUAL }, { NAN_EQUAL }, Value>;
234            if NullableEq::eqg(&wrap(lv), &wrap(rv)) != Value::Boolean(true) {
235                return Value::Boolean(false);
236            }
237        }
238        Value::Boolean(true)
239    }
240
241    #[inline(always)]
242    fn eqg(&self, rhs: &Self) -> Value {
243        let wrap = EqualityValue::<'_, true, { NAN_EQUAL }, _>;
244        NullableEq::eq(&wrap(self.0), &wrap(rhs.0))
245    }
246}
247
248impl PartialOrd for Tuple {
249    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
250        Some(self.cmp(other))
251    }
252}
253
254impl Hash for Tuple {
255    fn hash<H: Hasher>(&self, state: &mut H) {
256        for (k, v) in self.pairs().sorted() {
257            k.hash(state);
258            v.hash(state);
259        }
260    }
261}
262
263impl Debug for Tuple {
264    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
265        write!(f, "{{")?;
266        let mut iter = self.pairs().peekable();
267        while let Some((k, v)) = iter.next() {
268            if iter.peek().is_some() {
269                write!(f, " '{k}': {v:?},")?;
270            } else {
271                write!(f, " '{k}': {v:?} ")?;
272            }
273        }
274        write!(f, "}}")
275    }
276}
277
278impl<const NULLS_FIRST: bool> Ord for NullSortedValue<'_, NULLS_FIRST, Tuple> {
279    fn cmp(&self, other: &Self) -> Ordering {
280        let wrap = NullSortedValue::<{ NULLS_FIRST }, Value>;
281
282        let self_pairs = self.0.pairs();
283        let other_pairs = other.0.pairs();
284        let mut p1 = self_pairs.sorted();
285        let mut p2 = other_pairs.sorted();
286
287        loop {
288            return match (p1.next(), p2.next()) {
289                (None, None) => Ordering::Equal,
290                (Some(_), None) => Ordering::Greater,
291                (None, Some(_)) => Ordering::Less,
292                (Some((ls, lv)), Some((rs, rv))) => match (ls.cmp(rs), wrap(lv).cmp(&wrap(rv))) {
293                    (Ordering::Less, _) => Ordering::Less,
294                    (Ordering::Greater, _) => Ordering::Greater,
295                    (_, Ordering::Less) => Ordering::Less,
296                    (_, Ordering::Greater) => Ordering::Greater,
297                    (_, Ordering::Equal) => continue,
298                },
299            };
300        }
301    }
302}
303
304impl Ord for Tuple {
305    fn cmp(&self, other: &Self) -> Ordering {
306        let self_pairs = self.pairs();
307        let other_pairs = other.pairs();
308        let mut p1 = self_pairs.sorted();
309        let mut p2 = other_pairs.sorted();
310
311        loop {
312            return match (p1.next(), p2.next()) {
313                (None, None) => Ordering::Equal,
314                (Some(_), None) => Ordering::Greater,
315                (None, Some(_)) => Ordering::Less,
316                (Some(lv), Some(rv)) => match lv.cmp(&rv) {
317                    Ordering::Less => Ordering::Less,
318                    Ordering::Greater => Ordering::Greater,
319                    Ordering::Equal => continue,
320                },
321            };
322        }
323    }
324}
325
326#[macro_export]
327macro_rules! tuple {
328    () => (
329        $crate::Tuple::new()
330    );
331    ($(($x:expr, $y:expr)),+ $(,)?) => (
332        $crate::Tuple::from([$(($x, Value::from($y))),+])
333    );
334}