@@ -8838,76 +8838,38 @@ impl<'a> Parser<'a> {
88388838 Ok(IdentWithAlias { ident, alias })
88398839 }
88408840
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`
88688844 pub fn parse_optional_alias(
88698845 &mut self,
88708846 reserved_kwds: &[Keyword],
88718847 ) -> 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- {
88928848 let after_as = self.parse_keyword(Keyword::AS);
8893-
88948849 let next_token = self.next_token();
88958850 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) => {
89078857 Ok(Some(w.into_ident(next_token.span)))
89088858 }
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>."
89108871 Token::SingleQuotedString(s) => Ok(Some(Ident::with_quote('\'', s))),
8872+ // Support for MySql dialect double-quoted string, `AS "HOUR"` for example
89118873 Token::DoubleQuotedString(s) => Ok(Some(Ident::with_quote('\"', s))),
89128874 _ => {
89138875 if after_as {
@@ -8919,6 +8881,23 @@ impl<'a> Parser<'a> {
89198881 }
89208882 }
89218883
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+
89228901 pub fn parse_optional_group_by(&mut self) -> Result<Option<GroupByExpr>, ParserError> {
89238902 if self.parse_keywords(&[Keyword::GROUP, Keyword::BY]) {
89248903 let expressions = if self.parse_keyword(Keyword::ALL) {
@@ -10920,7 +10899,7 @@ impl<'a> Parser<'a> {
1092010899 let name = self.parse_object_name(false)?;
1092110900 self.expect_token(&Token::LParen)?;
1092210901 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 )?;
1092410903 Ok(TableFactor::Function {
1092510904 lateral: true,
1092610905 name,
@@ -10933,7 +10912,7 @@ impl<'a> Parser<'a> {
1093310912 self.expect_token(&Token::LParen)?;
1093410913 let expr = self.parse_expr()?;
1093510914 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 )?;
1093710916 Ok(TableFactor::TableFunction { expr, alias })
1093810917 } else if self.consume_token(&Token::LParen) {
1093910918 // A left paren introduces either a derived table (i.e., a subquery)
@@ -10982,7 +10961,7 @@ impl<'a> Parser<'a> {
1098210961 #[allow(clippy::if_same_then_else)]
1098310962 if !table_and_joins.joins.is_empty() {
1098410963 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 )?;
1098610965 Ok(TableFactor::NestedJoin {
1098710966 table_with_joins: Box::new(table_and_joins),
1098810967 alias,
@@ -10995,7 +10974,7 @@ impl<'a> Parser<'a> {
1099510974 // (B): `table_and_joins` (what we found inside the parentheses)
1099610975 // is a nested join `(foo JOIN bar)`, not followed by other joins.
1099710976 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 )?;
1099910978 Ok(TableFactor::NestedJoin {
1100010979 table_with_joins: Box::new(table_and_joins),
1100110980 alias,
@@ -11009,7 +10988,9 @@ impl<'a> Parser<'a> {
1100910988 // [AS alias])`) as well.
1101010989 self.expect_token(&Token::RParen)?;
1101110990
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+ {
1101310994 // Snowflake also allows specifying an alias *after* parens
1101410995 // e.g. `FROM (mytable) AS alias`
1101510996 match &mut table_and_joins.relation {
@@ -11062,7 +11043,7 @@ impl<'a> Parser<'a> {
1106211043 // SELECT * FROM VALUES (1, 'a'), (2, 'b') AS t (col1, col2)
1106311044 // where there are no parentheses around the VALUES clause.
1106411045 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 )?;
1106611047 Ok(TableFactor::Derived {
1106711048 lateral: false,
1106811049 subquery: Box::new(Query {
@@ -11088,7 +11069,7 @@ impl<'a> Parser<'a> {
1108811069 self.expect_token(&Token::RParen)?;
1108911070
1109011071 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 ) {
1109211073 Ok(Some(alias)) => Some(alias),
1109311074 Ok(None) => None,
1109411075 Err(e) => return Err(e),
@@ -11125,7 +11106,7 @@ impl<'a> Parser<'a> {
1112511106 let columns = self.parse_comma_separated(Parser::parse_json_table_column_def)?;
1112611107 self.expect_token(&Token::RParen)?;
1112711108 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 )?;
1112911110 Ok(TableFactor::JsonTable {
1113011111 json_expr,
1113111112 json_path,
@@ -11170,7 +11151,7 @@ impl<'a> Parser<'a> {
1117011151 }
1117111152 }
1117211153
11173- let alias = self.maybe_parse_table_alias( )?;
11154+ let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS )?;
1117411155
1117511156 // MSSQL-specific table hints:
1117611157 let mut with_hints = vec![];
@@ -11348,7 +11329,7 @@ impl<'a> Parser<'a> {
1134811329 } else {
1134911330 Vec::new()
1135011331 };
11351- let alias = self.maybe_parse_table_alias( )?;
11332+ let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS )?;
1135211333 Ok(TableFactor::OpenJsonTable {
1135311334 json_expr,
1135411335 json_path,
@@ -11447,7 +11428,7 @@ impl<'a> Parser<'a> {
1144711428
1144811429 self.expect_token(&Token::RParen)?;
1144911430
11450- let alias = self.maybe_parse_table_alias( )?;
11431+ let alias = self.parse_optional_table_alias(keywords::RESERVED_FOR_TABLE_ALIAS )?;
1145111432
1145211433 Ok(TableFactor::MatchRecognize {
1145311434 table: Box::new(table),
@@ -11691,7 +11672,7 @@ impl<'a> Parser<'a> {
1169111672 ) -> Result<TableFactor, ParserError> {
1169211673 let subquery = self.parse_query()?;
1169311674 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 )?;
1169511676 Ok(TableFactor::Derived {
1169611677 lateral: match lateral {
1169711678 Lateral => true,
@@ -11785,7 +11766,7 @@ impl<'a> Parser<'a> {
1178511766 };
1178611767
1178711768 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 )?;
1178911770 Ok(TableFactor::Pivot {
1179011771 table: Box::new(table),
1179111772 aggregate_functions,
@@ -11807,7 +11788,7 @@ impl<'a> Parser<'a> {
1180711788 self.expect_keyword_is(Keyword::IN)?;
1180811789 let columns = self.parse_parenthesized_column_list(Mandatory, false)?;
1180911790 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 )?;
1181111792 Ok(TableFactor::Unpivot {
1181211793 table: Box::new(table),
1181311794 value,
@@ -12633,7 +12614,7 @@ impl<'a> Parser<'a> {
1263312614 })
1263412615 }
1263512616 expr => self
12636- .maybe_parse_select_item_alias( )
12617+ .parse_optional_alias(keywords::RESERVED_FOR_COLUMN_ALIAS )
1263712618 .map(|alias| match alias {
1263812619 Some(alias) => SelectItem::ExprWithAlias { expr, alias },
1263912620 None => SelectItem::UnnamedExpr(expr),
0 commit comments