Skip to content

Commit 30ec0a5

Browse files
committed
MSSQL: Add support for WAITFOR statement
Signed-off-by: Guan-Ming (Wesley) Chiu <105915352+guan404ming@users.noreply.github.com>
1 parent 8e36e8e commit 30ec0a5

5 files changed

Lines changed: 104 additions & 1 deletion

File tree

src/ast/mod.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4743,6 +4743,10 @@ pub enum Statement {
47434743
///
47444744
/// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
47454745
Print(PrintStatement),
4746+
/// MSSQL `WAITFOR` statement.
4747+
///
4748+
/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
4749+
WaitFor(WaitForStatement),
47464750
/// ```sql
47474751
/// RETURN [ expression ]
47484752
/// ```
@@ -6196,6 +6200,7 @@ impl fmt::Display for Statement {
61966200
}
61976201
Statement::Throw(s) => write!(f, "{s}"),
61986202
Statement::Print(s) => write!(f, "{s}"),
6203+
Statement::WaitFor(s) => write!(f, "{s}"),
61996204
Statement::Return(r) => write!(f, "{r}"),
62006205
Statement::List(command) => write!(f, "LIST {command}"),
62016206
Statement::Remove(command) => write!(f, "REMOVE {command}"),
@@ -10939,6 +10944,47 @@ impl fmt::Display for PrintStatement {
1093910944
}
1094010945
}
1094110946

10947+
/// The type of `WAITFOR` statement (MSSQL).
10948+
///
10949+
/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
10950+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10951+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10952+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10953+
pub enum WaitForType {
10954+
/// `WAITFOR DELAY 'time_to_pass'`
10955+
Delay,
10956+
/// `WAITFOR TIME 'time_to_execute'`
10957+
Time,
10958+
}
10959+
10960+
impl fmt::Display for WaitForType {
10961+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10962+
match self {
10963+
WaitForType::Delay => write!(f, "DELAY"),
10964+
WaitForType::Time => write!(f, "TIME"),
10965+
}
10966+
}
10967+
}
10968+
10969+
/// MSSQL `WAITFOR` statement.
10970+
///
10971+
/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
10972+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10973+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10974+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10975+
pub struct WaitForStatement {
10976+
/// `DELAY` or `TIME`.
10977+
pub wait_type: WaitForType,
10978+
/// The time expression.
10979+
pub expr: Expr,
10980+
}
10981+
10982+
impl fmt::Display for WaitForStatement {
10983+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10984+
write!(f, "WAITFOR {} {}", self.wait_type, self.expr)
10985+
}
10986+
}
10987+
1094210988
/// Represents a `Return` statement.
1094310989
///
1094410990
/// [MsSql triggers](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql)

src/ast/spans.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,7 @@ impl Spanned for Statement {
483483
Statement::RaisError { .. } => Span::empty(),
484484
Statement::Throw(_) => Span::empty(),
485485
Statement::Print { .. } => Span::empty(),
486+
Statement::WaitFor { .. } => Span::empty(),
486487
Statement::Return { .. } => Span::empty(),
487488
Statement::List(..) | Statement::Remove(..) => Span::empty(),
488489
Statement::ExportData(ExportData {

src/dialect/mssql.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
use crate::ast::helpers::attached_token::AttachedToken;
1919
use crate::ast::{
2020
BeginEndStatements, ConditionalStatementBlock, ConditionalStatements, CreateTrigger,
21-
GranteesType, IfStatement, Statement,
21+
GranteesType, IfStatement, Statement, WaitForStatement, WaitForType,
2222
};
2323
use crate::dialect::Dialect;
2424
use crate::keywords::Keyword;
@@ -179,6 +179,8 @@ impl Dialect for MsSqlDialect {
179179
Keyword::TRIGGER,
180180
]) {
181181
Some(self.parse_create_trigger(parser, true))
182+
} else if parser.parse_keyword(Keyword::WAITFOR) {
183+
Some(self.parse_waitfor(parser))
182184
} else {
183185
None
184186
}
@@ -343,4 +345,19 @@ impl MsSqlDialect {
343345
}
344346
Ok(stmts)
345347
}
348+
349+
/// Parse `WAITFOR { DELAY 'time' | TIME 'time' }`
350+
///
351+
/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
352+
fn parse_waitfor(&self, parser: &mut Parser) -> Result<Statement, ParserError> {
353+
let wait_type = if parser.parse_keyword(Keyword::DELAY) {
354+
WaitForType::Delay
355+
} else if parser.parse_keyword(Keyword::TIME) {
356+
WaitForType::Time
357+
} else {
358+
return parser.expected("DELAY or TIME", parser.peek_token());
359+
};
360+
let expr = parser.parse_expr()?;
361+
Ok(Statement::WaitFor(WaitForStatement { wait_type, expr }))
362+
}
346363
}

src/keywords.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ define_keywords!(
312312
DEFINE,
313313
DEFINED,
314314
DEFINER,
315+
DELAY,
315316
DELAYED,
316317
DELAY_KEY_WRITE,
317318
DELEGATED,
@@ -1137,6 +1138,7 @@ define_keywords!(
11371138
VIRTUAL,
11381139
VOLATILE,
11391140
VOLUME,
1141+
WAITFOR,
11401142
WAREHOUSE,
11411143
WAREHOUSES,
11421144
WEEK,

tests/sqlparser_mssql.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,6 +1702,43 @@ fn test_parse_throw() {
17021702
);
17031703
}
17041704

1705+
#[test]
1706+
fn test_parse_waitfor() {
1707+
// WAITFOR DELAY
1708+
let sql = "WAITFOR DELAY '00:00:05'";
1709+
let stmt = ms().verified_stmt(sql);
1710+
assert_eq!(
1711+
stmt,
1712+
Statement::WaitFor(WaitForStatement {
1713+
wait_type: WaitForType::Delay,
1714+
expr: Expr::Value(
1715+
(Value::SingleQuotedString("00:00:05".to_string())).with_empty_span()
1716+
),
1717+
})
1718+
);
1719+
1720+
// WAITFOR TIME
1721+
let sql = "WAITFOR TIME '14:30:00'";
1722+
let stmt = ms().verified_stmt(sql);
1723+
assert_eq!(
1724+
stmt,
1725+
Statement::WaitFor(WaitForStatement {
1726+
wait_type: WaitForType::Time,
1727+
expr: Expr::Value(
1728+
(Value::SingleQuotedString("14:30:00".to_string())).with_empty_span()
1729+
),
1730+
})
1731+
);
1732+
1733+
// WAITFOR DELAY with variable
1734+
let sql = "WAITFOR DELAY @WaitTime";
1735+
let _ = ms().verified_stmt(sql);
1736+
1737+
// Error: WAITFOR without DELAY or TIME
1738+
let res = ms().parse_sql_statements("WAITFOR '00:00:05'");
1739+
assert!(res.is_err());
1740+
}
1741+
17051742
#[test]
17061743
fn parse_use() {
17071744
let valid_object_names = [

0 commit comments

Comments
 (0)