use crate::{
db::{
cursor::{
CursorBoundary, effective_keep_count_for_limit as continuation_keep_count_for_limit,
effective_page_offset_for_window as continuation_page_offset_for_window,
},
direction::Direction,
executor::{
AccessScanContinuationInput, ContinuationMode, RouteContinuationPlan,
planning::route::LoadOrderRouteMode,
},
query::plan::{AccessPlannedQuery, ContinuationPolicy},
},
error::InternalError,
};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(in crate::db::executor) enum ScalarContinuationContext {
Initial,
}
impl ScalarContinuationContext {
#[must_use]
pub(in crate::db::executor) const fn initial() -> Self {
Self::Initial
}
#[must_use]
pub(in crate::db::executor) const fn cursor_boundary(self) -> Option<&'static CursorBoundary> {
match self {
Self::Initial => None,
}
}
#[must_use]
pub(in crate::db::executor) const fn has_cursor_boundary(self) -> bool {
match self {
Self::Initial => false,
}
}
#[must_use]
pub(in crate::db::executor) const fn route_continuation_mode(self) -> ContinuationMode {
match self {
Self::Initial => ContinuationMode::Initial,
}
}
#[must_use]
pub(in crate::db::executor) fn route_continuation_plan(
self,
plan: &AccessPlannedQuery,
continuation_policy: ContinuationPolicy,
) -> RouteContinuationPlan {
RouteContinuationPlan::from_scalar_access_window_plan(
self.route_continuation_mode(),
continuation_policy,
plan.scalar_access_window_plan(self.has_cursor_boundary()),
)
}
#[must_use]
pub(in crate::db::executor) const fn access_scan_input(
self,
direction: Direction,
) -> AccessScanContinuationInput<'static> {
match self {
Self::Initial => {
AccessScanContinuationInput::with_primary_key_boundary(None, direction, None)
}
}
}
pub(in crate::db::executor) fn debug_assert_route_continuation_invariants(
self,
plan: &AccessPlannedQuery,
route_continuation: RouteContinuationPlan,
) {
debug_assert!(
route_continuation.strict_advance_required_when_applied(),
"route invariant: continuation executions must enforce strict advancement policy",
);
debug_assert_eq!(
route_continuation.effective_offset(),
continuation_page_offset_for_window(plan, self.has_cursor_boundary()),
"route window effective offset must match logical plan offset semantics",
);
}
#[must_use]
pub(in crate::db::executor) fn keep_count_for_limit_window(
self,
plan: &AccessPlannedQuery,
limit: u32,
) -> usize {
continuation_keep_count_for_limit(plan, self.has_cursor_boundary(), limit)
}
pub(in crate::db::executor) fn validate_load_scan_budget_hint(
self,
scan_budget_hint: Option<usize>,
load_order_route_mode: LoadOrderRouteMode,
) -> Result<(), InternalError> {
match self {
Self::Initial => {}
}
if scan_budget_hint.is_some() && !load_order_route_mode.allows_streaming_load() {
return Err(InternalError::query_executor_invariant());
}
Ok(())
}
}