use crate::{
db::{
access::ExecutableAccessPlan,
direction::Direction,
executor::{
AccessStreamBindings, ExecutionOptimization, LoweredIndexPrefixSpec,
pipeline::contracts::FastPathKeyResult,
scan::fast_stream::execute_structural_fast_stream_request,
stream::access::TraversalRuntime,
},
index::predicate::IndexPredicateExecution,
query::plan::AccessPlannedQuery,
},
error::InternalError,
value::Value,
};
pub(in crate::db::executor) fn execute_secondary_index_fast_stream_route(
runtime: &TraversalRuntime,
_plan: &AccessPlannedQuery,
executable: &ExecutableAccessPlan<'_, Value>,
index_prefix_spec: Option<&LoweredIndexPrefixSpec>,
stream_direction: Direction,
probe_fetch_hint: Option<usize>,
index_predicate_execution: Option<IndexPredicateExecution<'_>>,
) -> Result<Option<FastPathKeyResult>, InternalError> {
let Some(executable_path) = executable.as_path() else {
return Ok(None);
};
let path_capabilities = executable_path.capabilities();
let Some(details) = path_capabilities.index_prefix_details() else {
return Ok(None);
};
let index = details.index();
let Some(index_prefix_spec) = index_prefix_spec else {
return Err(InternalError::secondary_index_prefix_spec_required());
};
debug_assert_eq!(
index_prefix_spec.index(),
&index,
"secondary fast-path spec/index alignment must be validated by resolver",
);
let fast = execute_structural_fast_stream_request(
runtime,
executable,
AccessStreamBindings::with_index_prefix(index_prefix_spec, stream_direction),
probe_fetch_hint,
index_predicate_execution,
ExecutionOptimization::SecondaryOrderPushdown,
)?;
if let Some(fetch) = probe_fetch_hint {
debug_assert!(
fast.rows_scanned
.is_none_or(|rows_scanned| rows_scanned <= fetch),
"secondary fast-path rows_scanned must not exceed bounded fetch",
);
}
Ok(Some(fast))
}