Snowflake Reserved SQL Keywords as Implicit Table Alias (#1934)

This commit is contained in:
Yoav Cohen 2025-07-11 11:13:20 +02:00 committed by GitHub
parent fd4934ec74
commit 15f35e1476
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 163 additions and 12 deletions

View file

@ -5548,7 +5548,8 @@ fn parse_named_window_functions() {
WINDOW w AS (PARTITION BY x), win AS (ORDER BY y)";
supported_dialects.verified_stmt(sql);
let select = verified_only_select(sql);
let select = all_dialects_except(|d| d.is_table_alias(&Keyword::WINDOW, &mut Parser::new(d)))
.verified_only_select(sql);
const EXPECTED_PROJ_QTY: usize = 2;
assert_eq!(EXPECTED_PROJ_QTY, select.projection.len());
@ -5578,6 +5579,7 @@ fn parse_named_window_functions() {
#[test]
fn parse_window_clause() {
let dialects = all_dialects_except(|d| d.is_table_alias(&Keyword::WINDOW, &mut Parser::new(d)));
let sql = "SELECT * \
FROM mytable \
WINDOW \
@ -5590,10 +5592,14 @@ fn parse_window_clause() {
window7 AS (window1 ROWS UNBOUNDED PRECEDING), \
window8 AS (window1 PARTITION BY a ORDER BY b ROWS UNBOUNDED PRECEDING) \
ORDER BY C3";
verified_only_select(sql);
dialects.verified_only_select(sql);
let sql = "SELECT * from mytable WINDOW window1 AS window2";
let dialects = all_dialects_except(|d| d.is::<BigQueryDialect>() || d.is::<GenericDialect>());
let dialects = all_dialects_except(|d| {
d.is::<BigQueryDialect>()
|| d.is::<GenericDialect>()
|| d.is_table_alias(&Keyword::WINDOW, &mut Parser::new(d))
});
let res = dialects.parse_sql_statements(sql);
assert_eq!(
ParserError::ParserError("Expected: (, found: window2".to_string()),
@ -5603,6 +5609,7 @@ fn parse_window_clause() {
#[test]
fn test_parse_named_window() {
let dialects = all_dialects_except(|d| d.is_table_alias(&Keyword::WINDOW, &mut Parser::new(d)));
let sql = "SELECT \
MIN(c12) OVER window1 AS min1, \
MAX(c12) OVER window2 AS max1 \
@ -5610,7 +5617,7 @@ fn test_parse_named_window() {
WINDOW window1 AS (ORDER BY C12), \
window2 AS (PARTITION BY C11) \
ORDER BY C3";
let actual_select_only = verified_only_select(sql);
let actual_select_only = dialects.verified_only_select(sql);
let expected = Select {
select_token: AttachedToken::empty(),
distinct: None,
@ -5759,6 +5766,10 @@ fn test_parse_named_window() {
#[test]
fn parse_window_and_qualify_clause() {
let dialects = all_dialects_except(|d| {
d.is_table_alias(&Keyword::WINDOW, &mut Parser::new(d))
|| d.is_table_alias(&Keyword::QUALIFY, &mut Parser::new(d))
});
let sql = "SELECT \
MIN(c12) OVER window1 AS min1 \
FROM aggregate_test_100 \
@ -5766,7 +5777,7 @@ fn parse_window_and_qualify_clause() {
WINDOW window1 AS (ORDER BY C12), \
window2 AS (PARTITION BY C11) \
ORDER BY C3";
verified_only_select(sql);
dialects.verified_only_select(sql);
let sql = "SELECT \
MIN(c12) OVER window1 AS min1 \
@ -5775,7 +5786,7 @@ fn parse_window_and_qualify_clause() {
window2 AS (PARTITION BY C11) \
QUALIFY ROW_NUMBER() OVER my_window \
ORDER BY C3";
verified_only_select(sql);
dialects.verified_only_select(sql);
}
#[test]
@ -7443,7 +7454,8 @@ fn parse_join_syntax_variants() {
"SELECT c1 FROM t1 FULL JOIN t2 USING(c1)",
);
let res = parse_sql_statements("SELECT * FROM a OUTER JOIN b ON 1");
let dialects = all_dialects_except(|d| d.is_table_alias(&Keyword::OUTER, &mut Parser::new(d)));
let res = dialects.parse_sql_statements("SELECT * FROM a OUTER JOIN b ON 1");
assert_eq!(
ParserError::ParserError("Expected: APPLY, found: JOIN".to_string()),
res.unwrap_err()

View file

@ -3492,6 +3492,57 @@ fn test_sql_keywords_as_select_item_aliases() {
}
}
#[test]
fn test_sql_keywords_as_table_aliases() {
// Some keywords that should be parsed as an alias implicitly
let unreserved_kws = vec![
"VIEW",
"EXPLAIN",
"ANALYZE",
"SORT",
"PIVOT",
"UNPIVOT",
"TOP",
"LIMIT",
"OFFSET",
"FETCH",
"EXCEPT",
"CLUSTER",
"DISTRIBUTE",
"GLOBAL",
"ANTI",
"SEMI",
"RETURNING",
"OUTER",
"WINDOW",
"END",
"PARTITION",
"PREWHERE",
"SETTINGS",
"FORMAT",
"MATCH_RECOGNIZE",
"OPEN",
];
for kw in unreserved_kws {
snowflake().verified_stmt(&format!("SELECT * FROM tbl AS {kw}"));
snowflake().one_statement_parses_to(
&format!("SELECT * FROM tbl {kw}"),
&format!("SELECT * FROM tbl AS {kw}"),
);
}
// Some keywords that should not be parsed as an alias implicitly
let reserved_kws = vec![
"FROM", "GROUP", "HAVING", "ORDER", "SELECT", "UNION", "WHERE", "WITH",
];
for kw in reserved_kws {
assert!(snowflake()
.parse_sql_statements(&format!("SELECT * FROM tbl {kw}"))
.is_err());
}
}
#[test]
fn test_timetravel_at_before() {
snowflake().verified_only_select("SELECT * FROM tbl AT(TIMESTAMP => '2024-12-15 00:00:00')");