@@ -1388,9 +1388,9 @@ impl<'a> Parser<'a> {
13881388 | Token::HexStringLiteral(_)
13891389 if w.value.starts_with('_') =>
13901390 {
1391- Ok(Expr::IntroducedString {
1392- introducer : w.value. clone(),
1393- value: self.parse_introduced_string_value ()?,
1391+ Ok(Expr::Prefixed {
1392+ prefix : w.clone().into_ident(w_span ),
1393+ value: self.parse_introduced_string_expr ()?.into() ,
13941394 })
13951395 }
13961396 // string introducer https://dev.mysql.com/doc/refman/8.0/en/charset-introducer.html
@@ -1399,9 +1399,9 @@ impl<'a> Parser<'a> {
13991399 | Token::HexStringLiteral(_)
14001400 if w.value.starts_with('_') =>
14011401 {
1402- Ok(Expr::IntroducedString {
1403- introducer : w.value. clone(),
1404- value: self.parse_introduced_string_value ()?,
1402+ Ok(Expr::Prefixed {
1403+ prefix : w.clone().into_ident(w_span ),
1404+ value: self.parse_introduced_string_expr ()?.into() ,
14051405 })
14061406 }
14071407 Token::Arrow if self.dialect.supports_lambda_functions() => {
@@ -6446,7 +6446,7 @@ impl<'a> Parser<'a> {
64466446 /// DECLARE
64476447 // {
64486448 // { @local_variable [AS] data_type [ = value ] }
6449- // | { @cursor_variable_name CURSOR }
6449+ // | { @cursor_variable_name CURSOR [ FOR ] }
64506450 // } [ ,...n ]
64516451 /// ```
64526452 /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-local-variable-transact-sql?view=sql-server-ver16
@@ -6462,14 +6462,19 @@ impl<'a> Parser<'a> {
64626462 /// ```text
64636463 // {
64646464 // { @local_variable [AS] data_type [ = value ] }
6465- // | { @cursor_variable_name CURSOR }
6465+ // | { @cursor_variable_name CURSOR [ FOR ] }
64666466 // } [ ,...n ]
64676467 /// ```
64686468 /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-local-variable-transact-sql?view=sql-server-ver16
64696469 pub fn parse_mssql_declare_stmt(&mut self) -> Result<Declare, ParserError> {
64706470 let name = {
64716471 let ident = self.parse_identifier()?;
6472- if !ident.value.starts_with('@') {
6472+ if !ident.value.starts_with('@')
6473+ && !matches!(
6474+ self.peek_token().token,
6475+ Token::Word(w) if w.keyword == Keyword::CURSOR
6476+ )
6477+ {
64736478 Err(ParserError::TokenizerError(
64746479 "Invalid MsSql variable declaration.".to_string(),
64756480 ))
@@ -6493,7 +6498,14 @@ impl<'a> Parser<'a> {
64936498 _ => (None, Some(self.parse_data_type()?)),
64946499 };
64956500
6496- let assignment = self.parse_mssql_variable_declaration_expression()?;
6501+ let (for_query, assignment) = if self.peek_keyword(Keyword::FOR) {
6502+ self.next_token();
6503+ let query = Some(self.parse_query()?);
6504+ (query, None)
6505+ } else {
6506+ let assignment = self.parse_mssql_variable_declaration_expression()?;
6507+ (None, assignment)
6508+ };
64976509
64986510 Ok(Declare {
64996511 names: vec![name],
@@ -6504,7 +6516,7 @@ impl<'a> Parser<'a> {
65046516 sensitive: None,
65056517 scroll: None,
65066518 hold: None,
6507- for_query: None ,
6519+ for_query,
65086520 })
65096521 }
65106522
@@ -9023,13 +9035,19 @@ impl<'a> Parser<'a> {
90239035 }
90249036 }
90259037
9026- fn parse_introduced_string_value (&mut self) -> Result<Value , ParserError> {
9038+ fn parse_introduced_string_expr (&mut self) -> Result<Expr , ParserError> {
90279039 let next_token = self.next_token();
90289040 let span = next_token.span;
90299041 match next_token.token {
9030- Token::SingleQuotedString(ref s) => Ok(Value::SingleQuotedString(s.to_string())),
9031- Token::DoubleQuotedString(ref s) => Ok(Value::DoubleQuotedString(s.to_string())),
9032- Token::HexStringLiteral(ref s) => Ok(Value::HexStringLiteral(s.to_string())),
9042+ Token::SingleQuotedString(ref s) => Ok(Expr::Value(
9043+ Value::SingleQuotedString(s.to_string()).with_span(span),
9044+ )),
9045+ Token::DoubleQuotedString(ref s) => Ok(Expr::Value(
9046+ Value::DoubleQuotedString(s.to_string()).with_span(span),
9047+ )),
9048+ Token::HexStringLiteral(ref s) => Ok(Expr::Value(
9049+ Value::HexStringLiteral(s.to_string()).with_span(span),
9050+ )),
90339051 unexpected => self.expected(
90349052 "a string value",
90359053 TokenWithSpan {
@@ -13956,6 +13974,13 @@ impl<'a> Parser<'a> {
1395613974
1395713975 /// Parse a comma-delimited list of projections after SELECT
1395813976 pub fn parse_select_item(&mut self) -> Result<SelectItem, ParserError> {
13977+ let prefix = self
13978+ .parse_one_of_keywords(
13979+ self.dialect
13980+ .get_reserved_keywords_for_select_item_operator(),
13981+ )
13982+ .map(|keyword| Ident::new(format!("{:?}", keyword)));
13983+
1395913984 match self.parse_wildcard_expr()? {
1396013985 Expr::QualifiedWildcard(prefix, token) => Ok(SelectItem::QualifiedWildcard(
1396113986 SelectItemQualifiedWildcardKind::ObjectName(prefix),
@@ -14000,8 +14025,11 @@ impl<'a> Parser<'a> {
1400014025 expr => self
1400114026 .maybe_parse_select_item_alias()
1400214027 .map(|alias| match alias {
14003- Some(alias) => SelectItem::ExprWithAlias { expr, alias },
14004- None => SelectItem::UnnamedExpr(expr),
14028+ Some(alias) => SelectItem::ExprWithAlias {
14029+ expr: maybe_prefixed_expr(expr, prefix),
14030+ alias,
14031+ },
14032+ None => SelectItem::UnnamedExpr(maybe_prefixed_expr(expr, prefix)),
1400514033 }),
1400614034 }
1400714035 }
@@ -15363,6 +15391,17 @@ impl<'a> Parser<'a> {
1536315391 }
1536415392}
1536515393
15394+ fn maybe_prefixed_expr(expr: Expr, prefix: Option<Ident>) -> Expr {
15395+ if let Some(prefix) = prefix {
15396+ Expr::Prefixed {
15397+ prefix,
15398+ value: Box::new(expr),
15399+ }
15400+ } else {
15401+ expr
15402+ }
15403+ }
15404+
1536615405impl Word {
1536715406 #[deprecated(since = "0.54.0", note = "please use `into_ident` instead")]
1536815407 pub fn to_ident(&self, span: Span) -> Ident {
0 commit comments