use crate::{
db::query::{
construction::ConstructionBudget,
plan::{
OrderSpec, OrderTerm,
expr::{CaseWhenArm, Expr, FieldId, FieldPath},
},
},
error::InternalError,
};
use icydb_diagnostic_code::DiagnosticExecutionBudgetResource as Resource;
impl dyn ConstructionBudget + '_ {
pub(in crate::db) fn copy_order_spec(
&self,
order: &OrderSpec,
) -> Result<OrderSpec, InternalError> {
Ok(OrderSpec {
fields: self.copy_slice(&order.fields, |term| {
Ok(OrderTerm::new(
self.copy_expr(term.expr())?,
term.direction(),
))
})?,
})
}
pub(in crate::db) fn copy_expr(&self, expr: &Expr) -> Result<Expr, InternalError> {
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>, InternalError> {
self.charge(Resource::TemporaryBytes, size_of::<Expr>() as u64)?;
Ok(Box::new(self.copy_expr(expr)?))
}
}