proof_of_sql/sql/postprocessing/
order_by_postprocessing.rs1use super::{PostprocessingError, PostprocessingResult, PostprocessingStep};
2use crate::base::{
3 database::{
4 order_by_util::{
5 compare_indexes_by_owned_columns_with_direction, OrderIndexDirectionPairs,
6 },
7 OwnedTable,
8 },
9 math::permutation::Permutation,
10 scalar::Scalar,
11};
12use alloc::vec::Vec;
13use serde::{Deserialize, Serialize};
14
15#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
17pub struct OrderByPostprocessing {
18 index_direction_pairs: OrderIndexDirectionPairs,
19}
20
21impl OrderByPostprocessing {
22 #[must_use]
24 pub fn new(index_direction_pairs: OrderIndexDirectionPairs) -> Self {
25 Self {
26 index_direction_pairs,
27 }
28 }
29}
30
31impl<S: Scalar> PostprocessingStep<S> for OrderByPostprocessing {
32 fn apply(&self, owned_table: OwnedTable<S>) -> PostprocessingResult<OwnedTable<S>> {
34 let opt_max_index = self
35 .index_direction_pairs
36 .iter()
37 .map(|(index, _)| index)
38 .max();
39 if let Some(max_index) = opt_max_index {
40 if *max_index >= owned_table.num_columns() {
41 return Err(PostprocessingError::IndexOutOfBounds { index: *max_index });
42 }
43 }
44 let column_direction_pairs = self
45 .index_direction_pairs
46 .iter()
47 .map(|(index, direction)| {
48 (
49 owned_table
50 .column_by_index(*index)
51 .expect("The index should be valid here")
52 .clone(),
53 *direction,
54 )
55 })
56 .collect::<Vec<_>>();
57 let permutation = Permutation::unchecked_new_from_cmp(owned_table.num_rows(), |&a, &b| {
59 compare_indexes_by_owned_columns_with_direction(&column_direction_pairs, a, b)
60 });
61 Ok(
63 OwnedTable::<S>::try_from_iter(owned_table.into_inner().into_iter().map(
64 |(identifier, column)| {
65 (
66 identifier,
67 column
68 .try_permute(&permutation)
69 .expect("There should be no column length mismatch here"),
70 )
71 },
72 ))
73 .expect("There should be no column length mismatch here"),
74 )
75 }
76}