1use {
2 super::QueryPlan,
3 crate::{
4 ast::{
5 self, BinaryOperator, DataType, DateTimeField, Literal, TrimWhereField, UnaryOperator,
6 },
7 data::Value,
8 },
9 serde::{Deserialize, Serialize},
10 strum_macros::Display,
11};
12
13#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
14pub enum ExprPlan {
15 Identifier(String),
16 CompoundIdentifier {
17 alias: String,
18 ident: String,
19 },
20 IsNull(Box<ExprPlan>),
21 IsNotNull(Box<ExprPlan>),
22 InList {
23 expr: Box<ExprPlan>,
24 list: Vec<ExprPlan>,
25 negated: bool,
26 },
27 InSubquery {
28 expr: Box<ExprPlan>,
29 subquery: Box<QueryPlan>,
30 negated: bool,
31 },
32 Between {
33 expr: Box<ExprPlan>,
34 negated: bool,
35 low: Box<ExprPlan>,
36 high: Box<ExprPlan>,
37 },
38 Like {
39 expr: Box<ExprPlan>,
40 negated: bool,
41 pattern: Box<ExprPlan>,
42 },
43 ILike {
44 expr: Box<ExprPlan>,
45 negated: bool,
46 pattern: Box<ExprPlan>,
47 },
48 Regex {
49 expr: Box<ExprPlan>,
50 negated: bool,
51 pattern: Box<ExprPlan>,
52 case_sensitive: bool,
53 },
54 BinaryOp {
55 left: Box<ExprPlan>,
56 op: BinaryOperator,
57 right: Box<ExprPlan>,
58 },
59 UnaryOp {
60 op: UnaryOperator,
61 expr: Box<ExprPlan>,
62 },
63 Nested(Box<ExprPlan>),
64 Literal(Literal),
65 Value(Value),
66 TypedString {
67 data_type: DataType,
68 value: String,
69 },
70 Function(Box<FunctionExprPlan>),
71 Aggregate(Box<AggregateExprPlan>),
72 Exists {
73 subquery: Box<QueryPlan>,
74 negated: bool,
75 },
76 Subquery(Box<QueryPlan>),
77 Case {
78 operand: Option<Box<ExprPlan>>,
79 when_then: Vec<(ExprPlan, ExprPlan)>,
80 else_result: Option<Box<ExprPlan>>,
81 },
82 ArrayIndex {
83 obj: Box<ExprPlan>,
84 indexes: Vec<ExprPlan>,
85 },
86 Interval {
87 expr: Box<ExprPlan>,
88 leading_field: Option<DateTimeField>,
89 last_field: Option<DateTimeField>,
90 },
91 Array {
92 elem: Vec<ExprPlan>,
93 },
94}
95
96#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Display)]
97#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
98pub enum FunctionExprPlan {
99 Abs(ExprPlan),
100 AddMonth {
101 expr: ExprPlan,
102 size: ExprPlan,
103 },
104 Lower(ExprPlan),
105 Initcap(ExprPlan),
106 Upper(ExprPlan),
107 Left {
108 expr: ExprPlan,
109 size: ExprPlan,
110 },
111 Right {
112 expr: ExprPlan,
113 size: ExprPlan,
114 },
115 Asin(ExprPlan),
116 Acos(ExprPlan),
117 Atan(ExprPlan),
118 Lpad {
119 expr: ExprPlan,
120 size: ExprPlan,
121 fill: Option<ExprPlan>,
122 },
123 Rpad {
124 expr: ExprPlan,
125 size: ExprPlan,
126 fill: Option<ExprPlan>,
127 },
128 Replace {
129 expr: ExprPlan,
130 old: ExprPlan,
131 new: ExprPlan,
132 },
133 Cast {
134 expr: ExprPlan,
135 data_type: DataType,
136 },
137 Ceil(ExprPlan),
138 Coalesce(Vec<ExprPlan>),
139 Concat(Vec<ExprPlan>),
140 ConcatWs {
141 separator: ExprPlan,
142 exprs: Vec<ExprPlan>,
143 },
144 Custom {
145 name: String,
146 exprs: Vec<ExprPlan>,
147 },
148 IfNull {
149 expr: ExprPlan,
150 then: ExprPlan,
151 },
152 NullIf {
153 expr1: ExprPlan,
154 expr2: ExprPlan,
155 },
156 Rand(Option<ExprPlan>),
157 Round(ExprPlan),
158 Trunc(ExprPlan),
159 Floor(ExprPlan),
160 Trim {
161 expr: ExprPlan,
162 filter_chars: Option<ExprPlan>,
163 trim_where_field: Option<TrimWhereField>,
164 },
165 Exp(ExprPlan),
166 Extract {
167 field: DateTimeField,
168 expr: ExprPlan,
169 },
170 Ln(ExprPlan),
171 Log {
172 antilog: ExprPlan,
173 base: ExprPlan,
174 },
175 Log2(ExprPlan),
176 Log10(ExprPlan),
177 Div {
178 dividend: ExprPlan,
179 divisor: ExprPlan,
180 },
181 Mod {
182 dividend: ExprPlan,
183 divisor: ExprPlan,
184 },
185 Gcd {
186 left: ExprPlan,
187 right: ExprPlan,
188 },
189 Lcm {
190 left: ExprPlan,
191 right: ExprPlan,
192 },
193 Sin(ExprPlan),
194 Cos(ExprPlan),
195 Tan(ExprPlan),
196 Sqrt(ExprPlan),
197 Power {
198 expr: ExprPlan,
199 power: ExprPlan,
200 },
201 Radians(ExprPlan),
202 Degrees(ExprPlan),
203 Now(),
204 CurrentDate(),
205 CurrentTime(),
206 CurrentTimestamp(),
207 Pi(),
208 LastDay(ExprPlan),
209 Ltrim {
210 expr: ExprPlan,
211 chars: Option<ExprPlan>,
212 },
213 Rtrim {
214 expr: ExprPlan,
215 chars: Option<ExprPlan>,
216 },
217 Reverse(ExprPlan),
218 Repeat {
219 expr: ExprPlan,
220 num: ExprPlan,
221 },
222 Sign(ExprPlan),
223 Substr {
224 expr: ExprPlan,
225 start: ExprPlan,
226 count: Option<ExprPlan>,
227 },
228 Unwrap {
229 expr: ExprPlan,
230 selector: ExprPlan,
231 },
232 GenerateUuid(),
233 Greatest(Vec<ExprPlan>),
234 Format {
235 expr: ExprPlan,
236 format: ExprPlan,
237 },
238 ToDate {
239 expr: ExprPlan,
240 format: ExprPlan,
241 },
242 ToTimestamp {
243 expr: ExprPlan,
244 format: ExprPlan,
245 },
246 ToTime {
247 expr: ExprPlan,
248 format: ExprPlan,
249 },
250 Position {
251 from_expr: ExprPlan,
252 sub_expr: ExprPlan,
253 },
254 FindIdx {
255 from_expr: ExprPlan,
256 sub_expr: ExprPlan,
257 start: Option<ExprPlan>,
258 },
259 Ascii(ExprPlan),
260 Chr(ExprPlan),
261 Md5(ExprPlan),
262 Hex(ExprPlan),
263 Append {
264 expr: ExprPlan,
265 value: ExprPlan,
266 },
267 Sort {
268 expr: ExprPlan,
269 order: Option<ExprPlan>,
270 },
271 Slice {
272 expr: ExprPlan,
273 start: ExprPlan,
274 length: ExprPlan,
275 },
276 Prepend {
277 expr: ExprPlan,
278 value: ExprPlan,
279 },
280 Skip {
281 expr: ExprPlan,
282 size: ExprPlan,
283 },
284 Take {
285 expr: ExprPlan,
286 size: ExprPlan,
287 },
288 GetX(ExprPlan),
289 GetY(ExprPlan),
290 Point {
291 x: ExprPlan,
292 y: ExprPlan,
293 },
294 CalcDistance {
295 geometry1: ExprPlan,
296 geometry2: ExprPlan,
297 },
298 IsEmpty(ExprPlan),
299 Length(ExprPlan),
300 Entries(ExprPlan),
301 Keys(ExprPlan),
302 Values(ExprPlan),
303 Splice {
304 list_data: ExprPlan,
305 begin_index: ExprPlan,
306 end_index: ExprPlan,
307 values: Option<ExprPlan>,
308 },
309 Dedup(ExprPlan),
310}
311
312#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
313pub struct AggregateExprPlan {
314 pub func: AggregateFunctionPlan,
315 pub distinct: bool,
316 pub slot: Option<usize>,
317}
318
319#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
320pub enum AggregateFunctionPlan {
321 Count(CountArgExprPlan),
322 Sum(ExprPlan),
323 Max(ExprPlan),
324 Min(ExprPlan),
325 Avg(ExprPlan),
326 Variance(ExprPlan),
327 Stdev(ExprPlan),
328}
329
330#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
331pub enum CountArgExprPlan {
332 Wildcard,
333 Expr(ExprPlan),
334}
335
336pub fn plan_scalar_expr(expr: ast::Expr) -> ExprPlan {
337 expr.into()
338}
339
340impl From<ast::Expr> for ExprPlan {
341 fn from(expr: ast::Expr) -> Self {
342 match expr {
343 ast::Expr::Identifier(ident) => Self::Identifier(ident),
344 ast::Expr::CompoundIdentifier { alias, ident } => {
345 Self::CompoundIdentifier { alias, ident }
346 }
347 ast::Expr::IsNull(expr) => Self::IsNull(Box::new((*expr).into())),
348 ast::Expr::IsNotNull(expr) => Self::IsNotNull(Box::new((*expr).into())),
349 ast::Expr::InList {
350 expr,
351 list,
352 negated,
353 } => Self::InList {
354 expr: Box::new((*expr).into()),
355 list: list.into_iter().map(Into::into).collect(),
356 negated,
357 },
358 ast::Expr::InSubquery {
359 expr,
360 subquery,
361 negated,
362 } => Self::InSubquery {
363 expr: Box::new((*expr).into()),
364 subquery: Box::new((*subquery).into()),
365 negated,
366 },
367 ast::Expr::Between {
368 expr,
369 negated,
370 low,
371 high,
372 } => Self::Between {
373 expr: Box::new((*expr).into()),
374 negated,
375 low: Box::new((*low).into()),
376 high: Box::new((*high).into()),
377 },
378 ast::Expr::Like {
379 expr,
380 negated,
381 pattern,
382 } => Self::Like {
383 expr: Box::new((*expr).into()),
384 negated,
385 pattern: Box::new((*pattern).into()),
386 },
387 ast::Expr::ILike {
388 expr,
389 negated,
390 pattern,
391 } => Self::ILike {
392 expr: Box::new((*expr).into()),
393 negated,
394 pattern: Box::new((*pattern).into()),
395 },
396 ast::Expr::Regex {
397 expr,
398 negated,
399 pattern,
400 case_sensitive,
401 } => Self::Regex {
402 expr: Box::new((*expr).into()),
403 negated,
404 pattern: Box::new((*pattern).into()),
405 case_sensitive,
406 },
407 ast::Expr::BinaryOp { left, op, right } => Self::BinaryOp {
408 left: Box::new((*left).into()),
409 op,
410 right: Box::new((*right).into()),
411 },
412 ast::Expr::UnaryOp { op, expr } => Self::UnaryOp {
413 op,
414 expr: Box::new((*expr).into()),
415 },
416 ast::Expr::Nested(expr) => Self::Nested(Box::new((*expr).into())),
417 ast::Expr::Literal(literal) => Self::Literal(literal),
418 ast::Expr::Value(value) => Self::Value(value),
419 ast::Expr::TypedString { data_type, value } => Self::TypedString { data_type, value },
420 ast::Expr::Function(function) => Self::Function(Box::new((*function).into())),
421 ast::Expr::Aggregate(aggregate) => Self::Aggregate(Box::new((*aggregate).into())),
422 ast::Expr::Exists { subquery, negated } => Self::Exists {
423 subquery: Box::new((*subquery).into()),
424 negated,
425 },
426 ast::Expr::Subquery(query) => Self::Subquery(Box::new((*query).into())),
427 ast::Expr::Case {
428 operand,
429 when_then,
430 else_result,
431 } => Self::Case {
432 operand: operand.map(|expr| Box::new((*expr).into())),
433 when_then: when_then
434 .into_iter()
435 .map(|(when, then)| (when.into(), then.into()))
436 .collect(),
437 else_result: else_result.map(|expr| Box::new((*expr).into())),
438 },
439 ast::Expr::ArrayIndex { obj, indexes } => Self::ArrayIndex {
440 obj: Box::new((*obj).into()),
441 indexes: indexes.into_iter().map(Into::into).collect(),
442 },
443 ast::Expr::Interval {
444 expr,
445 leading_field,
446 last_field,
447 } => Self::Interval {
448 expr: Box::new((*expr).into()),
449 leading_field,
450 last_field,
451 },
452 ast::Expr::Array { elem } => Self::Array {
453 elem: elem.into_iter().map(Into::into).collect(),
454 },
455 }
456 }
457}
458
459impl From<ast::Function> for FunctionExprPlan {
460 fn from(function: ast::Function) -> Self {
461 match function {
462 ast::Function::Abs(expr) => Self::Abs(expr.into()),
463 ast::Function::AddMonth { expr, size } => Self::AddMonth {
464 expr: expr.into(),
465 size: size.into(),
466 },
467 ast::Function::Lower(expr) => Self::Lower(expr.into()),
468 ast::Function::Initcap(expr) => Self::Initcap(expr.into()),
469 ast::Function::Upper(expr) => Self::Upper(expr.into()),
470 ast::Function::Left { expr, size } => Self::Left {
471 expr: expr.into(),
472 size: size.into(),
473 },
474 ast::Function::Right { expr, size } => Self::Right {
475 expr: expr.into(),
476 size: size.into(),
477 },
478 ast::Function::Asin(expr) => Self::Asin(expr.into()),
479 ast::Function::Acos(expr) => Self::Acos(expr.into()),
480 ast::Function::Atan(expr) => Self::Atan(expr.into()),
481 ast::Function::Lpad { expr, size, fill } => Self::Lpad {
482 expr: expr.into(),
483 size: size.into(),
484 fill: fill.map(Into::into),
485 },
486 ast::Function::Rpad { expr, size, fill } => Self::Rpad {
487 expr: expr.into(),
488 size: size.into(),
489 fill: fill.map(Into::into),
490 },
491 ast::Function::Replace { expr, old, new } => Self::Replace {
492 expr: expr.into(),
493 old: old.into(),
494 new: new.into(),
495 },
496 ast::Function::Cast { expr, data_type } => Self::Cast {
497 expr: expr.into(),
498 data_type,
499 },
500 ast::Function::Ceil(expr) => Self::Ceil(expr.into()),
501 ast::Function::Coalesce(exprs) => {
502 Self::Coalesce(exprs.into_iter().map(Into::into).collect())
503 }
504 ast::Function::Concat(exprs) => {
505 Self::Concat(exprs.into_iter().map(Into::into).collect())
506 }
507 ast::Function::ConcatWs { separator, exprs } => Self::ConcatWs {
508 separator: separator.into(),
509 exprs: exprs.into_iter().map(Into::into).collect(),
510 },
511 ast::Function::Custom { name, exprs } => Self::Custom {
512 name,
513 exprs: exprs.into_iter().map(Into::into).collect(),
514 },
515 ast::Function::IfNull { expr, then } => Self::IfNull {
516 expr: expr.into(),
517 then: then.into(),
518 },
519 ast::Function::NullIf { expr1, expr2 } => Self::NullIf {
520 expr1: expr1.into(),
521 expr2: expr2.into(),
522 },
523 ast::Function::Rand(expr) => Self::Rand(expr.map(Into::into)),
524 ast::Function::Round(expr) => Self::Round(expr.into()),
525 ast::Function::Trunc(expr) => Self::Trunc(expr.into()),
526 ast::Function::Floor(expr) => Self::Floor(expr.into()),
527 ast::Function::Trim {
528 expr,
529 filter_chars,
530 trim_where_field,
531 } => Self::Trim {
532 expr: expr.into(),
533 filter_chars: filter_chars.map(Into::into),
534 trim_where_field,
535 },
536 ast::Function::Exp(expr) => Self::Exp(expr.into()),
537 ast::Function::Extract { field, expr } => Self::Extract {
538 field,
539 expr: expr.into(),
540 },
541 ast::Function::Ln(expr) => Self::Ln(expr.into()),
542 ast::Function::Log { antilog, base } => Self::Log {
543 antilog: antilog.into(),
544 base: base.into(),
545 },
546 ast::Function::Log2(expr) => Self::Log2(expr.into()),
547 ast::Function::Log10(expr) => Self::Log10(expr.into()),
548 ast::Function::Div { dividend, divisor } => Self::Div {
549 dividend: dividend.into(),
550 divisor: divisor.into(),
551 },
552 ast::Function::Mod { dividend, divisor } => Self::Mod {
553 dividend: dividend.into(),
554 divisor: divisor.into(),
555 },
556 ast::Function::Gcd { left, right } => Self::Gcd {
557 left: left.into(),
558 right: right.into(),
559 },
560 ast::Function::Lcm { left, right } => Self::Lcm {
561 left: left.into(),
562 right: right.into(),
563 },
564 ast::Function::Sin(expr) => Self::Sin(expr.into()),
565 ast::Function::Cos(expr) => Self::Cos(expr.into()),
566 ast::Function::Tan(expr) => Self::Tan(expr.into()),
567 ast::Function::Sqrt(expr) => Self::Sqrt(expr.into()),
568 ast::Function::Power { expr, power } => Self::Power {
569 expr: expr.into(),
570 power: power.into(),
571 },
572 ast::Function::Radians(expr) => Self::Radians(expr.into()),
573 ast::Function::Degrees(expr) => Self::Degrees(expr.into()),
574 ast::Function::Now() => Self::Now(),
575 ast::Function::CurrentDate() => Self::CurrentDate(),
576 ast::Function::CurrentTime() => Self::CurrentTime(),
577 ast::Function::CurrentTimestamp() => Self::CurrentTimestamp(),
578 ast::Function::Pi() => Self::Pi(),
579 ast::Function::LastDay(expr) => Self::LastDay(expr.into()),
580 ast::Function::Ltrim { expr, chars } => Self::Ltrim {
581 expr: expr.into(),
582 chars: chars.map(Into::into),
583 },
584 ast::Function::Rtrim { expr, chars } => Self::Rtrim {
585 expr: expr.into(),
586 chars: chars.map(Into::into),
587 },
588 ast::Function::Reverse(expr) => Self::Reverse(expr.into()),
589 ast::Function::Repeat { expr, num } => Self::Repeat {
590 expr: expr.into(),
591 num: num.into(),
592 },
593 ast::Function::Sign(expr) => Self::Sign(expr.into()),
594 ast::Function::Substr { expr, start, count } => Self::Substr {
595 expr: expr.into(),
596 start: start.into(),
597 count: count.map(Into::into),
598 },
599 ast::Function::Unwrap { expr, selector } => Self::Unwrap {
600 expr: expr.into(),
601 selector: selector.into(),
602 },
603 ast::Function::GenerateUuid() => Self::GenerateUuid(),
604 ast::Function::Greatest(exprs) => {
605 Self::Greatest(exprs.into_iter().map(Into::into).collect())
606 }
607 ast::Function::Format { expr, format } => Self::Format {
608 expr: expr.into(),
609 format: format.into(),
610 },
611 ast::Function::ToDate { expr, format } => Self::ToDate {
612 expr: expr.into(),
613 format: format.into(),
614 },
615 ast::Function::ToTimestamp { expr, format } => Self::ToTimestamp {
616 expr: expr.into(),
617 format: format.into(),
618 },
619 ast::Function::ToTime { expr, format } => Self::ToTime {
620 expr: expr.into(),
621 format: format.into(),
622 },
623 ast::Function::Position {
624 from_expr,
625 sub_expr,
626 } => Self::Position {
627 from_expr: from_expr.into(),
628 sub_expr: sub_expr.into(),
629 },
630 ast::Function::FindIdx {
631 from_expr,
632 sub_expr,
633 start,
634 } => Self::FindIdx {
635 from_expr: from_expr.into(),
636 sub_expr: sub_expr.into(),
637 start: start.map(Into::into),
638 },
639 ast::Function::Ascii(expr) => Self::Ascii(expr.into()),
640 ast::Function::Chr(expr) => Self::Chr(expr.into()),
641 ast::Function::Md5(expr) => Self::Md5(expr.into()),
642 ast::Function::Hex(expr) => Self::Hex(expr.into()),
643 ast::Function::Append { expr, value } => Self::Append {
644 expr: expr.into(),
645 value: value.into(),
646 },
647 ast::Function::Sort { expr, order } => Self::Sort {
648 expr: expr.into(),
649 order: order.map(Into::into),
650 },
651 ast::Function::Slice {
652 expr,
653 start,
654 length,
655 } => Self::Slice {
656 expr: expr.into(),
657 start: start.into(),
658 length: length.into(),
659 },
660 ast::Function::Prepend { expr, value } => Self::Prepend {
661 expr: expr.into(),
662 value: value.into(),
663 },
664 ast::Function::Skip { expr, size } => Self::Skip {
665 expr: expr.into(),
666 size: size.into(),
667 },
668 ast::Function::Take { expr, size } => Self::Take {
669 expr: expr.into(),
670 size: size.into(),
671 },
672 ast::Function::GetX(expr) => Self::GetX(expr.into()),
673 ast::Function::GetY(expr) => Self::GetY(expr.into()),
674 ast::Function::Point { x, y } => Self::Point {
675 x: x.into(),
676 y: y.into(),
677 },
678 ast::Function::CalcDistance {
679 geometry1,
680 geometry2,
681 } => Self::CalcDistance {
682 geometry1: geometry1.into(),
683 geometry2: geometry2.into(),
684 },
685 ast::Function::IsEmpty(expr) => Self::IsEmpty(expr.into()),
686 ast::Function::Length(expr) => Self::Length(expr.into()),
687 ast::Function::Entries(expr) => Self::Entries(expr.into()),
688 ast::Function::Keys(expr) => Self::Keys(expr.into()),
689 ast::Function::Values(expr) => Self::Values(expr.into()),
690 ast::Function::Splice {
691 list_data,
692 begin_index,
693 end_index,
694 values,
695 } => Self::Splice {
696 list_data: list_data.into(),
697 begin_index: begin_index.into(),
698 end_index: end_index.into(),
699 values: values.map(Into::into),
700 },
701 ast::Function::Dedup(expr) => Self::Dedup(expr.into()),
702 }
703 }
704}
705
706impl From<ast::Aggregate> for AggregateExprPlan {
707 fn from(aggregate: ast::Aggregate) -> Self {
708 let ast::Aggregate { func, distinct } = aggregate;
709
710 Self {
711 func: func.into(),
712 distinct,
713 slot: None,
714 }
715 }
716}
717
718impl From<ast::AggregateFunction> for AggregateFunctionPlan {
719 fn from(func: ast::AggregateFunction) -> Self {
720 match func {
721 ast::AggregateFunction::Count(expr) => Self::Count(expr.into()),
722 ast::AggregateFunction::Sum(expr) => Self::Sum(expr.into()),
723 ast::AggregateFunction::Max(expr) => Self::Max(expr.into()),
724 ast::AggregateFunction::Min(expr) => Self::Min(expr.into()),
725 ast::AggregateFunction::Avg(expr) => Self::Avg(expr.into()),
726 ast::AggregateFunction::Variance(expr) => Self::Variance(expr.into()),
727 ast::AggregateFunction::Stdev(expr) => Self::Stdev(expr.into()),
728 }
729 }
730}
731
732impl From<ast::CountArgExpr> for CountArgExprPlan {
733 fn from(expr: ast::CountArgExpr) -> Self {
734 match expr {
735 ast::CountArgExpr::Wildcard => Self::Wildcard,
736 ast::CountArgExpr::Expr(expr) => Self::Expr(expr.into()),
737 }
738 }
739}