Skip to content

Commit 366c7bb

Browse files
committed
Disallow keywords as table aliases for parsing statements without semicolons
1 parent ef977a3 commit 366c7bb

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

src/dialect/mod.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,8 +1047,14 @@ pub trait Dialect: Debug + Any {
10471047
/// Returns true if the specified keyword should be parsed as a table factor alias.
10481048
/// When explicit is true, the keyword is preceded by an `AS` word. Parser is provided
10491049
/// to enable looking ahead if needed.
1050-
fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
1051-
explicit || self.is_table_alias(kw, parser)
1050+
///
1051+
/// When the dialect supports statements without semicolon delimiter, actual keywords aren't parsed as aliases.
1052+
fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, _parser: &mut Parser) -> bool {
1053+
if self.supports_statements_without_semicolon_delimiter() {
1054+
kw == &Keyword::NoKeyword
1055+
} else {
1056+
explicit || self.is_table_alias(kw, _parser)
1057+
}
10521058
}
10531059

10541060
/// 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
@@ -672,6 +672,28 @@ fn parse_select_with_table_alias() {
672672
);
673673
}
674674

675+
#[test]
676+
fn parse_select_with_table_alias_keyword() {
677+
// note: DECLARE isn't included in RESERVED_FOR_TABLE_ALIAS
678+
let table_alias_non_reserved_keyword = "SELECT a FROM lineitem DECLARE";
679+
let statements = all_dialects_requiring_semicolon_statement_delimiter()
680+
.parse_sql_statements(table_alias_non_reserved_keyword)
681+
.unwrap();
682+
assert_eq!(1, statements.len());
683+
assert_eq!(
684+
ParserError::ParserError("Expected: identifier, found: EOF".to_string()),
685+
all_dialects_not_requiring_semicolon_statement_delimiter()
686+
.parse_sql_statements(table_alias_non_reserved_keyword)
687+
.unwrap_err()
688+
);
689+
690+
let table_alias_quoted_keyword = "SELECT a FROM lineitem \"DECLARE\"";
691+
let statements = all_dialects()
692+
.parse_sql_statements(table_alias_quoted_keyword)
693+
.unwrap();
694+
assert_eq!(1, statements.len());
695+
}
696+
675697
#[test]
676698
fn parse_consecutive_queries() {
677699
let select_then_exec = "SELECT * FROM deleted; EXECUTE my_sp 'some', 'params'";
@@ -955,7 +977,18 @@ fn parse_limit() {
955977

956978
#[test]
957979
fn parse_invalid_limit_by() {
958-
assert_err_parse_statements("SELECT * FROM user BY name", "name");
980+
assert_eq!(
981+
ParserError::ParserError("Expected: end of statement, found: name".to_string()),
982+
all_dialects_requiring_semicolon_statement_delimiter()
983+
.parse_sql_statements("SELECT * FROM user BY name")
984+
.unwrap_err()
985+
);
986+
assert_eq!(
987+
ParserError::ParserError("Expected: an SQL statement, found: BY".to_string()),
988+
all_dialects_not_requiring_semicolon_statement_delimiter()
989+
.parse_sql_statements("SELECT * FROM user BY name")
990+
.unwrap_err()
991+
);
959992
}
960993

961994
#[test]
@@ -11428,7 +11461,9 @@ fn parse_select_table_with_index_hints() {
1142811461

1142911462
// Test that dialects that don't support table hints will keep parsing the USE as table alias
1143011463
let sql = "SELECT * FROM T USE LIMIT 1";
11431-
let unsupported_dialects = all_dialects_where(|d| !d.supports_table_hints());
11464+
let unsupported_dialects = all_dialects_where(|d| {
11465+
!d.supports_table_hints() && !d.supports_statements_without_semicolon_delimiter()
11466+
});
1143211467
let select = unsupported_dialects
1143311468
.verified_only_select_with_canonical(sql, "SELECT * FROM T AS USE LIMIT 1");
1143411469
assert_eq!(

0 commit comments

Comments
 (0)