use crate::{db::query::plan::PlannedProjectionLayout, error::InternalError};
pub(in crate::db) fn validate_grouped_projection_layout(
projection_layout: &PlannedProjectionLayout,
group_fields_len: usize,
aggregate_exprs_len: usize,
) -> Result<(), InternalError> {
let group_positions = projection_layout.group_field_positions();
let aggregate_positions = projection_layout.aggregate_positions();
if group_positions.len() != group_fields_len {
return Err(PlannedProjectionLayout::group_field_count_mismatch(
group_positions.len(),
group_fields_len,
));
}
if aggregate_positions.len() != aggregate_exprs_len {
return Err(PlannedProjectionLayout::aggregate_count_mismatch(
aggregate_positions.len(),
aggregate_exprs_len,
));
}
if !group_positions
.windows(2)
.all(|window| window[0] < window[1])
{
return Err(PlannedProjectionLayout::group_field_positions_not_strictly_increasing());
}
if !aggregate_positions
.windows(2)
.all(|window| window[0] < window[1])
{
return Err(PlannedProjectionLayout::aggregate_positions_not_strictly_increasing());
}
if let (Some(last_group_position), Some(first_aggregate_position)) =
(group_positions.last(), aggregate_positions.first())
&& last_group_position >= first_aggregate_position
{
return Err(PlannedProjectionLayout::group_fields_must_precede_aggregates());
}
Ok(())
}