Skip to content

Commit 12a99e6

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

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
@@ -4764,6 +4764,10 @@ pub enum Statement {
47644764
///
47654765
/// See: <https://learn.microsoft.com/en-us/sql/t-sql/statements/print-transact-sql>
47664766
Print(PrintStatement),
4767+
/// MSSQL `WAITFOR` statement.
4768+
///
4769+
/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
4770+
WaitFor(WaitForStatement),
47674771
/// ```sql
47684772
/// RETURN [ expression ]
47694773
/// ```
@@ -6217,6 +6221,7 @@ impl fmt::Display for Statement {
62176221
}
62186222
Statement::Throw(s) => write!(f, "{s}"),
62196223
Statement::Print(s) => write!(f, "{s}"),
6224+
Statement::WaitFor(s) => write!(f, "{s}"),
62206225
Statement::Return(r) => write!(f, "{r}"),
62216226
Statement::List(command) => write!(f, "LIST {command}"),
62226227
Statement::Remove(command) => write!(f, "REMOVE {command}"),
@@ -10964,6 +10969,47 @@ impl fmt::Display for PrintStatement {
1096410969
}
1096510970
}
1096610971

10972+
/// The type of `WAITFOR` statement (MSSQL).
10973+
///
10974+
/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
10975+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10976+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10977+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
10978+
pub enum WaitForType {
10979+
/// `WAITFOR DELAY 'time_to_pass'`
10980+
Delay,
10981+
/// `WAITFOR TIME 'time_to_execute'`
10982+
Time,
10983+
}
10984+
10985+
impl fmt::Display for WaitForType {
10986+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10987+
match self {
10988+
WaitForType::Delay => write!(f, "DELAY"),
10989+
WaitForType::Time => write!(f, "TIME"),
10990+
}
10991+
}
10992+
}
10993+
10994+
/// MSSQL `WAITFOR` statement.
10995+
///
10996+
/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
10997+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10998+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
10999+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
11000+
pub struct WaitForStatement {
11001+
/// `DELAY` or `TIME`.
11002+
pub wait_type: WaitForType,
11003+
/// The time expression.
11004+
pub expr: Expr,
11005+
}
11006+
11007+
impl fmt::Display for WaitForStatement {
11008+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
11009+
write!(f, "WAITFOR {} {}", self.wait_type, self.expr)
11010+
}
11011+
}
11012+
1096711013
/// Represents a `Return` statement.
1096811014
///
1096911015
/// [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;
@@ -183,6 +183,8 @@ impl Dialect for MsSqlDialect {
183183
Keyword::TRIGGER,
184184
]) {
185185
Some(self.parse_create_trigger(parser, true))
186+
} else if parser.parse_keyword(Keyword::WAITFOR) {
187+
Some(self.parse_waitfor(parser))
186188
} else {
187189
None
188190
}
@@ -347,4 +349,19 @@ impl MsSqlDialect {
347349
}
348350
Ok(stmts)
349351
}
352+
353+
/// Parse `WAITFOR { DELAY 'time' | TIME 'time' }`
354+
///
355+
/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
356+
fn parse_waitfor(&self, parser: &mut Parser) -> Result<Statement, ParserError> {
357+
let wait_type = if parser.parse_keyword(Keyword::DELAY) {
358+
WaitForType::Delay
359+
} else if parser.parse_keyword(Keyword::TIME) {
360+
WaitForType::Time
361+
} else {
362+
return parser.expected("DELAY or TIME", parser.peek_token());
363+
};
364+
let expr = parser.parse_expr()?;
365+
Ok(Statement::WaitFor(WaitForStatement { wait_type, expr }))
366+
}
350367
}

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,
@@ -1138,6 +1139,7 @@ define_keywords!(
11381139
VIRTUAL,
11391140
VOLATILE,
11401141
VOLUME,
1142+
WAITFOR,
11411143
WAREHOUSE,
11421144
WAREHOUSES,
11431145
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)