1use 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 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 map(
473 rule! {
474 ( #ident ~ "." ~ ( #ident ~ "." )? )? ~ "*" ~ ( EXCLUDE ~ #exclude_col )?
475 },
476 |(res, star, opt_exclude)| qualified_wildcard_transform(res, star, opt_exclude),
477 ),
478 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 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 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 Named { name: Identifier, value: Expr },
718 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 TableFunction {
748 lateral: bool,
750 name: Identifier,
751 params: Vec<TableFunctionParam>,
752 alias: Option<TableAlias>,
753 sample: Option<SampleConfig>,
754 },
755 Subquery {
757 lateral: bool,
759 subquery: Box<Query>,
760 alias: Option<TableAlias>,
761 pivot: Option<Box<Pivot>>,
762 unpivot: Option<Box<Unpivot>>,
763 },
764 Join {
766 op: JoinOperator,
767 natural: bool,
768 },
769 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
893fn 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
931fn 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![]), 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 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}