#[cfg(test)]
mod tests;
use crate::{
db::{
index::{
IndexCompilePolicy, IndexPredicateProgram, compile_index_program,
compile_index_program_for_targets,
},
predicate::{
IndexCompileTarget, PredicateCapabilityContext, PredicateCapabilityProfile,
PredicateProgram, classify_predicate_capabilities,
classify_predicate_capabilities_for_targets,
},
query::construction::ConstructionBudget,
query::plan::{
AccessPlannedQuery, EffectiveRuntimeFilterProgram, covering_strict_predicate_compatible,
},
},
error::InternalError,
};
use std::borrow::Cow;
#[derive(Clone)]
pub(in crate::db::executor) struct ExecutionPreparation {
compiled_predicate: Option<PredicateProgram>,
effective_runtime_filter_program: Option<EffectiveRuntimeFilterProgram>,
compile_targets: Option<Vec<IndexCompileTarget>>,
index_program: Option<PreparedIndexProgram>,
predicate_capability_profile: Option<PredicateCapabilityProfile>,
slot_map: Option<Vec<usize>>,
}
#[derive(Clone)]
struct PreparedIndexProgram {
policy: IndexCompilePolicy,
program: Option<IndexPredicateProgram>,
}
impl PreparedIndexProgram {
fn resolve(
prepared: Option<&Self>,
policy: IndexCompilePolicy,
compile: impl FnOnce() -> Result<Option<IndexPredicateProgram>, InternalError>,
) -> Result<Option<Cow<'_, IndexPredicateProgram>>, InternalError> {
match prepared {
Some(prepared) if prepared.policy == policy => {
Ok(prepared.program.as_ref().map(Cow::Borrowed))
}
Some(_) | None => Ok(compile()?.map(Cow::Owned)),
}
}
}
#[derive(Clone, Copy)]
enum PreparationPredicateSource {
ExecutionPreparation,
EffectiveRuntime,
}
#[derive(Clone, Copy)]
struct PreparationBuildConfig {
predicate_source: PreparationPredicateSource,
include_predicate_capability_profile: bool,
}
impl ExecutionPreparation {
pub(in crate::db::executor) fn from_plan(
plan: &AccessPlannedQuery,
slot_map: Option<Vec<usize>>,
budget: &dyn ConstructionBudget,
) -> Result<Self, InternalError> {
Self::build(
plan,
slot_map,
PreparationBuildConfig {
predicate_source: PreparationPredicateSource::ExecutionPreparation,
include_predicate_capability_profile: true,
},
)
.compile_policy(IndexCompilePolicy::StrictAllOrNone, budget)
}
pub(in crate::db::executor) fn from_runtime_plan(
plan: &AccessPlannedQuery,
slot_map: Option<Vec<usize>>,
budget: &dyn ConstructionBudget,
) -> Result<Self, InternalError> {
Self::build(
plan,
slot_map,
PreparationBuildConfig {
predicate_source: PreparationPredicateSource::EffectiveRuntime,
include_predicate_capability_profile: false,
},
)
.compile_policy(IndexCompilePolicy::ConservativeSubset, budget)
}
fn compile_policy(
mut self,
policy: IndexCompilePolicy,
budget: &dyn ConstructionBudget,
) -> Result<Self, InternalError> {
let program = compile_index_program_for_preparation(
self.compiled_predicate.as_ref(),
self.compile_targets.as_deref(),
self.slot_map.as_deref(),
policy,
budget,
)?;
self.index_program = Some(PreparedIndexProgram { policy, program });
Ok(self)
}
#[must_use]
pub(in crate::db::executor) const fn compiled_predicate(&self) -> Option<&PredicateProgram> {
self.compiled_predicate.as_ref()
}
#[must_use]
pub(in crate::db::executor) const fn effective_runtime_filter_program(
&self,
) -> Option<&EffectiveRuntimeFilterProgram> {
self.effective_runtime_filter_program.as_ref()
}
#[must_use]
pub(in crate::db::executor) fn prepared_index_program(
&self,
policy: IndexCompilePolicy,
) -> Option<&IndexPredicateProgram> {
self.index_program
.as_ref()
.filter(|prepared| prepared.policy == policy)
.and_then(|prepared| prepared.program.as_ref())
}
pub(in crate::db::executor) fn resolve_index_program(
&self,
policy: IndexCompilePolicy,
budget: &dyn ConstructionBudget,
) -> Result<Option<Cow<'_, IndexPredicateProgram>>, InternalError> {
PreparedIndexProgram::resolve(self.index_program.as_ref(), policy, || {
compile_index_program_for_preparation(
self.compiled_predicate.as_ref(),
self.compile_targets.as_deref(),
self.slot_map.as_deref(),
policy,
budget,
)
})
}
#[must_use]
pub(in crate::db::executor) const fn predicate_capability_profile(
&self,
) -> Option<PredicateCapabilityProfile> {
self.predicate_capability_profile
}
fn build(
plan: &AccessPlannedQuery,
slot_map: Option<Vec<usize>>,
config: PreparationBuildConfig,
) -> Self {
let compiled_predicate = match config.predicate_source {
PreparationPredicateSource::ExecutionPreparation => {
plan.execution_preparation_compiled_predicate().cloned()
}
PreparationPredicateSource::EffectiveRuntime => {
plan.effective_runtime_compiled_predicate().cloned()
}
};
let effective_runtime_filter_program = matches!(
config.predicate_source,
PreparationPredicateSource::EffectiveRuntime
)
.then(|| plan.effective_runtime_filter_program().cloned())
.flatten();
let compile_targets = index_compile_targets_for_model_plan(plan);
let predicate_capability_profile = if config.include_predicate_capability_profile {
predicate_capability_profile_for_preparation(
compiled_predicate.as_ref(),
compile_targets.as_deref(),
slot_map.as_deref(),
)
} else {
None
};
Self {
compiled_predicate,
effective_runtime_filter_program,
compile_targets,
index_program: None,
predicate_capability_profile,
slot_map,
}
}
}
impl std::fmt::Debug for ExecutionPreparation {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("ExecutionPreparation(..)")
}
}
#[must_use]
pub(in crate::db::executor) fn predicate_capability_profile_for_plan(
plan: &AccessPlannedQuery,
) -> Option<PredicateCapabilityProfile> {
predicate_capability_profile_for_preparation(
plan.execution_preparation_compiled_predicate(),
plan.index_compile_targets(),
plan.slot_map(),
)
}
pub(in crate::db::executor) fn covering_strict_predicate_compatible_for_plan(
plan: &AccessPlannedQuery,
) -> Result<bool, InternalError> {
let residual = plan.residual_filter_contract()?;
if residual.residual_filter_predicate().is_none() {
return Ok(covering_strict_predicate_compatible(residual, None));
}
Ok(covering_strict_predicate_compatible(
residual,
predicate_capability_profile_for_plan(plan).map(PredicateCapabilityProfile::index),
))
}
fn predicate_capability_profile_for_preparation(
compiled_predicate: Option<&PredicateProgram>,
compile_targets: Option<&[IndexCompileTarget]>,
slot_map: Option<&[usize]>,
) -> Option<PredicateCapabilityProfile> {
match (compiled_predicate, compile_targets, slot_map) {
(Some(compiled_predicate), Some(compile_targets), _) => {
Some(classify_predicate_capabilities_for_targets(
compiled_predicate.executable(),
compile_targets,
))
}
(Some(compiled_predicate), None, Some(slot_map)) => Some(classify_predicate_capabilities(
compiled_predicate.executable(),
PredicateCapabilityContext::index_compile(slot_map),
)),
(Some(_) | None, None, None) | (None, Some(_), _) | (None, None, Some(_)) => None,
}
}
pub(in crate::db::executor) fn compile_strict_index_program_for_plan(
plan: &AccessPlannedQuery,
budget: &dyn ConstructionBudget,
) -> Result<Option<IndexPredicateProgram>, InternalError> {
compile_index_program_for_preparation(
plan.execution_preparation_compiled_predicate(),
plan.index_compile_targets(),
plan.slot_map(),
IndexCompilePolicy::StrictAllOrNone,
budget,
)
}
fn compile_index_program_for_preparation(
compiled_predicate: Option<&PredicateProgram>,
compile_targets: Option<&[IndexCompileTarget]>,
slot_map: Option<&[usize]>,
policy: IndexCompilePolicy,
budget: &dyn ConstructionBudget,
) -> Result<Option<IndexPredicateProgram>, InternalError> {
match (compiled_predicate, compile_targets, slot_map) {
(Some(compiled_predicate), Some(compile_targets), _) => compile_index_program_for_targets(
compiled_predicate.executable(),
compile_targets,
policy,
budget,
),
(Some(compiled_predicate), None, Some(slot_map)) => {
compile_index_program(compiled_predicate.executable(), slot_map, policy, budget)
}
(Some(_) | None, None, None) | (None, Some(_), _) | (None, None, Some(_)) => Ok(None),
}
}
pub(in crate::db::executor) fn slot_map_for_model_plan(
plan: &AccessPlannedQuery,
) -> Option<Vec<usize>> {
plan.slot_map().map(<[usize]>::to_vec)
}
fn index_compile_targets_for_model_plan(
plan: &AccessPlannedQuery,
) -> Option<Vec<IndexCompileTarget>> {
plan.index_compile_targets()
.map(<[IndexCompileTarget]>::to_vec)
}
crate::retained::retained_fields!(ExecutionPreparation {
Self{compiled_predicate,effective_runtime_filter_program,compile_targets,index_program,predicate_capability_profile,slot_map} => [compiled_predicate,effective_runtime_filter_program,compile_targets,index_program,predicate_capability_profile,slot_map],
});
crate::retained::retained_fields!(PreparedIndexProgram {
Self{policy: _,program} => [program],
});