Skip to content

Commit e4ceed7

Browse files
Fix Snowflake wildcard REPLACE ... RENAME order
1 parent a685e11 commit e4ceed7

File tree

3 files changed

+51
-12
lines changed

3 files changed

+51
-12
lines changed

src/ast/query.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -547,19 +547,20 @@ impl fmt::Display for IdentWithAlias {
547547
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
548548
pub struct WildcardAdditionalOptions {
549549
/// `[ILIKE...]`.
550-
/// Snowflake syntax: <https://docs.snowflake.com/en/sql-reference/sql/select>
550+
/// Snowflake syntax: <https://docs.snowflake.com/en/sql-reference/sql/select#parameters>
551551
pub opt_ilike: Option<IlikeSelectItem>,
552552
/// `[EXCLUDE...]`.
553553
pub opt_exclude: Option<ExcludeSelectItem>,
554554
/// `[EXCEPT...]`.
555555
/// Clickhouse syntax: <https://clickhouse.com/docs/en/sql-reference/statements/select#except>
556556
pub opt_except: Option<ExceptSelectItem>,
557-
/// `[RENAME ...]`.
558-
pub opt_rename: Option<RenameSelectItem>,
559557
/// `[REPLACE]`
560558
/// BigQuery syntax: <https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select_replace>
561559
/// Clickhouse syntax: <https://clickhouse.com/docs/en/sql-reference/statements/select#replace>
560+
/// Snowflake syntax: <https://docs.snowflake.com/en/sql-reference/sql/select#parameters>
562561
pub opt_replace: Option<ReplaceSelectItem>,
562+
/// `[RENAME ...]`.
563+
pub opt_rename: Option<RenameSelectItem>,
563564
}
564565

565566
impl fmt::Display for WildcardAdditionalOptions {
@@ -573,12 +574,12 @@ impl fmt::Display for WildcardAdditionalOptions {
573574
if let Some(except) = &self.opt_except {
574575
write!(f, " {except}")?;
575576
}
576-
if let Some(rename) = &self.opt_rename {
577-
write!(f, " {rename}")?;
578-
}
579577
if let Some(replace) = &self.opt_replace {
580578
write!(f, " {replace}")?;
581579
}
580+
if let Some(rename) = &self.opt_rename {
581+
write!(f, " {rename}")?;
582+
}
582583
Ok(())
583584
}
584585
}

src/parser/mod.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10175,15 +10175,14 @@ impl<'a> Parser<'a> {
1017510175
} else {
1017610176
None
1017710177
};
10178-
let opt_rename = if dialect_of!(self is GenericDialect | SnowflakeDialect) {
10179-
self.parse_optional_select_item_rename()?
10178+
let opt_replace = if dialect_of!(self is GenericDialect | BigQueryDialect | ClickHouseDialect | DuckDbDialect | SnowflakeDialect)
10179+
{
10180+
self.parse_optional_select_item_replace()?
1018010181
} else {
1018110182
None
1018210183
};
10183-
10184-
let opt_replace = if dialect_of!(self is GenericDialect | BigQueryDialect | ClickHouseDialect | DuckDbDialect | SnowflakeDialect)
10185-
{
10186-
self.parse_optional_select_item_replace()?
10184+
let opt_rename = if dialect_of!(self is GenericDialect | SnowflakeDialect) {
10185+
self.parse_optional_select_item_rename()?
1018710186
} else {
1018810187
None
1018910188
};

tests/sqlparser_snowflake.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,44 @@ fn test_select_wildcard_with_rename() {
10161016
assert_eq!(expected, select.projection[0]);
10171017
}
10181018

1019+
#[test]
1020+
fn test_select_wildcard_with_replace_and_rename() {
1021+
let select = snowflake_and_generic().verified_only_select(
1022+
"SELECT * REPLACE (col_z || col_z AS col_z) RENAME (col_z AS col_zz) FROM data",
1023+
);
1024+
let expected = SelectItem::Wildcard(WildcardAdditionalOptions {
1025+
opt_replace: Some(ReplaceSelectItem {
1026+
items: vec![Box::new(ReplaceSelectElement {
1027+
expr: Expr::BinaryOp {
1028+
left: Box::new(Expr::Identifier(Ident::new("col_z"))),
1029+
op: BinaryOperator::StringConcat,
1030+
right: Box::new(Expr::Identifier(Ident::new("col_z"))),
1031+
},
1032+
column_name: Ident::new("col_z"),
1033+
as_keyword: true,
1034+
})],
1035+
}),
1036+
opt_rename: Some(RenameSelectItem::Multiple(vec![IdentWithAlias {
1037+
ident: Ident::new("col_z"),
1038+
alias: Ident::new("col_zz"),
1039+
}])),
1040+
..Default::default()
1041+
});
1042+
assert_eq!(expected, select.projection[0]);
1043+
1044+
// rename cannot precede replace
1045+
// https://docs.snowflake.com/en/sql-reference/sql/select#parameters
1046+
assert_eq!(
1047+
snowflake_and_generic()
1048+
.parse_sql_statements(
1049+
"SELECT * RENAME (col_z AS col_zz) REPLACE (col_z || col_z AS col_z) FROM data"
1050+
)
1051+
.unwrap_err()
1052+
.to_string(),
1053+
"sql parser error: Expected: end of statement, found: REPLACE"
1054+
);
1055+
}
1056+
10191057
#[test]
10201058
fn test_select_wildcard_with_exclude_and_rename() {
10211059
let select = snowflake_and_generic()
@@ -1031,6 +1069,7 @@ fn test_select_wildcard_with_exclude_and_rename() {
10311069
assert_eq!(expected, select.projection[0]);
10321070

10331071
// rename cannot precede exclude
1072+
// https://docs.snowflake.com/en/sql-reference/sql/select#parameters
10341073
assert_eq!(
10351074
snowflake_and_generic()
10361075
.parse_sql_statements("SELECT * RENAME col_a AS col_b EXCLUDE col_z FROM data")

0 commit comments

Comments
 (0)