use crate::{
db::{
DbSession, PagedGroupedExecutionWithTrace, PersistedRow, Query, QueryError,
cursor::{ValidatedGroupedCursor, decode_optional_grouped_cursor_token},
diagnostics::ExecutionTrace,
executor::{LoadExecutor, PreparedExecutionPlan, StructuralGroupedProjectionResult},
session::{
finalize_structural_grouped_projection_result,
query::query_error_from_executor_plan_error,
},
},
error::InternalError,
traits::{CanisterKind, EntityValue},
};
impl<C: CanisterKind> DbSession<C> {
#[cfg_attr(
not(test),
allow(
dead_code,
reason = "crate-local grouped pagination tests exercise this boundary before public grouped paging APIs expose it"
)
)]
pub(in crate::db) fn execute_grouped<E>(
&self,
query: &Query<E>,
cursor_token: Option<&str>,
) -> Result<PagedGroupedExecutionWithTrace, QueryError>
where
E: PersistedRow<Canister = C> + EntityValue,
{
let plan = self.cached_prepared_query_plan_for_entity::<E>(query)?.0;
let (result, trace) = self.execute_grouped_with_trace(plan, cursor_token)?;
finalize_structural_grouped_projection_result(result, trace)
}
pub(in crate::db::session) fn execute_grouped_with_cursor<E, T>(
&self,
plan: PreparedExecutionPlan<E>,
cursor_token: Option<&str>,
op: impl FnOnce(
LoadExecutor<E>,
PreparedExecutionPlan<E>,
ValidatedGroupedCursor,
) -> Result<T, InternalError>,
) -> Result<T, QueryError>
where
E: PersistedRow<Canister = C> + EntityValue,
{
Self::ensure_grouped_execution_family(
plan.execution_family().map_err(QueryError::execute)?,
)?;
let cursor = decode_optional_grouped_cursor_token(cursor_token)
.map_err(QueryError::from_cursor_plan_error)?;
let cursor = plan
.prepare_grouped_cursor_token(cursor)
.map_err(query_error_from_executor_plan_error)?;
self.with_metrics(|| op(self.load_executor::<E>(), plan, cursor))
.map_err(QueryError::execute)
}
pub(in crate::db::session) fn execute_grouped_with_trace<E>(
&self,
plan: PreparedExecutionPlan<E>,
cursor_token: Option<&str>,
) -> Result<(StructuralGroupedProjectionResult, Option<ExecutionTrace>), QueryError>
where
E: PersistedRow<Canister = C> + EntityValue,
{
self.execute_grouped_with_cursor(plan, cursor_token, |executor, plan, cursor| {
executor.execute_grouped_paged_with_cursor_traced(plan, cursor)
})
}
}