use vibesql_types::SqlValue;
use crate::errors::ExecutorError;
pub(crate) fn iif(args: &[SqlValue]) -> Result<SqlValue, ExecutorError> {
if args.len() != 3 {
return Err(ExecutorError::UnsupportedFeature(format!(
"IIF requires exactly 3 arguments, got {}",
args.len()
)));
}
let condition = &args[0];
let is_true = match condition {
SqlValue::Null => false,
SqlValue::Boolean(b) => *b,
SqlValue::Integer(i) => *i != 0,
SqlValue::Bigint(i) => *i != 0,
SqlValue::Smallint(i) => *i != 0,
SqlValue::Unsigned(u) => *u != 0,
SqlValue::Real(r) => *r != 0.0,
SqlValue::Double(d) => *d != 0.0,
SqlValue::Numeric(n) => *n != 0.0,
SqlValue::Float(f) => *f != 0.0,
SqlValue::Varchar(s) | SqlValue::Character(s) => !s.is_empty(),
_ => true, };
if is_true {
Ok(args[1].clone())
} else {
Ok(args[2].clone())
}
}
pub(crate) fn ifnull(args: &[SqlValue]) -> Result<SqlValue, ExecutorError> {
if args.len() != 2 {
return Err(ExecutorError::UnsupportedFeature(format!(
"IFNULL requires exactly 2 arguments, got {}",
args.len()
)));
}
if matches!(args[0], SqlValue::Null) {
Ok(args[1].clone())
} else {
Ok(args[0].clone())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_iif() {
assert_eq!(
iif(&[SqlValue::Boolean(true), SqlValue::Integer(1), SqlValue::Integer(2)]).unwrap(),
SqlValue::Integer(1)
);
assert_eq!(
iif(&[SqlValue::Boolean(false), SqlValue::Integer(1), SqlValue::Integer(2)]).unwrap(),
SqlValue::Integer(2)
);
assert_eq!(
iif(&[SqlValue::Null, SqlValue::Integer(1), SqlValue::Integer(2)]).unwrap(),
SqlValue::Integer(2)
);
assert_eq!(
iif(&[SqlValue::Integer(5), SqlValue::Integer(1), SqlValue::Integer(2)]).unwrap(),
SqlValue::Integer(1)
);
assert_eq!(
iif(&[SqlValue::Integer(0), SqlValue::Integer(1), SqlValue::Integer(2)]).unwrap(),
SqlValue::Integer(2)
);
}
#[test]
fn test_ifnull() {
assert_eq!(
ifnull(&[SqlValue::Null, SqlValue::Integer(42)]).unwrap(),
SqlValue::Integer(42)
);
assert_eq!(
ifnull(&[SqlValue::Integer(1), SqlValue::Integer(42)]).unwrap(),
SqlValue::Integer(1)
);
}
}