Skip to main content

linkrs_query/executor/streaming/helpers/
comparison.rs

1//! Value comparison for sorting
2//!
3//! Provides comparison logic for VALUES in streaming executor.
4
5use linkrs_core::Value;
6use std::cmp::Ordering;
7
8/// Compare two values for sorting
9///
10/// Handles NULL values (NULL comes last), numeric values, strings, and other types.
11/// Used in Sort and other comparison operations.
12pub fn compare_values(a: &Value, b: &Value) -> Ordering {
13    // Handle NULL values - NULL comes last
14    match (a, b) {
15        (Value::Null(_), Value::Null(_)) => Ordering::Equal,
16        (Value::Null(_), _) => Ordering::Greater,
17        (_, Value::Null(_)) => Ordering::Less,
18        (Value::Bool(a), Value::Bool(b)) => a.cmp(b),
19        (Value::Int(a), Value::Int(b)) => a.cmp(b),
20        (Value::BigInt(a), Value::BigInt(b)) => a.cmp(b),
21        (Value::Float(a), Value::Float(b)) => {
22            if a < b {
23                Ordering::Less
24            } else if a > b {
25                Ordering::Greater
26            } else {
27                Ordering::Equal
28            }
29        }
30        (Value::Double(a), Value::Double(b)) => {
31            if a < b {
32                Ordering::Less
33            } else if a > b {
34                Ordering::Greater
35            } else {
36                Ordering::Equal
37            }
38        }
39        (Value::String(a), Value::String(b)) => a.cmp(b),
40        _ => a.to_string().cmp(&b.to_string()),
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47    use linkrs_core::value::NullType;
48
49    #[test]
50    fn test_null_ordering() {
51        let null_val = Value::Null(NullType::Null);
52        let int_val = Value::Int(1);
53        let string_val = Value::string("a");
54
55        // NULL should be Greater (sorted last)
56        assert_eq!(compare_values(&null_val, &int_val), Ordering::Greater);
57        assert_eq!(compare_values(&int_val, &null_val), Ordering::Less);
58        assert_eq!(compare_values(&null_val, &null_val), Ordering::Equal);
59        assert_eq!(compare_values(&null_val, &string_val), Ordering::Greater);
60    }
61
62    #[test]
63    fn test_numeric_ordering() {
64        let v1 = Value::Int(1);
65        let v2 = Value::Int(2);
66        let v3 = Value::BigInt(100);
67        let v4 = Value::BigInt(99);
68
69        assert_eq!(compare_values(&v1, &v2), Ordering::Less);
70        assert_eq!(compare_values(&v2, &v1), Ordering::Greater);
71        assert_eq!(compare_values(&v1, &v1), Ordering::Equal);
72        assert_eq!(compare_values(&v3, &v4), Ordering::Greater);
73        assert_eq!(compare_values(&v4, &v3), Ordering::Less);
74    }
75
76    #[test]
77    fn test_string_ordering() {
78        let va = Value::string("a");
79        let vb = Value::string("b");
80        let vc = Value::string("c");
81
82        assert_eq!(compare_values(&va, &vb), Ordering::Less);
83        assert_eq!(compare_values(&vb, &va), Ordering::Greater);
84        assert_eq!(compare_values(&va, &va), Ordering::Equal);
85        assert_eq!(compare_values(&vb, &vc), Ordering::Less);
86    }
87
88    #[test]
89    fn test_float_ordering() {
90        let v1 = Value::Float(1.5);
91        let v2 = Value::Float(2.5);
92        let v3 = Value::Double(std::f64::consts::PI);
93        let v4 = Value::Double(2.71);
94
95        assert_eq!(compare_values(&v1, &v2), Ordering::Less);
96        assert_eq!(compare_values(&v2, &v1), Ordering::Greater);
97        assert_eq!(compare_values(&v1, &v1), Ordering::Equal);
98        assert_eq!(compare_values(&v3, &v4), Ordering::Greater);
99    }
100}