This is an automated email from the ASF dual-hosted git repository.

github-bot pushed a commit to branch 
gh-readonly-queue/main/pr-2210-0f37c278fb43e42e42941c763b9329b199e494a9
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git

commit fb10a76f1772fc7f5805931dc308792f3c3ee716
Author: Guan-Ming (Wesley) Chiu <[email protected]>
AuthorDate: Thu Feb 19 19:28:19 2026 +0800

    MSSQL: Add support for WAITFOR statement (#2210)
    
    Signed-off-by: Guan-Ming (Wesley) Chiu 
<[email protected]>
    Signed-off-by: Guan-Ming Chiu <[email protected]>
    Co-authored-by: Ifeanyi Ubah <[email protected]>
---
 src/ast/mod.rs           | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 src/ast/spans.rs         |  1 +
 src/keywords.rs          |  2 ++
 src/parser/mod.rs        | 17 +++++++++++++++++
 tests/sqlparser_mssql.rs | 37 +++++++++++++++++++++++++++++++++++++
 5 files changed, 103 insertions(+)

diff --git a/src/ast/mod.rs b/src/ast/mod.rs
index eda28226..dbf5003c 100644
--- a/src/ast/mod.rs
+++ b/src/ast/mod.rs
@@ -4764,6 +4764,10 @@ pub enum Statement {
     ///
     /// See: 
<https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
     Print(PrintStatement),
+    /// MSSQL `WAITFOR` statement.
+    ///
+    /// See: 
<https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
+    WaitFor(WaitForStatement),
     /// ```sql
     /// RETURN [ expression ]
     /// ```
@@ -6217,6 +6221,7 @@ impl fmt::Display for Statement {
             }
             Statement::Throw(s) => write!(f, "{s}"),
             Statement::Print(s) => write!(f, "{s}"),
+            Statement::WaitFor(s) => write!(f, "{s}"),
             Statement::Return(r) => write!(f, "{r}"),
             Statement::List(command) => write!(f, "LIST {command}"),
             Statement::Remove(command) => write!(f, "REMOVE {command}"),
@@ -10964,6 +10969,47 @@ impl fmt::Display for PrintStatement {
     }
 }
 
+/// The type of `WAITFOR` statement (MSSQL).
+///
+/// See: 
<https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub enum WaitForType {
+    /// `WAITFOR DELAY 'time_to_pass'`
+    Delay,
+    /// `WAITFOR TIME 'time_to_execute'`
+    Time,
+}
+
+impl fmt::Display for WaitForType {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            WaitForType::Delay => write!(f, "DELAY"),
+            WaitForType::Time => write!(f, "TIME"),
+        }
+    }
+}
+
+/// MSSQL `WAITFOR` statement.
+///
+/// See: 
<https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct WaitForStatement {
+    /// `DELAY` or `TIME`.
+    pub wait_type: WaitForType,
+    /// The time expression.
+    pub expr: Expr,
+}
+
+impl fmt::Display for WaitForStatement {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "WAITFOR {} {}", self.wait_type, self.expr)
+    }
+}
+
 /// Represents a `Return` statement.
 ///
 /// [MsSql 
triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)
diff --git a/src/ast/spans.rs b/src/ast/spans.rs
index f4bdf85a..d792c13c 100644
--- a/src/ast/spans.rs
+++ b/src/ast/spans.rs
@@ -483,6 +483,7 @@ impl Spanned for Statement {
             Statement::RaisError { .. } => Span::empty(),
             Statement::Throw(_) => Span::empty(),
             Statement::Print { .. } => Span::empty(),
+            Statement::WaitFor(_) => Span::empty(),
             Statement::Return { .. } => Span::empty(),
             Statement::List(..) | Statement::Remove(..) => Span::empty(),
             Statement::ExportData(ExportData {
diff --git a/src/keywords.rs b/src/keywords.rs
index f1dbcd93..cc2b9e9d 100644
--- a/src/keywords.rs
+++ b/src/keywords.rs
@@ -312,6 +312,7 @@ define_keywords!(
     DEFINE,
     DEFINED,
     DEFINER,
+    DELAY,
     DELAYED,
     DELAY_KEY_WRITE,
     DELEGATED,
@@ -1138,6 +1139,7 @@ define_keywords!(
     VIRTUAL,
     VOLATILE,
     VOLUME,
+    WAITFOR,
     WAREHOUSE,
     WAREHOUSES,
     WEEK,
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index eba9b32d..4f32422f 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -703,6 +703,8 @@ impl<'a> Parser<'a> {
                 // `COMMENT` is snowflake specific 
https://docs.snowflake.com/en/sql-reference/sql/comment
                 Keyword::COMMENT if self.dialect.supports_comment_on() => 
self.parse_comment(),
                 Keyword::PRINT => self.parse_print(),
+                // `WAITFOR` is MSSQL specific 
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql
+                Keyword::WAITFOR => self.parse_waitfor(),
                 Keyword::RETURN => self.parse_return(),
                 Keyword::EXPORT => {
                     self.prev_token();
@@ -19289,6 +19291,21 @@ impl<'a> Parser<'a> {
         }))
     }
 
+    /// Parse [Statement::WaitFor]
+    ///
+    /// See: 
<https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
+    fn parse_waitfor(&mut self) -> Result<Statement, ParserError> {
+        let wait_type = if self.parse_keyword(Keyword::DELAY) {
+            WaitForType::Delay
+        } else if self.parse_keyword(Keyword::TIME) {
+            WaitForType::Time
+        } else {
+            return self.expected("DELAY or TIME", self.peek_token());
+        };
+        let expr = self.parse_expr()?;
+        Ok(Statement::WaitFor(WaitForStatement { wait_type, expr }))
+    }
+
     /// Parse [Statement::Return]
     fn parse_return(&mut self) -> Result<Statement, ParserError> {
         match self.maybe_parse(|p| p.parse_expr())? {
diff --git a/tests/sqlparser_mssql.rs b/tests/sqlparser_mssql.rs
index cf9ae898..d7d11ba6 100644
--- a/tests/sqlparser_mssql.rs
+++ b/tests/sqlparser_mssql.rs
@@ -1702,6 +1702,43 @@ fn test_parse_throw() {
     );
 }
 
+#[test]
+fn test_parse_waitfor() {
+    // WAITFOR DELAY
+    let sql = "WAITFOR DELAY '00:00:05'";
+    let stmt = ms_and_generic().verified_stmt(sql);
+    assert_eq!(
+        stmt,
+        Statement::WaitFor(WaitForStatement {
+            wait_type: WaitForType::Delay,
+            expr: Expr::Value(
+                
(Value::SingleQuotedString("00:00:05".to_string())).with_empty_span()
+            ),
+        })
+    );
+
+    // WAITFOR TIME
+    let sql = "WAITFOR TIME '14:30:00'";
+    let stmt = ms_and_generic().verified_stmt(sql);
+    assert_eq!(
+        stmt,
+        Statement::WaitFor(WaitForStatement {
+            wait_type: WaitForType::Time,
+            expr: Expr::Value(
+                
(Value::SingleQuotedString("14:30:00".to_string())).with_empty_span()
+            ),
+        })
+    );
+
+    // WAITFOR DELAY with variable
+    let sql = "WAITFOR DELAY @WaitTime";
+    let _ = ms_and_generic().verified_stmt(sql);
+
+    // Error: WAITFOR without DELAY or TIME
+    let res = ms_and_generic().parse_sql_statements("WAITFOR '00:00:05'");
+    assert!(res.is_err());
+}
+
 #[test]
 fn parse_use() {
     let valid_object_names = [


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to