Skip to main content

gluesql_core/plan/statement/
expr.rs

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}