@@ -8838,76 +8838,38 @@ impl<'a> Parser<'a> {
8838
8838
Ok(IdentWithAlias { ident, alias })
8839
8839
}
8840
8840
8841
- /// Optionally parses an alias for a select list item
8842
- fn maybe_parse_select_item_alias(&mut self) -> Result<Option<Ident>, ParserError> {
8843
- fn validator(explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
8844
- parser.dialect.is_select_item_alias(explicit, kw, parser)
8845
- }
8846
- self.parse_optional_alias_inner(None, validator)
8847
- }
8848
-
8849
- /// Optionally parses an alias for a table like in `... FROM generate_series(1, 10) AS t (col)`.
8850
- /// In this case, the alias is allowed to optionally name the columns in the table, in
8851
- /// addition to the table itself.
8852
- pub fn maybe_parse_table_alias(&mut self) -> Result<Option<TableAlias>, ParserError> {
8853
- fn validator(explicit: bool, kw: &Keyword, parser: &mut Parser) -> bool {
8854
- parser.dialect.is_table_factor_alias(explicit, kw, parser)
8855
- }
8856
- match self.parse_optional_alias_inner(None, validator)? {
8857
- Some(name) => {
8858
- let columns = self.parse_table_alias_column_defs()?;
8859
- Ok(Some(TableAlias { name, columns }))
8860
- }
8861
- None => Ok(None),
8862
- }
8863
- }
8864
-
8865
- /// Wrapper for parse_optional_alias_inner, left for backwards-compatibility
8866
- /// but new flows should use the context-specific methods such as `maybe_parse_select_item_alias`
8867
- /// and `maybe_parse_table_alias`.
8841
+ /// Parse `AS identifier` (or simply `identifier` if it's not a reserved keyword)
8842
+ /// Some examples with aliases: `SELECT 1 foo`, `SELECT COUNT(*) AS cnt`,
8843
+ /// `SELECT ... FROM t1 foo, t2 bar`, `SELECT ... FROM (...) AS bar`
8868
8844
pub fn parse_optional_alias(
8869
8845
&mut self,
8870
8846
reserved_kwds: &[Keyword],
8871
8847
) -> Result<Option<Ident>, ParserError> {
8872
- fn validator(_explicit: bool, _kw: &Keyword, _parser: &mut Parser) -> bool {
8873
- false
8874
- }
8875
- self.parse_optional_alias_inner(Some(reserved_kwds), validator)
8876
- }
8877
-
8878
- /// Parses an optional alias after a SQL element such as a select list item
8879
- /// or a table name.
8880
- ///
8881
- /// This method accepts an optional list of reserved keywords or a function
8882
- /// to call to validate if a keyword should be parsed as an alias, to allow
8883
- /// callers to customize the parsing logic based on their context.
8884
- fn parse_optional_alias_inner<F>(
8885
- &mut self,
8886
- reserved_kwds: Option<&[Keyword]>,
8887
- validator: F,
8888
- ) -> Result<Option<Ident>, ParserError>
8889
- where
8890
- F: Fn(bool, &Keyword, &mut Parser) -> bool,
8891
- {
8892
8848
let after_as = self.parse_keyword(Keyword::AS);
8893
-
8894
8849
let next_token = self.next_token();
8895
8850
match next_token.token {
8896
- // By default, if a word is located after the `AS` keyword we consider it an alias
8897
- // as long as it's not reserved.
8898
- Token::Word(w)
8899
- if after_as || reserved_kwds.is_some_and(|x| !x.contains(&w.keyword)) =>
8900
- {
8901
- Ok(Some(w.into_ident(next_token.span)))
8902
- }
8903
- // This pattern allows for customizing the acceptance of words as aliases based on the caller's
8904
- // context, such as to what SQL element this word is a potential alias of (select item alias, table name
8905
- // alias, etc.) or dialect-specific logic that goes beyond a simple list of reserved keywords.
8906
- Token::Word(w) if validator(after_as, &w.keyword, self) => {
8851
+ // Accept any identifier after `AS` (though many dialects have restrictions on
8852
+ // keywords that may appear here). If there's no `AS`: don't parse keywords,
8853
+ // which may start a construct allowed in this position, to be parsed as aliases.
8854
+ // (For example, in `FROM t1 JOIN` the `JOIN` will always be parsed as a keyword,
8855
+ // not an alias.)
8856
+ Token::Word(w) if after_as || !reserved_kwds.contains(&w.keyword) => {
8907
8857
Ok(Some(w.into_ident(next_token.span)))
8908
8858
}
8909
- // For backwards-compatibility, we accept quoted strings as aliases regardless of the context.
8859
+ // MSSQL supports single-quoted strings as aliases for columns
8860
+ // We accept them as table aliases too, although MSSQL does not.
8861
+ //
8862
+ // Note, that this conflicts with an obscure rule from the SQL
8863
+ // standard, which we don't implement:
8864
+ // https://crate.io/docs/sql-99/en/latest/chapters/07.html#character-string-literal-s
8865
+ // "[Obscure Rule] SQL allows you to break a long <character
8866
+ // string literal> up into two or more smaller <character string
8867
+ // literal>s, split by a <separator> that includes a newline
8868
+ // character. When it sees such a <literal>, your DBMS will
8869
+ // ignore the <separator> and treat the multiple strings as
8870
+ // a single <literal>."
8910
8871
Token::SingleQuotedString(s) => Ok(Some(Ident::with_quote('\'', s))),
8872
+ // Support for MySql dialect double-quoted string, `AS "HOUR"` for example
8911
8873
Token::DoubleQuotedString(s) => Ok(Some(Ident::with_quote('\"', s))),
8912
8874
_ => {
8913
8875
if after_as {
@@ -8919,6 +8881,23 @@ impl<'a> Parser<'a> {
8919
8881
}
8920
8882
}
8921
8883
8884
+ /// Parse `AS identifier` when the AS is describing a table-valued object,
8885
+ /// like in `... FROM generate_series(1, 10) AS t (col)`. In this case
8886
+ /// the alias is allowed to optionally name the columns in the table, in
8887
+ /// addition to the table itself.
8888
+ pub fn parse_optional_table_alias(
8889
+ &mut self,
8890
+ reserved_kwds: &[Keyword],
8891
+ ) -> Result<Option<TableAlias>, ParserError> {
8892
+ match self.parse_optional_alias(reserved_kwds)? {
8893
+ Some(name) => {
8894
+ let columns = self.parse_table_alias_column_defs()?;
8895
+ Ok(Some(TableAlias { name, columns }))
8896
+ }
8897
+ None => Ok(None),
8898
+ }
8899
+ }
8900
+
8922
8901
pub fn parse_optional_group_by(&mut self) -> Result<Option<GroupByExpr>, ParserError> {
8923
8902
if self.parse_keywords(&[Keyword::GROUP, Keyword::BY]) {
8924
8903
let expressions = if self.parse_keyword(Keyword::ALL) {
@@ -10920,7 +10899,7 @@ impl<'a> Parser<'a> {
10920
10899
let name = self.parse_object_name(false)?;
10921
10900
self.expect_token(&Token::LParen)?;
10922
10901
let args = self.parse_optional_args()?;
10923
- let alias = self.maybe_parse_table_alias( )?;
10902
+ let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS )?;
10924
10903
Ok(TableFactor::Function {
10925
10904
lateral: true,
10926
10905
name,
@@ -10933,7 +10912,7 @@ impl<'a> Parser<'a> {
10933
10912
self.expect_token(&Token::LParen)?;
10934
10913
let expr = self.parse_expr()?;
10935
10914
self.expect_token(&Token::RParen)?;
10936
- let alias = self.maybe_parse_table_alias( )?;
10915
+ let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS )?;
10937
10916
Ok(TableFactor::TableFunction { expr, alias })
10938
10917
} else if self.consume_token(&Token::LParen) {
10939
10918
// A left paren introduces either a derived table (i.e., a subquery)
@@ -10982,7 +10961,7 @@ impl<'a> Parser<'a> {
10982
10961
#[allow(clippy::if_same_then_else)]
10983
10962
if !table_and_joins.joins.is_empty() {
10984
10963
self.expect_token(&Token::RParen)?;
10985
- let alias = self.maybe_parse_table_alias( )?;
10964
+ let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS )?;
10986
10965
Ok(TableFactor::NestedJoin {
10987
10966
table_with_joins: Box::new(table_and_joins),
10988
10967
alias,
@@ -10995,7 +10974,7 @@ impl<'a> Parser<'a> {
10995
10974
// (B): `table_and_joins` (what we found inside the parentheses)
10996
10975
// is a nested join `(foo JOIN bar)`, not followed by other joins.
10997
10976
self.expect_token(&Token::RParen)?;
10998
- let alias = self.maybe_parse_table_alias( )?;
10977
+ let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS )?;
10999
10978
Ok(TableFactor::NestedJoin {
11000
10979
table_with_joins: Box::new(table_and_joins),
11001
10980
alias,
@@ -11009,7 +10988,9 @@ impl<'a> Parser<'a> {
11009
10988
// [AS alias])`) as well.
11010
10989
self.expect_token(&Token::RParen)?;
11011
10990
11012
- if let Some(outer_alias) = self.maybe_parse_table_alias()? {
10991
+ if let Some(outer_alias) =
10992
+ self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS)?
10993
+ {
11013
10994
// Snowflake also allows specifying an alias *after* parens
11014
10995
// e.g. `FROM (mytable) AS alias`
11015
10996
match &mut table_and_joins.relation {
@@ -11062,7 +11043,7 @@ impl<'a> Parser<'a> {
11062
11043
// SELECT * FROM VALUES (1, 'a'), (2, 'b') AS t (col1, col2)
11063
11044
// where there are no parentheses around the VALUES clause.
11064
11045
let values = SetExpr::Values(self.parse_values(false)?);
11065
- let alias = self.maybe_parse_table_alias( )?;
11046
+ let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS )?;
11066
11047
Ok(TableFactor::Derived {
11067
11048
lateral: false,
11068
11049
subquery: Box::new(Query {
@@ -11088,7 +11069,7 @@ impl<'a> Parser<'a> {
11088
11069
self.expect_token(&Token::RParen)?;
11089
11070
11090
11071
let with_ordinality = self.parse_keywords(&[Keyword::WITH, Keyword::ORDINALITY]);
11091
- let alias = match self.maybe_parse_table_alias( ) {
11072
+ let alias = match self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS ) {
11092
11073
Ok(Some(alias)) => Some(alias),
11093
11074
Ok(None) => None,
11094
11075
Err(e) => return Err(e),
@@ -11125,7 +11106,7 @@ impl<'a> Parser<'a> {
11125
11106
let columns = self.parse_comma_separated(Parser::parse_json_table_column_def)?;
11126
11107
self.expect_token(&Token::RParen)?;
11127
11108
self.expect_token(&Token::RParen)?;
11128
- let alias = self.maybe_parse_table_alias( )?;
11109
+ let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS )?;
11129
11110
Ok(TableFactor::JsonTable {
11130
11111
json_expr,
11131
11112
json_path,
@@ -11170,7 +11151,7 @@ impl<'a> Parser<'a> {
11170
11151
}
11171
11152
}
11172
11153
11173
- let alias = self.maybe_parse_table_alias( )?;
11154
+ let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS )?;
11174
11155
11175
11156
// MSSQL-specific table hints:
11176
11157
let mut with_hints = vec![];
@@ -11348,7 +11329,7 @@ impl<'a> Parser<'a> {
11348
11329
} else {
11349
11330
Vec::new()
11350
11331
};
11351
- let alias = self.maybe_parse_table_alias( )?;
11332
+ let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS )?;
11352
11333
Ok(TableFactor::OpenJsonTable {
11353
11334
json_expr,
11354
11335
json_path,
@@ -11447,7 +11428,7 @@ impl<'a> Parser<'a> {
11447
11428
11448
11429
self.expect_token(&Token::RParen)?;
11449
11430
11450
- let alias = self.maybe_parse_table_alias( )?;
11431
+ let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS )?;
11451
11432
11452
11433
Ok(TableFactor::MatchRecognize {
11453
11434
table: Box::new(table),
@@ -11691,7 +11672,7 @@ impl<'a> Parser<'a> {
11691
11672
) -> Result<TableFactor, ParserError> {
11692
11673
let subquery = self.parse_query()?;
11693
11674
self.expect_token(&Token::RParen)?;
11694
- let alias = self.maybe_parse_table_alias( )?;
11675
+ let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS )?;
11695
11676
Ok(TableFactor::Derived {
11696
11677
lateral: match lateral {
11697
11678
Lateral => true,
@@ -11785,7 +11766,7 @@ impl<'a> Parser<'a> {
11785
11766
};
11786
11767
11787
11768
self.expect_token(&Token::RParen)?;
11788
- let alias = self.maybe_parse_table_alias( )?;
11769
+ let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS )?;
11789
11770
Ok(TableFactor::Pivot {
11790
11771
table: Box::new(table),
11791
11772
aggregate_functions,
@@ -11807,7 +11788,7 @@ impl<'a> Parser<'a> {
11807
11788
self.expect_keyword_is(Keyword::IN)?;
11808
11789
let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
11809
11790
self.expect_token(&Token::RParen)?;
11810
- let alias = self.maybe_parse_table_alias( )?;
11791
+ let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS )?;
11811
11792
Ok(TableFactor::Unpivot {
11812
11793
table: Box::new(table),
11813
11794
value,
@@ -12633,7 +12614,7 @@ impl<'a> Parser<'a> {
12633
12614
})
12634
12615
}
12635
12616
expr => self
12636
- .maybe_parse_select_item_alias( )
12617
+ .parse_optional_alias(keywords::RESERVED_FOR_COLUMN_ALIAS )
12637
12618
.map(|alias| match alias {
12638
12619
Some(alias) => SelectItem::ExprWithAlias { expr, alias },
12639
12620
None => SelectItem::UnnamedExpr(expr),
0 commit comments