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