Skip to content

Commit 34ba719

Browse files
committed
self review
1 parent 4478d6b commit 34ba719

2 files changed

Lines changed: 64 additions & 109 deletions

File tree

src/ast/query.rs

Lines changed: 31 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2812,69 +2812,15 @@ impl fmt::Display for PipeOperator {
28122812
PipeOperator::Union {
28132813
set_quantifier,
28142814
queries,
2815-
} => {
2816-
write!(f, "UNION")?;
2817-
match set_quantifier {
2818-
SetQuantifier::All => write!(f, " ALL")?,
2819-
SetQuantifier::Distinct => write!(f, " DISTINCT")?,
2820-
SetQuantifier::None => {}
2821-
_ => {
2822-
write!(f, " {}", set_quantifier)?;
2823-
}
2824-
}
2825-
write!(f, " ")?;
2826-
for (i, query) in queries.iter().enumerate() {
2827-
if i > 0 {
2828-
write!(f, ", ")?;
2829-
}
2830-
write!(f, "({})", query)?;
2831-
}
2832-
Ok(())
2833-
}
2815+
} => Self::fmt_set_operation(f, "UNION", set_quantifier, queries),
28342816
PipeOperator::Intersect {
28352817
set_quantifier,
28362818
queries,
2837-
} => {
2838-
write!(f, "INTERSECT")?;
2839-
match set_quantifier {
2840-
SetQuantifier::All => write!(f, " ALL")?,
2841-
SetQuantifier::Distinct => write!(f, " DISTINCT")?,
2842-
SetQuantifier::None => {}
2843-
_ => {
2844-
write!(f, " {}", set_quantifier)?;
2845-
}
2846-
}
2847-
write!(f, " ")?;
2848-
for (i, query) in queries.iter().enumerate() {
2849-
if i > 0 {
2850-
write!(f, ", ")?;
2851-
}
2852-
write!(f, "({})", query)?;
2853-
}
2854-
Ok(())
2855-
}
2819+
} => Self::fmt_set_operation(f, "INTERSECT", set_quantifier, queries),
28562820
PipeOperator::Except {
28572821
set_quantifier,
28582822
queries,
2859-
} => {
2860-
write!(f, "EXCEPT")?;
2861-
match set_quantifier {
2862-
SetQuantifier::All => write!(f, " ALL")?,
2863-
SetQuantifier::Distinct => write!(f, " DISTINCT")?,
2864-
SetQuantifier::None => {}
2865-
_ => {
2866-
write!(f, " {}", set_quantifier)?;
2867-
}
2868-
}
2869-
write!(f, " ")?;
2870-
for (i, query) in queries.iter().enumerate() {
2871-
if i > 0 {
2872-
write!(f, ", ")?;
2873-
}
2874-
write!(f, "({})", query)?;
2875-
}
2876-
Ok(())
2877-
}
2823+
} => Self::fmt_set_operation(f, "EXCEPT", set_quantifier, queries),
28782824
PipeOperator::Call { function, alias } => {
28792825
write!(f, "CALL {}", function)?;
28802826
if let Some(alias) = alias {
@@ -2922,6 +2868,34 @@ impl fmt::Display for PipeOperator {
29222868
}
29232869
}
29242870

2871+
impl PipeOperator {
2872+
/// Helper function to format set operations (UNION, INTERSECT, EXCEPT) with queries
2873+
fn fmt_set_operation(
2874+
f: &mut fmt::Formatter<'_>,
2875+
operation: &str,
2876+
set_quantifier: &SetQuantifier,
2877+
queries: &[Box<Query>],
2878+
) -> fmt::Result {
2879+
write!(f, "{}", operation)?;
2880+
match set_quantifier {
2881+
SetQuantifier::All => write!(f, " ALL")?,
2882+
SetQuantifier::Distinct => write!(f, " DISTINCT")?,
2883+
SetQuantifier::None => {}
2884+
_ => {
2885+
write!(f, " {}", set_quantifier)?;
2886+
}
2887+
}
2888+
write!(f, " ")?;
2889+
for (i, query) in queries.iter().enumerate() {
2890+
if i > 0 {
2891+
write!(f, ", ")?;
2892+
}
2893+
write!(f, "({})", query)?;
2894+
}
2895+
Ok(())
2896+
}
2897+
}
2898+
29252899
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
29262900
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
29272901
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]

src/parser/mod.rs

Lines changed: 33 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -9947,13 +9947,41 @@ impl<'a> Parser<'a> {
99479947
Ok(IdentWithAlias { ident, alias })
99489948
}
99499949

9950+
/// Parse `identifier [AS] identifier` where the AS keyword is optional
99509951
pub fn parse_identifier_with_optional_alias(&mut self) -> Result<IdentWithAlias, ParserError> {
99519952
let ident = self.parse_identifier()?;
99529953
let _after_as = self.parse_keyword(Keyword::AS);
99539954
let alias = self.parse_identifier()?;
99549955
Ok(IdentWithAlias { ident, alias })
99559956
}
99569957

