@@ -9988,6 +9988,48 @@ impl<'a> Parser<'a> {
9988
9988
Ok(IdentWithAlias { ident, alias })
9989
9989
}
9990
9990
9991
+ /// Parse `identifier [AS] identifier` where the AS keyword is optional
9992
+ fn parse_identifier_with_optional_alias(&mut self) -> Result<IdentWithAlias, ParserError> {
9993
+ let ident = self.parse_identifier()?;
9994
+ let _after_as = self.parse_keyword(Keyword::AS);
9995
+ let alias = self.parse_identifier()?;
9996
+ Ok(IdentWithAlias { ident, alias })
9997
+ }
9998
+
9999
+ /// Parse comma-separated list of parenthesized queries for pipe operators
10000
+ fn parse_pipe_operator_queries(&mut self) -> Result<Vec<Query>, ParserError> {
10001
+ self.parse_comma_separated(|parser| {
10002
+ parser.expect_token(&Token::LParen)?;
10003
+ let query = parser.parse_query()?;
10004
+ parser.expect_token(&Token::RParen)?;
10005
+ Ok(*query)
10006
+ })
10007
+ }
10008
+
10009
+ /// Parse set quantifier for pipe operators that require DISTINCT. E.g. INTERSECT and EXCEPT
10010
+ fn parse_distinct_required_set_quantifier(
10011
+ &mut self,
10012
+ operator_name: &str,
10013
+ ) -> Result<SetQuantifier, ParserError> {
10014
+ let quantifier = self.parse_set_quantifier(&Some(SetOperator::Intersect));
10015
+ match quantifier {
10016
+ SetQuantifier::Distinct | SetQuantifier::DistinctByName => Ok(quantifier),
10017
+ _ => Err(ParserError::ParserError(format!(
10018
+ "{operator_name} pipe operator requires DISTINCT modifier",
10019
+ ))),
10020
+ }
10021
+ }
10022
+
10023
+ /// Parse optional identifier alias (with or without AS keyword)
10024
+ fn parse_identifier_optional_alias(&mut self) -> Result<Option<Ident>, ParserError> {
10025
+ if self.parse_keyword(Keyword::AS) {
10026
+ Ok(Some(self.parse_identifier()?))
10027
+ } else {
10028
+ // Check if the next token is an identifier (implicit alias)
10029
+ self.maybe_parse(|parser| parser.parse_identifier())
10030
+ }
10031
+ }
10032
+
9991
10033
/// Optionally parses an alias for a select list item
9992
10034
fn maybe_parse_select_item_alias(&mut self) -> Result<Option<Ident>, ParserError> {
9993
10035
fn validator(explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
@@ -11134,6 +11176,19 @@ impl<'a> Parser<'a> {
11134
11176
Keyword::AGGREGATE,
11135
11177
Keyword::ORDER,
11136
11178
Keyword::TABLESAMPLE,
11179
+ Keyword::RENAME,
11180
+ Keyword::UNION,
11181
+ Keyword::INTERSECT,
11182
+ Keyword::EXCEPT,
11183
+ Keyword::CALL,
11184
+ Keyword::PIVOT,
11185
+ Keyword::UNPIVOT,
11186
+ Keyword::JOIN,
11187
+ Keyword::INNER,
11188
+ Keyword::LEFT,
11189
+ Keyword::RIGHT,
11190
+ Keyword::FULL,
11191
+ Keyword::CROSS,
11137
11192
])?;
11138
11193
match kw {
11139
11194
Keyword::SELECT => {
@@ -11200,6 +11255,121 @@ impl<'a> Parser<'a> {
11200
11255
let sample = self.parse_table_sample(TableSampleModifier::TableSample)?;
11201
11256
pipe_operators.push(PipeOperator::TableSample { sample });
11202
11257
}
11258
+ Keyword::RENAME => {
11259
+ let mappings =
11260
+ self.parse_comma_separated(Parser::parse_identifier_with_optional_alias)?;
11261
+ pipe_operators.push(PipeOperator::Rename { mappings });
11262
+ }
11263
+ Keyword::UNION => {
11264
+ let set_quantifier = self.parse_set_quantifier(&Some(SetOperator::Union));
11265
+ let queries = self.parse_pipe_operator_queries()?;
11266
+ pipe_operators.push(PipeOperator::Union {
11267
+ set_quantifier,
11268
+ queries,
11269
+ });
11270
+ }
11271
+ Keyword::INTERSECT => {
11272
+ let set_quantifier =
11273
+ self.parse_distinct_required_set_quantifier("INTERSECT")?;
11274
+ let queries = self.parse_pipe_operator_queries()?;
11275
+ pipe_operators.push(PipeOperator::Intersect {
11276
+ set_quantifier,
11277
+ queries,
11278
+ });
11279
+ }
11280
+ Keyword::EXCEPT => {
11281
+ let set_quantifier = self.parse_distinct_required_set_quantifier("EXCEPT")?;
11282
+ let queries = self.parse_pipe_operator_queries()?;
11283
+ pipe_operators.push(PipeOperator::Except {
11284
+ set_quantifier,
11285
+ queries,
11286
+ });
11287
+ }
11288
+ Keyword::CALL => {
11289
+ let function_name = self.parse_object_name(false)?;
11290
+ let function_expr = self.parse_function(function_name)?;
11291
+ if let Expr::Function(function) = function_expr {
11292
+ let alias = self.parse_identifier_optional_alias()?;
11293
+ pipe_operators.push(PipeOperator::Call { function, alias });
11294
+ } else {
11295
+ return Err(ParserError::ParserError(
11296
+ "Expected function call after CALL".to_string(),
11297
+ ));
11298
+ }
11299
+ }
11300
+ Keyword::PIVOT => {
11301
+ self.expect_token(&Token::LParen)?;
11302
+ let aggregate_functions =
11303
+ self.parse_comma_separated(Self::parse_aliased_function_call)?;
11304
+ self.expect_keyword_is(Keyword::FOR)?;
11305
+ let value_column = self.parse_period_separated(|p| p.parse_identifier())?;
11306
+ self.expect_keyword_is(Keyword::IN)?;
11307
+
11308
+ self.expect_token(&Token::LParen)?;
11309
+ let value_source = if self.parse_keyword(Keyword::ANY) {
11310
+ let order_by = if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) {
11311
+ self.parse_comma_separated(Parser::parse_order_by_expr)?
11312
+ } else {
11313
+ vec![]
11314
+ };
11315
+ PivotValueSource::Any(order_by)
11316
+ } else if self.peek_sub_query() {
11317
+ PivotValueSource::Subquery(self.parse_query()?)
11318
+ } else {
11319
+ PivotValueSource::List(
11320
+ self.parse_comma_separated(Self::parse_expr_with_alias)?,
11321
+ )
11322
+ };
11323
+ self.expect_token(&Token::RParen)?;
11324
+ self.expect_token(&Token::RParen)?;
11325
+
11326
+ let alias = self.parse_identifier_optional_alias()?;
11327
+
11328
+ pipe_operators.push(PipeOperator::Pivot {
11329
+ aggregate_functions,
11330
+ value_column,
11331
+ value_source,
11332
+ alias,
11333
+ });
11334
+ }
11335
+ Keyword::UNPIVOT => {
11336
+ self.expect_token(&Token::LParen)?;
11337
+ let value_column = self.parse_identifier()?;
11338
+ self.expect_keyword(Keyword::FOR)?;
11339
+ let name_column = self.parse_identifier()?;
11340
+ self.expect_keyword(Keyword::IN)?;
11341
+
11342
+ self.expect_token(&Token::LParen)?;
11343
+ let unpivot_columns = self.parse_comma_separated(Parser::parse_identifier)?;
11344
+ self.expect_token(&Token::RParen)?;
11345
+
11346
+ self.expect_token(&Token::RParen)?;
11347
+
11348
+ let alias = self.parse_identifier_optional_alias()?;
11349
+
11350
+ pipe_operators.push(PipeOperator::Unpivot {
11351
+ value_column,
11352
+ name_column,
11353
+ unpivot_columns,
11354
+ alias,
11355
+ });
11356
+ }
11357
+ Keyword::JOIN
11358
+ | Keyword::INNER
11359
+ | Keyword::LEFT
11360
+ | Keyword::RIGHT
11361
+ | Keyword::FULL
11362
+ | Keyword::CROSS => {
11363
+ self.prev_token();
11364
+ let mut joins = self.parse_joins()?;
11365
+ if joins.len() != 1 {
11366
+ return Err(ParserError::ParserError(
11367
+ "Join pipe operator must have a single join".to_string(),
11368
+ ));
11369
+ }
11370
+ let join = joins.swap_remove(0);
11371
+ pipe_operators.push(PipeOperator::Join(join))
11372
+ }
11203
11373
unhandled => {
11204
11374
return Err(ParserError::ParserError(format!(
11205
11375
"`expect_one_of_keywords` further up allowed unhandled keyword: {unhandled:?}"
0 commit comments