Improve support for cursors for SQL Server (#1831)

Co-authored-by: Ifeanyi Ubah <ify1992@yahoo.com>
This commit is contained in:
Andrew Harper 2025-05-01 23:25:30 -04:00 committed by GitHub
parent 483394cd1a
commit a464f8e8d7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 289 additions and 20 deletions

View file

@ -23,7 +23,8 @@
mod test_utils;
use helpers::attached_token::AttachedToken;
use sqlparser::tokenizer::{Location, Span};
use sqlparser::keywords::Keyword;
use sqlparser::tokenizer::{Location, Span, Token, TokenWithSpan, Word};
use test_utils::*;
use sqlparser::ast::DataType::{Int, Text, Varbinary};
@ -223,7 +224,7 @@ fn parse_create_function() {
value: Some(ReturnStatementValue::Expr(Expr::Value(
(number("1")).with_empty_span()
))),
}),],
})],
end_token: AttachedToken::empty(),
})),
behavior: None,
@ -1397,6 +1398,85 @@ fn parse_mssql_declare() {
let _ = ms().verified_stmt(declare_cursor_for_select);
}
#[test]
fn test_mssql_cursor() {
let full_cursor_usage = "\
DECLARE Employee_Cursor CURSOR FOR \
SELECT LastName, FirstName \
FROM AdventureWorks2022.HumanResources.vEmployee \
WHERE LastName LIKE 'B%'; \
\
OPEN Employee_Cursor; \
\
FETCH NEXT FROM Employee_Cursor; \
\
WHILE @@FETCH_STATUS = 0 \
BEGIN \
FETCH NEXT FROM Employee_Cursor; \
END; \
\
CLOSE Employee_Cursor; \
DEALLOCATE Employee_Cursor\
";
let _ = ms().statements_parse_to(full_cursor_usage, "");
}
#[test]
fn test_mssql_while_statement() {
let while_single_statement = "WHILE 1 = 0 PRINT 'Hello World';";
let stmt = ms().verified_stmt(while_single_statement);
assert_eq!(
stmt,
Statement::While(sqlparser::ast::WhileStatement {
while_block: ConditionalStatementBlock {
start_token: AttachedToken(TokenWithSpan {
token: Token::Word(Word {
value: "WHILE".to_string(),
quote_style: None,
keyword: Keyword::WHILE
}),
span: Span::empty()
}),
condition: Some(Expr::BinaryOp {
left: Box::new(Expr::Value(
(Value::Number("1".parse().unwrap(), false)).with_empty_span()
)),
op: BinaryOperator::Eq,
right: Box::new(Expr::Value(
(Value::Number("0".parse().unwrap(), false)).with_empty_span()
)),
}),
then_token: None,
conditional_statements: ConditionalStatements::Sequence {
statements: vec![Statement::Print(PrintStatement {
message: Box::new(Expr::Value(
(Value::SingleQuotedString("Hello World".to_string()))
.with_empty_span()
)),
})],
}
}
})
);
let while_begin_end = "\
WHILE @@FETCH_STATUS = 0 \
BEGIN \
FETCH NEXT FROM Employee_Cursor; \
END\
";
let _ = ms().verified_stmt(while_begin_end);
let while_begin_end_multiple_statements = "\
WHILE @@FETCH_STATUS = 0 \
BEGIN \
FETCH NEXT FROM Employee_Cursor; \
PRINT 'Hello World'; \
END\
";
let _ = ms().verified_stmt(while_begin_end_multiple_statements);
}
#[test]
fn test_parse_raiserror() {
let sql = r#"RAISERROR('This is a test', 16, 1)"#;