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