Implement ASSERT statement (#226)

As supported by PostgreSQL and BigQuery (with some differences between them)
This commit is contained in:
Daniël Heres 2020-07-16 17:28:03 +02:00 committed by GitHub
parent 5cab18963e
commit c24b0e01db
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 78 additions and 0 deletions

View file

@ -551,6 +551,14 @@ pub enum Statement {
Rollback { chain: bool },
/// CREATE SCHEMA
CreateSchema { schema_name: ObjectName },
/// ASSERT <condition> [AS <message>]
Assert {
condition: Expr,
// AS or ,
separator: String,
message: Option<Expr>,
},
}
impl fmt::Display for Statement {
@ -810,6 +818,18 @@ impl fmt::Display for Statement {
write!(f, "ROLLBACK{}", if *chain { " AND CHAIN" } else { "" },)
}
Statement::CreateSchema { schema_name } => write!(f, "CREATE SCHEMA {}", schema_name),
Statement::Assert {
condition,
separator,
message,
} => {
write!(f, "ASSERT {}", condition)?;
if let Some(m) = message {
write!(f, " {} {}", separator, m)?;
}
Ok(())
}
}
}
}

View file

@ -79,6 +79,7 @@ define_keywords!(
AS,
ASC,
ASENSITIVE,
ASSERT,
ASYMMETRIC,
AT,
ATOMIC,

View file

@ -148,6 +148,7 @@ impl Parser {
Keyword::BEGIN => Ok(self.parse_begin()?),
Keyword::COMMIT => Ok(self.parse_commit()?),
Keyword::ROLLBACK => Ok(self.parse_rollback()?),
Keyword::ASSERT => Ok(self.parse_assert()?),
_ => self.expected("an SQL statement", Token::Word(w)),
},
Token::LParen => {
@ -179,6 +180,22 @@ impl Parser {
}
Ok(expr)
}
pub fn parse_assert(&mut self) -> Result<Statement, ParserError> {
let condition = self.parse_expr()?;
let (separator, message) = if self.consume_token(&Token::Comma) {
(",".to_string(), Some(self.parse_expr()?))
} else if self.parse_keyword(Keyword::AS) {
("AS".to_string(), Some(self.parse_expr()?))
} else {
("".to_string(), None)
};
Ok(Statement::Assert {
condition,
separator,
message,
})
}
/// Parse an expression prefix
pub fn parse_prefix(&mut self) -> Result<Expr, ParserError> {

View file

@ -1156,6 +1156,46 @@ fn parse_create_table_with_multiple_on_delete_fails() {
.expect_err("should have failed");
}
#[test]
fn parse_assert() {
let sql = "ASSERT (SELECT COUNT(*) FROM table) > 0";
let ast = one_statement_parses_to(sql, "ASSERT (SELECT COUNT(*) FROM table) > 0");
match ast {
Statement::Assert {
condition: _condition,
separator,
message,
} => {
assert_eq!(message, None);
assert_eq!(separator, "");
}
_ => unreachable!(),
}
}
#[test]
fn parse_assert_message() {
let sql = "ASSERT (SELECT COUNT(*) FROM table) > 0 AS 'No rows in table'";
let ast = one_statement_parses_to(
sql,
"ASSERT (SELECT COUNT(*) FROM table) > 0 AS 'No rows in table'",
);
match ast {
Statement::Assert {
condition: _condition,
message: Some(message),
separator,
} => {
assert_eq!(separator, "AS");
match message {
Expr::Value(Value::SingleQuotedString(s)) => assert_eq!(s, "No rows in table"),
_ => unreachable!(),
};
}
_ => unreachable!(),
}
}
#[test]
fn parse_create_schema() {
let sql = "CREATE SCHEMA X";