Skip to content

Commit c8436d7

Browse files
committed
Disallow keywords as table aliases for parsing statements without semicolons
1 parent 2acb8ce commit c8436d7

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
@@ -1028,8 +1028,14 @@ pub trait Dialect: Debug + Any {
10281028
/// Returns true if the specified keyword should be parsed as a table factor alias.
10291029
/// When explicit is true, the keyword is preceded by an `AS` word. Parser is provided
10301030
/// to enable looking ahead if needed.
1031-
fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
1032-
explicit || self.is_table_alias(kw, parser)
1031+
///
1032+
/// When the dialect supports statements without semicolon delimiter, actual keywords aren't parsed as aliases.
1033+
fn is_table_factor_alias(&self, explicit: bool, kw: &Keyword, _parser: &mut Parser) -> bool {
1034+
if self.supports_statements_without_semicolon_delimiter() {
1035+
kw == &Keyword::NoKeyword
1036+
} else {
1037+
explicit || self.is_table_alias(kw, _parser)
1038+
}
10331039
}
10341040

10351041
/// 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
@@ -668,6 +668,28 @@ fn parse_select_with_table_alias() {
668668
);
669669
}
670670

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

952974
#[test]
953975
fn parse_invalid_limit_by() {
954-
assert_err_parse_statements("SELECT * FROM user BY name", "name");
976+
assert_eq!(
977+
ParserError::ParserError("Expected: end of statement, found: name".to_string()),
978+
all_dialects_requiring_semicolon_statement_delimiter()
979+
.parse_sql_statements("SELECT * FROM user BY name")
980+
.unwrap_err()
981+
);
982+
assert_eq!(
983+
ParserError::ParserError("Expected: an SQL statement, found: BY".to_string()),
984+
all_dialects_not_requiring_semicolon_statement_delimiter()
985+
.parse_sql_statements("SELECT * FROM user BY name")
986+
.unwrap_err()
987+
);
955988
}
956989

957990
#[test]
@@ -11029,7 +11062,9 @@ fn parse_select_table_with_index_hints() {
1102911062

1103011063
// Test that dialects that don't support table hints will keep parsing the USE as table alias
1103111064
let sql = "SELECT * FROM T USE LIMIT 1";
11032-
let unsupported_dialects = all_dialects_where(|d| !d.supports_table_hints());
11065+
let unsupported_dialects = all_dialects_where(|d| {
11066+
!d.supports_table_hints() && !d.supports_statements_without_semicolon_delimiter()
11067+
});
1103311068
let select = unsupported_dialects
1103411069
.verified_only_select_with_canonical(sql, "SELECT * FROM T AS USE LIMIT 1");
1103511070
assert_eq!(

0 commit comments

Comments
 (0)