9958+
/// Parse comma-separated list of parenthesized queries for pipe operators
9959+
fn parse_pipe_operator_queries(&mut self) -> Result<Vec<Box<Query>>, ParserError> {
9960+
self.parse_comma_separated(|parser| {
9961+
parser.expect_token(&Token::LParen)?;
9962+
let query = parser.parse_query()?;
9963+
parser.expect_token(&Token::RParen)?;
9964+
Ok(query)
9965+
})
9966+
}
9967+
9968+
/// Parse optional alias (with or without AS keyword) for pipe operators
9969+
fn parse_optional_pipe_alias(&mut self) -> Result<Option<Ident>, ParserError> {
9970+
if self.parse_keyword(Keyword::AS) {
9971+
Some(self.parse_identifier()).transpose()
9972+
} else {
9973+
// Check if the next token is an identifier (implicit alias)
9974+
let checkpoint = self.index;
9975+
match self.parse_identifier() {
9976+
Ok(ident) => Ok(Some(ident)),
9977+
Err(_) => {
9978+
self.index = checkpoint; // Rewind on failure
9979+
Ok(None)
9980+
}
9981+
}
9982+
}
9983+
}
9984+
99579985
/// Optionally parses an alias for a select list item
99589986
fn maybe_parse_select_item_alias(&mut self) -> Result<Option<Ident>, ParserError> {
99599987
fn validator(explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
@@ -11164,14 +11192,7 @@ impl<'a> Parser<'a> {
1116411192
Keyword::UNION => {
1116511193
// Reuse existing set quantifier parser for consistent BY NAME support
1116611194
let set_quantifier = self.parse_set_quantifier(&Some(SetOperator::Union));
11167-
// BigQuery UNION pipe operator requires parentheses around queries
11168-
// Parse comma-separated list of parenthesized queries
11169-
let queries = self.parse_comma_separated(|parser| {
11170-
parser.expect_token(&Token::LParen)?;
11171-
let query = parser.parse_query()?;
11172-
parser.expect_token(&Token::RParen)?;
11173-
Ok(query)
11174-
})?;
11195+
let queries = self.parse_pipe_operator_queries()?;
1117511196
pipe_operators.push(PipeOperator::Union {
1117611197
set_quantifier,
1117711198
queries,
@@ -11189,14 +11210,7 @@ impl<'a> Parser<'a> {
1118911210
"INTERSECT pipe operator requires DISTINCT modifier".to_string(),
1119011211
));
1119111212
};
11192-
// BigQuery INTERSECT pipe operator requires parentheses around queries
11193-
// Parse comma-separated list of parenthesized queries
11194-
let queries = self.parse_comma_separated(|parser| {
11195-
parser.expect_token(&Token::LParen)?;
11196-
let query = parser.parse_query()?;
11197-
parser.expect_token(&Token::RParen)?;
11198-
Ok(query)
11199-
})?;
11213+
let queries = self.parse_pipe_operator_queries()?;
1120011214
pipe_operators.push(PipeOperator::Intersect {
1120111215
set_quantifier,
1120211216
queries,
@@ -11214,14 +11228,7 @@ impl<'a> Parser<'a> {
1121411228
"EXCEPT pipe operator requires DISTINCT modifier".to_string(),
1121511229
));
1121611230
};
11217-
// BigQuery EXCEPT pipe operator requires parentheses around queries
11218-
// Parse comma-separated list of parenthesized queries
11219-
let queries = self.parse_comma_separated(|parser| {
11220-
parser.expect_token(&Token::LParen)?;
11221-
let query = parser.parse_query()?;
11222-
parser.expect_token(&Token::RParen)?;
11223-
Ok(query)
11224-
})?;
11231+
let queries = self.parse_pipe_operator_queries()?;
1122511232
pipe_operators.push(PipeOperator::Except {
1122611233
set_quantifier,
1122711234
queries,
@@ -11271,20 +11278,7 @@ impl<'a> Parser<'a> {
1127111278
self.expect_token(&Token::RParen)?;
1127211279
self.expect_token(&Token::RParen)?;
1127311280

11274-
// Parse optional alias (with or without AS keyword)
11275-
let alias = if self.parse_keyword(Keyword::AS) {
11276-
Some(self.parse_identifier()?)
11277-
} else {
11278-
// Check if the next token is an identifier (implicit alias)
11279-
let checkpoint = self.index;
11280-
match self.parse_identifier() {
11281-
Ok(ident) => Some(ident),
11282-
Err(_) => {
11283-
self.index = checkpoint; // Rewind on failure
11284-
None
11285-
}
11286-
}
11287-
};
11281+
let alias = self.parse_optional_pipe_alias()?;
1128811282

1128911283
pipe_operators.push(PipeOperator::Pivot {
1129011284
aggregate_functions,
@@ -11316,20 +11310,7 @@ impl<'a> Parser<'a> {
1131611310

1131711311
self.expect_token(&Token::RParen)?;
1131811312

11319-
// Parse optional alias (with or without AS keyword)
11320-
let alias = if self.parse_keyword(Keyword::AS) {
11321-
Some(self.parse_identifier()?)
11322-
} else {
11323-
// Check if the next token is an identifier (implicit alias)
11324-
let checkpoint = self.index;
11325-
match self.parse_identifier() {
11326-
Ok(ident) => Some(ident),
11327-
Err(_) => {
11328-
self.index = checkpoint; // Rewind on failure
11329-
None
11330-
}
11331-
}
11332-
};
11313+
let alias = self.parse_optional_pipe_alias()?;
1133311314

1133411315
pipe_operators.push(PipeOperator::Unpivot {
1133511316
value_column,

0 commit comments

Comments
 (0)