use crate::{
db::{
Db, PersistedRow,
executor::{
PreparedExecutionPlan,
delete::{
DeleteProjection, apply_delete_commit_window_for_type,
execute_structural_delete_projection_core, package_typed_delete_count,
package_typed_delete_rows, prepare_delete_runtime, prepare_typed_delete_core,
},
plan_metrics::{record_plan_metrics, set_rows_from_len},
},
response::EntityResponse,
},
error::InternalError,
metrics::sink::{ExecKind, Span},
traits::EntityValue,
};
#[derive(Clone, Copy)]
pub(in crate::db) struct DeleteExecutor<E>
where
E: PersistedRow,
{
db: Db<E::Canister>,
}
impl<E> DeleteExecutor<E>
where
E: PersistedRow + EntityValue,
{
#[must_use]
pub(in crate::db) const fn new(db: Db<E::Canister>) -> Self {
Self { db }
}
pub(in crate::db) fn execute(
self,
plan: PreparedExecutionPlan<E>,
) -> Result<EntityResponse<E>, InternalError> {
(|| {
let (prepared, store) = prepare_delete_runtime(&self.db, plan)?;
let mut span = Span::<E>::new(ExecKind::Delete);
record_plan_metrics(&prepared.logical_plan.access);
let Some(typed) = prepare_typed_delete_core(
&self.db,
store,
&prepared,
package_typed_delete_rows::<E>,
)?
else {
set_rows_from_len(&mut span, 0);
return Ok(EntityResponse::new(Vec::new()));
};
apply_delete_commit_window_for_type::<E>(
&self.db,
prepared.authority.entity,
typed.commit.row_ops,
"delete_row_apply",
)?;
set_rows_from_len(&mut span, typed.row_count);
Ok(EntityResponse::new(typed.output))
})()
}
#[cfg(feature = "sql")]
pub(in crate::db) fn execute_structural_projection(
self,
plan: PreparedExecutionPlan<E>,
) -> Result<DeleteProjection, InternalError> {
(|| {
let (prepared, store) = prepare_delete_runtime(&self.db, plan)?;
let mut span = Span::<E>::new(ExecKind::Delete);
record_plan_metrics(&prepared.logical_plan.access);
let projection = execute_structural_delete_projection_core(
&self.db,
store,
&prepared,
apply_delete_commit_window_for_type::<E>,
)?;
if projection.row_count() == 0 {
set_rows_from_len(&mut span, 0);
return Ok(projection);
}
set_rows_from_len(
&mut span,
usize::try_from(projection.row_count()).unwrap_or(usize::MAX),
);
Ok(projection)
})()
}
pub(in crate::db) fn execute_count(
self,
plan: PreparedExecutionPlan<E>,
) -> Result<u32, InternalError> {
(|| {
let (prepared, store) = prepare_delete_runtime(&self.db, plan)?;
let mut span = Span::<E>::new(ExecKind::Delete);
record_plan_metrics(&prepared.logical_plan.access);
let Some(counted) = prepare_typed_delete_core(
&self.db,
store,
&prepared,
package_typed_delete_count::<E>,
)?
else {
set_rows_from_len(&mut span, 0);
return Ok(0);
};
apply_delete_commit_window_for_type::<E>(
&self.db,
prepared.authority.entity,
counted.commit.row_ops,
"delete_row_apply",
)?;
set_rows_from_len(&mut span, counted.row_count);
Ok(counted.output)
})()
}
}