use vibesql_ast::*;
use vibesql_storage::Database;
use crate::errors::ExecutorError;
pub fn execute_create_assertion(
stmt: &CreateAssertionStmt,
db: &mut Database,
) -> Result<(), ExecutorError> {
use vibesql_catalog::Assertion;
let assertion = Assertion::new(stmt.assertion_name.clone(), (*stmt.check_condition).clone());
db.catalog.create_assertion(assertion)?;
Ok(())
}
pub fn execute_drop_assertion(
stmt: &DropAssertionStmt,
db: &mut Database,
) -> Result<(), ExecutorError> {
db.catalog.drop_assertion(&stmt.assertion_name, stmt.cascade)?;
Ok(())
}
pub struct AssertionChecker;
impl AssertionChecker {
pub fn check_all_assertions(db: &Database) -> Result<(), ExecutorError> {
let assertions: Vec<_> = db
.catalog
.get_all_assertions()
.map(|a| (a.name.clone(), a.check_condition.clone()))
.collect();
if assertions.is_empty() {
return Ok(());
}
for (assertion_name, check_condition) in assertions {
Self::check_assertion(db, &assertion_name, &check_condition)?;
}
Ok(())
}
fn check_assertion(
db: &Database,
assertion_name: &str,
check_condition: &Expression,
) -> Result<(), ExecutorError> {
let select_stmt = SelectStmt {
with_clause: None,
distinct: false,
select_list: vec![SelectItem::Expression {
expr: check_condition.clone(),
alias: None,
source_text: None,
}],
into_table: None,
into_variables: None,
from: None,
where_clause: None,
group_by: None,
having: None,
window_definitions: None,
order_by: None,
limit: None,
offset: None,
set_operation: None,
values: None,
};
let executor = crate::SelectExecutor::new(db);
let rows = executor.execute(&select_stmt)?;
if rows.is_empty() {
return Err(ExecutorError::AssertionViolation {
assertion_name: assertion_name.to_string(),
});
}
let result = &rows[0].values[0];
match result {
vibesql_types::SqlValue::Boolean(true) => Ok(()),
vibesql_types::SqlValue::Boolean(false) => Err(ExecutorError::AssertionViolation {
assertion_name: assertion_name.to_string(),
}),
vibesql_types::SqlValue::Null => {
Ok(())
}
vibesql_types::SqlValue::Integer(0) => {
Err(ExecutorError::AssertionViolation {
assertion_name: assertion_name.to_string(),
})
}
vibesql_types::SqlValue::Integer(_) => {
Ok(())
}
_ => {
Ok(())
}
}
}
}