use vibesql_catalog::TableSchema;
use vibesql_storage::Row;
use vibesql_types::SqlValue;
use crate::evaluator::ExpressionEvaluator;
#[test]
fn test_coalesce_lazy_evaluation_short_circuits() {
let schema = TableSchema::new("test".to_string(), vec![]);
let evaluator = ExpressionEvaluator::new(&schema);
let row = Row::new(vec![]);
let expr = vibesql_ast::Expression::Function {
name: vibesql_ast::FunctionIdentifier::new("COALESCE"),
args: vec![
vibesql_ast::Expression::Literal(SqlValue::Integer(10)),
vibesql_ast::Expression::BinaryOp {
left: Box::new(vibesql_ast::Expression::Literal(SqlValue::Integer(1))),
op: vibesql_ast::BinaryOperator::Divide,
right: Box::new(vibesql_ast::Expression::Literal(SqlValue::Integer(0))),
},
],
character_unit: None,
};
let result = evaluator.eval(&expr, &row);
assert!(result.is_ok(), "COALESCE should short-circuit on non-NULL value");
assert_eq!(result.unwrap(), SqlValue::Integer(10));
}
#[test]
fn test_coalesce_evaluates_all_when_all_null() {
let schema = TableSchema::new("test".to_string(), vec![]);
let evaluator = ExpressionEvaluator::new(&schema);
let row = Row::new(vec![]);
let expr = vibesql_ast::Expression::Function {
name: vibesql_ast::FunctionIdentifier::new("COALESCE"),
args: vec![
vibesql_ast::Expression::Literal(SqlValue::Null),
vibesql_ast::Expression::Literal(SqlValue::Null),
vibesql_ast::Expression::Literal(SqlValue::Integer(42)),
],
character_unit: None,
};
let result = evaluator.eval(&expr, &row);
assert!(result.is_ok());
assert_eq!(result.unwrap(), SqlValue::Integer(42));
}
#[test]
fn test_nullif_lazy_evaluation_short_circuits() {
let schema = TableSchema::new("test".to_string(), vec![]);
let evaluator = ExpressionEvaluator::new(&schema);
let row = Row::new(vec![]);
let expr = vibesql_ast::Expression::Function {
name: vibesql_ast::FunctionIdentifier::new("NULLIF"),
args: vec![
vibesql_ast::Expression::Literal(SqlValue::Null),
vibesql_ast::Expression::BinaryOp {
left: Box::new(vibesql_ast::Expression::Literal(SqlValue::Integer(1))),
op: vibesql_ast::BinaryOperator::Divide,
right: Box::new(vibesql_ast::Expression::Literal(SqlValue::Integer(0))),
},
],
character_unit: None,
};
let result = evaluator.eval(&expr, &row);
assert!(result.is_ok(), "NULLIF should short-circuit on NULL first argument");
assert_eq!(result.unwrap(), SqlValue::Null);
}
#[test]
fn test_nullif_evaluates_second_when_first_not_null() {
let schema = TableSchema::new("test".to_string(), vec![]);
let evaluator = ExpressionEvaluator::new(&schema);
let row = Row::new(vec![]);
let expr = vibesql_ast::Expression::Function {
name: vibesql_ast::FunctionIdentifier::new("NULLIF"),
args: vec![
vibesql_ast::Expression::Literal(SqlValue::Integer(42)),
vibesql_ast::Expression::Literal(SqlValue::Integer(42)),
],
character_unit: None,
};
let result = evaluator.eval(&expr, &row);
assert!(result.is_ok());
assert_eq!(result.unwrap(), SqlValue::Null);
}
#[test]
fn test_nullif_returns_first_when_not_equal() {
let schema = TableSchema::new("test".to_string(), vec![]);
let evaluator = ExpressionEvaluator::new(&schema);
let row = Row::new(vec![]);
let expr = vibesql_ast::Expression::Function {
name: vibesql_ast::FunctionIdentifier::new("NULLIF"),
args: vec![
vibesql_ast::Expression::Literal(SqlValue::Integer(42)),
vibesql_ast::Expression::Literal(SqlValue::Integer(43)),
],
character_unit: None,
};
let result = evaluator.eval(&expr, &row);
assert!(result.is_ok());
assert_eq!(result.unwrap(), SqlValue::Integer(42));
}
#[test]
fn test_coalesce_with_strings() {
let schema = TableSchema::new("test".to_string(), vec![]);
let evaluator = ExpressionEvaluator::new(&schema);
let row = Row::new(vec![]);
let expr = vibesql_ast::Expression::Function {
name: vibesql_ast::FunctionIdentifier::new("COALESCE"),
args: vec![
vibesql_ast::Expression::Literal(SqlValue::Null),
vibesql_ast::Expression::Literal(SqlValue::Varchar(arcstr::ArcStr::from("hello"))),
vibesql_ast::Expression::Literal(SqlValue::Varchar(arcstr::ArcStr::from("world"))),
],
character_unit: None,
};
let result = evaluator.eval(&expr, &row);
assert!(result.is_ok());
assert_eq!(result.unwrap(), SqlValue::Varchar(arcstr::ArcStr::from("hello")));
}
#[test]
fn test_nested_coalesce() {
let schema = TableSchema::new("test".to_string(), vec![]);
let evaluator = ExpressionEvaluator::new(&schema);
let row = Row::new(vec![]);
let expr = vibesql_ast::Expression::Function {
name: vibesql_ast::FunctionIdentifier::new("COALESCE"),
args: vec![
vibesql_ast::Expression::Literal(SqlValue::Null),
vibesql_ast::Expression::Function {
name: vibesql_ast::FunctionIdentifier::new("COALESCE"),
args: vec![
vibesql_ast::Expression::Literal(SqlValue::Null),
vibesql_ast::Expression::Literal(SqlValue::Integer(42)),
],
character_unit: None,
},
],
character_unit: None,
};
let result = evaluator.eval(&expr, &row);
assert!(result.is_ok());
assert_eq!(result.unwrap(), SqlValue::Integer(42));
}