1use crate::data::datatable::DataValue;
2use std::cmp::Ordering;
3
4pub fn compare_datavalues(a: &DataValue, b: &DataValue) -> Ordering {
7 match (a, b) {
8 (DataValue::Integer(a), DataValue::Integer(b)) => a.cmp(b),
10
11 (DataValue::Float(a), DataValue::Float(b)) => a.partial_cmp(b).unwrap_or(Ordering::Equal),
13
14 (DataValue::String(a), DataValue::String(b)) => a.cmp(b),
16
17 (DataValue::InternedString(a), DataValue::InternedString(b)) => a.as_ref().cmp(b.as_ref()),
19
20 (DataValue::String(a), DataValue::InternedString(b)) => a.cmp(b.as_ref()),
22 (DataValue::InternedString(a), DataValue::String(b)) => a.as_ref().cmp(b),
23
24 (DataValue::Boolean(a), DataValue::Boolean(b)) => a.cmp(b),
26
27 (DataValue::DateTime(a), DataValue::DateTime(b)) => a.cmp(b),
29
30 (DataValue::Null, DataValue::Null) => Ordering::Equal,
32 (DataValue::Null, _) => Ordering::Less,
33 (_, DataValue::Null) => Ordering::Greater,
34
35 (DataValue::Boolean(_), DataValue::Integer(_)) => Ordering::Less,
38 (DataValue::Boolean(_), DataValue::Float(_)) => Ordering::Less,
39 (DataValue::Boolean(_), DataValue::String(_)) => Ordering::Less,
40 (DataValue::Boolean(_), DataValue::InternedString(_)) => Ordering::Less,
41 (DataValue::Boolean(_), DataValue::DateTime(_)) => Ordering::Less,
42
43 (DataValue::Integer(_), DataValue::Boolean(_)) => Ordering::Greater,
44 (DataValue::Integer(i), DataValue::Float(f)) => {
45 (*i as f64).partial_cmp(f).unwrap_or(Ordering::Equal)
47 }
48 (DataValue::Integer(_), DataValue::String(_)) => Ordering::Less,
49 (DataValue::Integer(_), DataValue::InternedString(_)) => Ordering::Less,
50 (DataValue::Integer(_), DataValue::DateTime(_)) => Ordering::Less,
51
52 (DataValue::Float(_), DataValue::Boolean(_)) => Ordering::Greater,
53 (DataValue::Float(f), DataValue::Integer(i)) => {
54 f.partial_cmp(&(*i as f64)).unwrap_or(Ordering::Equal)
56 }
57 (DataValue::Float(_), DataValue::String(_)) => Ordering::Less,
58 (DataValue::Float(_), DataValue::InternedString(_)) => Ordering::Less,
59 (DataValue::Float(_), DataValue::DateTime(_)) => Ordering::Less,
60
61 (DataValue::String(_), DataValue::Boolean(_)) => Ordering::Greater,
62 (DataValue::String(_), DataValue::Integer(_)) => Ordering::Greater,
63 (DataValue::String(_), DataValue::Float(_)) => Ordering::Greater,
64 (DataValue::String(_), DataValue::DateTime(_)) => Ordering::Less,
65
66 (DataValue::InternedString(_), DataValue::Boolean(_)) => Ordering::Greater,
67 (DataValue::InternedString(_), DataValue::Integer(_)) => Ordering::Greater,
68 (DataValue::InternedString(_), DataValue::Float(_)) => Ordering::Greater,
69 (DataValue::InternedString(_), DataValue::DateTime(_)) => Ordering::Less,
70
71 (DataValue::DateTime(_), DataValue::Boolean(_)) => Ordering::Greater,
72 (DataValue::DateTime(_), DataValue::Integer(_)) => Ordering::Greater,
73 (DataValue::DateTime(_), DataValue::Float(_)) => Ordering::Greater,
74 (DataValue::DateTime(_), DataValue::String(_)) => Ordering::Greater,
75 (DataValue::DateTime(_), DataValue::InternedString(_)) => Ordering::Greater,
76 }
77}
78
79pub fn compare_optional_datavalues(a: Option<&DataValue>, b: Option<&DataValue>) -> Ordering {
81 match (a, b) {
82 (None, None) => Ordering::Equal,
83 (None, Some(_)) => Ordering::Less,
84 (Some(_), None) => Ordering::Greater,
85 (Some(a), Some(b)) => compare_datavalues(a, b),
86 }
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92 use std::sync::Arc;
93
94 #[test]
95 fn test_integer_comparison() {
96 assert_eq!(
97 compare_datavalues(&DataValue::Integer(1), &DataValue::Integer(2)),
98 Ordering::Less
99 );
100 assert_eq!(
101 compare_datavalues(&DataValue::Integer(2), &DataValue::Integer(2)),
102 Ordering::Equal
103 );
104 assert_eq!(
105 compare_datavalues(&DataValue::Integer(3), &DataValue::Integer(2)),
106 Ordering::Greater
107 );
108 }
109
110 #[test]
111 fn test_string_comparison() {
112 assert_eq!(
113 compare_datavalues(
114 &DataValue::String("apple".to_string()),
115 &DataValue::String("banana".to_string())
116 ),
117 Ordering::Less
118 );
119 }
120
121 #[test]
122 fn test_interned_string_comparison() {
123 let a = Arc::new("apple".to_string());
124 let b = Arc::new("banana".to_string());
125 assert_eq!(
126 compare_datavalues(&DataValue::InternedString(a), &DataValue::InternedString(b)),
127 Ordering::Less
128 );
129 }
130
131 #[test]
132 fn test_mixed_string_comparison() {
133 let interned = Arc::new("banana".to_string());
134 assert_eq!(
135 compare_datavalues(
136 &DataValue::String("apple".to_string()),
137 &DataValue::InternedString(interned.clone())
138 ),
139 Ordering::Less
140 );
141 assert_eq!(
142 compare_datavalues(
143 &DataValue::InternedString(interned),
144 &DataValue::String("apple".to_string())
145 ),
146 Ordering::Greater
147 );
148 }
149
150 #[test]
151 fn test_null_comparison() {
152 assert_eq!(
153 compare_datavalues(&DataValue::Null, &DataValue::Integer(1)),
154 Ordering::Less
155 );
156 assert_eq!(
157 compare_datavalues(&DataValue::Integer(1), &DataValue::Null),
158 Ordering::Greater
159 );
160 assert_eq!(
161 compare_datavalues(&DataValue::Null, &DataValue::Null),
162 Ordering::Equal
163 );
164 }
165
166 #[test]
167 fn test_cross_type_comparison() {
168 assert_eq!(
170 compare_datavalues(&DataValue::Boolean(true), &DataValue::Integer(1)),
171 Ordering::Less
172 );
173
174 assert_eq!(
176 compare_datavalues(&DataValue::Integer(1), &DataValue::Float(1.0)),
177 Ordering::Equal );
179 assert_eq!(
180 compare_datavalues(&DataValue::Integer(1), &DataValue::Float(1.5)),
181 Ordering::Less );
183 assert_eq!(
184 compare_datavalues(&DataValue::Integer(2), &DataValue::Float(1.5)),
185 Ordering::Greater );
187
188 assert_eq!(
189 compare_datavalues(&DataValue::Float(1.0), &DataValue::String("a".to_string())),
190 Ordering::Less
191 );
192 }
193}