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_neg_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 neg_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_bang_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 bang_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 ///
445 /// No need to define the result type, it always BoolType
446 fn can_perform_contains_op_with(&self) -> Vec<Box<dyn DataType>> {
447 vec![]
448 }
449
450 /// Return true if this Expression can be casted to the current type without any evaluation
451 ///
452 /// For example casting Text with specific format to Date or Time
453 ///
454 /// The result type is equal to the current type
455 #[allow(unused_variables)]
456 #[allow(clippy::borrowed_box)]
457 fn has_implicit_cast_from(&self, expr: &Box<dyn Expr>) -> bool {
458 false
459 }
460
461 /// Return a list of types that it's possible to perform `Cast' operator to
462 ///
463 /// For example casting column with float value to integer or verse versa
464 ///
465 /// The result type is equal to the current type
466 fn can_perform_explicit_cast_op_to(&self) -> Vec<Box<dyn DataType>> {
467 vec![]
468 }
469
470 /// Return a list of types that it's possible to perform unary `LIKE' operator with
471 /// between current DataType and any one of them
472 ///
473 /// No need to define the result type, it always BoolType
474 fn can_perform_like_op_with(&self) -> Vec<Box<dyn DataType>> {
475 vec![]
476 }
477
478 /// Return a list of types that it's possible to perform unary `GLOB' operator with
479 /// between current DataType and any one of them
480 ///
481 /// No need to define the result type, it always BoolType
482 fn can_perform_glob_op_with(&self) -> Vec<Box<dyn DataType>> {
483 vec![]
484 }
485
486 /// Return a list of types that it's possible to perform unary `REGEXP' operator with
487 /// between current DataType and any one of them
488 ///
489 /// No need to define the result type, it always BoolType
490 fn can_perform_regexp_op_with(&self) -> Vec<Box<dyn DataType>> {
491 vec![]
492 }
493}
494
495impl dyn DataType {
496 /// Return true if this type is [`AnyType`]
497 pub fn is_any(&self) -> bool {
498 self.as_any().downcast_ref::<AnyType>().is_some()
499 }
500
501 /// Return true if this type is [`TextType`]
502 pub fn is_text(&self) -> bool {
503 self.as_any().downcast_ref::<TextType>().is_some()
504 }
505
506 /// Return true if this type is [`IntType`]
507 pub fn is_int(&self) -> bool {
508 self.as_any().downcast_ref::<IntType>().is_some()
509 }
510
511 /// Return true if this type is [`FloatType`]
512 pub fn is_float(&self) -> bool {
513 self.as_any().downcast_ref::<FloatType>().is_some()
514 }
515
516 /// Return true if this type is [`IntType`] or [`FloatType`]
517 pub fn is_number(&self) -> bool {
518 self.is_int() || self.is_float()
519 }
520
521 /// Return true if this type is [`BoolType`]
522 pub fn is_bool(&self) -> bool {
523 self.as_any().downcast_ref::<BoolType>().is_some()
524 }
525
526 /// Return true if this type is [`DateType`]
527 pub fn is_date(&self) -> bool {
528 self.as_any().downcast_ref::<DateType>().is_some()
529 }
530
531 /// Return true if this type is [`TimeType`]
532 pub fn is_time(&self) -> bool {
533 self.as_any().downcast_ref::<TimeType>().is_some()
534 }
535
536 /// Return true if this type is [`DateTimeType`]
537 pub fn is_date_time(&self) -> bool {
538 self.as_any().downcast_ref::<DateTimeType>().is_some()
539 }
540
541 /// Return true if this type is [`IntervalType`]
542 pub fn is_interval(&self) -> bool {
543 self.as_any().downcast_ref::<IntervalType>().is_some()
544 }
545
546 /// Return true if this type is [`ArrayType`]
547 pub fn is_array(&self) -> bool {
548 self.as_any().downcast_ref::<ArrayType>().is_some()
549 }
550
551 /// Return true if this type is [`RangeType`]
552 pub fn is_range(&self) -> bool {
553 self.as_any().downcast_ref::<RangeType>().is_some()
554 }
555
556 /// Return true if this type is [`VariantType`]
557 pub fn is_variant(&self) -> bool {
558 self.as_any().downcast_ref::<VariantType>().is_some()
559 }
560
561 /// Return true if this type is [`VariantType`]
562 /// and applying the matcher function is return true on one of the variants
563 pub fn is_variant_with(&self, matcher: fn(&Box<dyn DataType>) -> bool) -> bool {
564 if let Some(variant_type) = self.as_any().downcast_ref::<VariantType>() {
565 for variant in variant_type.variants.iter() {
566 if matcher(variant) {
567 return true;
568 }
569 }
570 }
571 false
572 }
573
574 /// Return true if this type is [`VariantType`] and contain specific type as one of it variants
575 #[allow(clippy::borrowed_box)]
576 pub fn is_variant_contains(&self, other: &Box<dyn DataType>) -> bool {
577 if let Some(variant_type) = self.as_any().downcast_ref::<VariantType>() {
578 return variant_type.variants.contains(other);
579 }
580 false
581 }
582
583 /// Return true if this type is [`OptionType`]
584 pub fn is_optional(&self) -> bool {
585 self.as_any().downcast_ref::<OptionType>().is_some()
586 }
587
588 /// Return true if this type is [`VarargsType`]
589 pub fn is_varargs(&self) -> bool {
590 self.as_any().downcast_ref::<VarargsType>().is_some()
591 }
592
593 /// Return true if this type is [`RowType`]
594 pub fn is_row(&self) -> bool {
595 self.as_any().downcast_ref::<RowType>().is_some()
596 }
597
598 /// Return true if this type is [`CompositeType`]
599 pub fn is_composite(&self) -> bool {
600 self.as_any().downcast_ref::<CompositeType>().is_some()
601 }
602
603 /// Return true if this type is [`UndefType`]
604 pub fn is_undefined(&self) -> bool {
605 self.as_any().downcast_ref::<UndefType>().is_some()
606 }
607
608 /// Return true if this type is [`NullType`]
609 pub fn is_null(&self) -> bool {
610 self.as_any().downcast_ref::<NullType>().is_some()
611 }
612}
613
614impl fmt::Display for Box<dyn DataType> {
615 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
616 write!(f, "{}", self.literal())
617 }
618}
619
620impl PartialEq for Box<dyn DataType> {
621 fn eq(&self, other: &Self) -> bool {
622 self.equals(other)
623 }
624}