use super::*;
use crate::background::{
CheckpointAllocationOwner, CheckpointDecodeContext, CheckpointOperationError,
};
pub(super) struct DefinitionPlan {
by_subject: BTreeMap<ProjectionSubject, Vec<PreparedProjectionDefinition>>,
_memory: CheckpointAllocationOwner,
}
impl std::ops::Deref for DefinitionPlan {
type Target = BTreeMap<ProjectionSubject, Vec<PreparedProjectionDefinition>>;
fn deref(&self) -> &Self::Target {
&self.by_subject
}
}
pub(super) fn prepare(
definitions: &[PersistentPropertyProjectionDefinition],
work: &CheckpointWorkContext,
) -> Result<DefinitionPlan, PersistentPropertyProjectionError> {
work.classify(|work| {
let memory = CheckpointDecodeContext {
work: work.clone(),
memory: std::cell::RefCell::default(),
};
let mut by_subject: BTreeMap<ProjectionSubject, Vec<PreparedProjectionDefinition>> =
BTreeMap::new();
let mut tree_memory = crate::projection::predicate_checkpoint::decode::MapMemory::<
Vec<PreparedProjectionDefinition>,
>::default();
for (index, definition) in definitions.iter().enumerate() {
let value_source =
if definition.kind == PersistentPropertyProjectionKind::CompositeEquality {
ProjectionValueSource::Composite(decode_composite_property_identity_inner(
&definition.property,
Some(&memory),
)?)
} else {
ProjectionValueSource::Scalar
};
let unit = work.start_unit()?;
let subject = definition_subject(definition);
if !by_subject.contains_key(&subject) {
tree_memory
.before_insert(by_subject.len(), &memory)
.map_err(|error| {
PersistentPropertyProjectionError::Source(error.to_string())
})?;
}
let bucket = by_subject.entry(subject).or_default();
unit.finish();
memory
.push(
bucket,
PreparedProjectionDefinition {
definition_index: index,
value_source,
},
)
.map_err(|error| PersistentPropertyProjectionError::Source(error.to_string()))?;
}
work.checkpoint()?;
Ok(DefinitionPlan {
by_subject,
_memory: memory.memory.into_inner(),
})
})
.map_err(|error| match error {
CheckpointOperationError::Work(error) => PersistentPropertyProjectionError::Work(error),
CheckpointOperationError::Operation(error) => error,
})
}
#[cfg(all(test, not(target_arch = "wasm32")))]
mod tests;