gitql_ast/types/
base.rs

1use std::any::Any;
2use std::fmt;
3
4use dyn_clone::DynClone;
5
6use crate::expression::Expr;
7use crate::types::row::RowType;
8
9use super::any::AnyType;
10use super::array::ArrayType;
11use super::boolean::BoolType;
12use super::composite::CompositeType;
13use super::date::DateType;
14use super::datetime::DateTimeType;
15use super::float::FloatType;
16use super::integer::IntType;
17use super::interval::IntervalType;
18use super::null::NullType;
19use super::optional::OptionType;
20use super::range::RangeType;
21use super::text::TextType;
22use super::time::TimeType;
23use super::undefined::UndefType;
24use super::varargs::VarargsType;
25use super::variant::VariantType;
26
27dyn_clone::clone_trait_object!(DataType);
28
29/// The in memory representation of the Data type in the GitQL query engine
30pub trait DataType: DynClone {
31    /// Return the literal representation for this [`DataType`]
32    fn literal(&self) -> String;
33
34    /// Return if other [`DataType`] is equal or not to current Type
35    #[allow(unused_variables)]
36    #[allow(clippy::borrowed_box)]
37    fn equals(&self, other: &Box<dyn DataType>) -> bool {
38        false
39    }
40
41    /// Return the current value as dynamic [`Any`]
42    fn as_any(&self) -> &dyn Any;
43
44    /// Return a list of types that it's possible to perform `+` operator with
45    /// between current DataType and any one of them
46    fn can_perform_add_op_with(&self) -> Vec<Box<dyn DataType>> {
47        vec![]
48    }
49
50    /// Return the expected type after perform `=` operator between current type and argument type
51    ///
52    /// Note that you don't need to check again that the argument type is possible to perform operator with
53    #[allow(unused_variables)]
54    #[allow(clippy::borrowed_box)]
55    fn add_op_result_type(&self, other: &Box<dyn DataType>) -> Box<dyn DataType> {
56        Box::new(NullType)
57    }
58
59    /// Return a list of types that it's possible to perform `-` operator with
60    /// between current DataType and any one of them
61    #[allow(unused_variables)]
62    #[allow(clippy::borrowed_box)]
63    fn can_perform_sub_op_with(&self) -> Vec<Box<dyn DataType>> {
64        vec![]
65    }
66
67    /// Return the expected type after perform `-` operator between current type and argument type
68    ///
69    /// Note that you don't need to check again that the argument type is possible to perform operator with
70    #[allow(unused_variables)]
71    #[allow(clippy::borrowed_box)]
72    fn sub_op_result_type(&self, other: &Box<dyn DataType>) -> Box<dyn DataType> {
73        Box::new(NullType)
74    }
75
76    /// Return a list of types that it's possible to perform `*` operator with
77    /// between current DataType and any one of them
78    fn can_perform_mul_op_with(&self) -> Vec<Box<dyn DataType>> {
79        vec![]
80    }
81
82    /// Return the expected type after perform `*` operator between current type and argument type
83    ///
84    /// Note that you don't need to check again that the argument type is possible to perform operator with
85    #[allow(unused_variables)]
86    #[allow(clippy::borrowed_box)]
87    fn mul_op_result_type(&self, other: &Box<dyn DataType>) -> Box<dyn DataType> {
88        Box::new(NullType)
89    }
90
91    /// Return a list of types that it's possible to perform `/` operator with
92    /// between current DataType and any one of them
93    fn can_perform_div_op_with(&self) -> Vec<Box<dyn DataType>> {
94        vec![]
95    }
96
97    /// Return the expected type after perform `/` operator between current type and argument type
98    ///
99    /// Note that you don't need to check again that the argument type is possible to perform operator with
100    #[allow(unused_variables)]
101    #[allow(clippy::borrowed_box)]
102    fn div_op_result_type(&self, other: &Box<dyn DataType>) -> Box<dyn DataType> {
103        Box::new(NullType)
104    }
105
106    /// Return a list of types that it's possible to perform `%` operator with
107    /// between current DataType and any one of them
108    fn can_perform_rem_op_with(&self) -> Vec<Box<dyn DataType>> {
109        vec![]
110    }
111
112    /// Return the expected type after perform `&` operator between current type and argument type
113    ///
114    /// Note that you don't need to check again that the argument type is possible to perform operator with
115    #[allow(unused_variables)]
116    #[allow(clippy::borrowed_box)]
117    fn rem_op_result_type(&self, other: &Box<dyn DataType>) -> Box<dyn DataType> {
118        Box::new(NullType)
119    }
120
121    /// Return a list of types that it's possible to perform `^` operator with
122    /// between current DataType and any one of them
123    fn can_perform_caret_op_with(&self) -> Vec<Box<dyn DataType>> {
124        vec![]
125    }
126
127    /// Return the expected type after perform `^` operator between current type and argument type
128    ///
129    /// Note that you don't need to check again that the argument type is possible to perform operator with
130    #[allow(unused_variables)]
131    #[allow(clippy::borrowed_box)]
132    fn caret_op_result_type(&self, other: &Box<dyn DataType>) -> Box<dyn DataType> {
133        Box::new(NullType)
134    }
135
136    /// Return a list of types that it's possible to perform `|` operator with
137    /// between current DataType and any one of them
138    fn can_perform_or_op_with(&self) -> Vec<Box<dyn DataType>> {
139        vec![]
140    }
141
142    /// Return the expected type after perform `|` operator between current type and argument type
143    ///
144    /// Note that you don't need to check again that the argument type is possible to perform operator with
145    #[allow(unused_variables)]
146    #[allow(clippy::borrowed_box)]
147    fn or_op_result_type(&self, other: &Box<dyn DataType>) -> Box<dyn DataType> {
148        Box::new(NullType)
149    }
150
151    /// Return a list of types that it's possible to perform `&` operator with
152    /// between current DataType and any one of them
153    fn can_perform_and_op_with(&self) -> Vec<Box<dyn DataType>> {
154        vec![]
155    }
156
157    /// Return the expected type after perform `&` operator between current type and argument type
158    ///
159    /// Note that you don't need to check again that the argument type is possible to perform operator with
160    #[allow(unused_variables)]
161    #[allow(clippy::borrowed_box)]
162    fn and_op_result_type(&self, other: &Box<dyn DataType>) -> Box<dyn DataType> {
163        Box::new(NullType)
164    }
165
166    /// Return a list of types that it's possible to perform `#` operator with
167    /// between current DataType and any one of them
168    fn can_perform_xor_op_with(&self) -> Vec<Box<dyn DataType>> {
169        vec![]
170    }
171
172    /// Return the expected type after perform `#` operator between current type and argument type
173    ///
174    /// Note that you don't need to check again that the argument type is possible to perform operator with
175    #[allow(unused_variables)]
176    #[allow(clippy::borrowed_box)]
177    fn xor_op_result_type(&self, other: &Box<dyn DataType>) -> Box<dyn DataType> {
178        Box::new(NullType)
179    }
180
181    /// Return a list of types that it's possible to perform `<<` operator with
182    /// between current DataType and any one of them
183    fn can_perform_shl_op_with(&self) -> Vec<Box<dyn DataType>> {
184        vec![]
185    }
186
187    /// Return the expected type after perform `<<` operator between current type and argument type
188    ///
189    /// Note that you don't need to check again that the argument type is possible to perform operator with
190    #[allow(unused_variables)]
191    #[allow(clippy::borrowed_box)]
192    fn shl_op_result_type(&self, other: &Box<dyn DataType>) -> Box<dyn DataType> {
193        Box::new(NullType)
194    }
195
196    /// Return a list of types that it's possible to perform `>>` operator with
197    /// between current DataType and any one of them
198    fn can_perform_shr_op_with(&self) -> Vec<Box<dyn DataType>> {
199        vec![]
200    }
201
202    /// Return the expected type after perform `>>` operator between current type and argument type
203    ///
204    /// Note that you don't need to check again that the argument type is possible to perform operator with
205    #[allow(unused_variables)]
206    #[allow(clippy::borrowed_box)]
207    fn shr_op_result_type(&self, other: &Box<dyn DataType>) -> Box<dyn DataType> {
208        Box::new(NullType)
209    }
210
211    /// Return a list of types that it's possible to perform `||` or  `OR` operator with
212    /// between current DataType and any one of them
213    fn can_perform_logical_or_op_with(&self) -> Vec<Box<dyn DataType>> {
214        vec![]
215    }
216
217    /// Return the expected type after perform `||` or `OR` operator between current type and argument type
218    ///
219    /// Note that you don't need to check again that the argument type is possible to perform operator with
220    #[allow(unused_variables)]
221    #[allow(clippy::borrowed_box)]
222    fn logical_or_op_result_type(&self, other: &Box<dyn DataType>) -> Box<dyn DataType> {
223        Box::new(NullType)
224    }
225
226    /// Return a list of types that it's possible to perform `&&` or `AND` operator with
227    /// between current DataType and any one of them
228    fn can_perform_logical_and_op_with(&self) -> Vec<Box<dyn DataType>> {
229        vec![]
230    }
231
232    /// Return the expected type after perform `&&` or `AND` operator between current type and argument type
233    ///
234    /// Note that you don't need to check again that the argument type is possible to perform operator with
235    #[allow(unused_variables)]
236    #[allow(clippy::borrowed_box)]
237    fn logical_and_op_result_type(&self, other: &Box<dyn DataType>) -> Box<dyn DataType> {
238        Box::new(NullType)
239    }
240
241    /// Return a list of types that it's possible to perform `XOR' operator with
242    /// between current DataType and any one of them
243    fn can_perform_logical_xor_op_with(&self) -> Vec<Box<dyn DataType>> {
244        vec![]
245    }
246
247    /// Return the expected type after perform 'XOR' operator between current type and argument type
248    ///
249    /// Note that you don't need to check again that the argument type is possible to perform operator with
250    #[allow(unused_variables)]
251    #[allow(clippy::borrowed_box)]
252    fn logical_xor_op_result_type(&self, other: &Box<dyn DataType>) -> Box<dyn DataType> {
253        Box::new(NullType)
254    }
255
256    /// Return a list of types that it's possible to perform `[I]' operator with
257    /// between current DataType and any one of them
258    fn can_perform_index_op_with(&self) -> Vec<Box<dyn DataType>> {
259        vec![]
260    }
261
262    /// Return the expected type after perform '[]' operator on current type
263    ///
264    /// * `other` - The index type
265    ///
266    /// Note that you don't need to check again that the argument type is possible to perform operator with
267    #[allow(unused_variables)]
268    #[allow(clippy::borrowed_box)]
269    fn index_op_result_type(&self, other: &Box<dyn DataType>) -> Box<dyn DataType> {
270        Box::new(NullType)
271    }
272
273    /// Return true if this type support Slice operator with
274    fn can_perform_slice_op(&self) -> bool {
275        false
276    }
277
278    /// Return a list of types that it's possible to perform `[S : E]' operator with
279    /// between current DataType and any one of them
280    fn can_perform_slice_op_with(&self) -> Vec<Box<dyn DataType>> {
281        vec![]
282    }
283
284    /// Return a list of types that it's possible to perform `=' operator with
285    /// between current DataType and any one of them
286    ///
287    /// No need to define the result type, it always BoolType
288    fn can_perform_eq_op_with(&self) -> Vec<Box<dyn DataType>> {
289        vec![]
290    }
291
292    /// Return a list of types that it's possible to perform `= [ALL|ANY|SOME]' operator with
293    /// between current DataType and any one of them
294    ///
295    /// No need to define the result type, it always BoolType
296    #[allow(unused_variables)]
297    fn can_perform_group_eq_op_with(&self) -> Vec<Box<dyn DataType>> {
298        vec![]
299    }
300
301    /// Return a list of types that it's possible to perform `!=' or `<>` operator with
302    /// between current DataType and any one of them
303    ///
304    /// No need to define the result type, it always BoolType
305    fn can_perform_bang_eq_op_with(&self) -> Vec<Box<dyn DataType>> {
306        vec![]
307    }
308
309    /// Return a list of types that it's possible to perform `!= [ALL|ANY|SOME]' operator with
310    /// between current DataType and any one of them
311    ///
312    /// No need to define the result type, it always BoolType
313    #[allow(unused_variables)]
314    fn can_perform_group_bang_eq_op_with(&self) -> Vec<Box<dyn DataType>> {
315        vec![]
316    }
317
318    /// Return a list of types that it's possible to perform `<=>' operator with
319    /// between current DataType and any one of them
320    ///
321    /// No need to define the result type, it always IntType
322    fn can_perform_null_safe_eq_op_with(&self) -> Vec<Box<dyn DataType>> {
323        vec![]
324    }
325
326    /// Return a list of types that it's possible to perform `<=> [ALL|ANY|SOME]' operator with
327    /// between current DataType and any one of them
328    ///
329    /// No need to define the result type, it always IntType
330    #[allow(unused_variables)]
331    fn can_perform_group_null_safe_eq_op_with(&self) -> Vec<Box<dyn DataType>> {
332        vec![]
333    }
334
335    /// Return a list of types that it's possible to perform `>' operator with
336    /// between current DataType and any one of them
337    ///
338    /// No need to define the result type, it always BoolType
339    fn can_perform_gt_op_with(&self) -> Vec<Box<dyn DataType>> {
340        vec![]
341    }
342
343    /// Return a list of types that it's possible to perform `> [ALL|ANY|SOME]' operator with
344    /// between current DataType and any one of them
345    ///
346    /// No need to define the result type, it always BoolType
347    #[allow(unused_variables)]
348    fn can_perform_group_gt_op_with(&self) -> Vec<Box<dyn DataType>> {
349        vec![]
350    }
351
352    /// Return a list of types that it's possible to perform `>=' operator with
353    /// between current DataType and any one of them
354    ///
355    /// No need to define the result type, it always BoolType
356    fn can_perform_gte_op_with(&self) -> Vec<Box<dyn DataType>> {
357        vec![]
358    }
359
360    /// Return a list of types that it's possible to perform `>= [ALL|ANY|SOME]' operator with
361    /// between current DataType and any one of them
362    ///
363    /// No need to define the result type, it always BoolType
364    #[allow(unused_variables)]
365    fn can_perform_group_gte_op_with(&self) -> Vec<Box<dyn DataType>> {
366        vec![]
367    }
368
369    /// Return a list of types that it's possible to perform `<' operator with
370    /// between current DataType and any one of them
371    ///
372    /// No need to define the result type, it always BoolType
373    fn can_perform_lt_op_with(&self) -> Vec<Box<dyn DataType>> {
374        vec![]
375    }
376
377    /// Return a list of types that it's possible to perform `< [ALL|ANY|SOME]' operator with
378    /// between current DataType and any one of them
379    ///
380    /// No need to define the result type, it always BoolType
381    #[allow(unused_variables)]
382    fn can_perform_group_lt_op_with(&self) -> Vec<Box<dyn DataType>> {
383        vec![]
384    }
385
386    /// Return a list of types that it's possible to perform `=<' operator with
387    /// between current DataType and any one of them
388    ///
389    /// No need to define the result type, it always BoolType
390    fn can_perform_lte_op_with(&self) -> Vec<Box<dyn DataType>> {
391        vec![]
392    }
393
394    /// Return a list of types that it's possible to perform `<= [ALL|ANY|SOME]' operator with
395    /// between current DataType and any one of them
396    ///
397    /// No need to define the result type, it always BoolType
398    #[allow(unused_variables)]
399    fn can_perform_group_lte_op_with(&self) -> Vec<Box<dyn DataType>> {
400        vec![]
401    }
402
403    /// Return a list of types that it's possible to perform unary `NOT' operator with
404    /// between current DataType and any one of them
405    fn can_perform_not_op(&self) -> bool {
406        false
407    }
408
409    /// Return the expected type after perform unary `NOT' operator on current type
410    ///
411    /// Note that you don't need to check again that the argument type is possible to perform operator with
412    fn not_op_result_type(&self) -> Box<dyn DataType> {
413        Box::new(NullType)
414    }
415
416    /// Return a list of types that it's possible to perform unary `+' operator with
417    /// between current DataType and any one of them
418    fn can_perform_plus_op(&self) -> bool {
419        false
420    }
421
422    /// Return the expected type after perform unary `+' operator on current type
423    ///
424    /// Note that you don't need to check again that the argument type is possible to perform operator with
425    fn plus_op_result_type(&self) -> Box<dyn DataType> {
426        Box::new(NullType)
427    }
428
429    /// Return a list of types that it's possible to perform unary `-' operator with
430    /// between current DataType and any one of them
431    fn can_perform_neg_op(&self) -> bool {
432        false
433    }
434
435    /// Return the expected type after perform unary `-' operator on current type
436    ///
437    /// Note that you don't need to check again that the argument type is possible to perform operator with
438    fn neg_op_result_type(&self) -> Box<dyn DataType> {
439        Box::new(NullType)
440    }
441
442    /// Return a list of types that it's possible to perform unary `!' operator with
443    /// between current DataType and any one of them
444    fn can_perform_bang_op(&self) -> bool {
445        false
446    }
447
448    /// Return the expected type after perform unary `!' operator on current type
449    ///
450    /// Note that you don't need to check again that the argument type is possible to perform operator with
451    fn bang_op_result_type(&self) -> Box<dyn DataType> {
452        Box::new(NullType)
453    }
454
455    /// Return a list of types that it's possible to perform unary `@>' operator with
456    /// between current DataType and any one of them
457    ///
458    /// No need to define the result type, it always BoolType
459    fn can_perform_contains_op_with(&self) -> Vec<Box<dyn DataType>> {
460        vec![]
461    }
462
463    /// Return true if this Expression can be casted to the current type without any evaluation
464    ///
465    /// For example casting Text with specific format to Date or Time
466    ///
467    /// The result type is equal to the current type
468    #[allow(unused_variables)]
469    #[allow(clippy::borrowed_box)]
470    fn has_implicit_cast_from(&self, expr: &Box<dyn Expr>) -> bool {
471        false
472    }
473
474    /// Return a list of types that it's possible to perform `Cast' operator to
475    ///
476    /// For example casting column with float value to integer or verse versa
477    ///
478    /// The result type is equal to the current type
479    fn can_perform_explicit_cast_op_to(&self) -> Vec<Box<dyn DataType>> {
480        vec![]
481    }
482
483    /// Return a list of types that it's possible to perform unary `LIKE' operator with
484    /// between current DataType and any one of them
485    ///
486    /// No need to define the result type, it always BoolType
487    fn can_perform_like_op_with(&self) -> Vec<Box<dyn DataType>> {
488        vec![]
489    }
490
491    /// Return a list of types that it's possible to perform unary `GLOB' operator with
492    /// between current DataType and any one of them
493    ///
494    /// No need to define the result type, it always BoolType
495    fn can_perform_glob_op_with(&self) -> Vec<Box<dyn DataType>> {
496        vec![]
497    }
498
499    /// Return a list of types that it's possible to perform unary `REGEXP' operator with
500    /// between current DataType and any one of them
501    ///
502    /// No need to define the result type, it always BoolType
503    fn can_perform_regexp_op_with(&self) -> Vec<Box<dyn DataType>> {
504        vec![]
505    }
506}
507
508impl dyn DataType {
509    /// Return true if this type is [`AnyType`]
510    pub fn is_any(&self) -> bool {
511        self.as_any().downcast_ref::<AnyType>().is_some()
512    }
513
514    /// Return true if this type is [`TextType`]
515    pub fn is_text(&self) -> bool {
516        self.as_any().downcast_ref::<TextType>().is_some()
517    }
518
519    /// Return true if this type is [`IntType`]
520    pub fn is_int(&self) -> bool {
521        self.as_any().downcast_ref::<IntType>().is_some()
522    }
523
524    /// Return true if this type is [`FloatType`]
525    pub fn is_float(&self) -> bool {
526        self.as_any().downcast_ref::<FloatType>().is_some()
527    }
528
529    /// Return true if this type is [`IntType`] or [`FloatType`]
530    pub fn is_number(&self) -> bool {
531        self.is_int() || self.is_float()
532    }
533
534    /// Return true if this type is [`BoolType`]
535    pub fn is_bool(&self) -> bool {
536        self.as_any().downcast_ref::<BoolType>().is_some()
537    }
538
539    /// Return true if this type is [`DateType`]
540    pub fn is_date(&self) -> bool {
541        self.as_any().downcast_ref::<DateType>().is_some()
542    }
543
544    /// Return true if this type is [`TimeType`]
545    pub fn is_time(&self) -> bool {
546        self.as_any().downcast_ref::<TimeType>().is_some()
547    }
548
549    /// Return true if this type is [`DateTimeType`]
550    pub fn is_date_time(&self) -> bool {
551        self.as_any().downcast_ref::<DateTimeType>().is_some()
552    }
553
554    /// Return true if this type is [`IntervalType`]
555    pub fn is_interval(&self) -> bool {
556        self.as_any().downcast_ref::<IntervalType>().is_some()
557    }
558
559    /// Return true if this type is [`ArrayType`]
560    pub fn is_array(&self) -> bool {
561        self.as_any().downcast_ref::<ArrayType>().is_some()
562    }
563
564    /// Return true if this type is [`RangeType`]
565    pub fn is_range(&self) -> bool {
566        self.as_any().downcast_ref::<RangeType>().is_some()
567    }
568
569    /// Return true if this type is [`VariantType`]
570    pub fn is_variant(&self) -> bool {
571        self.as_any().downcast_ref::<VariantType>().is_some()
572    }
573
574    /// Return true if this type is [`VariantType`]
575    /// and applying the matcher function is return true on one of the variants
576    pub fn is_variant_with(&self, matcher: fn(&Box<dyn DataType>) -> bool) -> bool {
577        if let Some(variant_type) = self.as_any().downcast_ref::<VariantType>() {
578            for variant in variant_type.variants.iter() {
579                if matcher(variant) {
580                    return true;
581                }
582            }
583        }
584        false
585    }
586
587    /// Return true if this type is [`VariantType`] and contain specific type as one of it variants
588    #[allow(clippy::borrowed_box)]
589    pub fn is_variant_contains(&self, other: &Box<dyn DataType>) -> bool {
590        if let Some(variant_type) = self.as_any().downcast_ref::<VariantType>() {
591            return variant_type.variants.contains(other);
592        }
593        false
594    }
595
596    /// Return true if this type is [`OptionType`]
597    pub fn is_optional(&self) -> bool {
598        self.as_any().downcast_ref::<OptionType>().is_some()
599    }
600
601    /// Return true if this type is [`VarargsType`]
602    pub fn is_varargs(&self) -> bool {
603        self.as_any().downcast_ref::<VarargsType>().is_some()
604    }
605
606    /// Return true if this type is [`RowType`]
607    pub fn is_row(&self) -> bool {
608        self.as_any().downcast_ref::<RowType>().is_some()
609    }
610
611    /// Return true if this type is [`CompositeType`]
612    pub fn is_composite(&self) -> bool {
613        self.as_any().downcast_ref::<CompositeType>().is_some()
614    }
615
616    /// Return true if this type is [`UndefType`]
617    pub fn is_undefined(&self) -> bool {
618        self.as_any().downcast_ref::<UndefType>().is_some()
619    }
620
621    /// Return true if this type is [`NullType`]
622    pub fn is_null(&self) -> bool {
623        self.as_any().downcast_ref::<NullType>().is_some()
624    }
625}
626
627impl fmt::Display for Box<dyn DataType> {
628    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
629        write!(f, "{}", self.literal())
630    }
631}
632
633impl PartialEq for Box<dyn DataType> {
634    fn eq(&self, other: &Self) -> bool {
635        self.equals(other)
636    }
637}