use crate::{
db::{
Db,
commit::CommitRowOp,
data::{RawDataKey, RawRow, canonical_row_from_raw_row_with_structural_contract},
executor::{
EntityAuthority,
delete::types::{DeleteExecutionAuthority, PreparedDeleteCommit},
mutation::{
commit_delete_row_ops_with_window, commit_delete_row_ops_with_window_for_path,
},
},
registry::StoreHandle,
},
error::InternalError,
traits::{CanisterKind, EntityKind, EntityValue, Storable},
};
use std::collections::BTreeSet;
fn delete_before_image_bytes(
authority: &DeleteExecutionAuthority,
raw_row: &RawRow,
) -> Result<Vec<u8>, InternalError> {
let row_layout = authority.entity.row_layout();
let canonical = canonical_row_from_raw_row_with_structural_contract(
authority.entity.model(),
raw_row,
row_layout.contract().clone(),
)?;
Ok(canonical.into_raw_row().into_bytes())
}
#[inline(never)]
pub(in crate::db::executor::delete) fn prepare_delete_commit<C>(
db: &Db<C>,
_store: StoreHandle,
authority: &DeleteExecutionAuthority,
rollback_rows: Vec<(RawDataKey, RawRow)>,
) -> Result<PreparedDeleteCommit, InternalError>
where
C: CanisterKind,
{
let deleted_target_keys = rollback_rows
.iter()
.map(|(raw_key, _)| *raw_key)
.collect::<BTreeSet<_>>();
db.validate_delete_strong_relations(authority.entity.entity_path(), &deleted_target_keys)?;
let row_ops = rollback_rows
.into_iter()
.map(|(raw_key, raw_row)| {
let before_bytes = delete_before_image_bytes(authority, &raw_row)?;
Ok(CommitRowOp::new(
authority.entity.entity_path(),
raw_key,
Some(before_bytes),
None,
authority.schema_fingerprint,
))
})
.collect::<Result<Vec<_>, InternalError>>()?;
Ok(PreparedDeleteCommit { row_ops })
}
pub(in crate::db::executor::delete) fn apply_delete_commit_window_for_type<E>(
db: &Db<E::Canister>,
authority: EntityAuthority,
row_ops: Vec<CommitRowOp>,
apply_phase: &'static str,
) -> Result<(), InternalError>
where
E: EntityKind + EntityValue,
{
if db.has_runtime_hooks() {
commit_delete_row_ops_with_window_for_path(
db,
authority.entity_path(),
row_ops,
apply_phase,
)
} else {
commit_delete_row_ops_with_window::<E>(db, row_ops, apply_phase)
}
}