nodedb_query/
json_expr.rs1use crate::expr::{EvalError, SqlExpr};
12use crate::json_ops::compare_json_numbers;
13
14pub fn eval_expr_on_json(
20 expr: &SqlExpr,
21 doc: &serde_json::Value,
22) -> Result<serde_json::Value, EvalError> {
23 match expr {
24 SqlExpr::Column(name) => Ok(doc.get(name).cloned().unwrap_or(serde_json::Value::Null)),
25 SqlExpr::Literal(v) => Ok(serde_json::Value::from(v.clone())),
26 other => {
27 let row = nodedb_types::Value::from(doc.clone());
28 Ok(serde_json::Value::from(other.eval(&row)?))
29 }
30 }
31}
32
33pub fn compare_json(a: &serde_json::Value, b: &serde_json::Value) -> std::cmp::Ordering {
40 use serde_json::Value;
41 match (a, b) {
42 (Value::Null, Value::Null) => std::cmp::Ordering::Equal,
43 (Value::Null, _) => std::cmp::Ordering::Less,
44 (_, Value::Null) => std::cmp::Ordering::Greater,
45 (Value::Bool(x), Value::Bool(y)) => x.cmp(y),
46 (Value::Number(x), Value::Number(y)) => match compare_json_numbers(x, y) {
47 Some(order) => order,
48 None => a.to_string().cmp(&b.to_string()),
49 },
50 (Value::String(x), Value::String(y)) => x.cmp(y),
51 _ => a.to_string().cmp(&b.to_string()),
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58 use serde_json::json;
59 use std::cmp::Ordering;
60
61 fn sorted(mut values: Vec<serde_json::Value>) -> Vec<serde_json::Value> {
62 values.sort_by(compare_json);
63 values
64 }
65
66 #[test]
68 fn integers_past_two_pow_53_order_exactly() {
69 let above = json!(9_007_199_254_740_993_i64);
70 let at = json!(9_007_199_254_740_992_i64);
71 assert_eq!(compare_json(&above, &at), Ordering::Greater);
72 assert_eq!(compare_json(&at, &above), Ordering::Less);
73 assert_eq!(sorted(vec![above.clone(), at.clone()]), vec![at, above]);
74 }
75
76 #[test]
77 fn nanosecond_timestamps_order_exactly() {
78 let t0 = json!(1_700_000_000_000_000_001_i64);
79 let t1 = json!(1_700_000_000_000_000_002_i64);
80 let t2 = json!(1_700_000_000_000_000_003_i64);
81 assert_eq!(
82 sorted(vec![t2.clone(), t0.clone(), t1.clone()]),
83 vec![t0, t1, t2]
84 );
85 }
86
87 #[test]
88 fn u64_against_i64_orders_exactly() {
89 let u_max = json!(u64::MAX);
90 let i_max = json!(i64::MAX);
91 let i_min = json!(i64::MIN);
92 assert_eq!(compare_json(&u_max, &i_max), Ordering::Greater);
93 assert_eq!(compare_json(&i_max, &u_max), Ordering::Less);
94 assert_eq!(
95 sorted(vec![u_max.clone(), i_min.clone(), i_max.clone()]),
96 vec![i_min, i_max, u_max]
97 );
98 }
99
100 #[test]
101 fn integer_against_float_near_two_pow_53_orders_without_rounding() {
102 let above = json!(9_007_199_254_740_993_i64);
103 let float = json!(9_007_199_254_740_992.0_f64);
104 assert_eq!(compare_json(&above, &float), Ordering::Greater);
105 assert_eq!(compare_json(&float, &above), Ordering::Less);
106 assert_eq!(
107 compare_json(&json!(9_007_199_254_740_992_i64), &float),
108 Ordering::Equal
109 );
110 }
111
112 #[test]
113 fn small_values_keep_their_order() {
114 assert_eq!(
115 sorted(vec![json!(2), json!(null), json!(1.5), json!(-1), json!(1)]),
116 vec![json!(null), json!(-1), json!(1), json!(1.5), json!(2)]
117 );
118 assert_eq!(compare_json(&json!(3), &json!(3.0)), Ordering::Equal);
119 assert_eq!(compare_json(&json!("a"), &json!("b")), Ordering::Less);
120 assert_eq!(compare_json(&json!(false), &json!(true)), Ordering::Less);
121 }
122
123 #[test]
125 fn nan_sorts_as_null() {
126 let nan = json!(f64::NAN);
127 assert!(nan.is_null());
128 assert_eq!(compare_json(&nan, &json!(1)), Ordering::Less);
129 assert_eq!(compare_json(&nan, &json!(null)), Ordering::Equal);
130 }
131}