1use crate::data::datatable::DataValue;
2use std::cmp::Ordering;
3
4#[must_use]
7pub fn compare_datavalues(a: &DataValue, b: &DataValue) -> Ordering {
8 match (a, b) {
9 (DataValue::Integer(a), DataValue::Integer(b)) => a.cmp(b),
11
12 (DataValue::Float(a), DataValue::Float(b)) => a.partial_cmp(b).unwrap_or(Ordering::Equal),
14
15 (DataValue::String(a), DataValue::String(b)) => a.cmp(b),
17
18 (DataValue::InternedString(a), DataValue::InternedString(b)) => a.as_ref().cmp(b.as_ref()),
20
21 (DataValue::String(a), DataValue::InternedString(b)) => a.cmp(b.as_ref()),
23 (DataValue::InternedString(a), DataValue::String(b)) => a.as_ref().cmp(b),
24
25 (DataValue::Boolean(a), DataValue::Boolean(b)) => a.cmp(b),
27
28 (DataValue::DateTime(a), DataValue::DateTime(b)) => a.cmp(b),
30
31 (DataValue::Vector(a), DataValue::Vector(b)) => {
33 for (av, bv) in a.iter().zip(b.iter()) {
34 match av.partial_cmp(bv).unwrap_or(Ordering::Equal) {
35 Ordering::Equal => continue,
36 other => return other,
37 }
38 }
39 a.len().cmp(&b.len())
40 }
41
42 (DataValue::Null, DataValue::Null) => Ordering::Equal,
44 (DataValue::Null, _) => Ordering::Less,
45 (_, DataValue::Null) => Ordering::Greater,
46
47 (DataValue::Boolean(_), DataValue::Integer(_)) => Ordering::Less,
50 (DataValue::Boolean(_), DataValue::Float(_)) => Ordering::Less,
51 (DataValue::Boolean(_), DataValue::String(_)) => Ordering::Less,
52 (DataValue::Boolean(_), DataValue::InternedString(_)) => Ordering::Less,
53 (DataValue::Boolean(_), DataValue::DateTime(_)) => Ordering::Less,
54 (DataValue::Boolean(_), DataValue::Vector(_)) => Ordering::Less,
55
56 (DataValue::Integer(_), DataValue::Boolean(_)) => Ordering::Greater,
57 (DataValue::Integer(i), DataValue::Float(f)) => {
58 (*i as f64).partial_cmp(f).unwrap_or(Ordering::Equal)
60 }
61 (DataValue::Integer(_), DataValue::String(_)) => Ordering::Less,
62 (DataValue::Integer(_), DataValue::InternedString(_)) => Ordering::Less,
63 (DataValue::Integer(_), DataValue::DateTime(_)) => Ordering::Less,
64 (DataValue::Integer(_), DataValue::Vector(_)) => Ordering::Less,
65
66 (DataValue::Float(_), DataValue::Boolean(_)) => Ordering::Greater,
67 (DataValue::Float(f), DataValue::Integer(i)) => {
68 f.partial_cmp(&(*i as f64)).unwrap_or(Ordering::Equal)
70 }
71 (DataValue::Float(_), DataValue::String(_)) => Ordering::Less,
72 (DataValue::Float(_), DataValue::InternedString(_)) => Ordering::Less,
73 (DataValue::Float(_), DataValue::DateTime(_)) => Ordering::Less,
74 (DataValue::Float(_), DataValue::Vector(_)) => Ordering::Less,
75
76 (DataValue::String(_), DataValue::Boolean(_)) => Ordering::Greater,
77 (DataValue::String(_), DataValue::Integer(_)) => Ordering::Greater,
78 (DataValue::String(_), DataValue::Float(_)) => Ordering::Greater,
79 (DataValue::String(_), DataValue::DateTime(_)) => Ordering::Less,
80 (DataValue::String(_), DataValue::Vector(_)) => Ordering::Less,
81
82 (DataValue::InternedString(_), DataValue::Boolean(_)) => Ordering::Greater,
83 (DataValue::InternedString(_), DataValue::Integer(_)) => Ordering::Greater,
84 (DataValue::InternedString(_), DataValue::Float(_)) => Ordering::Greater,
85 (DataValue::InternedString(_), DataValue::DateTime(_)) => Ordering::Less,
86 (DataValue::InternedString(_), DataValue::Vector(_)) => Ordering::Less,
87
88 (DataValue::DateTime(_), DataValue::Boolean(_)) => Ordering::Greater,
89 (DataValue::DateTime(_), DataValue::Integer(_)) => Ordering::Greater,
90 (DataValue::DateTime(_), DataValue::Float(_)) => Ordering::Greater,
91 (DataValue::DateTime(_), DataValue::String(_)) => Ordering::Greater,
92 (DataValue::DateTime(_), DataValue::InternedString(_)) => Ordering::Greater,
93 (DataValue::DateTime(_), DataValue::Vector(_)) => Ordering::Less,
94
95 (DataValue::Vector(_), DataValue::Boolean(_)) => Ordering::Greater,
96 (DataValue::Vector(_), DataValue::Integer(_)) => Ordering::Greater,
97 (DataValue::Vector(_), DataValue::Float(_)) => Ordering::Greater,
98 (DataValue::Vector(_), DataValue::String(_)) => Ordering::Greater,
99 (DataValue::Vector(_), DataValue::InternedString(_)) => Ordering::Greater,
100 (DataValue::Vector(_), DataValue::DateTime(_)) => Ordering::Greater,
101 }
102}
103
104#[must_use]
106pub fn compare_optional_datavalues(a: Option<&DataValue>, b: Option<&DataValue>) -> Ordering {
107 match (a, b) {
108 (None, None) => Ordering::Equal,
109 (None, Some(_)) => Ordering::Less,
110 (Some(_), None) => Ordering::Greater,
111 (Some(a), Some(b)) => compare_datavalues(a, b),
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118 use std::sync::Arc;
119
120 #[test]
121 fn test_integer_comparison() {
122 assert_eq!(
123 compare_datavalues(&DataValue::Integer(1), &DataValue::Integer(2)),
124 Ordering::Less
125 );
126 assert_eq!(
127 compare_datavalues(&DataValue::Integer(2), &DataValue::Integer(2)),
128 Ordering::Equal
129 );
130 assert_eq!(
131 compare_datavalues(&DataValue::Integer(3), &DataValue::Integer(2)),
132 Ordering::Greater
133 );
134 }
135
136 #[test]
137 fn test_string_comparison() {
138 assert_eq!(
139 compare_datavalues(
140 &DataValue::String("apple".to_string()),
141 &DataValue::String("banana".to_string())
142 ),
143 Ordering::Less
144 );
145 }
146
147 #[test]
148 fn test_interned_string_comparison() {
149 let a = Arc::new("apple".to_string());
150 let b = Arc::new("banana".to_string());
151 assert_eq!(
152 compare_datavalues(&DataValue::InternedString(a), &DataValue::InternedString(b)),
153 Ordering::Less
154 );
155 }
156
157 #[test]
158 fn test_mixed_string_comparison() {
159 let interned = Arc::new("banana".to_string());
160 assert_eq!(
161 compare_datavalues(
162 &DataValue::String("apple".to_string()),
163 &DataValue::InternedString(interned.clone())
164 ),
165 Ordering::Less
166 );
167 assert_eq!(
168 compare_datavalues(
169 &DataValue::InternedString(interned),
170 &DataValue::String("apple".to_string())
171 ),
172 Ordering::Greater
173 );
174 }
175
176 #[test]
177 fn test_null_comparison() {
178 assert_eq!(
179 compare_datavalues(&DataValue::Null, &DataValue::Integer(1)),
180 Ordering::Less
181 );
182 assert_eq!(
183 compare_datavalues(&DataValue::Integer(1), &DataValue::Null),
184 Ordering::Greater
185 );
186 assert_eq!(
187 compare_datavalues(&DataValue::Null, &DataValue::Null),
188 Ordering::Equal
189 );
190 }
191
192 #[test]
193 fn test_cross_type_comparison() {
194 assert_eq!(
196 compare_datavalues(&DataValue::Boolean(true), &DataValue::Integer(1)),
197 Ordering::Less
198 );
199
200 assert_eq!(
202 compare_datavalues(&DataValue::Integer(1), &DataValue::Float(1.0)),
203 Ordering::Equal );
205 assert_eq!(
206 compare_datavalues(&DataValue::Integer(1), &DataValue::Float(1.5)),
207 Ordering::Less );
209 assert_eq!(
210 compare_datavalues(&DataValue::Integer(2), &DataValue::Float(1.5)),
211 Ordering::Greater );
213
214 assert_eq!(
215 compare_datavalues(&DataValue::Float(1.0), &DataValue::String("a".to_string())),
216 Ordering::Less
217 );
218 }
219}