Add DECLARE ... CURSOR FOR support for SQL Server (#1821)

This commit is contained in:
Andrew Harper 2025-04-24 14:16:49 -04:00 committed by GitHub
parent 87d190734c
commit 7703fd0d31
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 23 additions and 6 deletions

View file

@ -2472,10 +2472,11 @@ impl fmt::Display for DeclareAssignment {
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum DeclareType { pub enum DeclareType {
/// Cursor variable type. e.g. [Snowflake] [PostgreSQL] /// Cursor variable type. e.g. [Snowflake] [PostgreSQL] [MsSql]
/// ///
/// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor /// [Snowflake]: https://docs.snowflake.com/en/developer-guide/snowflake-scripting/cursors#declaring-a-cursor
/// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html /// [PostgreSQL]: https://www.postgresql.org/docs/current/plpgsql-cursors.html
/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-cursor-transact-sql
Cursor, Cursor,
/// Result set variable type. [Snowflake] /// Result set variable type. [Snowflake]

View file

@ -6446,7 +6446,7 @@ impl<'a> Parser<'a> {
/// DECLARE /// DECLARE
// { // {
// { @local_variable [AS] data_type [ = value ] } // { @local_variable [AS] data_type [ = value ] }
// | { @cursor_variable_name CURSOR } // | { @cursor_variable_name CURSOR [ FOR ] }
// } [ ,...n ] // } [ ,...n ]
/// ``` /// ```
/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-local-variable-transact-sql?view=sql-server-ver16 /// [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> {
/// ```text /// ```text
// { // {
// { @local_variable [AS] data_type [ = value ] } // { @local_variable [AS] data_type [ = value ] }
// | { @cursor_variable_name CURSOR } // | { @cursor_variable_name CURSOR [ FOR ]}
// } [ ,...n ] // } [ ,...n ]
/// ``` /// ```
/// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-local-variable-transact-sql?view=sql-server-ver16 /// [MsSql]: https://learn.microsoft.com/en-us/sql/t-sql/language-elements/declare-local-variable-transact-sql?view=sql-server-ver16
pub fn parse_mssql_declare_stmt(&mut self) -> Result<Declare, ParserError> { pub fn parse_mssql_declare_stmt(&mut self) -> Result<Declare, ParserError> {
let name = { let name = {
let ident = self.parse_identifier()?; let ident = self.parse_identifier()?;
if !ident.value.starts_with('@') { if !ident.value.starts_with('@')
&& !matches!(
self.peek_token().token,
Token::Word(w) if w.keyword == Keyword::CURSOR
)
{
Err(ParserError::TokenizerError( Err(ParserError::TokenizerError(
"Invalid MsSql variable declaration.".to_string(), "Invalid MsSql variable declaration.".to_string(),
)) ))
@ -6493,7 +6498,14 @@ impl<'a> Parser<'a> {
_ => (None, Some(self.parse_data_type()?)), _ => (None, Some(self.parse_data_type()?)),
}; };
let assignment = self.parse_mssql_variable_declaration_expression()?; let (for_query, assignment) = if self.peek_keyword(Keyword::FOR) {
self.next_token();
let query = Some(self.parse_query()?);
(query, None)
} else {
let assignment = self.parse_mssql_variable_declaration_expression()?;
(None, assignment)
};
Ok(Declare { Ok(Declare {
names: vec![name], names: vec![name],
@ -6504,7 +6516,7 @@ impl<'a> Parser<'a> {
sensitive: None, sensitive: None,
scroll: None, scroll: None,
hold: None, hold: None,
for_query: None, for_query,
}) })
} }

View file

@ -1387,6 +1387,10 @@ fn parse_mssql_declare() {
], ],
ast ast
); );
let declare_cursor_for_select =
"DECLARE vend_cursor CURSOR FOR SELECT * FROM Purchasing.Vendor";
let _ = ms().verified_stmt(declare_cursor_for_select);
} }
#[test] #[test]