Skip to content

Commit 0b92e92

Browse files
committed
Disallow keywords as table aliases for parsing statements without semicolons
1 parent 792ed03 commit 0b92e92

2 files changed

Lines changed: 45 additions & 4 deletions

File tree

src/dialect/mod.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,8 +1291,14 @@ pub trait Dialect: Debug + Any {
12911291
/// Returns true if the specified keyword should be parsed as a table factor alias.
12921292
/// When explicit is true, the keyword is preceded by an `AS` word. Parser is provided
12931293
/// to enable looking ahead if needed.
1294-
fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
1295-
explicit || self.is_table_alias(kw, parser)
1294+
///
1295+
/// When the dialect supports statements without semicolon delimiter, actual keywords aren't parsed as aliases.
1296+
fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, _parser: &mut Parser) -> bool {
1297+
if self.supports_statements_without_semicolon_delimiter() {
1298+
kw == &Keyword::NoKeyword
1299+
} else {
1300+
explicit || self.is_table_alias(kw, _parser)
1301+
}
12961302
}
12971303

12981304
/// Returns true if this dialect supports querying historical table data

tests/sqlparser_common.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,28 @@ fn parse_select_with_table_alias() {
697697
);
698698
}
699699

700+
#[test]
701+
fn parse_select_with_table_alias_keyword() {
702+
// note: DECLARE isn't included in RESERVED_FOR_TABLE_ALIAS
703+
let table_alias_non_reserved_keyword = "SELECT a FROM lineitem DECLARE";
704+
let statements = all_dialects_requiring_semicolon_statement_delimiter()
705+
.parse_sql_statements(table_alias_non_reserved_keyword)
706+
.unwrap();
707+
assert_eq!(1, statements.len());
708+
assert_eq!(
709+
ParserError::ParserError("Expected: identifier, found: EOF".to_string()),
710+
all_dialects_not_requiring_semicolon_statement_delimiter()
711+
.parse_sql_statements(table_alias_non_reserved_keyword)
712+
.unwrap_err()
713+
);
714+
715+
let table_alias_quoted_keyword = "SELECT a FROM lineitem \"DECLARE\"";
716+
let statements = all_dialects()
717+
.parse_sql_statements(table_alias_quoted_keyword)
718+
.unwrap();
719+
assert_eq!(1, statements.len());
720+
}
721+
700722
#[test]
701723
fn parse_consecutive_queries() {
702724
let select_then_exec = "SELECT * FROM deleted; EXECUTE my_sp 'some', 'params'";
@@ -978,7 +1000,18 @@ fn parse_limit() {
9781000

9791001
#[test]
9801002
fn parse_invalid_limit_by() {
981-
assert_err_parse_statements("SELECT * FROM user BY name", "name");
1003+
assert_eq!(
1004+
ParserError::ParserError("Expected: end of statement, found: name".to_string()),
1005+
all_dialects_requiring_semicolon_statement_delimiter()
1006+
.parse_sql_statements("SELECT * FROM user BY name")
1007+
.unwrap_err()
1008+
);
1009+
assert_eq!(
1010+
ParserError::ParserError("Expected: an SQL statement, found: BY".to_string()),
1011+
all_dialects_not_requiring_semicolon_statement_delimiter()
1012+
.parse_sql_statements("SELECT * FROM user BY name")
1013+
.unwrap_err()
1014+
);
9821015
}
9831016

9841017
#[test]
@@ -11693,7 +11726,9 @@ fn parse_select_table_with_index_hints() {
1169311726

1169411727
// Test that dialects that don't support table hints will keep parsing the USE as table alias
1169511728
let sql = "SELECT * FROM T USE LIMIT 1";
11696-
let unsupported_dialects = all_dialects_where(|d| !d.supports_table_hints());
11729+
let unsupported_dialects = all_dialects_where(|d| {
11730+
!d.supports_table_hints() && !d.supports_statements_without_semicolon_delimiter()
11731+
});
1169711732
let select = unsupported_dialects
1169811733
.verified_only_select_with_canonical(sql, "SELECT * FROM T USE LIMIT 1");
1169911734
assert_eq!(

0 commit comments

Comments
 (0)