proof_of_sql/sql/postprocessing/
order_by_postprocessing.rsuse super::{PostprocessingError, PostprocessingResult, PostprocessingStep};
use crate::base::{
database::{compare_indexes_by_owned_columns_with_direction, OwnedColumn, OwnedTable},
if_rayon,
math::permutation::Permutation,
scalar::Scalar,
};
use alloc::{string::ToString, vec::Vec};
use proof_of_sql_parser::intermediate_ast::{OrderBy, OrderByDirection};
#[cfg(feature = "rayon")]
use rayon::prelude::ParallelSliceMut;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct OrderByPostprocessing {
by_exprs: Vec<OrderBy>,
}
impl OrderByPostprocessing {
#[must_use]
pub fn new(by_exprs: Vec<OrderBy>) -> Self {
Self { by_exprs }
}
}
impl<S: Scalar> PostprocessingStep<S> for OrderByPostprocessing {
fn apply(&self, owned_table: OwnedTable<S>) -> PostprocessingResult<OwnedTable<S>> {
let mut indexes = (0..owned_table.num_rows()).collect::<Vec<_>>();
let order_by_pairs: Vec<(OwnedColumn<S>, OrderByDirection)> = self
.by_exprs
.iter()
.map(
|order_by| -> PostprocessingResult<(OwnedColumn<S>, OrderByDirection)> {
Ok((
owned_table
.inner_table()
.get(&order_by.expr)
.ok_or(PostprocessingError::ColumnNotFound {
column: order_by.expr.to_string(),
})?
.clone(),
order_by.direction,
))
},
)
.collect::<PostprocessingResult<Vec<(OwnedColumn<S>, OrderByDirection)>>>()?;
if_rayon!(
indexes.par_sort_unstable_by(|&a, &b| {
compare_indexes_by_owned_columns_with_direction(&order_by_pairs, a, b)
}),
indexes.sort_unstable_by(|&a, &b| {
compare_indexes_by_owned_columns_with_direction(&order_by_pairs, a, b)
})
);
let permutation = Permutation::unchecked_new(indexes);
Ok(
OwnedTable::<S>::try_from_iter(owned_table.into_inner().into_iter().map(
|(identifier, column)| {
(
identifier,
column
.try_permute(&permutation)
.expect("There should be no column length mismatch here"),
)
},
))
.expect("There should be no column length mismatch here"),
)
}
}