Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4686,6 +4686,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 ]
/// ```
Expand Down Expand Up @@ -6125,6 +6129,7 @@ impl fmt::Display for Statement {
Ok(())
}
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}"),
Expand Down Expand Up @@ -10868,6 +10873,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)
Expand Down
1 change: 1 addition & 0 deletions src/ast/spans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ impl Spanned for Statement {
Statement::RenameTable { .. } => Span::empty(),
Statement::RaisError { .. } => Span::empty(),
Statement::Print { .. } => Span::empty(),
Statement::WaitFor { .. } => Span::empty(),
Statement::Return { .. } => Span::empty(),
Statement::List(..) | Statement::Remove(..) => Span::empty(),
Statement::ExportData(ExportData {
Expand Down
19 changes: 18 additions & 1 deletion src/dialect/mssql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
use crate::ast::helpers::attached_token::AttachedToken;
use crate::ast::{
BeginEndStatements, ConditionalStatementBlock, ConditionalStatements, CreateTrigger,
GranteesType, IfStatement, Statement,
GranteesType, IfStatement, Statement, WaitForStatement, WaitForType,
};
use crate::dialect::Dialect;
use crate::keywords::Keyword;
Expand Down Expand Up @@ -179,6 +179,8 @@ impl Dialect for MsSqlDialect {
Keyword::TRIGGER,
]) {
Some(self.parse_create_trigger(parser, true))
} else if parser.parse_keyword(Keyword::WAITFOR) {
Some(self.parse_waitfor(parser))
} else {
None
}
Expand Down Expand Up @@ -343,4 +345,19 @@ impl MsSqlDialect {
}
Ok(stmts)
}

/// Parse `WAITFOR { DELAY 'time' | TIME 'time' }`
///
/// See: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/waitfor-transact-sql>
fn parse_waitfor(&self, parser: &mut Parser) -> Result<Statement, ParserError> {
let wait_type = if parser.parse_keyword(Keyword::DELAY) {
WaitForType::Delay
} else if parser.parse_keyword(Keyword::TIME) {
WaitForType::Time
} else {
return parser.expected("DELAY or TIME", parser.peek_token());
};
let expr = parser.parse_expr()?;
Ok(Statement::WaitFor(WaitForStatement { wait_type, expr }))
}
}
2 changes: 2 additions & 0 deletions src/keywords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ define_keywords!(
DEFINE,
DEFINED,
DEFINER,
DELAY,
DELAYED,
DELAY_KEY_WRITE,
DELEGATED,
Expand Down Expand Up @@ -1136,6 +1137,7 @@ define_keywords!(
VIRTUAL,
VOLATILE,
VOLUME,
WAITFOR,
WAREHOUSE,
WAREHOUSES,
WEEK,
Expand Down
37 changes: 37 additions & 0 deletions tests/sqlparser_mssql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1665,6 +1665,43 @@ fn test_parse_raiserror() {
let _ = ms().verified_stmt(sql);
}

#[test]
fn test_parse_waitfor() {
// WAITFOR DELAY
let sql = "WAITFOR DELAY '00:00:05'";
let stmt = ms().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().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().verified_stmt(sql);

// Error: WAITFOR without DELAY or TIME
let res = ms().parse_sql_statements("WAITFOR '00:00:05'");
assert!(res.is_err());
}

#[test]
fn parse_use() {
let valid_object_names = [
Expand Down
Loading