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::plan::AccessPlannedQuery,
};
#[derive(Clone)]
pub(in crate::db::executor) struct ExecutionPreparation {
compiled_predicate: Option<PredicateProgram>,
compile_targets: Option<Vec<IndexCompileTarget>>,
conservative_mode: Option<IndexPredicateProgram>,
predicate_capability_profile: Option<PredicateCapabilityProfile>,
slot_map: Option<Vec<usize>>,
strict_mode: Option<IndexPredicateProgram>,
}
#[derive(Clone, Copy)]
enum PreparationPredicateSource {
ExecutionPreparation,
EffectiveRuntime,
}
#[derive(Clone, Copy)]
struct PreparationBuildConfig {
predicate_source: PreparationPredicateSource,
include_predicate_capability_profile: bool,
strict_policy: Option<IndexCompilePolicy>,
conservative_policy: Option<IndexCompilePolicy>,
}
impl ExecutionPreparation {
#[must_use]
pub(in crate::db::executor) fn from_plan(
plan: &AccessPlannedQuery,
slot_map: Option<Vec<usize>>,
) -> Self {
Self::build(
plan,
slot_map,
PreparationBuildConfig {
predicate_source: PreparationPredicateSource::ExecutionPreparation,
include_predicate_capability_profile: true,
strict_policy: Some(IndexCompilePolicy::StrictAllOrNone),
conservative_policy: None,
},
)
}
#[must_use]
pub(in crate::db::executor) fn from_covering_route_plan(
plan: &AccessPlannedQuery,
slot_map: Option<Vec<usize>>,
) -> Self {
Self::build(
plan,
slot_map,
PreparationBuildConfig {
predicate_source: PreparationPredicateSource::ExecutionPreparation,
include_predicate_capability_profile: true,
strict_policy: None,
conservative_policy: None,
},
)
}
#[must_use]
pub(in crate::db::executor) fn from_runtime_plan(
plan: &AccessPlannedQuery,
slot_map: Option<Vec<usize>>,
) -> Self {
Self::build(
plan,
slot_map,
PreparationBuildConfig {
predicate_source: PreparationPredicateSource::EffectiveRuntime,
include_predicate_capability_profile: false,
strict_policy: None,
conservative_policy: Some(IndexCompilePolicy::ConservativeSubset),
},
)
}
#[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 conservative_mode(
&self,
) -> Option<&IndexPredicateProgram> {
self.conservative_mode.as_ref()
}
#[must_use]
pub(in crate::db::executor) fn slot_map(&self) -> Option<&[usize]> {
self.slot_map.as_deref()
}
#[must_use]
pub(in crate::db::executor) fn compile_targets(&self) -> Option<&[IndexCompileTarget]> {
self.compile_targets.as_deref()
}
#[must_use]
pub(in crate::db::executor) const fn predicate_capability_profile(
&self,
) -> Option<PredicateCapabilityProfile> {
self.predicate_capability_profile
}
#[must_use]
pub(in crate::db::executor) const fn strict_mode(&self) -> Option<&IndexPredicateProgram> {
self.strict_mode.as_ref()
}
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 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
};
let strict_mode = config.strict_policy.and_then(|policy| {
compile_index_program_for_preparation(
compiled_predicate.as_ref(),
compile_targets.as_deref(),
slot_map.as_deref(),
policy,
)
});
let conservative_mode = config.conservative_policy.and_then(|policy| {
compile_index_program_for_preparation(
compiled_predicate.as_ref(),
compile_targets.as_deref(),
slot_map.as_deref(),
policy,
)
});
Self {
compiled_predicate,
compile_targets,
conservative_mode,
predicate_capability_profile,
slot_map,
strict_mode,
}
}
}
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,
}
}
fn compile_index_program_for_preparation(
compiled_predicate: Option<&PredicateProgram>,
compile_targets: Option<&[IndexCompileTarget]>,
slot_map: Option<&[usize]>,
policy: IndexCompilePolicy,
) -> Option<IndexPredicateProgram> {
match (compiled_predicate, compile_targets, slot_map) {
(Some(compiled_predicate), Some(compile_targets), _) => compile_index_program_for_targets(
compiled_predicate.executable(),
compile_targets,
policy,
),
(Some(compiled_predicate), None, Some(slot_map)) => {
compile_index_program(compiled_predicate.executable(), slot_map, policy)
}
(Some(_) | None, None, None) | (None, Some(_), _) | (None, None, Some(_)) => 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)
}