cynos_query/executor/
sort.rs1use crate::ast::SortOrder;
4use crate::executor::{Relation, RelationEntry};
5use alloc::vec::Vec;
6use core::cmp::Ordering;
7
8pub struct SortExecutor {
10 order_by: Vec<(usize, SortOrder)>,
12}
13
14impl SortExecutor {
15 pub fn new(order_by: Vec<(usize, SortOrder)>) -> Self {
17 Self { order_by }
18 }
19
20 pub fn execute(&self, mut input: Relation) -> Relation {
22 input.entries.sort_by(|a, b| self.compare_entries(a, b));
23 input
24 }
25
26 fn compare_entries(&self, a: &RelationEntry, b: &RelationEntry) -> Ordering {
27 for (col_idx, order) in &self.order_by {
28 let a_val = a.get_field(*col_idx);
29 let b_val = b.get_field(*col_idx);
30
31 let cmp = match (a_val, b_val) {
32 (Some(av), Some(bv)) => av.cmp(bv),
33 (None, Some(_)) => Ordering::Less,
34 (Some(_), None) => Ordering::Greater,
35 (None, None) => Ordering::Equal,
36 };
37
38 if cmp != Ordering::Equal {
39 return match order {
40 SortOrder::Asc => cmp,
41 SortOrder::Desc => cmp.reverse(),
42 };
43 }
44 }
45 Ordering::Equal
46 }
47}
48
49#[allow(dead_code)]
51pub fn sort_relation<K, F>(mut input: Relation, key_fn: F) -> Relation
52where
53 K: Ord,
54 F: Fn(&RelationEntry) -> K,
55{
56 input.entries.sort_by(|a, b| key_fn(a).cmp(&key_fn(b)));
57 input
58}
59
60#[allow(dead_code)]
62pub fn sort_relation_by<F>(mut input: Relation, compare: F) -> Relation
63where
64 F: Fn(&RelationEntry, &RelationEntry) -> Ordering,
65{
66 input.entries.sort_by(compare);
67 input
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73 use alloc::rc::Rc;
74 use alloc::vec;
75 use cynos_core::{Row, Value};
76
77 #[test]
78 fn test_sort_executor_asc() {
79 let rows = vec![
80 Rc::new(Row::new(1, vec![Value::Int64(30)])),
81 Rc::new(Row::new(2, vec![Value::Int64(10)])),
82 Rc::new(Row::new(3, vec![Value::Int64(20)])),
83 ];
84 let input = Relation::from_rows(rows, vec!["t".into()]);
85
86 let executor = SortExecutor::new(vec![(0, SortOrder::Asc)]);
87 let result = executor.execute(input);
88
89 assert_eq!(result.entries[0].get_field(0), Some(&Value::Int64(10)));
90 assert_eq!(result.entries[1].get_field(0), Some(&Value::Int64(20)));
91 assert_eq!(result.entries[2].get_field(0), Some(&Value::Int64(30)));
92 }
93
94 #[test]
95 fn test_sort_executor_desc() {
96 let rows = vec![
97 Rc::new(Row::new(1, vec![Value::Int64(10)])),
98 Rc::new(Row::new(2, vec![Value::Int64(30)])),
99 Rc::new(Row::new(3, vec![Value::Int64(20)])),
100 ];
101 let input = Relation::from_rows(rows, vec!["t".into()]);
102
103 let executor = SortExecutor::new(vec![(0, SortOrder::Desc)]);
104 let result = executor.execute(input);
105
106 assert_eq!(result.entries[0].get_field(0), Some(&Value::Int64(30)));
107 assert_eq!(result.entries[1].get_field(0), Some(&Value::Int64(20)));
108 assert_eq!(result.entries[2].get_field(0), Some(&Value::Int64(10)));
109 }
110
111 #[test]
112 fn test_sort_executor_multi_column() {
113 let rows = vec![
114 Rc::new(Row::new(1, vec![Value::Int64(1), Value::String("B".into())])),
115 Rc::new(Row::new(2, vec![Value::Int64(1), Value::String("A".into())])),
116 Rc::new(Row::new(3, vec![Value::Int64(2), Value::String("A".into())])),
117 ];
118 let input = Relation::from_rows(rows, vec!["t".into()]);
119
120 let executor = SortExecutor::new(vec![(0, SortOrder::Asc), (1, SortOrder::Asc)]);
121 let result = executor.execute(input);
122
123 assert_eq!(result.entries[0].get_field(1), Some(&Value::String("A".into())));
125 assert_eq!(result.entries[1].get_field(1), Some(&Value::String("B".into())));
126 assert_eq!(result.entries[2].get_field(0), Some(&Value::Int64(2)));
127 }
128}