use crate::{
db::{
data::StructuralRowContract,
predicate::PredicateProgram,
schema::{SchemaExpressionIndexKeyItemInfo, SchemaIndexFieldPathInfo, SchemaInfo},
},
error::InternalError,
};
pub(in crate::db) struct PreparedIndexMutationMetadata {
pub(super) schema_info: SchemaInfo,
pub(super) row_contract: StructuralRowContract,
pub(super) field_path_inputs: Vec<PreparedIndexInputs>,
pub(super) expression_inputs: Vec<PreparedIndexInputs>,
}
impl PreparedIndexMutationMetadata {
pub(in crate::db) fn new(
schema_info: SchemaInfo,
row_contract: StructuralRowContract,
) -> Result<Self, InternalError> {
let field_path_inputs = schema_info
.field_path_indexes()
.iter()
.map(|index| {
let program = index.predicate()?.map(|predicate| {
PredicateProgram::compile_with_row_contract(&row_contract, &predicate)
});
Ok(PreparedIndexInputs::new(
&row_contract,
program,
index.fields().iter().map(SchemaIndexFieldPathInfo::slot),
))
})
.collect::<Result<Vec<_>, InternalError>>()?;
let expression_inputs = schema_info
.expression_indexes()
.iter()
.map(|index| {
let program = index.predicate()?.map(|predicate| {
PredicateProgram::compile_with_row_contract(&row_contract, &predicate)
});
Ok(PreparedIndexInputs::new(
&row_contract,
program,
index.key_items().iter().map(|item| match item {
SchemaExpressionIndexKeyItemInfo::FieldPath(field) => field.slot(),
SchemaExpressionIndexKeyItemInfo::Expression(expression) => {
expression.source().slot()
}
}),
))
})
.collect::<Result<Vec<_>, InternalError>>()?;
Ok(Self {
schema_info,
row_contract,
field_path_inputs,
expression_inputs,
})
}
}
pub(super) struct PreparedIndexInputs {
pub(super) predicate_program: Option<PredicateProgram>,
pub(super) referenced_slots: Box<[bool]>,
}
impl PreparedIndexInputs {
fn new(
row_contract: &StructuralRowContract,
predicate_program: Option<PredicateProgram>,
key_slots: impl Iterator<Item = usize>,
) -> Self {
let mut referenced_slots = vec![false; row_contract.field_count()];
for slot in key_slots {
if let Some(referenced) = referenced_slots.get_mut(slot) {
*referenced = true;
}
}
if let Some(program) = predicate_program.as_ref() {
program.mark_referenced_slots(&mut referenced_slots);
}
Self {
predicate_program,
referenced_slots: referenced_slots.into_boxed_slice(),
}
}
}