#[cfg(feature = "sql")]
use crate::db::cursor::encode_cursor;
use crate::db::{
GroupedRow, QueryError,
cursor::GroupedContinuationToken,
diagnostics::ExecutionTrace,
executor::{RuntimeGroupedRow, StructuralGroupedProjectionResult},
schema::{AcceptedEnumCatalog, output_value_from_runtime},
};
type FinalizedGroupedProjection = (Vec<GroupedRow>, Option<Vec<u8>>, Option<ExecutionTrace>);
fn encode_grouped_page_cursor(
cursor: Option<GroupedContinuationToken>,
) -> Result<Option<Vec<u8>>, QueryError> {
cursor
.map(|token| {
token
.encode()
.map_err(|_err| QueryError::serialize_internal())
})
.transpose()
}
fn grouped_row_from_runtime_row(
catalog: &AcceptedEnumCatalog,
row: RuntimeGroupedRow,
) -> Result<GroupedRow, QueryError> {
let (group_key, aggregate_values) = row.into_group_key_and_aggregate_values();
let group_key = group_key
.iter()
.map(|value| {
output_value_from_runtime(catalog, value).map_err(|_error| QueryError::invariant())
})
.collect::<Result<Vec<_>, _>>()?;
let aggregate_values = aggregate_values
.iter()
.map(|value| {
output_value_from_runtime(catalog, value).map_err(|_error| QueryError::invariant())
})
.collect::<Result<Vec<_>, _>>()?;
Ok(GroupedRow::new(group_key, aggregate_values))
}
fn grouped_rows_from_runtime_rows(
catalog: &AcceptedEnumCatalog,
rows: Vec<RuntimeGroupedRow>,
) -> Result<Vec<GroupedRow>, QueryError> {
rows.into_iter()
.map(|row| grouped_row_from_runtime_row(catalog, row))
.collect()
}
pub(in crate::db) fn finalize_structural_grouped_projection_result(
result: StructuralGroupedProjectionResult,
trace: Option<ExecutionTrace>,
) -> Result<FinalizedGroupedProjection, QueryError> {
let (rows, next_cursor, value_catalog) = result.into_rows_and_cursor();
let next_cursor = encode_grouped_page_cursor(next_cursor)?;
let rows = grouped_rows_from_runtime_rows(value_catalog.enum_catalog(), rows)?;
Ok((rows, next_cursor, trace))
}
#[cfg(feature = "sql")]
pub(in crate::db) fn sql_grouped_cursor_from_bytes(cursor: Option<Vec<u8>>) -> Option<String> {
cursor.as_deref().map(encode_cursor)
}