gitql_core/values/
base.rs

1use std::any::Any;
2use std::cmp::Ordering;
3use std::fmt;
4
5use dyn_clone::DynClone;
6use gitql_ast::operator::GroupComparisonOperator;
7use gitql_ast::types::DataType;
8use gitql_ast::Interval;
9
10use super::array::ArrayValue;
11use super::boolean::BoolValue;
12use super::composite::CompositeValue;
13use super::date::DateValue;
14use super::datetime::DateTimeValue;
15use super::float::FloatValue;
16use super::integer::IntValue;
17use super::interval::IntervalValue;
18use super::null::NullValue;
19use super::range::RangeValue;
20use super::text::TextValue;
21use super::time::TimeValue;
22
23dyn_clone::clone_trait_object!(Value);
24
25/// The in memory representation of the Values in the GitQL query engine
26pub trait Value: DynClone {
27    /// Return the literal representation for this [`Value`]
28    fn literal(&self) -> String;
29
30    /// Return if other [`Value`] is equal or not to current value
31    #[allow(clippy::borrowed_box)]
32    fn equals(&self, other: &Box<dyn Value>) -> bool;
33
34    /// Return the order between [`Value`] and the current value,
35    /// or None if they can't be ordered
36    #[allow(clippy::borrowed_box)]
37    fn compare(&self, other: &Box<dyn Value>) -> Option<Ordering>;
38
39    /// Return the [`DataType`] for the current [`Value`]
40    fn data_type(&self) -> Box<dyn DataType>;
41
42    /// Return the current value as dynamic [`Any`]
43    fn as_any(&self) -> &dyn Any;
44
45    /// Perform unary `=` operator and return new [`Value`] represent the result or Exception message as [`String`]
46    #[allow(unused_variables)]
47    #[allow(clippy::borrowed_box)]
48    fn add_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
49        Err("Unsupported operator for this type".to_string())
50    }
51
52    /// Perform unary `-` operator and return new [`Value`] represent the result or Exception message as [`String`]
53    #[allow(unused_variables)]
54    #[allow(clippy::borrowed_box)]
55    fn sub_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
56        Err("Unsupported operator for this type".to_string())
57    }
58
59    /// Perform unary `*` operator and return new [`Value`] represent the result or Exception message as [`String`]
60    #[allow(unused_variables)]
61    #[allow(clippy::borrowed_box)]
62    fn mul_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
63        Err("Unsupported operator for this type".to_string())
64    }
65
66    /// Perform unary `/` operator and return new [`Value`] represent the result or Exception message as [`String`]
67    #[allow(unused_variables)]
68    #[allow(clippy::borrowed_box)]
69    fn div_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
70        Err("Unsupported operator for this type".to_string())
71    }
72
73    /// Perform unary `%` operator and return new [`Value`] represent the result or Exception message as [`String`]
74    #[allow(unused_variables)]
75    #[allow(clippy::borrowed_box)]
76    fn rem_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
77        Err("Unsupported operator for this type".to_string())
78    }
79
80    /// Perform unary `^` operator and return new [`Value`] represent the result or Exception message as [`String`]
81    #[allow(unused_variables)]
82    #[allow(clippy::borrowed_box)]
83    fn caret_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
84        Err("Unsupported operator for this type".to_string())
85    }
86
87    /// Perform unary `|` operator and return new [`Value`] represent the result or Exception message as [`String`]
88    #[allow(unused_variables)]
89    #[allow(clippy::borrowed_box)]
90    fn or_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
91        Err("Unsupported operator for this type".to_string())
92    }
93
94    /// Perform unary `&` operator and return new [`Value`] represent the result or Exception message as [`String`]
95    #[allow(unused_variables)]
96    #[allow(clippy::borrowed_box)]
97    fn and_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
98        Err("Unsupported operator for this type".to_string())
99    }
100
101    /// Perform unary `#` operator and return new [`Value`] represent the result or Exception message as [`String`]
102    #[allow(unused_variables)]
103    #[allow(clippy::borrowed_box)]
104    fn xor_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
105        Err("Unsupported operator for this type".to_string())
106    }
107
108    /// Perform unary `||` or `OR` operator and return new [`Value`] represent the result or Exception message as [`String`]
109    #[allow(unused_variables)]
110    #[allow(clippy::borrowed_box)]
111    fn logical_or_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
112        Err("Unsupported operator for this type".to_string())
113    }
114
115    /// Perform unary `&&` or `AND` operator and return new [`Value`] represent the result or Exception message as [`String`]
116    #[allow(unused_variables)]
117    #[allow(clippy::borrowed_box)]
118    fn logical_and_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
119        Err("Unsupported operator for this type".to_string())
120    }
121
122    /// Perform unary `XOR` operator and return new [`Value`] represent the result or Exception message as [`String`]
123    #[allow(unused_variables)]
124    #[allow(clippy::borrowed_box)]
125    fn logical_xor_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
126        Err("Unsupported operator for this type".to_string())
127    }
128
129    /// Perform unary `<<` operator and return new [`Value`] represent the result or Exception message as [`String`]
130    #[allow(unused_variables)]
131    #[allow(clippy::borrowed_box)]
132    fn shl_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
133        Err("Unsupported operator for this type".to_string())
134    }
135
136    /// Perform unary `>>` operator and return new [`Value`] represent the result or Exception message as [`String`]
137    #[allow(unused_variables)]
138    #[allow(clippy::borrowed_box)]
139    fn shr_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
140        Err("Unsupported operator for this type".to_string())
141    }
142
143    /// Perform unary `[I]` operator and return new [`Value`] represent the result or Exception message as [`String`]
144    #[allow(unused_variables)]
145    #[allow(clippy::borrowed_box)]
146    fn index_op(&self, index: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
147        Err("Unsupported operator for this type".to_string())
148    }
149
150    /// Perform unary `[S:E]` operator and return new [`Value`] represent the result or Exception message as [`String`]
151    #[allow(unused_variables)]
152    #[allow(clippy::borrowed_box)]
153    fn slice_op(
154        &self,
155        start: &Option<Box<dyn Value>>,
156        end: &Option<Box<dyn Value>>,
157    ) -> Result<Box<dyn Value>, String> {
158        Err("Unsupported operator for this type".to_string())
159    }
160
161    /// Perform unary `=` operator and return new [`Value`] represent the result or Exception message as [`String`]
162    #[allow(unused_variables)]
163    #[allow(clippy::borrowed_box)]
164    fn eq_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
165        Err("Unsupported operator for this type".to_string())
166    }
167
168    /// Perform unary `= [ALL|ANY|SOME]` operator and return new [`Value`] represent the result or Exception message as [`String`]
169    #[allow(unused_variables)]
170    #[allow(clippy::borrowed_box)]
171    fn group_eq_op(
172        &self,
173        other: &Box<dyn Value>,
174        group_op: &GroupComparisonOperator,
175    ) -> Result<Box<dyn Value>, String> {
176        Err("Unsupported operator for this type".to_string())
177    }
178
179    /// Perform unary `!=` or `<>` operator and return new [`Value`] represent the result or Exception message as [`String`]
180    #[allow(unused_variables)]
181    #[allow(clippy::borrowed_box)]
182    fn bang_eq_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
183        Err("Unsupported operator for this type".to_string())
184    }
185
186    /// Perform unary `!= or <> [ALL|ANY|SOME]` operator and return new [`Value`] represent the result or Exception message as [`String`]
187    #[allow(unused_variables)]
188    #[allow(clippy::borrowed_box)]
189    fn group_bang_eq_op(
190        &self,
191        other: &Box<dyn Value>,
192        group_op: &GroupComparisonOperator,
193    ) -> Result<Box<dyn Value>, String> {
194        Err("Unsupported operator for this type".to_string())
195    }
196
197    /// Perform unary `<=>` operator and return new [`Value`] represent the result or Exception message as [`String`]
198    #[allow(unused_variables)]
199    #[allow(clippy::borrowed_box)]
200    fn null_safe_eq_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
201        Err("Unsupported operator for this type".to_string())
202    }
203
204    /// Perform unary `<=> [ALL|ANY|SOME]` operator and return new [`Value`] represent the result or Exception message as [`String`]
205    #[allow(unused_variables)]
206    #[allow(clippy::borrowed_box)]
207    fn group_null_safe_eq_op(
208        &self,
209        other: &Box<dyn Value>,
210        group_op: &GroupComparisonOperator,
211    ) -> Result<Box<dyn Value>, String> {
212        Err("Unsupported operator for this type".to_string())
213    }
214
215    /// Perform unary `>` operator and return new [`Value`] represent the result or Exception message as [`String`]
216    #[allow(unused_variables)]
217    #[allow(clippy::borrowed_box)]
218    fn gt_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
219        Err("Unsupported operator for this type".to_string())
220    }
221
222    /// Perform unary `> [ALL|ANY|SOME]` operator and return new [`Value`] represent the result or Exception message as [`String`]
223    #[allow(unused_variables)]
224    #[allow(clippy::borrowed_box)]
225    fn group_gt_op(
226        &self,
227        other: &Box<dyn Value>,
228        group_op: &GroupComparisonOperator,
229    ) -> Result<Box<dyn Value>, String> {
230        Err("Unsupported operator for this type".to_string())
231    }
232
233    /// Perform unary `>=` operator and return new [`Value`] represent the result or Exception message as [`String`]
234    #[allow(unused_variables)]
235    #[allow(clippy::borrowed_box)]
236    fn gte_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
237        Err("Unsupported operator for this type".to_string())
238    }
239
240    /// Perform unary `>= [ALL|ANY|SOME]` operator and return new [`Value`] represent the result or Exception message as [`String`]
241    #[allow(unused_variables)]
242    #[allow(clippy::borrowed_box)]
243    fn group_gte_op(
244        &self,
245        other: &Box<dyn Value>,
246        group_op: &GroupComparisonOperator,
247    ) -> Result<Box<dyn Value>, String> {
248        Err("Unsupported operator for this type".to_string())
249    }
250
251    /// Perform unary `<` operator and return new [`Value`] represent the result or Exception message as [`String`]
252    #[allow(unused_variables)]
253    #[allow(clippy::borrowed_box)]
254    fn lt_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
255        Err("Unsupported operator for this type".to_string())
256    }
257
258    /// Perform unary `< [ALL|ANY|SOME]` operator and return new [`Value`] represent the result or Exception message as [`String`]
259    #[allow(unused_variables)]
260    #[allow(clippy::borrowed_box)]
261    fn group_lt_op(
262        &self,
263        other: &Box<dyn Value>,
264        group_op: &GroupComparisonOperator,
265    ) -> Result<Box<dyn Value>, String> {
266        Err("Unsupported operator for this type".to_string())
267    }
268
269    /// Perform unary `<=` operator and return new [`Value`] represent the result or Exception message as [`String`]
270    #[allow(unused_variables)]
271    #[allow(clippy::borrowed_box)]
272    fn lte_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
273        Err("Unsupported operator for this type".to_string())
274    }
275
276    /// Perform unary `<= [ALL|ANY|SOME]` operator and return new [`Value`] represent the result or Exception message as [`String`]
277    #[allow(unused_variables)]
278    #[allow(clippy::borrowed_box)]
279    fn group_lte_op(
280        &self,
281        other: &Box<dyn Value>,
282        group_op: &GroupComparisonOperator,
283    ) -> Result<Box<dyn Value>, String> {
284        Err("Unsupported operator for this type".to_string())
285    }
286
287    /// Perform unary `NOT` operator and return new [`Value`] represent the result or Exception message as [`String`]
288    fn not_op(&self) -> Result<Box<dyn Value>, String> {
289        Err("Unsupported operator for this type".to_string())
290    }
291
292    /// Perform unary `+` operator and return new [`Value`] represent the result or Exception message as [`String`]
293    fn plus_op(&self) -> Result<Box<dyn Value>, String> {
294        Err("Unsupported operator for this type".to_string())
295    }
296
297    /// Perform unary `-` operator and return new [`Value`] represent the result or Exception message as [`String`]
298    fn neg_op(&self) -> Result<Box<dyn Value>, String> {
299        Err("Unsupported operator for this type".to_string())
300    }
301
302    /// Perform unary `!` operator and return new [`Value`] represent the result or Exception message as [`String`]
303    fn bang_op(&self) -> Result<Box<dyn Value>, String> {
304        Err("Unsupported operator for this type".to_string())
305    }
306
307    /// Perform `@>` operator and return new [`Value`] represent the result or Exception message as [`String`]
308    #[allow(unused_variables)]
309    #[allow(clippy::borrowed_box)]
310    fn contains_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
311        Err("Unsupported operator for this type".to_string())
312    }
313
314    /// Perform `LIKE` operator and return new [`Value`] represent the result or Exception message as [`String`]
315    #[allow(unused_variables)]
316    #[allow(clippy::borrowed_box)]
317    fn like_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
318        Err("Unsupported operator for this type".to_string())
319    }
320
321    /// Perform `GLOB` operator and return new [`Value`] represent the result or Exception message as [`String`]
322    #[allow(unused_variables)]
323    #[allow(clippy::borrowed_box)]
324    fn glob_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
325        Err("Unsupported operator for this type".to_string())
326    }
327
328    /// Perform `REGEXP` operator and return new [`Value`] represent the result or Exception message as [`String`]
329    #[allow(unused_variables)]
330    #[allow(clippy::borrowed_box)]
331    fn regexp_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
332        Err("Unsupported operator for this type".to_string())
333    }
334
335    /// Perform Cast operator and return new [`Value`] represent the result or Exception message as [`String`]
336    #[allow(unused_variables)]
337    #[allow(clippy::borrowed_box)]
338    fn cast_op(&self, target_type: &Box<dyn DataType>) -> Result<Box<dyn Value>, String> {
339        Err("Unsupported operator for this type".to_string())
340    }
341}
342
343impl dyn Value {
344    /// Return true if this value is [`TextValue`]
345    pub fn is_text(&self) -> bool {
346        self.as_any().downcast_ref::<TextValue>().is_some()
347    }
348
349    /// Return List of [`String`] represent the inner value of [`IntValue`]
350    /// or None if this type it's called from wrong [`Value`]
351    pub fn as_text(&self) -> Option<String> {
352        if let Some(text_value) = self.as_any().downcast_ref::<TextValue>() {
353            return Some(text_value.value.to_string());
354        }
355        None
356    }
357
358    /// Return true if this value is [`IntValue`]
359    pub fn is_int(&self) -> bool {
360        self.as_any().downcast_ref::<IntValue>().is_some()
361    }
362
363    /// Return List of [`i64`] represent the inner value of [`IntValue`]
364    /// or None if this type it's called from wrong [`Value`]
365    pub fn as_int(&self) -> Option<i64> {
366        if let Some(int_value) = self.as_any().downcast_ref::<IntValue>() {
367            return Some(int_value.value);
368        }
369        None
370    }
371
372    /// Return true if this value is [`FloatValue`]
373    pub fn is_float(&self) -> bool {
374        self.as_any().downcast_ref::<FloatValue>().is_some()
375    }
376
377    /// Return List of [`f64`] represent the inner value of [`FloatValue`]
378    /// or None if this type it's called from wrong [`Value`]
379    pub fn as_float(&self) -> Option<f64> {
380        if let Some(float_value) = self.as_any().downcast_ref::<FloatValue>() {
381            return Some(float_value.value);
382        }
383        None
384    }
385
386    /// Return true if this value is [`IntValue`] or [`FloatValue`]
387    pub fn is_number(&self) -> bool {
388        self.is_int() || self.is_float()
389    }
390
391    /// Return true if this value is [`BoolValue`]
392    pub fn is_bool(&self) -> bool {
393        self.as_any().downcast_ref::<BoolValue>().is_some()
394    }
395
396    /// Return List of [`bool`] represent the inner value of [`BoolValue`]
397    /// or None if this type it's called from wrong [`Value`]
398    pub fn as_bool(&self) -> Option<bool> {
399        if let Some(bool_value) = self.as_any().downcast_ref::<BoolValue>() {
400            return Some(bool_value.value);
401        }
402        None
403    }
404
405    /// Return true if this value is [`DateValue`]
406    pub fn is_date(&self) -> bool {
407        self.as_any().downcast_ref::<DateValue>().is_some()
408    }
409
410    /// Return List of [`i64`] represent the inner value of [`DateValue`]
411    /// or None if this type it's called from wrong [`Value`]
412    pub fn as_date(&self) -> Option<i64> {
413        if let Some(date_value) = self.as_any().downcast_ref::<DateValue>() {
414            return Some(date_value.timestamp);
415        }
416        None
417    }
418
419    /// Return true if this value is [`TimeValue`]
420    pub fn is_time(&self) -> bool {
421        self.as_any().downcast_ref::<TimeValue>().is_some()
422    }
423
424    /// Return List of [`String`] represent the inner value of [`DateValue`]
425    /// or None if this type it's called from wrong [`Value`]
426    pub fn as_time(&self) -> Option<String> {
427        if let Some(time_value) = self.as_any().downcast_ref::<DateValue>() {
428            return Some(time_value.timestamp.to_string());
429        }
430        None
431    }
432
433    /// Return true if this value is [`DateTimeValue`]
434    pub fn is_date_time(&self) -> bool {
435        self.as_any().downcast_ref::<DateTimeValue>().is_some()
436    }
437
438    /// Return List of [`i64`] represent the value of [`DateTimeValue`]
439    /// or None if this type it's called from wrong [`Value`]
440    pub fn as_date_time(&self) -> Option<i64> {
441        if let Some(date_time_value) = self.as_any().downcast_ref::<DateTimeValue>() {
442            return Some(date_time_value.value);
443        }
444        None
445    }
446
447    /// Return true if this value is [`IntervalValue`]
448    pub fn is_interval(&self) -> bool {
449        self.as_any().downcast_ref::<IntervalValue>().is_some()
450    }
451
452    /// Return List of [`Interval`] represent the value of [`IntervalValue`]
453    /// or None if this type it's called from wrong [`Value`]
454    pub fn as_interval(&self) -> Option<Interval> {
455        if let Some(interval_value) = self.as_any().downcast_ref::<IntervalValue>() {
456            return Some(interval_value.interval.clone());
457        }
458        None
459    }
460
461    /// Return true if this value is [`ArrayValue`]
462    pub fn is_array(&self) -> bool {
463        self.as_any().downcast_ref::<ArrayValue>().is_some()
464    }
465
466    /// Return true if this value is [`ArrayValue`] and element type match condition
467    pub fn is_array_of(&self, condition: fn(&Box<dyn DataType>) -> bool) -> bool {
468        if let Some(array) = self.as_any().downcast_ref::<ArrayValue>() {
469            return condition(&array.base_type);
470        }
471        false
472    }
473
474    /// Return List of [`Value`] represent the inner values of [`ArrayValue`]
475    /// or None if this type it's called from wrong [`Value`]
476    pub fn as_array(&self) -> Option<Vec<Box<dyn Value>>> {
477        if let Some(array_value) = self.as_any().downcast_ref::<ArrayValue>() {
478            return Some(array_value.values.clone());
479        }
480        None
481    }
482
483    /// Return true if this value is [`RangeValue`]
484    pub fn is_range(&self) -> bool {
485        self.as_any().downcast_ref::<RangeValue>().is_some()
486    }
487
488    /// Return Tuple of two [`Value`] represent the start and the end of [`RangeValue`]
489    /// or None if this type it's called from wrong [`Value`]
490    pub fn as_range(&self) -> Option<(Box<dyn Value>, Box<dyn Value>)> {
491        if let Some(range_value) = self.as_any().downcast_ref::<RangeValue>() {
492            return Some((range_value.lower.clone(), range_value.upper.clone()));
493        }
494        None
495    }
496
497    /// Return true if this value is [`NullValue`]
498    pub fn is_null(&self) -> bool {
499        self.as_any().downcast_ref::<NullValue>().is_some()
500    }
501
502    /// Return true if this value is [`CompositeValue`]
503    pub fn is_composite(&self) -> bool {
504        self.as_any().downcast_ref::<CompositeValue>().is_some()
505    }
506}
507
508impl fmt::Display for Box<dyn Value> {
509    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
510        write!(f, "{}", self.literal())
511    }
512}
513
514impl PartialEq for Box<dyn Value> {
515    fn eq(&self, other: &Self) -> bool {
516        self.equals(other)
517    }
518}
519
520impl PartialOrd for Box<dyn Value> {
521    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
522        self.compare(other)
523    }
524}