databend_common_ast/parser/
query.rs

1// Copyright 2021 Datafuse Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::collections::BTreeMap;
16
17use nom::branch::alt;
18use nom::combinator::consumed;
19use nom::combinator::map;
20use nom::combinator::value;
21use nom::error::context;
22use nom_rule::rule;
23use pratt::Affix;
24use pratt::Associativity;
25use pratt::PrattParser;
26use pratt::Precedence;
27
28use crate::ast::*;
29use crate::parser::common::*;
30use crate::parser::expr::*;
31use crate::parser::input::Input;
32use crate::parser::input::WithSpan;
33use crate::parser::stage::file_location;
34use crate::parser::stage::select_stage_option;
35use crate::parser::statement::hint;
36use crate::parser::statement::set_table_option;
37use crate::parser::statement::top_n;
38use crate::parser::token::*;
39use crate::parser::ErrorKind;
40use crate::Range;
41
42pub fn query(i: Input) -> IResult<Query> {
43    context(
44        "`SELECT ...`",
45        map(set_operation, |set_expr| set_expr.into_query()),
46    )(i)
47}
48
49pub fn set_operation(i: Input) -> IResult<SetExpr> {
50    let (rest, set_operation_elements) = rule! { #set_operation_element+ }(i)?;
51    let iter = &mut set_operation_elements.into_iter();
52    run_pratt_parser(SetOperationParser, iter, rest, i)
53}
54
55#[derive(Debug, Clone, PartialEq)]
56#[allow(clippy::large_enum_variant)]
57pub enum SetOperationElement {
58    With(With),
59    SelectStmt {
60        hints: Option<Hint>,
61        distinct: bool,
62        top_n: Option<u64>,
63        select_list: Vec<SelectTarget>,
64        from: Vec<TableReference>,
65        selection: Option<Expr>,
66        group_by: Option<GroupBy>,
67        having: Option<Expr>,
68        window_list: Option<Vec<WindowDefinition>>,
69        qualify: Option<Expr>,
70    },
71    SetOperation {
72        op: SetOperator,
73        all: bool,
74    },
75    Values(Vec<Vec<Expr>>),
76    OrderBy {
77        order_by: Vec<OrderByExpr>,
78    },
79    Limit {
80        limit: Vec<Expr>,
81    },
82    Offset {
83        offset: Expr,
84    },
85    IgnoreResult,
86    Group(SetExpr),
87}
88
89pub fn set_operation_element(i: Input) -> IResult<WithSpan<SetOperationElement>> {
90    let with = map(with, SetOperationElement::With);
91    let set_operator = map(
92        rule! {
93            ( UNION | EXCEPT | INTERSECT ) ~ ALL?
94        },
95        |(op, all)| {
96            let op = match op.kind {
97                UNION => SetOperator::Union,
98                INTERSECT => SetOperator::Intersect,
99                EXCEPT => SetOperator::Except,
100                _ => unreachable!(),
101            };
102            SetOperationElement::SetOperation {
103                op,
104                all: all.is_some(),
105            }
106        },
107    );
108    let from_stmt = map_res(
109        rule! {
110            FROM ~ ^#comma_separated_list1(table_reference)
111        },
112        |(_from, from_block)| {
113            if from_block.len() != 1 {
114                return Err(nom::Err::Failure(ErrorKind::Other(
115                    "FROM query only support query one table",
116                )));
117            }
118            Ok(SetOperationElement::SelectStmt {
119                hints: None,
120                distinct: false,
121                top_n: None,
122                select_list: vec![SelectTarget::StarColumns {
123                    qualified: vec![Indirection::Star(Some(Range { start: 0, end: 0 }))],
124                    column_filter: None,
125                }],
126                from: from_block,
127                selection: None,
128                group_by: None,
129                having: None,
130                window_list: None,
131                qualify: None,
132            })
133        },
134    );
135
136    let select_stmt = map_res(
137        rule! {
138            ( FROM ~ ^#comma_separated_list1(table_reference) )?
139            ~ SELECT ~ #hint? ~ DISTINCT? ~ #top_n? ~ ^#comma_separated_list1(select_target)
140            ~ ( FROM ~ ^#comma_separated_list1(table_reference) )?
141            ~ ( WHERE ~ ^#expr )?
142            ~ ( GROUP ~ ^BY ~ ^#group_by_items )?
143            ~ ( HAVING ~ ^#expr )?
144            ~ ( WINDOW ~ ^#comma_separated_list1(window_clause) )?
145            ~ ( QUALIFY ~ ^#expr )?
146        },
147        |(
148            opt_from_block_first,
149            _select,
150            opt_hints,
151            opt_distinct,
152            opt_top_n,
153            select_list,
154            opt_from_block_second,
155            opt_where_block,
156            opt_group_by_block,
157            opt_having_block,
158            opt_window_block,
159            opt_qualify_block,
160        )| {
161            if opt_from_block_first.is_some() && opt_from_block_second.is_some() {
162                return Err(nom::Err::Failure(ErrorKind::Other(
163                    "duplicated FROM clause",
164                )));
165            }
166
167            Ok(SetOperationElement::SelectStmt {
168                hints: opt_hints,
169                distinct: opt_distinct.is_some(),
170                top_n: opt_top_n,
171                select_list,
172                from: opt_from_block_first
173                    .or(opt_from_block_second)
174                    .map(|(_, table_refs)| table_refs)
175                    .unwrap_or_default(),
176                selection: opt_where_block.map(|(_, selection)| selection),
177                group_by: opt_group_by_block.map(|(_, _, group_by)| group_by),
178                having: opt_having_block.map(|(_, having)| having),
179                window_list: opt_window_block.map(|(_, windows)| windows),
180                qualify: opt_qualify_block.map(|(_, qualify)| qualify),
181            })
182        },
183    );
184
185    let values = map(
186        rule! {
187            VALUES ~ ^#comma_separated_list1(row_values)
188        },
189        |(_, values)| SetOperationElement::Values(values),
190    );
191    let order_by = map(
192        rule! {
193            ORDER ~ ^BY ~ ^#comma_separated_list1(order_by_expr)
194        },
195        |(_, _, order_by)| SetOperationElement::OrderBy { order_by },
196    );
197    let limit = map(
198        rule! {
199            LIMIT ~ ^#comma_separated_list1(expr)
200        },
201        |(_, limit)| SetOperationElement::Limit { limit },
202    );
203    let offset = map(
204        rule! {
205            OFFSET ~ ^#expr
206        },
207        |(_, offset)| SetOperationElement::Offset { offset },
208    );
209    let ignore_result = map(
210        rule! {
211            IGNORE_RESULT
212        },
213        |_| SetOperationElement::IgnoreResult,
214    );
215    let group = map(
216        rule! {
217           "(" ~ #set_operation ~ ^")"
218        },
219        |(_, set_expr, _)| SetOperationElement::Group(set_expr),
220    );
221
222    map(
223        consumed(rule! {
224            #group
225            | #with
226            | #set_operator
227            | #select_stmt
228            | #from_stmt
229            | #values
230            | #order_by
231            | #limit
232            | #offset
233            | #ignore_result
234        }),
235        |(span, elem)| WithSpan { span, elem },
236    )(i)
237}
238
239struct SetOperationParser;
240
241impl<'a, I: Iterator<Item = WithSpan<'a, SetOperationElement>>> PrattParser<I>
242    for SetOperationParser
243{
244    type Error = &'static str;
245    type Input = WithSpan<'a, SetOperationElement>;
246    type Output = SetExpr;
247
248    fn query(&mut self, input: &Self::Input) -> Result<Affix, &'static str> {
249        let affix = match &input.elem {
250            // https://learn.microsoft.com/en-us/sql/t-sql/language-elements/set-operators-except-and-intersect-transact-sql?view=sql-server-2017
251            // If EXCEPT or INTERSECT is used together with other operators in an expression, it's evaluated in the context of the following precedence:
252            // 1. Expressions in parentheses
253            // 2. The INTERSECT operator
254            // 3. EXCEPT and UNION evaluated from left to right based on their position in the expression
255            SetOperationElement::SetOperation { op, .. } => match op {
256                SetOperator::Union | SetOperator::Except => {
257                    Affix::Infix(Precedence(10), Associativity::Left)
258                }
259                SetOperator::Intersect => Affix::Infix(Precedence(20), Associativity::Left),
260            },
261            SetOperationElement::With(_) => Affix::Prefix(Precedence(5)),
262            SetOperationElement::OrderBy { .. } => Affix::Postfix(Precedence(5)),
263            SetOperationElement::Limit { .. } => Affix::Postfix(Precedence(5)),
264            SetOperationElement::Offset { .. } => Affix::Postfix(Precedence(5)),
265            SetOperationElement::IgnoreResult => Affix::Postfix(Precedence(5)),
266            _ => Affix::Nilfix,
267        };
268        Ok(affix)
269    }
270
271    fn primary(&mut self, input: Self::Input) -> Result<Self::Output, &'static str> {
272        let set_expr = match input.elem {
273            SetOperationElement::Group(expr) => expr,
274            SetOperationElement::SelectStmt {
275                hints,
276                distinct,
277                top_n,
278                select_list,
279                from,
280                selection,
281                group_by,
282                having,
283                window_list,
284                qualify,
285            } => SetExpr::Select(Box::new(SelectStmt {
286                span: transform_span(input.span.tokens),
287                hints,
288                top_n,
289                distinct,
290                select_list,
291                from,
292                selection,
293                group_by,
294                having,
295                window_list,
296                qualify,
297            })),
298            SetOperationElement::Values(values) => SetExpr::Values {
299                span: transform_span(input.span.tokens),
300                values,
301            },
302            _ => unreachable!(),
303        };
304        Ok(set_expr)
305    }
306
307    fn infix(
308        &mut self,
309        lhs: Self::Output,
310        input: Self::Input,
311        rhs: Self::Output,
312    ) -> Result<Self::Output, &'static str> {
313        let set_expr = match input.elem {
314            SetOperationElement::SetOperation { op, all, .. } => {
315                SetExpr::SetOperation(Box::new(SetOperation {
316                    span: transform_span(input.span.tokens),
317                    op,
318                    all,
319                    left: Box::new(lhs),
320                    right: Box::new(rhs),
321                }))
322            }
323            _ => unreachable!(),
324        };
325        Ok(set_expr)
326    }
327
328    fn prefix(&mut self, op: Self::Input, rhs: Self::Output) -> Result<Self::Output, Self::Error> {
329        let mut query = rhs.into_query();
330        match op.elem {
331            SetOperationElement::With(with) => {
332                if query.with.is_some() {
333                    return Err("duplicated WITH clause");
334                }
335                query.with = Some(with);
336            }
337            _ => unreachable!(),
338        }
339        Ok(SetExpr::Query(Box::new(query)))
340    }
341
342    fn postfix(&mut self, lhs: Self::Output, op: Self::Input) -> Result<Self::Output, Self::Error> {
343        let mut query = lhs.into_query();
344        match op.elem {
345            SetOperationElement::OrderBy { order_by } => {
346                if !query.order_by.is_empty() {
347                    return Err("duplicated ORDER BY clause");
348                }
349                if !query.limit.is_empty() {
350                    return Err("ORDER BY must appear before LIMIT");
351                }
352                if query.offset.is_some() {
353                    return Err("ORDER BY must appear before OFFSET");
354                }
355                query.order_by = order_by;
356            }
357            SetOperationElement::Limit { limit } => {
358                if query.limit.is_empty() && limit.len() > 2 {
359                    return Err("[LIMIT n OFFSET m] or [LIMIT n,m]");
360                }
361                if !query.limit.is_empty() {
362                    return Err("duplicated LIMIT clause");
363                }
364                if query.offset.is_some() {
365                    return Err("LIMIT must appear before OFFSET");
366                }
367                query.limit = limit;
368            }
369            SetOperationElement::Offset { offset } => {
370                if query.limit.len() == 2 {
371                    return Err("LIMIT n,m should not appear OFFSET");
372                }
373                if query.offset.is_some() {
374                    return Err("duplicated OFFSET clause");
375                }
376                query.offset = Some(offset);
377            }
378            SetOperationElement::IgnoreResult => {
379                query.ignore_result = true;
380            }
381            _ => unreachable!(),
382        }
383        Ok(SetExpr::Query(Box::new(query)))
384    }
385}
386
387pub fn row_values(i: Input) -> IResult<Vec<Expr>> {
388    map(
389        rule! {"(" ~ #comma_separated_list1(expr) ~ ")"},
390        |(_, row_values, _)| row_values,
391    )(i)
392}
393
394pub fn with(i: Input) -> IResult<With> {
395    let cte = map(
396        consumed(rule! {
397            #table_alias_without_as ~ AS ~ MATERIALIZED? ~ "(" ~ #query ~ ")"
398        }),
399        |(span, (table_alias, _, materialized, _, query, _))| CTE {
400            span: transform_span(span.tokens),
401            alias: table_alias,
402            materialized: materialized.is_some(),
403            query: Box::new(query),
404        },
405    );
406
407    map(
408        consumed(rule! {
409            WITH ~ RECURSIVE? ~ ^#comma_separated_list1(cte)
410        }),
411        |(span, (_, recursive, ctes))| With {
412            span: transform_span(span.tokens),
413            recursive: recursive.is_some(),
414            ctes,
415        },
416    )(i)
417}
418
419pub fn exclude_col(i: Input) -> IResult<Vec<Identifier>> {
420    let var = map(
421        rule! {
422            #ident
423        },
424        |col| vec![col],
425    );
426    let vars = map(
427        rule! {
428             "(" ~ ^#comma_separated_list1(ident) ~ ^")"
429        },
430        |(_, cols, _)| cols,
431    );
432
433    rule!(
434        #var
435        | #vars
436    )(i)
437}
438
439#[allow(clippy::type_complexity)]
440pub fn select_target(i: Input) -> IResult<SelectTarget> {
441    fn qualified_wildcard_transform(
442        res: Option<(Identifier, &Token<'_>, Option<(Identifier, &Token<'_>)>)>,
443        star: &Token<'_>,
444        opt_exclude: Option<(&Token<'_>, Vec<Identifier>)>,
445    ) -> SelectTarget {
446        let column_filter = opt_exclude.map(|(_, exclude)| ColumnFilter::Excludes(exclude));
447        match res {
448            Some((fst, _, Some((snd, _)))) => SelectTarget::StarColumns {
449                qualified: vec![
450                    Indirection::Identifier(fst),
451                    Indirection::Identifier(snd),
452                    Indirection::Star(Some(star.span)),
453                ],
454                column_filter,
455            },
456            Some((fst, _, None)) => SelectTarget::StarColumns {
457                qualified: vec![
458                    Indirection::Identifier(fst),
459                    Indirection::Star(Some(star.span)),
460                ],
461                column_filter,
462            },
463            None => SelectTarget::StarColumns {
464                qualified: vec![Indirection::Star(Some(star.span))],
465                column_filter,
466            },
467        }
468    }
469
470    let qualified_wildcard = alt((
471        // select * exclude ...
472        map(
473            rule! {
474               ( #ident ~ "." ~ ( #ident ~ "." )? )? ~ "*" ~ ( EXCLUDE ~ #exclude_col )?
475            },
476            |(res, star, opt_exclude)| qualified_wildcard_transform(res, star, opt_exclude),
477        ),
478        // select columns(* exclude ...)
479        map(
480            rule! {
481              COLUMNS ~ "(" ~  ( #ident ~ "." ~ ( #ident ~ "." )? )? ~ "*" ~ ( EXCLUDE ~ #exclude_col )? ~ ")"
482            },
483            |(_, _, res, star, opt_exclude, _)| {
484                qualified_wildcard_transform(res, star, opt_exclude)
485            },
486        ),
487    ));
488
489    // columns('.*abc.*')
490    let columns_regexp = map(
491        rule! {
492            COLUMNS ~ "(" ~ #literal_string ~ ")"
493        },
494        |(t, _, s, _)| SelectTarget::StarColumns {
495            qualified: vec![Indirection::Star(Some(t.span))],
496            column_filter: Some(ColumnFilter::Lambda(Lambda {
497                params: vec![Identifier::from_name(Some(t.span), "_t")],
498                expr: Box::new(Expr::BinaryOp {
499                    span: Some(t.span),
500                    op: BinaryOperator::Regexp,
501                    left: Box::new(Expr::ColumnRef {
502                        span: None,
503                        column: ColumnRef {
504                            database: None,
505                            table: None,
506                            column: ColumnID::Name(Identifier::from_name(Some(t.span), "_t")),
507                        },
508                    }),
509                    right: Box::new(Expr::Literal {
510                        span: Some(t.span),
511                        value: Literal::String(s),
512                    }),
513                }),
514            })),
515        },
516    );
517
518    // columns(a -> filter)
519    let columns_lambda = map(
520        rule! {
521            COLUMNS ~ "(" ~ #ident ~ "->" ~ #subexpr(0) ~ ")"
522        },
523        |(t, _, ident, _, expr, _)| SelectTarget::StarColumns {
524            qualified: vec![Indirection::Star(Some(t.span))],
525            column_filter: Some(ColumnFilter::Lambda(Lambda {
526                params: vec![ident],
527                expr: Box::new(expr),
528            })),
529        },
530    );
531
532    let projection = map(
533        rule! {
534            #expr ~ #alias_name?
535        },
536        |(expr, alias)| SelectTarget::AliasedExpr {
537            expr: Box::new(expr),
538            alias,
539        },
540    );
541
542    rule!(
543        #qualified_wildcard
544        | #columns_regexp
545        | #columns_lambda
546        | #projection
547    )(i)
548}
549
550pub fn travel_point(i: Input) -> IResult<TimeTravelPoint> {
551    let at_stream = map(
552        rule! { "(" ~ STREAM ~ "=>" ~  #dot_separated_idents_1_to_3 ~ ")" },
553        |(_, _, _, (catalog, database, name), _)| TimeTravelPoint::Stream {
554            catalog,
555            database,
556            name,
557        },
558    );
559
560    rule!(
561        #at_stream | #at_snapshot_or_ts
562    )(i)
563}
564
565pub fn at_snapshot_or_ts(i: Input) -> IResult<TimeTravelPoint> {
566    let at_snapshot = map(
567        rule! { "(" ~ SNAPSHOT ~ "=>" ~ #literal_string ~ ")" },
568        |(_, _, _, s, _)| TimeTravelPoint::Snapshot(s),
569    );
570    let at_timestamp = map(
571        rule! { "(" ~ TIMESTAMP ~ "=>" ~ #expr ~ ")" },
572        |(_, _, _, e, _)| TimeTravelPoint::Timestamp(Box::new(e)),
573    );
574    let at_offset = map(
575        rule! { "(" ~ OFFSET ~ "=>" ~ #expr ~ ")" },
576        |(_, _, _, e, _)| TimeTravelPoint::Offset(Box::new(e)),
577    );
578
579    rule!(
580        #at_snapshot | #at_timestamp | #at_offset
581    )(i)
582}
583
584pub fn temporal_clause(i: Input) -> IResult<TemporalClause> {
585    let time_travel = map(
586        rule! {
587            AT ~ ^#travel_point
588        },
589        |(_, travel_point)| TemporalClause::TimeTravel(travel_point),
590    );
591
592    let changes = map(
593        rule! {
594            CHANGES ~ "(" ~ INFORMATION ~ "=>" ~ ( DEFAULT | APPEND_ONLY ) ~ ")" ~ AT ~ ^#travel_point ~ (END ~ ^#at_snapshot_or_ts)?
595        },
596        |(_, _, _, _, changes_type, _, _, at_point, opt_end_point)| {
597            let append_only = matches!(changes_type.kind, APPEND_ONLY);
598            TemporalClause::Changes(ChangesInterval {
599                append_only,
600                at_point,
601                end_point: opt_end_point.map(|p| p.1),
602            })
603        },
604    );
605
606    rule!(
607        #time_travel
608        | #changes
609    )(i)
610}
611
612pub fn alias_name(i: Input) -> IResult<Identifier> {
613    let short_alias = map(
614        rule! {
615            #ident
616            ~ #error_hint(
617                rule! { AS },
618                "an alias without `AS` keyword has already been defined before this one, \
619                    please remove one of them"
620            )
621        },
622        |(ident, _)| ident,
623    );
624    let as_alias = map(
625        rule! {
626            AS ~ #ident_after_as
627        },
628        |(_, name)| name,
629    );
630
631    rule!(
632        #short_alias
633        | #as_alias
634    )(i)
635}
636
637pub fn with_options(i: Input) -> IResult<WithOptions> {
638    alt((
639        map(rule! { WITH ~ CONSUME }, |_| WithOptions {
640            options: BTreeMap::from([("consume".to_string(), "true".to_string())]),
641        }),
642        map(
643            rule! {
644                WITH ~ "(" ~ #set_table_option ~ ")"
645            },
646            |(_, _, options, _)| WithOptions { options },
647        ),
648    ))(i)
649}
650
651pub fn table_alias(i: Input) -> IResult<TableAlias> {
652    map(
653        rule! { #alias_name ~ ( "(" ~ ^#comma_separated_list1(ident) ~ ^")" )? },
654        |(name, opt_columns)| TableAlias {
655            name,
656            columns: opt_columns.map(|(_, cols, _)| cols).unwrap_or_default(),
657        },
658    )(i)
659}
660
661pub fn table_alias_without_as(i: Input) -> IResult<TableAlias> {
662    map(
663        rule! { #ident ~ ( "(" ~ ^#comma_separated_list1(ident) ~ ^")" )? },
664        |(name, opt_columns)| TableAlias {
665            name,
666            columns: opt_columns.map(|(_, cols, _)| cols).unwrap_or_default(),
667        },
668    )(i)
669}
670
671pub fn join_operator(i: Input) -> IResult<JoinOperator> {
672    alt((
673        value(JoinOperator::Inner, rule! { INNER }),
674        value(JoinOperator::LeftSemi, rule! { LEFT? ~ SEMI }),
675        value(JoinOperator::RightSemi, rule! { RIGHT ~ SEMI }),
676        value(JoinOperator::LeftAnti, rule! { LEFT? ~ ANTI }),
677        value(JoinOperator::RightAnti, rule! { RIGHT ~ ANTI }),
678        value(JoinOperator::LeftOuter, rule! { LEFT ~ OUTER? }),
679        value(JoinOperator::RightOuter, rule! { RIGHT ~ OUTER? }),
680        value(JoinOperator::FullOuter, rule! { FULL ~ OUTER? }),
681        value(JoinOperator::CrossJoin, rule! { CROSS }),
682        value(JoinOperator::LeftAsof, rule! { ASOF ~ LEFT }),
683        value(JoinOperator::RightAsof, rule! { ASOF ~ RIGHT }),
684        value(JoinOperator::Asof, rule! { ASOF }),
685    ))(i)
686}
687
688pub fn order_by_expr(i: Input) -> IResult<OrderByExpr> {
689    let nulls_first = map(
690        rule! {
691            NULLS ~ ( FIRST | LAST )
692        },
693        |(_, first_last)| first_last.kind == FIRST,
694    );
695
696    map(
697        rule! {
698            #expr ~ ( ASC | DESC )? ~ #nulls_first?
699        },
700        |(expr, opt_asc, opt_nulls_first)| OrderByExpr {
701            expr,
702            asc: opt_asc.map(|asc| asc.kind == ASC),
703            nulls_first: opt_nulls_first,
704        },
705    )(i)
706}
707
708pub fn table_reference(i: Input) -> IResult<TableReference> {
709    let (rest, table_reference_elements) = rule! { #table_reference_element+ }(i)?;
710    let iter = &mut table_reference_elements.into_iter();
711    run_pratt_parser(TableReferenceParser, iter, rest, i)
712}
713
714#[derive(Debug, Clone, PartialEq)]
715pub enum TableFunctionParam {
716    // func(name => arg)
717    Named { name: Identifier, value: Expr },
718    // func(arg)
719    Normal(Expr),
720}
721
722pub fn table_function_param(i: Input) -> IResult<TableFunctionParam> {
723    let named = map(rule! { #ident ~ "=>" ~ #expr  }, |(name, _, value)| {
724        TableFunctionParam::Named { name, value }
725    });
726    let normal = map(rule! { #expr }, TableFunctionParam::Normal);
727
728    rule!(
729        #named | #normal
730    )(i)
731}
732
733#[derive(Debug, Clone, PartialEq)]
734pub enum TableReferenceElement {
735    Table {
736        catalog: Option<Identifier>,
737        database: Option<Identifier>,
738        table: Identifier,
739        alias: Option<TableAlias>,
740        temporal: Option<TemporalClause>,
741        with_options: Option<WithOptions>,
742        pivot: Option<Box<Pivot>>,
743        unpivot: Option<Box<Unpivot>>,
744        sample: Option<SampleConfig>,
745    },
746    // `TABLE(expr)[ AS alias ]`
747    TableFunction {
748        /// If the table function is a lateral table function
749        lateral: bool,
750        name: Identifier,
751        params: Vec<TableFunctionParam>,
752        alias: Option<TableAlias>,
753        sample: Option<SampleConfig>,
754    },
755    // Derived table, which can be a subquery or joined tables or combination of them
756    Subquery {
757        /// If the subquery is a lateral subquery
758        lateral: bool,
759        subquery: Box<Query>,
760        alias: Option<TableAlias>,
761        pivot: Option<Box<Pivot>>,
762        unpivot: Option<Box<Unpivot>>,
763    },
764    // [NATURAL] [INNER|OUTER|CROSS|...] JOIN
765    Join {
766        op: JoinOperator,
767        natural: bool,
768    },
769    // ON expr | USING (ident, ...)
770    JoinCondition(JoinCondition),
771    Group(TableReference),
772    Stage {
773        location: FileLocation,
774        options: Vec<SelectStageOption>,
775        alias: Option<TableAlias>,
776    },
777}
778
779pub fn table_reference_element(i: Input) -> IResult<WithSpan<TableReferenceElement>> {
780    let aliased_table = map(
781        rule! {
782            #dot_separated_idents_1_to_3 ~ #temporal_clause? ~ #with_options? ~ #table_alias? ~ #pivot? ~ #unpivot? ~ SAMPLE? ~ (BLOCK ~ "(" ~ #expr ~ ")")? ~ (ROW ~ "(" ~ #expr ~ ROWS? ~ ")")?
783        },
784        |(
785            (catalog, database, table),
786            temporal,
787            with_options,
788            alias,
789            pivot,
790            unpivot,
791            sample,
792            sample_block_level,
793            sample_row_level,
794        )| {
795            let table_sample = get_table_sample(sample, sample_block_level, sample_row_level);
796            TableReferenceElement::Table {
797                catalog,
798                database,
799                table,
800                alias,
801                temporal,
802                with_options,
803                pivot: pivot.map(Box::new),
804                unpivot: unpivot.map(Box::new),
805                sample: table_sample,
806            }
807        },
808    );
809    let join = map(
810        rule! {
811            NATURAL? ~ #join_operator? ~ JOIN
812        },
813        |(opt_natural, opt_op, _)| TableReferenceElement::Join {
814            op: opt_op.unwrap_or(JoinOperator::Inner),
815            natural: opt_natural.is_some(),
816        },
817    );
818    let join_condition_on = map(
819        rule! {
820            ON ~ #expr
821        },
822        |(_, expr)| TableReferenceElement::JoinCondition(JoinCondition::On(Box::new(expr))),
823    );
824    let join_condition_using = map(
825        rule! {
826            USING ~ "(" ~ #comma_separated_list1(ident) ~ ")"
827        },
828        |(_, _, idents, _)| TableReferenceElement::JoinCondition(JoinCondition::Using(idents)),
829    );
830    let table_function = map(
831        rule! {
832            LATERAL? ~ #function_name ~ "(" ~ #comma_separated_list0(table_function_param) ~ ")" ~ #table_alias? ~ SAMPLE? ~ (BLOCK ~ "(" ~ #expr ~ ")")? ~ (ROW ~ "(" ~ #expr ~ ROWS? ~ ")")?
833        },
834        |(lateral, name, _, params, _, alias, sample, level, sample_conf)| {
835            let table_sample = get_table_sample(sample, level, sample_conf);
836            TableReferenceElement::TableFunction {
837                lateral: lateral.is_some(),
838                name,
839                params,
840                alias,
841                sample: table_sample,
842            }
843        },
844    );
845    let subquery = map(
846        rule! {
847            LATERAL? ~ "(" ~ #query ~ ")" ~ #table_alias? ~ #pivot? ~ #unpivot?
848        },
849        |(lateral, _, subquery, _, alias, pivot, unpivot)| TableReferenceElement::Subquery {
850            lateral: lateral.is_some(),
851            subquery: Box::new(subquery),
852            alias,
853            pivot: pivot.map(Box::new),
854            unpivot: unpivot.map(Box::new),
855        },
856    );
857
858    let group = map(
859        rule! {
860           "(" ~ #table_reference ~ ^")"
861        },
862        |(_, table_ref, _)| TableReferenceElement::Group(table_ref),
863    );
864    let aliased_stage = map(
865        rule! {
866            #file_location ~  ( "(" ~ (#select_stage_option ~ ","?)* ~ ^")" )? ~ #table_alias?
867        },
868        |(location, options, alias)| {
869            let options = options
870                .map(|(_, options, _)| options.into_iter().map(|(option, _)| option).collect())
871                .unwrap_or_default();
872            TableReferenceElement::Stage {
873                location,
874                alias,
875                options,
876            }
877        },
878    );
879
880    let (rest, (span, elem)) = consumed(rule! {
881        #aliased_stage
882        | #table_function
883        | #aliased_table
884        | #subquery
885        | #group
886        | #join
887        | #join_condition_on
888        | #join_condition_using
889    })(i)?;
890    Ok((rest, WithSpan { span, elem }))
891}
892
893// PIVOT(expr FOR col IN (ident, ... | subquery))
894fn pivot(i: Input) -> IResult<Pivot> {
895    map(
896        rule! {
897            PIVOT ~ "(" ~ #expr ~ FOR ~ #ident ~ IN ~ "(" ~ #pivot_values ~ ")" ~ ")"
898        },
899        |(_pivot, _, aggregate, _for, value_column, _in, _, values, _, _)| Pivot {
900            aggregate,
901            value_column,
902            values,
903        },
904    )(i)
905}
906
907fn unpivot_name(i: Input) -> IResult<UnpivotName> {
908    let short_alias = map(
909        rule! {
910            #literal_string
911            ~ #error_hint(
912                rule! { AS },
913                "an alias without `AS` keyword has already been defined before this one, \
914                    please remove one of them"
915            )
916        },
917        |(string, _)| string,
918    );
919    let as_alias = map(
920        rule! {
921            AS ~ #literal_string
922        },
923        |(_, string)| string,
924    );
925    map(
926        rule! {#ident ~ (#short_alias | #as_alias)?},
927        |(ident, alias)| UnpivotName { ident, alias },
928    )(i)
929}
930
931// UNPIVOT(ident for ident IN (ident, ...))
932fn unpivot(i: Input) -> IResult<Unpivot> {
933    map(
934        rule! {
935            UNPIVOT ~ "(" ~ #ident ~ FOR ~ #ident ~ IN ~ "(" ~ #comma_separated_list1(unpivot_name) ~ ")" ~ ")"
936        },
937        |(_unpivot, _, value_column, _for, unpivot_column, _in, _, column_names, _, _)| Unpivot {
938            value_column,
939            unpivot_column,
940            column_names,
941        },
942    )(i)
943}
944
945fn pivot_values(i: Input) -> IResult<PivotValues> {
946    alt((
947        map(comma_separated_list1(expr), PivotValues::ColumnValues),
948        map(query, |q| PivotValues::Subquery(Box::new(q))),
949    ))(i)
950}
951
952fn get_table_sample(
953    sample: Option<&Token>,
954    block_level_sample: Option<(&Token, &Token, Expr, &Token)>,
955    row_level_sample: Option<(&Token, &Token, Expr, Option<&Token>, &Token)>,
956) -> Option<SampleConfig> {
957    let mut default_sample_conf = SampleConfig::default();
958    if sample.is_some() {
959        if let Some((_, _, Expr::Literal { value, .. }, _)) = block_level_sample {
960            default_sample_conf.set_block_level_sample(value.as_double().unwrap_or_default());
961        }
962        if let Some((_, _, Expr::Literal { value, .. }, rows, _)) = row_level_sample {
963            default_sample_conf
964                .set_row_level_sample(value.as_double().unwrap_or_default(), rows.is_some());
965        }
966        return Some(default_sample_conf);
967    }
968    None
969}
970
971struct TableReferenceParser;
972
973impl<'a, I: Iterator<Item = WithSpan<'a, TableReferenceElement>>> PrattParser<I>
974    for TableReferenceParser
975{
976    type Error = &'static str;
977    type Input = WithSpan<'a, TableReferenceElement>;
978    type Output = TableReference;
979
980    fn query(&mut self, input: &Self::Input) -> Result<Affix, &'static str> {
981        let affix = match &input.elem {
982            TableReferenceElement::Join { .. } => Affix::Infix(Precedence(10), Associativity::Left),
983            TableReferenceElement::JoinCondition(..) => Affix::Postfix(Precedence(5)),
984            _ => Affix::Nilfix,
985        };
986        Ok(affix)
987    }
988
989    fn primary(&mut self, input: Self::Input) -> Result<Self::Output, &'static str> {
990        let table_ref = match input.elem {
991            TableReferenceElement::Group(table_ref) => table_ref,
992            TableReferenceElement::Table {
993                catalog,
994                database,
995                table,
996                alias,
997                temporal,
998                with_options,
999                pivot,
1000                unpivot,
1001                sample,
1002            } => TableReference::Table {
1003                span: transform_span(input.span.tokens),
1004                catalog,
1005                database,
1006                table,
1007                alias,
1008                temporal,
1009                with_options,
1010                pivot,
1011                unpivot,
1012                sample,
1013            },
1014            TableReferenceElement::TableFunction {
1015                lateral,
1016                name,
1017                params,
1018                alias,
1019                sample,
1020            } => {
1021                let normal_params = params
1022                    .iter()
1023                    .filter_map(|p| match p {
1024                        TableFunctionParam::Normal(p) => Some(p.clone()),
1025                        _ => None,
1026                    })
1027                    .collect();
1028                let named_params = params
1029                    .into_iter()
1030                    .filter_map(|p| match p {
1031                        TableFunctionParam::Named { name, value } => Some((name, value)),
1032                        _ => None,
1033                    })
1034                    .collect();
1035                TableReference::TableFunction {
1036                    span: transform_span(input.span.tokens),
1037                    lateral,
1038                    name,
1039                    params: normal_params,
1040                    named_params,
1041                    alias,
1042                    sample,
1043                }
1044            }
1045            TableReferenceElement::Subquery {
1046                lateral,
1047                subquery,
1048                alias,
1049                pivot,
1050                unpivot,
1051            } => TableReference::Subquery {
1052                span: transform_span(input.span.tokens),
1053                lateral,
1054                subquery,
1055                alias,
1056                pivot,
1057                unpivot,
1058            },
1059            TableReferenceElement::Stage {
1060                location,
1061                options,
1062                alias,
1063            } => {
1064                let options = SelectStageOptions::from(options);
1065                TableReference::Location {
1066                    span: transform_span(input.span.tokens),
1067                    location,
1068                    options,
1069                    alias,
1070                }
1071            }
1072            _ => unreachable!(),
1073        };
1074        Ok(table_ref)
1075    }
1076
1077    fn infix(
1078        &mut self,
1079        lhs: Self::Output,
1080        input: Self::Input,
1081        rhs: Self::Output,
1082    ) -> Result<Self::Output, &'static str> {
1083        let table_ref = match input.elem {
1084            TableReferenceElement::Join { op, natural } => {
1085                let condition = if natural {
1086                    JoinCondition::Natural
1087                } else {
1088                    JoinCondition::None
1089                };
1090                TableReference::Join {
1091                    span: transform_span(input.span.tokens),
1092                    join: Join {
1093                        op,
1094                        condition,
1095                        left: Box::new(lhs),
1096                        right: Box::new(rhs),
1097                    },
1098                }
1099            }
1100            _ => unreachable!(),
1101        };
1102        Ok(table_ref)
1103    }
1104
1105    fn prefix(
1106        &mut self,
1107        _op: Self::Input,
1108        _rhs: Self::Output,
1109    ) -> Result<Self::Output, Self::Error> {
1110        unreachable!()
1111    }
1112
1113    fn postfix(
1114        &mut self,
1115        mut lhs: Self::Output,
1116        op: Self::Input,
1117    ) -> Result<Self::Output, Self::Error> {
1118        match op.elem {
1119            TableReferenceElement::JoinCondition(new_condition) => match &mut lhs {
1120                TableReference::Join {
1121                    join: Join { condition, .. },
1122                    ..
1123                } => match *condition {
1124                    JoinCondition::None => {
1125                        *condition = new_condition;
1126                        Ok(lhs)
1127                    }
1128                    JoinCondition::Natural => Err("join condition conflicting with NATURAL"),
1129                    _ => Err("join condition already set"),
1130                },
1131                _ => Err("join condition must apply to a join"),
1132            },
1133            _ => unreachable!(),
1134        }
1135    }
1136}
1137
1138pub fn group_by_items(i: Input) -> IResult<GroupBy> {
1139    let all = map(rule! { ALL }, |_| GroupBy::All);
1140
1141    let cube = map(
1142        rule! { CUBE ~ "(" ~ ^#comma_separated_list1(expr) ~ ")" },
1143        |(_, _, groups, _)| GroupBy::Cube(groups),
1144    );
1145    let rollup = map(
1146        rule! { ROLLUP ~ "(" ~ ^#comma_separated_list1(expr) ~ ")" },
1147        |(_, _, groups, _)| GroupBy::Rollup(groups),
1148    );
1149    let group_set = alt((
1150        map(rule! {"(" ~ ")"}, |(_, _)| vec![]), // empty grouping set
1151        map(
1152            rule! {"(" ~ #comma_separated_list1(expr) ~ ")"},
1153            |(_, sets, _)| sets,
1154        ),
1155        map(rule! { #expr }, |e| vec![e]),
1156    ));
1157    let group_sets = map(
1158        rule! { GROUPING ~ ^SETS ~ "(" ~ ^#comma_separated_list1(group_set) ~ ")"  },
1159        |(_, _, _, sets, _)| GroupBy::GroupingSets(sets),
1160    );
1161
1162    // New rule to handle multiple GroupBy items
1163    let single_normal = map(rule! { #expr }, |group| GroupBy::Normal(vec![group]));
1164    let group_by_item = alt((all, group_sets, cube, rollup, single_normal));
1165    map(rule! { ^#comma_separated_list1(group_by_item) }, |items| {
1166        if items.len() > 1 {
1167            if items.iter().all(|item| matches!(item, GroupBy::Normal(_))) {
1168                let items = items
1169                    .into_iter()
1170                    .flat_map(|item| match item {
1171                        GroupBy::Normal(exprs) => exprs,
1172                        _ => unreachable!(),
1173                    })
1174                    .collect();
1175                GroupBy::Normal(items)
1176            } else {
1177                GroupBy::Combined(items)
1178            }
1179        } else {
1180            items.into_iter().next().unwrap()
1181        }
1182    })(i)
1183}
1184
1185pub fn window_frame_bound(i: Input) -> IResult<WindowFrameBound> {
1186    alt((
1187        value(WindowFrameBound::CurrentRow, rule! { CURRENT ~ ROW }),
1188        value(
1189            WindowFrameBound::Preceding(None),
1190            rule! { UNBOUNDED ~ PRECEDING },
1191        ),
1192        map(rule! { #subexpr(0) ~ PRECEDING }, |(expr, _)| {
1193            WindowFrameBound::Preceding(Some(Box::new(expr)))
1194        }),
1195        value(
1196            WindowFrameBound::Following(None),
1197            rule! { UNBOUNDED ~ FOLLOWING },
1198        ),
1199        map(rule! { #subexpr(0) ~ FOLLOWING }, |(expr, _)| {
1200            WindowFrameBound::Following(Some(Box::new(expr)))
1201        }),
1202    ))(i)
1203}
1204
1205pub fn window_frame_between(i: Input) -> IResult<(WindowFrameBound, WindowFrameBound)> {
1206    alt((
1207        map(
1208            rule! { BETWEEN ~ #window_frame_bound ~ AND ~ #window_frame_bound },
1209            |(_, s, _, e)| (s, e),
1210        ),
1211        map(rule! { #window_frame_bound }, |s| {
1212            (s, WindowFrameBound::CurrentRow)
1213        }),
1214    ))(i)
1215}
1216
1217pub fn window_spec(i: Input) -> IResult<WindowSpec> {
1218    map(
1219        rule! {
1220            #ident?
1221            ~ ( PARTITION ~ ^BY ~ ^#comma_separated_list1(subexpr(0)) )?
1222            ~ ( ORDER ~ ^BY ~ ^#comma_separated_list1(order_by_expr) )?
1223            ~ ( (ROWS | RANGE) ~ ^#window_frame_between )?
1224        },
1225        |(existing_window_name, opt_partition, opt_order, between)| WindowSpec {
1226            existing_window_name,
1227            partition_by: opt_partition.map(|x| x.2).unwrap_or_default(),
1228            order_by: opt_order.map(|x| x.2).unwrap_or_default(),
1229            window_frame: between.map(|x| {
1230                let unit = match x.0.kind {
1231                    ROWS => WindowFrameUnits::Rows,
1232                    RANGE => WindowFrameUnits::Range,
1233                    _ => unreachable!(),
1234                };
1235                let bw = x.1;
1236                WindowFrame {
1237                    units: unit,
1238                    start_bound: bw.0,
1239                    end_bound: bw.1,
1240                }
1241            }),
1242        },
1243    )(i)
1244}
1245
1246pub fn window_spec_ident(i: Input) -> IResult<Window> {
1247    alt((
1248        map(
1249            rule! {
1250               "(" ~ #window_spec ~ ")"
1251            },
1252            |(_, spec, _)| Window::WindowSpec(spec),
1253        ),
1254        map(
1255            rule! {
1256                #ident
1257            },
1258            |window_name| Window::WindowReference(WindowRef { window_name }),
1259        ),
1260    ))(i)
1261}
1262
1263pub fn within_group(i: Input) -> IResult<Vec<OrderByExpr>> {
1264    map(
1265        rule! {
1266        WITHIN ~ GROUP ~ "(" ~ ORDER ~ ^BY ~ ^#comma_separated_list1(order_by_expr) ~ ")"
1267        },
1268        |(_, _, _, _, _, order_by, _)| order_by,
1269    )(i)
1270}
1271
1272pub fn window_function(i: Input) -> IResult<WindowDesc> {
1273    map(
1274        rule! {
1275        (( IGNORE | RESPECT ) ~ NULLS)? ~ (OVER ~ #window_spec_ident)
1276        },
1277        |(opt_ignore_nulls, window)| WindowDesc {
1278            ignore_nulls: opt_ignore_nulls.map(|key| key.0.kind == IGNORE),
1279            window: window.1,
1280        },
1281    )(i)
1282}
1283
1284pub fn window_clause(i: Input) -> IResult<WindowDefinition> {
1285    map(
1286        rule! {
1287            #ident ~ AS ~ "(" ~ #window_spec ~ ")"
1288        },
1289        |(ident, _, _, window, _)| WindowDefinition {
1290            name: ident,
1291            spec: window,
1292        },
1293    )(i)
1294}