use crate::db::{
QueryError,
query::{
plan::expr::{CaseWhenArm, Expr, FieldId, FieldPath},
preparation::PreparationWork,
},
};
use icydb_diagnostic_code::DiagnosticExecutionBudgetResource as Resource;
impl PreparationWork<'_> {
pub(in crate::db) fn copy_expr(&self, expr: &Expr) -> Result<Expr, QueryError> {
self.charge(Resource::PredicateExpressionSteps, 1)?;
Ok(match expr {
Expr::Field(field) => Expr::Field(FieldId::new(self.copy_text(field.as_str())?)),
Expr::FieldPath(path) => Expr::FieldPath(FieldPath::new(
self.copy_text(path.root().as_str())?,
self.copy_slice(path.segments(), |segment| self.copy_text(segment))?,
)),
Expr::Literal(value) => Expr::Literal(self.copy_value(value)?),
Expr::FunctionCall { function, args } => Expr::FunctionCall {
function: *function,
args: self.copy_slice(args, |arg| self.copy_expr(arg))?,
},
Expr::Unary { op, expr } => Expr::Unary {
op: *op,
expr: self.copy_boxed_expr(expr)?,
},
Expr::Binary { op, left, right } => Expr::Binary {
op: *op,
left: self.copy_boxed_expr(left)?,
right: self.copy_boxed_expr(right)?,
},
Expr::Case {
when_then_arms,
else_expr,
} => Expr::Case {
when_then_arms: self.copy_slice(when_then_arms, |arm| {
Ok(CaseWhenArm::new(
self.copy_expr(arm.condition())?,
self.copy_expr(arm.result())?,
))
})?,
else_expr: self.copy_boxed_expr(else_expr)?,
},
Expr::Aggregate(aggregate) => Expr::Aggregate(aggregate.copy_for_preparation(self)?),
#[cfg(test)]
Expr::Alias { expr, name } => Expr::Alias {
expr: self.copy_boxed_expr(expr)?,
name: self.copy_text(name.as_str())?.into(),
},
})
}
pub(in crate::db) fn copy_boxed_expr(&self, expr: &Expr) -> Result<Box<Expr>, QueryError> {
self.charge(Resource::TemporaryBytes, size_of::<Expr>() as u64)?;
Ok(Box::new(self.copy_expr(expr)?))
}
}
#[cfg(test)]
mod tests;