use crate::db::{
access::{
AccessCapabilities, PushdownApplicability, SecondaryOrderPushdownEligibility,
SecondaryOrderPushdownRejection,
},
query::plan::{
AccessPlannedQuery, DeterministicSecondaryIndexOrderMatch,
DeterministicSecondaryOrderContract, LogicalPushdownEligibility, PlannerRouteProfile,
index_order_terms,
},
};
fn validated_secondary_order_contract(
planner_route_profile: &PlannerRouteProfile,
) -> Option<&DeterministicSecondaryOrderContract> {
secondary_order_contract_active(planner_route_profile.logical_pushdown_eligibility())
.then_some(())?;
planner_route_profile.secondary_order_contract()
}
pub(in crate::db) fn derive_secondary_pushdown_applicability_from_contract(
plan: &AccessPlannedQuery,
planner_route_profile: &PlannerRouteProfile,
) -> PushdownApplicability {
let Some(order_contract) = validated_secondary_order_contract(planner_route_profile) else {
return PushdownApplicability::NotApplicable;
};
let access_capabilities = plan.access_strategy().capabilities();
secondary_order_pushdown_applicability(&access_capabilities, order_contract)
}
fn match_secondary_order_pushdown_core(
order_contract: &DeterministicSecondaryOrderContract,
index_name: &'static str,
index_order_terms: &[String],
prefix_len: usize,
) -> SecondaryOrderPushdownEligibility {
if !matches!(
order_contract.classify_index_match(index_order_terms, prefix_len),
DeterministicSecondaryIndexOrderMatch::None
) {
return SecondaryOrderPushdownEligibility::Eligible {
index: index_name,
prefix_len,
};
}
SecondaryOrderPushdownEligibility::Rejected(
SecondaryOrderPushdownRejection::OrderFieldsDoNotMatchIndex {
index: index_name,
prefix_len,
expected_suffix: index_order_terms.iter().skip(prefix_len).cloned().collect(),
expected_full: index_order_terms.to_vec(),
actual: order_contract.non_primary_key_terms().to_vec(),
},
)
}
const fn prefix_order_contract_safe(access_capabilities: &AccessCapabilities) -> bool {
let Some((index, prefix_len)) = access_capabilities.single_path_index_prefix_details() else {
return false;
};
index.is_unique() || prefix_len > 0
}
#[must_use]
pub(in crate::db) fn index_path_satisfies_secondary_order_contract(
access_capabilities: &AccessCapabilities,
order_contract: &DeterministicSecondaryOrderContract,
) -> bool {
access_capabilities.has_index_path()
&& (access_capabilities
.single_path_index_prefix_details()
.is_none()
|| prefix_order_contract_safe(access_capabilities))
&& secondary_order_pushdown_applicability(access_capabilities, order_contract).is_eligible()
}
#[must_use]
pub(in crate::db) fn secondary_order_pushdown_applicability(
access_capabilities: &AccessCapabilities,
order_contract: &DeterministicSecondaryOrderContract,
) -> PushdownApplicability {
if !access_capabilities.is_single_path() {
if let Some(details) = access_capabilities.first_index_range_details() {
return PushdownApplicability::Applicable(SecondaryOrderPushdownEligibility::Rejected(
SecondaryOrderPushdownRejection::AccessPathIndexRangeUnsupported {
index: details.index().name(),
prefix_len: details.slot_arity(),
},
));
}
return PushdownApplicability::NotApplicable;
}
if access_capabilities.prefix_scan() {
let Some((index, prefix_len)) = access_capabilities.single_path_index_prefix_details()
else {
debug_assert!(
false,
"route invariant: prefix-scan single-path routes must expose prefix details",
);
return PushdownApplicability::NotApplicable;
};
if prefix_len > index.fields().len() {
return PushdownApplicability::Applicable(SecondaryOrderPushdownEligibility::Rejected(
SecondaryOrderPushdownRejection::InvalidIndexPrefixBounds {
prefix_len,
index_field_len: index.fields().len(),
},
));
}
let index_terms = index_order_terms(&index);
return PushdownApplicability::Applicable(match_secondary_order_pushdown_core(
order_contract,
index.name(),
&index_terms,
prefix_len,
));
}
if access_capabilities.range_scan() {
let Some((index, prefix_len)) = access_capabilities.single_path_index_range_details()
else {
debug_assert!(
false,
"route invariant: range-scan single-path routes must expose range details",
);
return PushdownApplicability::NotApplicable;
};
if prefix_len > index.fields().len() {
return PushdownApplicability::Applicable(SecondaryOrderPushdownEligibility::Rejected(
SecondaryOrderPushdownRejection::InvalidIndexPrefixBounds {
prefix_len,
index_field_len: index.fields().len(),
},
));
}
let index_terms = index_order_terms(&index);
let eligibility = match_secondary_order_pushdown_core(
order_contract,
index.name(),
&index_terms,
prefix_len,
);
return match eligibility {
SecondaryOrderPushdownEligibility::Eligible { .. } => {
PushdownApplicability::Applicable(eligibility)
}
SecondaryOrderPushdownEligibility::Rejected(_) => {
PushdownApplicability::Applicable(SecondaryOrderPushdownEligibility::Rejected(
SecondaryOrderPushdownRejection::AccessPathIndexRangeUnsupported {
index: index.name(),
prefix_len,
},
))
}
};
}
PushdownApplicability::NotApplicable
}
#[must_use]
pub(in crate::db::executor::planning::route) fn index_range_limit_pushdown_shape_supported_for_order_contract(
access_capabilities: &AccessCapabilities,
order_contract: Option<&DeterministicSecondaryOrderContract>,
order_present: bool,
) -> bool {
if !access_capabilities.is_single_path() {
return false;
}
let Some((index, prefix_len)) = access_capabilities.single_path_index_range_details() else {
return false;
};
if !order_present {
return true;
}
let Some(order_contract) = order_contract else {
return false;
};
let index_terms = index_order_terms(&index);
matches!(
order_contract.classify_index_match(&index_terms, prefix_len),
DeterministicSecondaryIndexOrderMatch::Full | DeterministicSecondaryIndexOrderMatch::Suffix
)
}
pub(in crate::db::executor) const fn secondary_order_contract_active(
logical_pushdown_eligibility: LogicalPushdownEligibility,
) -> bool {
logical_pushdown_eligibility.secondary_order_allowed()
&& !logical_pushdown_eligibility.requires_full_materialization()
}
pub(in crate::db::executor) fn access_order_satisfied_by_route_contract(
plan: &AccessPlannedQuery,
) -> bool {
let logical = plan.scalar_plan();
let Some(order) = logical.order.as_ref() else {
return false;
};
let access_capabilities = plan.access_strategy().capabilities();
let planner_route_profile = plan.planner_route_profile();
let has_order_fields = !order.fields.is_empty();
let primary_key_order_satisfied =
order.is_primary_key_only(plan.primary_key_name()) && !access_capabilities.has_index_path();
let secondary_pushdown_eligible = validated_secondary_order_contract(planner_route_profile)
.is_some_and(|order_contract| {
index_path_satisfies_secondary_order_contract(&access_capabilities, order_contract)
});
has_order_fields && (primary_key_order_satisfied || secondary_pushdown_eligible)
}