ag/
data.rs

1use crate::operator::expr::{Expr, ValueRef};
2use crate::operator::EvalError;
3use chrono::{DateTime, Duration, Utc};
4use itertools::Itertools;
5use ordered_float::OrderedFloat;
6use serde::ser::{SerializeMap, SerializeSeq};
7use serde::Serializer;
8use std::cmp::Ordering;
9use std::collections::HashMap;
10use std::convert::{TryFrom, TryInto};
11use std::fmt;
12use std::fmt::{Display, Formatter};
13use std::ops::{Add, Div, Mul, Sub};
14
15pub type VMap = HashMap<String, Value>;
16
17pub enum Row {
18    Aggregate(Aggregate),
19    Record(Record),
20}
21
22/// Helper to allow for a custom serde Serializer for the rows in an Aggregate.
23/// Serde serializers are not allowed to emit nested serializations directly, so
24/// it's necessary to create an intermediary type for each row, and to provide
25/// it with the columns to enable ordering.
26pub(crate) struct WrappedAggregateRow<'a> {
27    pub columns: &'a Vec<String>,
28    pub data: &'a VMap,
29}
30
31impl serde::Serialize for WrappedAggregateRow<'_> {
32    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
33    where
34        S: Serializer,
35    {
36        let mut map = serializer.serialize_map(Some(self.columns.len()))?;
37        for k in self.columns {
38            map.serialize_entry(k, self.data.get(k).unwrap_or(&Value::None))?;
39        }
40        map.end()
41    }
42}
43
44#[derive(Debug, PartialEq, Eq, Clone)]
45pub struct Aggregate {
46    pub columns: Vec<String>,
47    pub data: Vec<VMap>,
48}
49
50// This custom serializer respects column order, whereas directly serializing
51// the `data` map would not.  (At least not while VMap is a HashMap.  serde_json
52// supports a "preserve_order" feature that uses the "indexmap" crate.  But
53// since we already have the info necessary for ordering, we use that.)
54impl serde::Serialize for Aggregate {
55    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
56    where
57        S: Serializer,
58    {
59        let mut seq = serializer.serialize_seq(Some(self.data.len()))?;
60        for row in &self.data {
61            seq.serialize_element(&WrappedAggregateRow {
62                columns: &self.columns,
63                data: row,
64            })?
65        }
66        seq.end()
67    }
68}
69
70#[derive(Debug, PartialEq, Eq, Clone)]
71pub struct Record {
72    pub data: VMap,
73    pub raw: String,
74}
75
76impl serde::Serialize for Record {
77    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
78    where
79        S: Serializer,
80    {
81        let mut map = serializer.serialize_map(Some(self.data.len()))?;
82        for (k, v) in self.data.iter().sorted() {
83            map.serialize_entry(k, v)?;
84        }
85        map.end()
86    }
87}
88
89#[derive(Clone, Debug, PartialEq, Eq, Hash)]
90pub enum Value {
91    Str(String),
92    // Consider big int
93    Int(i64),
94    Float(OrderedFloat<f64>),
95    Bool(bool),
96    DateTime(DateTime<Utc>),
97    Duration(Duration),
98    Obj(im::HashMap<String, Value>),
99    Array(Vec<Value>),
100    None,
101}
102
103impl serde::Serialize for Value {
104    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
105    where
106        S: Serializer,
107    {
108        match self {
109            Value::Str(s) => serializer.serialize_str(s),
110            Value::Int(i) => serializer.serialize_i64(*i),
111            Value::Float(ofloat) => serializer.serialize_f64(ofloat.0),
112            Value::Bool(b) => serializer.serialize_bool(*b),
113            Value::DateTime(dt) => serializer.serialize_str(dt.to_rfc3339().as_str()),
114            Value::Duration(d) => serializer.serialize_str(d.to_string().as_str()),
115            Value::Obj(map) => {
116                let mut m = serializer.serialize_map(Some(map.len()))?;
117                for (k, v) in map {
118                    m.serialize_entry(k, v)?;
119                }
120                m.end()
121            }
122            Value::Array(v) => serializer.collect_seq(v),
123            Value::None => serializer.serialize_none(),
124        }
125    }
126}
127
128impl Ord for Value {
129    fn cmp(&self, other: &Self) -> Ordering {
130        match (self, other) {
131            // Ints and floats are converted to floats
132            (Value::Int(int_val), Value::Float(float_val)) => {
133                (OrderedFloat::from(*int_val as f64)).cmp(float_val)
134            }
135            (Value::Float(float_val), Value::Int(int_val)) => {
136                float_val.cmp(&OrderedFloat::from(*int_val as f64))
137            }
138            (Value::Float(l), Value::Float(r)) => l.cmp(r),
139            (Value::Int(l), Value::Int(r)) => l.cmp(r),
140            (Value::Str(l), Value::Str(r)) => l.cmp(r),
141            (Value::Bool(l), Value::Bool(r)) => l.cmp(r),
142            (Value::DateTime(l), Value::DateTime(r)) => l.cmp(r),
143            (Value::Duration(l), Value::Duration(r)) => l.cmp(r),
144            (Value::Obj(l), Value::Obj(r)) => l.cmp(r),
145            // All these remaining cases aren't directly comparable
146            (unrelated_l, unrelated_r) => unrelated_l.rank().cmp(&unrelated_r.rank()),
147        }
148    }
149}
150
151impl PartialOrd for Value {
152    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
153        Some(self.cmp(other))
154    }
155}
156
157impl Display for Value {
158    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
159        match *self {
160            Value::Str(ref s) => write!(f, "{}", s),
161            Value::Int(ref s) => write!(f, "{}", s),
162            Value::Float(ref s) => write!(f, "{}", s),
163            Value::Bool(ref s) => write!(f, "{}", s),
164            Value::DateTime(ref dt) => write!(f, "{:?}", dt),
165            Value::Duration(ref d) => write!(f, "{:?}", d),
166            Value::Obj(ref o) => write!(f, "{:?}", o),
167            Value::Array(ref o) => write!(f, "{:?}", o),
168            Value::None => write!(f, "None"),
169        }
170    }
171}
172
173impl Add for Value {
174    type Output = Result<Value, EvalError>;
175
176    fn add(self, rhs: Self) -> Self::Output {
177        match (self, rhs) {
178            (Value::DateTime(ldt), Value::Duration(rd)) => Ok(Value::DateTime(ldt.add(rd))),
179            (Value::Duration(ld), Value::DateTime(rdt)) => Ok(Value::DateTime(rdt.add(ld))),
180            (Value::Duration(ld), Value::Duration(rd)) => Ok(Value::Duration(ld.add(rd))),
181            (Value::Float(lf), Value::Float(rf)) => Ok(Value::Float(lf + rf)),
182            (Value::Int(li), Value::Int(ri)) => Ok(Value::Int(li + ri)),
183            (left, right) => left.binary_op(&f64::add, "+", &right),
184        }
185    }
186}
187
188impl Sub for Value {
189    type Output = Result<Value, EvalError>;
190
191    fn sub(self, rhs: Self) -> Self::Output {
192        match (self, rhs) {
193            (Value::DateTime(ldt), Value::Duration(rf)) => Ok(Value::DateTime(ldt.sub(rf))),
194            (Value::DateTime(ldt), Value::DateTime(rdt)) => Ok(Value::Duration(ldt.sub(rdt))),
195            (Value::Duration(ld), Value::Duration(rd)) => Ok(Value::Duration(ld.sub(rd))),
196            (Value::Float(lf), Value::Float(rf)) => Ok(Value::Float(lf - rf)),
197            (Value::Int(li), Value::Int(ri)) => Ok(Value::Int(li - ri)),
198            (left, right) => left.binary_op(&f64::sub, "-", &right),
199        }
200    }
201}
202
203impl Mul for Value {
204    type Output = Result<Value, EvalError>;
205
206    fn mul(self, rhs: Self) -> Self::Output {
207        match (self, rhs) {
208            (Value::Duration(ld), Value::Int(ri)) => Ok(Value::Duration(ld.mul(ri as i32))),
209            (Value::Int(li), Value::Duration(rd)) => Ok(Value::Duration(rd.mul(li as i32))),
210            (Value::Float(lf), Value::Float(rf)) => Ok(Value::Float(lf * rf)),
211            (Value::Int(li), Value::Int(ri)) => Ok(Value::Int(li * ri)),
212            (left, right) => left.binary_op(&f64::mul, "*", &right),
213        }
214    }
215}
216
217impl Div for Value {
218    type Output = Result<Value, EvalError>;
219
220    fn div(self, rhs: Self) -> Self::Output {
221        match (self, rhs) {
222            (Value::Duration(ld), Value::Int(ri)) => Ok(Value::Duration(ld.div(ri as i32))),
223            (left, right) => left.binary_op(&f64::div, "/", &right),
224        }
225    }
226}
227
228#[derive(Clone)]
229pub struct DisplayConfig {
230    pub floating_points: usize,
231}
232
233impl Default for DisplayConfig {
234    fn default() -> Self {
235        DisplayConfig { floating_points: 2 }
236    }
237}
238
239pub(crate) struct ValueDisplay<'a> {
240    value: &'a Value,
241    display_config: &'a DisplayConfig,
242}
243
244impl<'a> ValueDisplay<'a> {
245    pub(crate) fn new(value: &'a Value, display_config: &'a DisplayConfig) -> Self {
246        Self {
247            value,
248            display_config,
249        }
250    }
251
252    fn nested(&self, new_value: &'a Value) -> ValueDisplay<'a> {
253        ValueDisplay {
254            value: new_value,
255            display_config: self.display_config,
256        }
257    }
258}
259
260impl Display for ValueDisplay<'_> {
261    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
262        match *self.value {
263            Value::Str(ref s) => write!(f, "{}", s),
264            Value::Int(ref s) => write!(f, "{}", s),
265            Value::None => write!(f, "None"),
266            Value::Float(ref s) => write!(f, "{:.*}", self.display_config.floating_points, s),
267            Value::Bool(ref s) => write!(f, "{}", s),
268            Value::DateTime(ref dt) => write!(f, "{}", dt),
269            Value::Duration(ref d) => {
270                let mut remaining: Duration = *d;
271                let weeks = remaining.num_seconds() / Duration::weeks(1).num_seconds();
272                remaining = remaining - Duration::weeks(weeks);
273                let days = remaining.num_seconds() / Duration::days(1).num_seconds();
274                remaining = remaining - Duration::days(days);
275                let hours = remaining.num_seconds() / Duration::hours(1).num_seconds();
276                remaining = remaining - Duration::hours(hours);
277                let mins = remaining.num_seconds() / Duration::minutes(1).num_seconds();
278                remaining = remaining - Duration::minutes(mins);
279                let secs = remaining.num_seconds() / Duration::seconds(1).num_seconds();
280                remaining = remaining - Duration::seconds(secs);
281                let msecs = remaining.num_milliseconds();
282                remaining = remaining - Duration::milliseconds(msecs);
283                let usecs = remaining.num_microseconds().unwrap_or(0);
284
285                let pairs = &[
286                    (weeks, "w"),
287                    (days, "d"),
288                    (hours, "h"),
289                    (mins, "m"),
290                    (secs, "s"),
291                    (msecs, "ms"),
292                    (usecs, "us"),
293                ];
294
295                for (val, sym) in pairs.iter().filter(|(val, _sym)| *val != 0) {
296                    write!(f, "{}{}", val, sym)?;
297                }
298                Ok(())
299            }
300            Value::Obj(ref o) => {
301                // todo: this is pretty janky...
302                // These values are sorted so the output is deterministic.
303                let mut items = o.iter().collect::<Vec<_>>();
304                items.sort();
305
306                let mut rendered = items
307                    .iter()
308                    .map(|(k, v)| format!("{}:{}", k, self.nested(v)));
309                write!(f, "{{{}}}", rendered.join(", "))
310            }
311            Value::Array(ref o) => {
312                let rendered: Vec<_> = o.iter().map(|v| format!("{}", self.nested(v))).collect();
313                write!(f, "[{}]", rendered.join(", "))
314            }
315        }
316    }
317}
318
319impl Value {
320    /// Used to sort mixed values
321    pub fn rank(&self) -> u8 {
322        match self {
323            Value::None => 0,
324            Value::Bool(_) => 1,
325            Value::Int(_) => 2,
326            Value::Float(_) => 2,
327            Value::Str(_) => 3,
328            Value::DateTime(_) => 4,
329            Value::Duration(_) => 5,
330            Value::Array(_) => 6,
331            Value::Obj(_) => 7,
332        }
333    }
334
335    pub fn render(&self, render_config: &DisplayConfig) -> String {
336        ValueDisplay::new(self, render_config).to_string()
337    }
338
339    pub fn from_bool(b: bool) -> Value {
340        Value::Bool(b)
341    }
342
343    pub fn from_float(f: f64) -> Value {
344        let rounded = f as i64;
345        if (f - f.floor()).abs() < f64::EPSILON {
346            Value::Int(rounded)
347        } else {
348            Value::Float(OrderedFloat(f))
349        }
350    }
351
352    pub fn aggressively_to_num(s: impl AsRef<str> + Into<String>) -> Result<f64, EvalError> {
353        // Handle cases like
354        // 1,000,000
355        match Value::from_string(
356            s.as_ref()
357                .chars()
358                .filter(|c| c.is_numeric() || c == &'.')
359                .collect::<String>(),
360        ) {
361            Value::Float(f) => Ok(f.0),
362            Value::Int(i) => Ok(i as f64),
363            _other => {
364                //println!("not a number...{}", s);
365                Err(EvalError::ExpectedNumber { found: s.into() })
366            }
367        }
368    }
369
370    pub fn from_string(s: impl AsRef<str> + Into<String>) -> Value {
371        let trimmed = s.as_ref().trim();
372        let int_value = trimmed.parse::<i64>();
373        let float_value = trimmed.parse::<f64>();
374        let bool_value = trimmed.parse::<bool>();
375        int_value
376            .map(Value::Int)
377            .or_else(|_| float_value.map(Value::from_float))
378            .or_else(|_| bool_value.map(Value::Bool))
379            .unwrap_or_else(|_| Value::Str(trimmed.into()))
380    }
381
382    pub fn binary_op(
383        &self,
384        op_fn: &dyn Fn(f64, f64) -> f64,
385        op: &'static str,
386        right: &Value,
387    ) -> Result<Value, EvalError> {
388        let left_res: Result<f64, EvalError> = self.try_into();
389        let right_res: Result<f64, EvalError> = right.try_into();
390
391        match (left_res, right_res) {
392            (Ok(lf1), Ok(rf1)) => Ok(Value::from_float(op_fn(lf1, rf1))),
393            _ => Err(EvalError::ExpectedNumericOperands {
394                left: format!("{}", self),
395                op,
396                right: format!("{}", right),
397            }),
398        }
399    }
400}
401
402impl From<f64> for Value {
403    fn from(f: f64) -> Self {
404        Value::from_float(f)
405    }
406}
407
408impl TryFrom<&Value> for f64 {
409    type Error = EvalError;
410
411    fn try_from(value: &Value) -> Result<Self, Self::Error> {
412        match value {
413            Value::Int(i) => Ok(*i as f64),
414            Value::Float(f) => Ok(f.0),
415            Value::Str(s) => Value::aggressively_to_num(s),
416            Value::DateTime(dt) => Ok(dt.timestamp_millis() as f64),
417            _ => Err(EvalError::ExpectedNumber {
418                found: format!("{}", value),
419            }),
420        }
421    }
422}
423
424impl TryFrom<&Value> for usize {
425    type Error = EvalError;
426
427    fn try_from(value: &Value) -> Result<Self, Self::Error> {
428        match value {
429            Value::Int(i) if *i >= 0 => Ok(*i as usize),
430            Value::Float(f) if f.0 >= 0.0 => Ok(f.0 as usize),
431            Value::Str(s) => {
432                let num = Value::aggressively_to_num(s)?;
433
434                if num < 0.0 {
435                    Err(EvalError::ExpectedPositiveNumber {
436                        found: format!("{}", value),
437                    })
438                } else {
439                    Ok(num as usize)
440                }
441            }
442            _ => Err(EvalError::ExpectedPositiveNumber {
443                found: format!("{}", value),
444            }),
445        }
446    }
447}
448
449impl Aggregate {
450    #[cfg(test)]
451    pub fn new(
452        key_columns: &[String],
453        agg_column: String,
454        data: &[(HashMap<String, String>, Value)],
455    ) -> Aggregate {
456        data.iter().for_each(|(row, _value)| {
457            if row.len() != key_columns.len() {
458                panic!("Invalid number of key columns")
459            }
460            key_columns.iter().for_each(|key_column| {
461                if !row.contains_key(key_column) {
462                    panic!("New row missing key column: {}", key_column);
463                }
464            });
465        });
466        let raw_data: Vec<HashMap<String, Value>> = data
467            .iter()
468            .map(|(keycols, value)| {
469                let mut new_map: HashMap<String, Value> = keycols
470                    .iter()
471                    .map(|(keycol, val)| (keycol.clone(), Value::Str(val.clone())))
472                    .collect();
473                new_map.insert(agg_column.clone(), value.clone());
474                new_map
475            })
476            .collect();
477        let mut columns = key_columns.to_owned();
478        columns.push(agg_column);
479
480        Aggregate {
481            data: raw_data,
482            columns,
483        }
484    }
485}
486
487impl Record {
488    pub fn put<T: Into<String>>(mut self, key: T, value: Value) -> Record {
489        self.data.insert(key.into(), value);
490        self
491    }
492
493    pub fn put_mut<T: Into<String>>(&mut self, key: T, value: Value) {
494        self.data.insert(key.into(), value);
495    }
496
497    /// Places a Value in the data based on the Expr accessor.
498    /// Only works with NestedColumn exprs.
499    pub fn put_expr(mut self, key: &Expr, value: Value) -> Result<Record, EvalError> {
500        match key {
501            Expr::NestedColumn { ref head, ref rest } => {
502                let mut root_record: &mut Value = if let Some(record) = self.data.get_mut(head) {
503                    record
504                } else {
505                    return if rest.is_empty() {
506                        self.data.insert(head.clone(), value);
507                        Ok(self)
508                    } else {
509                        Err(EvalError::NoValueForKey { key: head.clone() })
510                    };
511                };
512
513                let rest_len = rest.len();
514                for (index, value_reference) in rest.iter().enumerate() {
515                    match (value_reference, root_record) {
516                        (ValueRef::Field(ref key), Value::Obj(map)) => {
517                            if !map.contains_key(key) {
518                                let is_last = index + 1 == rest_len;
519                                return if is_last {
520                                    map.insert(key.clone(), value);
521                                    Ok(self)
522                                } else {
523                                    Err(EvalError::NoValueForKey { key: key.clone() })
524                                };
525                            }
526
527                            root_record = map.get_mut(key).expect("exists");
528                        }
529                        (ValueRef::Field(_), other) => {
530                            return Err(EvalError::ExpectedXYZ {
531                                expected: "object".to_string(),
532                                found: other.render(&DisplayConfig::default()),
533                            });
534                        }
535                        (ValueRef::IndexAt(index), Value::Array(vec)) => {
536                            let vec_len: i64 = vec.len().try_into().unwrap();
537                            let real_index = if *index < 0 { *index + vec_len } else { *index };
538
539                            if real_index < 0 || real_index >= vec_len {
540                                return Err(EvalError::IndexOutOfRange { index: *index });
541                            }
542                            root_record = &mut vec[real_index as usize];
543                        }
544                        (ValueRef::IndexAt(_), other) => {
545                            return Err(EvalError::ExpectedXYZ {
546                                expected: "array".to_string(),
547                                found: other.render(&DisplayConfig::default()),
548                            });
549                        }
550                    }
551                }
552                *root_record = value;
553            }
554            // These should not happen, if so this is a programming error
555            // since the data cannot be indexed by BoolUnary / Comparison / Value Exprs.
556            Expr::BoolUnary(_) => {
557                return Err(EvalError::ExpectedXYZ {
558                    expected: "valid expr".to_string(),
559                    found: "bool unary expr".to_string(),
560                })
561            }
562            Expr::Comparison(_) => {
563                return Err(EvalError::ExpectedXYZ {
564                    expected: "valid expr".to_string(),
565                    found: "comparison expr".to_string(),
566                })
567            }
568            Expr::Arithmetic(_) => {
569                return Err(EvalError::ExpectedXYZ {
570                    expected: "valid expr".to_string(),
571                    found: "arithmetic expr".to_string(),
572                })
573            }
574            Expr::Logical(_) => {
575                return Err(EvalError::ExpectedXYZ {
576                    expected: "valid expr".to_string(),
577                    found: "logical expr".to_string(),
578                })
579            }
580            Expr::FunctionCall { .. } => {
581                return Err(EvalError::ExpectedXYZ {
582                    expected: "valid expr".to_string(),
583                    found: "function call".to_string(),
584                })
585            }
586            Expr::IfOp { .. } => {
587                return Err(EvalError::ExpectedXYZ {
588                    expected: "valid expr".to_string(),
589                    found: "if operator".to_string(),
590                })
591            }
592            Expr::Value(_) => {
593                return Err(EvalError::ExpectedXYZ {
594                    expected: "valid expr".to_string(),
595                    found: "value expr".to_string(),
596                })
597            }
598        }
599        Ok(self)
600    }
601
602    pub fn new<T: Into<String>>(raw: T) -> Record {
603        Record {
604            data: HashMap::new(),
605            raw: raw.into(),
606        }
607    }
608
609    pub fn ordering<T: Into<Expr> + Send + Sync>(
610        columns: Vec<T>,
611    ) -> impl Fn(&VMap, &VMap) -> Result<Ordering, EvalError> + Send + Sync {
612        let columns: Vec<Expr> = columns.into_iter().map(Into::into).collect();
613        move |rec_l: &VMap, rec_r: &VMap| {
614            for col in &columns {
615                let l_val = col.eval_value(rec_l)?;
616                let r_val = col.eval_value(rec_r)?;
617                let cmp = l_val.cmp(&r_val);
618                if cmp != Ordering::Equal {
619                    return Ok(cmp);
620                }
621            }
622            Ok(Ordering::Equal)
623        }
624    }
625
626    pub fn ordering_ref<'a, T: 'a + AsRef<str> + Send + Sync>(
627        columns: &'a [T],
628    ) -> impl Fn(&VMap, &VMap) -> Ordering + 'a + Send + Sync {
629        move |rec_l: &VMap, rec_r: &VMap| {
630            for col in columns {
631                let l_val = rec_l.get(col.as_ref());
632                let r_val = rec_r.get(col.as_ref());
633                let cmp = l_val.cmp(&r_val);
634                if cmp != Ordering::Equal {
635                    return cmp;
636                }
637            }
638            Ordering::Equal
639        }
640    }
641}
642
643#[cfg(test)]
644mod tests {
645    use super::*;
646    use maplit::hashmap;
647    use std::str::FromStr;
648
649    #[test]
650    fn render_duration() {
651        let cfg = DisplayConfig { floating_points: 2 };
652
653        assert_eq!("2w", Value::Duration(Duration::weeks(2)).render(&cfg));
654        assert_eq!(
655            "2w2d5h25m4s232ms",
656            Value::Duration(
657                Duration::weeks(2)
658                    + Duration::days(2)
659                    + Duration::hours(5)
660                    + Duration::minutes(25)
661                    + Duration::seconds(4)
662                    + Duration::milliseconds(232)
663            )
664            .render(&cfg)
665        );
666    }
667
668    #[test]
669    fn record_put_get() {
670        let rec = Record::new("heres some data");
671        let rec = rec.put("key1", Value::Int(9999));
672        assert_eq!(rec.data.get("key1").unwrap(), &Value::Int(9999));
673        assert!(rec.data.get("key2").is_none());
674        assert_eq!(rec.raw, "heres some data");
675    }
676
677    #[test]
678    fn agg() {
679        let agg = Aggregate::new(
680            &["kc1".to_string(), "kc2".to_string()],
681            "count".to_string(),
682            &[(
683                hashmap! {
684                "kc1".to_string() => "k1".to_string(),
685                "kc2".to_string() => "k2".to_string()
686                },
687                Value::Int(100),
688            )],
689        );
690        assert_eq!(agg.data.len(), 1);
691    }
692
693    #[test]
694    fn serialize_vec() {
695        let rec = Value::Array(vec![
696            Value::Bool(false),
697            Value::from_string("123.5"),
698            Value::Array(vec![]),
699        ]);
700        assert_eq!(rec.render(&DisplayConfig::default()), "[false, 123.50, []]");
701    }
702
703    #[test]
704    #[should_panic]
705    fn panic_on_invalid_row() {
706        Aggregate::new(
707            &["k1".to_string(), "k2".to_string()],
708            "count".to_string(),
709            &[(
710                hashmap! {
711                "kc2".to_string() => "k2".to_string()
712                },
713                Value::Int(100),
714            )],
715        );
716    }
717
718    #[test]
719    fn from_string() {
720        assert_eq!(Value::from_string("949919"), Value::Int(949919));
721        assert_eq!(Value::from_string("0.00001"), Value::from_float(0.00001));
722        assert_eq!(
723            Value::from_string("not a number"),
724            Value::Str("not a number".to_string())
725        );
726        assert_eq!(Value::from_string("1 "), Value::Int(1));
727        assert_eq!(Value::from_string("abcd "), Value::Str("abcd".to_owned()));
728    }
729
730    #[test]
731    fn value_ordering() {
732        assert_eq!(
733            Value::from_string("hello").cmp(&Value::Int(0)),
734            Ordering::Greater
735        );
736    }
737
738    #[test]
739    fn test_aggresively_to_num() {
740        assert_eq!(
741            Value::from_string("1,000,000"),
742            Value::Str("1,000,000".to_owned())
743        );
744        assert_eq!(Value::aggressively_to_num("1,000,000"), Ok(1_000_000_f64));
745        assert_eq!(
746            Value::aggressively_to_num("1,000,000.1"),
747            Ok(1_000_000.1_f64)
748        );
749    }
750
751    #[test]
752    fn record_ordering() {
753        let mut r1 = HashMap::<String, Value>::new();
754        r1.insert("k1".to_string(), Value::Int(5));
755        r1.insert("k3".to_string(), Value::from_float(0.1));
756        r1.insert("k2".to_string(), Value::Str("abc".to_string()));
757        let mut r2 = HashMap::<String, Value>::new();
758        r2.insert("k1".to_string(), Value::Int(4));
759        r2.insert("k2".to_string(), Value::Str("xyz".to_string()));
760        r2.insert("k3".to_string(), Value::from_float(0.1));
761        let ord1 = Record::ordering(vec!["k1".to_string(), "k2".to_string()]);
762        assert_eq!(ord1(&r1, &r2), Ok(Ordering::Greater));
763        assert_eq!(ord1(&r1, &r1), Ok(Ordering::Equal));
764        assert_eq!(ord1(&r2, &r1), Ok(Ordering::Less));
765
766        let ord2 = Record::ordering(vec!["k2".to_string(), "k1".to_string()]);
767        assert_eq!(ord2(&r1, &r2), Ok(Ordering::Less));
768        assert_eq!(ord2(&r1, &r1), Ok(Ordering::Equal));
769        assert_eq!(ord2(&r2, &r1), Ok(Ordering::Greater));
770
771        let ord3 = Record::ordering(vec!["k3".to_string()]);
772        assert_eq!(ord3(&r1, &r2), Ok(Ordering::Equal));
773
774        let ord4 = Record::ordering(vec!["k3".to_string(), "k1".to_string()]);
775        assert_eq!(ord4(&r1, &r2), Ok(Ordering::Greater));
776        assert_eq!(ord4(&r1, &r1), Ok(Ordering::Equal));
777        assert_eq!(ord4(&r2, &r1), Ok(Ordering::Less));
778    }
779
780    #[test]
781    fn record_ordering_matching_prefix() {
782        let mut r1 = HashMap::<String, Value>::new();
783        r1.insert("k1".to_string(), Value::Int(5));
784        r1.insert("k2".to_string(), Value::from_float(6.0));
785
786        let mut r2 = HashMap::<String, Value>::new();
787        r2.insert("k1".to_string(), Value::from_float(5.0));
788        r2.insert("k2".to_string(), Value::Int(7));
789
790        let ord = Record::ordering(vec!["k1".to_string(), "k2".to_string()]);
791        assert_eq!(ord(&r1, &r2), Ok(Ordering::Less));
792    }
793
794    #[test]
795    fn arithmetic() {
796        assert_eq!(
797            Value::from_float(5.),
798            (Value::from_float(4.) + Value::from_float(1.)).unwrap()
799        );
800        assert_eq!(Value::Int(5), (Value::Int(4) + Value::Int(1)).unwrap());
801        assert_eq!(
802            Value::from_float(5.),
803            (Value::Int(4) + Value::from_float(1.0)).unwrap()
804        );
805        assert_eq!(
806            Value::from_float(5.),
807            (Value::from_float(4.) + Value::Int(1)).unwrap()
808        );
809
810        assert_eq!(
811            Value::from_float(3.),
812            (Value::from_float(4.) - Value::from_float(1.)).unwrap()
813        );
814        assert_eq!(Value::Int(3), (Value::Int(4) - Value::Int(1)).unwrap());
815        assert_eq!(
816            Value::from_float(3.),
817            (Value::Int(4) - Value::from_float(1.0)).unwrap()
818        );
819        assert_eq!(
820            Value::from_float(3.),
821            (Value::from_float(4.) - Value::Int(1)).unwrap()
822        );
823
824        assert_eq!(
825            Value::from_float(4.),
826            (Value::from_float(4.) * Value::from_float(1.)).unwrap()
827        );
828        assert_eq!(Value::Int(4), (Value::Int(4) * Value::Int(1)).unwrap());
829        assert_eq!(
830            Value::from_float(4.),
831            (Value::Int(4) * Value::from_float(1.0)).unwrap()
832        );
833        assert_eq!(
834            Value::from_float(4.),
835            (Value::from_float(4.) * Value::Int(1)).unwrap()
836        );
837
838        assert_eq!(
839            Value::from_float(2.),
840            (Value::from_float(4.) / Value::from_float(2.)).unwrap()
841        );
842        assert_eq!(Value::Int(2), (Value::Int(4) / Value::Int(2)).unwrap());
843        assert_eq!(
844            Value::from_float(2.),
845            (Value::Int(4) / Value::from_float(2.0)).unwrap()
846        );
847        assert_eq!(
848            Value::from_float(2.),
849            (Value::from_float(4.) / Value::Int(2)).unwrap()
850        );
851
852        assert_eq!(
853            Value::Duration(Duration::days(1)),
854            (Value::DateTime(DateTime::<Utc>::from_str("2021-08-11T00:00:00Z").unwrap())
855                - Value::DateTime(DateTime::<Utc>::from_str("2021-08-10T00:00:00Z").unwrap()))
856            .unwrap()
857        );
858        assert_eq!(
859            Value::Duration(Duration::days(1)),
860            (Value::Duration(Duration::days(2)) - Value::Duration(Duration::days(1))).unwrap()
861        );
862        assert_eq!(
863            Value::Duration(Duration::days(3)),
864            (Value::Duration(Duration::days(2)) + Value::Duration(Duration::days(1))).unwrap()
865        );
866        assert_eq!(
867            Value::Duration(Duration::days(4)),
868            (Value::Duration(Duration::days(2)) * Value::Int(2)).unwrap()
869        );
870        assert_eq!(
871            Value::Duration(Duration::days(1)),
872            (Value::Duration(Duration::days(2)) / Value::Int(2)).unwrap()
873        );
874    }
875}