use crate::ast::Expr;
use crate::catalog::Catalog;
use crate::error::DbError;
use crate::storage::Storage;
use crate::types::Value;
use super::super::clock::Clock;
use super::super::context::ExecutionContext;
use super::super::evaluator::eval_expr;
use super::super::model::ContextTable;
pub(crate) fn eval_coalesce(
args: &[Expr],
row: &[ContextTable],
ctx: &mut ExecutionContext,
catalog: &dyn Catalog,
storage: &dyn Storage,
clock: &dyn Clock,
) -> Result<Value, DbError> {
if args.is_empty() {
return Err(DbError::Execution(
"COALESCE requires at least one argument".into(),
));
}
for arg in args {
let val = eval_expr(arg, row, ctx, catalog, storage, clock)?;
if !val.is_null() {
return Ok(val);
}
}
Ok(Value::Null)
}
pub(crate) fn eval_isnull(
args: &[Expr],
row: &[ContextTable],
ctx: &mut ExecutionContext,
catalog: &dyn Catalog,
storage: &dyn Storage,
clock: &dyn Clock,
) -> Result<Value, DbError> {
if args.len() != 2 {
return Err(DbError::Execution("ISNULL expects 2 arguments".into()));
}
let left = eval_expr(&args[0], row, ctx, catalog, storage, clock)?;
if !left.is_null() {
Ok(left)
} else {
eval_expr(&args[1], row, ctx, catalog, storage, clock)
}
}
pub(crate) fn eval_iif(
args: &[Expr],
row: &[ContextTable],
ctx: &mut ExecutionContext,
catalog: &dyn Catalog,
storage: &dyn Storage,
clock: &dyn Clock,
) -> Result<Value, DbError> {
if args.len() != 3 {
return Err(DbError::Execution("IIF expects 3 arguments".into()));
}
let condition = eval_expr(&args[0], row, ctx, catalog, storage, clock)?;
let is_true = match condition {
Value::Bit(b) => b,
Value::Null => false,
Value::Int(v) => v != 0,
Value::BigInt(v) => v != 0,
Value::TinyInt(v) => v != 0,
Value::SmallInt(v) => v != 0,
_ => !condition.to_string_value().is_empty(),
};
if is_true {
eval_expr(&args[1], row, ctx, catalog, storage, clock)
} else {
eval_expr(&args[2], row, ctx, catalog, storage, clock)
}
}
pub(crate) fn eval_nullif(
args: &[Expr],
row: &[ContextTable],
ctx: &mut ExecutionContext,
catalog: &dyn Catalog,
storage: &dyn Storage,
clock: &dyn Clock,
) -> Result<Value, DbError> {
if args.len() != 2 {
return Err(DbError::Execution("NULLIF expects 2 arguments".into()));
}
let left = eval_expr(&args[0], row, ctx, catalog, storage, clock)?;
let right = eval_expr(&args[1], row, ctx, catalog, storage, clock)?;
if left == right {
Ok(Value::Null)
} else {
Ok(left)
}
}
pub(crate) fn eval_choose(
args: &[Expr],
row: &[ContextTable],
ctx: &mut ExecutionContext,
catalog: &dyn Catalog,
storage: &dyn Storage,
clock: &dyn Clock,
) -> Result<Value, DbError> {
if args.len() < 2 {
return Err(DbError::Execution(
"CHOOSE expects at least 2 arguments".into(),
));
}
let index_val = eval_expr(&args[0], row, ctx, catalog, storage, clock)?;
let idx = index_val.to_integer_i64().unwrap_or(0);
if idx < 1 || idx as usize > args.len() - 1 {
return Ok(Value::Null);
}
eval_expr(&args[idx as usize], row, ctx, catalog, storage, clock)
}