You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datafusion.apache.org by gi...@apache.org on 2026/02/27 10:45:22 UTC
(datafusion-sqlparser-rs) branch gh-readonly-queue/main/pr-2234-523d78ea2aceee54c4f999728edcb5603ff25a24 created (now 6f0e803a)
This is an automated email from the ASF dual-hosted git repository.
github-bot pushed a change to branch gh-readonly-queue/main/pr-2234-523d78ea2aceee54c4f999728edcb5603ff25a24
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
at 6f0e803a MSSQL: support EXEC (@sql) dynamic SQL execution (#2234)
This branch includes the following new commits:
new 6f0e803a MSSQL: support EXEC (@sql) dynamic SQL execution (#2234)
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org
(datafusion-sqlparser-rs) 01/01: MSSQL: support EXEC (@sql) dynamic SQL execution (#2234)
Posted by gi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
github-bot pushed a commit to branch gh-readonly-queue/main/pr-2234-523d78ea2aceee54c4f999728edcb5603ff25a24
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
commit 6f0e803aa77414e83aefd326e23231c51b60ae32
Author: Yoabot <yo...@gmail.com>
AuthorDate: Fri Feb 27 11:44:59 2026 +0100
MSSQL: support EXEC (@sql) dynamic SQL execution (#2234)
---
src/parser/mod.rs | 23 ++++++++++++++++++++---
tests/sqlparser_mssql.rs | 23 +++++++++++++++++++++++
2 files changed, 43 insertions(+), 3 deletions(-)
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index bea566bb..75db4d24 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -18583,6 +18583,9 @@ impl<'a> Parser<'a> {
/// Parse a SQL `EXECUTE` statement
pub fn parse_execute(&mut self) -> Result<Statement, ParserError> {
+ // Track whether the procedure/expression name itself was wrapped in parens,
+ // i.e. `EXEC (@sql)` (dynamic string execution) vs `EXEC sp_name`.
+ // When the name has parens there are no additional parameters.
let name = if self.dialect.supports_execute_immediate()
&& self.parse_keyword(Keyword::IMMEDIATE)
{
@@ -18593,10 +18596,18 @@ impl<'a> Parser<'a> {
if has_parentheses {
self.expect_token(&Token::RParen)?;
}
- Some(name)
+ Some((name, has_parentheses))
};
- let has_parentheses = self.consume_token(&Token::LParen);
+ let name_had_parentheses = name.as_ref().map(|(_, p)| *p).unwrap_or(false);
+
+ // Only look for a parameter list when the name was NOT wrapped in parens.
+ // `EXEC (@sql)` is dynamic SQL execution and takes no parameters here.
+ let has_parentheses = if name_had_parentheses {
+ false
+ } else {
+ self.consume_token(&Token::LParen)
+ };
let end_kws = &[Keyword::USING, Keyword::OUTPUT, Keyword::DEFAULT];
let end_token = match (has_parentheses, self.peek_token().token) {
@@ -18606,12 +18617,18 @@ impl<'a> Parser<'a> {
(false, _) => Token::SemiColon,
};
- let parameters = self.parse_comma_separated0(Parser::parse_expr, end_token)?;
+ let parameters = if name_had_parentheses {
+ vec![]
+ } else {
+ self.parse_comma_separated0(Parser::parse_expr, end_token)?
+ };
if has_parentheses {
self.expect_token(&Token::RParen)?;
}
+ let name = name.map(|(n, _)| n);
+
let into = if self.parse_keyword(Keyword::INTO) {
self.parse_comma_separated(Self::parse_identifier)?
} else {
diff --git a/tests/sqlparser_mssql.rs b/tests/sqlparser_mssql.rs
index 6c8412a4..8bdb1c20 100644
--- a/tests/sqlparser_mssql.rs
+++ b/tests/sqlparser_mssql.rs
@@ -2783,3 +2783,26 @@ fn test_tsql_statement_keywords_not_implicit_aliases() {
);
}
}
+
+#[test]
+fn test_exec_dynamic_sql() {
+ // EXEC (@sql) executes a dynamic SQL string held in a variable.
+ // It must parse as a single Execute statement and not attempt to parse
+ // parameters after the closing paren.
+ let stmts = tsql()
+ .parse_sql_statements("EXEC (@sql)")
+ .expect("EXEC (@sql) should parse");
+ assert_eq!(stmts.len(), 1);
+ assert!(
+ matches!(&stmts[0], Statement::Execute { .. }),
+ "expected Execute, got: {:?}",
+ stmts[0]
+ );
+
+ // Verify that a statement following EXEC (@sql) on the next line is parsed
+ // as a separate statement and not consumed as a parameter.
+ let stmts = tsql()
+ .parse_sql_statements("EXEC (@sql)\nDROP TABLE #tmp")
+ .expect("EXEC (@sql) followed by DROP TABLE should parse");
+ assert_eq!(stmts.len(), 2);
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org