use crate::{
db::{
Db,
commit::CommitRowOp,
data::{RawDataStoreKey, RawRow},
executor::{
EntityAuthority,
delete::types::{DeleteExecutionAuthority, PreparedDeleteCommit},
mutation::commit_delete_row_ops_with_window_for_path,
},
registry::StoreHandle,
},
entity::{EntityKind, EntityValue},
error::InternalError,
traits::CanisterKind,
};
use ic_stable_structures::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 = row_layout.canonical_row_from_raw_row(raw_row)?;
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<(RawDataStoreKey, RawRow)>,
) -> Result<PreparedDeleteCommit, InternalError>
where
C: CanisterKind,
{
let deleted_target_keys = rollback_rows
.iter()
.map(|(raw_key, _)| raw_key.clone())
.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,
{
commit_delete_row_ops_with_window_for_path(db, authority.entity_path(), row_ops, apply_phase)
}