vibesql-executor 0.2.0

Query execution engine for vibesql SQL database
Documentation
//! Tests for WHEN clause conditional trigger execution

use vibesql_ast::{
    CreateTriggerStmt, TriggerAction, TriggerEvent, TriggerGranularity, TriggerTiming,
};
use vibesql_storage::Database;

use super::{count_audit_rows, create_audit_table};
use crate::{CreateTableExecutor, InsertExecutor};

#[test]
fn test_when_clause_filters_firing() {
    let mut db = Database::new();

    // Create table with amount column
    let table_stmt = vibesql_ast::CreateTableStmt {
        temporary: false,
        if_not_exists: false,
        table_name: "TRANSACTIONS".to_string(),
        columns: vec![
            vibesql_ast::ColumnDef {
                name: "id".to_string(),
                data_type: vibesql_types::DataType::Integer,
                nullable: false,
                constraints: vec![],
                default_value: None,
                comment: None,
                generated_expr: None,
                is_exact_integer_type: false,
            },
            vibesql_ast::ColumnDef {
                name: "amount".to_string(),
                data_type: vibesql_types::DataType::Integer,
                nullable: true,
                constraints: vec![],
                default_value: None,
                comment: None,
                generated_expr: None,
                is_exact_integer_type: false,
            },
        ],
        table_constraints: vec![],
        table_options: vec![],
        quoted: false,
        name_source: None,
        as_query: None,
        without_rowid: false,
    };
    CreateTableExecutor::execute(&table_stmt, &mut db)
        .expect("Failed to create transactions table");
    create_audit_table(&mut db);

    // Create trigger with WHEN (amount > 100) condition
    let trigger_stmt = CreateTriggerStmt {
        if_not_exists: false,
        schema: None,
        trigger_name: "log_high_amount".to_string(),
        name_source: None,
        timing: TriggerTiming::After,
        event: TriggerEvent::Insert,
        table_name: "TRANSACTIONS".to_string(),
        granularity: TriggerGranularity::Row,
        when_condition: Some(Box::new(vibesql_ast::Expression::BinaryOp {
            op: vibesql_ast::BinaryOperator::GreaterThan,
            left: Box::new(vibesql_ast::Expression::ColumnRef(
                vibesql_ast::ColumnIdentifier::simple("amount", false),
            )),
            right: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(
                100,
            ))),
        })),
        triggered_action: TriggerAction::RawSql(
            "INSERT INTO audit_log (event) VALUES ('High amount')".to_string(),
        ),
    };
    crate::advanced_objects::execute_create_trigger(&trigger_stmt, &mut db)
        .expect("Failed to create trigger");

    // Insert row with amount=50 (should NOT fire)
    let insert1 = vibesql_ast::InsertStmt {
        with_clause: None,
        schema_name: None,
        schema_quoted: false,
        table_quoted: false,
        table_name: "TRANSACTIONS".to_string(),
        columns: vec!["id".to_string(), "amount".to_string()],
        source: vibesql_ast::InsertSource::Values(vec![vec![
            vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(1)),
            vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(50)),
        ]]),
        conflict_clause: None,
        on_conflict: None,
        on_duplicate_key_update: None,
        returning: None,
    };
    InsertExecutor::execute(&mut db, &insert1).expect("Failed to insert");

    // Verify trigger did NOT fire
    assert_eq!(count_audit_rows(&db), 0);

    // Insert row with amount=150 (should fire)
    let insert2 = vibesql_ast::InsertStmt {
        with_clause: None,
        schema_name: None,
        schema_quoted: false,
        table_quoted: false,
        table_name: "TRANSACTIONS".to_string(),
        columns: vec!["id".to_string(), "amount".to_string()],
        source: vibesql_ast::InsertSource::Values(vec![vec![
            vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(2)),
            vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(150)),
        ]]),
        conflict_clause: None,
        on_conflict: None,
        on_duplicate_key_update: None,
        returning: None,
    };
    InsertExecutor::execute(&mut db, &insert2).expect("Failed to insert");

    // Verify trigger fired only once (for amount=150)
    assert_eq!(count_audit_rows(&db), 1);
}