use crate::{
db::{
executor::{ExecutableAccessPath, LoweredIndexRangeSpec},
predicate::MissingRowPolicy,
query::plan::AccessPlannedQuery,
},
error::InternalError,
};
pub(in crate::db::executor) struct IndexRangeTraversalContract;
impl IndexRangeTraversalContract {
pub(in crate::db::executor) fn validate_spec_alignment<K>(
path: &ExecutableAccessPath<'_, K>,
index_range_spec: Option<&LoweredIndexRangeSpec>,
) -> Result<(), InternalError> {
let path_capabilities = path.capabilities();
if let Some(spec) = index_range_spec
&& let Some(index) = path_capabilities.index_range_model()
&& spec.index() != &index
{
return Err(InternalError::query_executor_invariant(
"index-range spec does not match access path index",
));
}
Ok(())
}
pub(in crate::db::executor) fn require_spec(
index_range_spec: Option<&LoweredIndexRangeSpec>,
) -> Result<&LoweredIndexRangeSpec, InternalError> {
index_range_spec.ok_or_else(|| {
InternalError::query_executor_invariant(
"index-range execution requires pre-lowered index-range spec",
)
})
}
pub(in crate::db::executor) fn validate_specs_consumed(
consumed: usize,
available: usize,
) -> Result<(), InternalError> {
if consumed < available {
return Err(InternalError::query_executor_invariant(
"unused index-range executable specs after access-plan traversal",
));
}
Ok(())
}
}
#[must_use]
pub(in crate::db::executor) const fn row_read_consistency_for_plan(
plan: &AccessPlannedQuery,
) -> MissingRowPolicy {
plan.scalar_plan().consistency
}