1use std::cmp::Ordering;
4
5use arrow_array::RecordBatch;
6use arrow_schema::Schema;
7
8use crate::filter::{resolve, Filter, Predicate};
9use crate::sorted::{Entry, SortedRows};
10use crate::table::Slot;
11use crate::value::{compare, prefix, ValueFn};
12use crate::{DataError, RowId, RowRef};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
16#[non_exhaustive]
17pub enum Order {
18 #[default]
20 Ascending,
21 Descending,
23}
24
25#[derive(Debug, Clone, Default, PartialEq)]
27pub struct ViewSpec {
28 sort: Vec<(String, Order)>,
29 filter: Option<Filter>,
30}
31
32impl ViewSpec {
33 pub fn new() -> Self {
35 Self::default()
36 }
37
38 #[must_use]
41 pub fn sort_by(mut self, column: impl Into<String>, order: Order) -> Self {
42 self.sort.push((column.into(), order));
43 self
44 }
45
46 #[must_use]
48 pub fn filter(mut self, filter: Filter) -> Self {
49 self.filter = Some(filter);
50 self
51 }
52}
53
54#[derive(Debug, Clone)]
56pub(crate) struct SortColumn {
57 column: usize,
58 read: ValueFn,
59 descending: bool,
60}
61
62impl SortColumn {
63 pub(crate) fn ascending(column: usize, read: ValueFn) -> Self {
64 Self {
65 column,
66 read,
67 descending: false,
68 }
69 }
70}
71
72#[derive(Debug, Clone)]
74pub(crate) struct ViewState {
75 sort: Vec<SortColumn>,
76 filter: Option<Predicate>,
77 rows: SortedRows,
78 member: Vec<bool>,
80}
81
82#[derive(Debug, Clone, Copy)]
84pub(crate) struct Rows<'a> {
85 pub(crate) batches: &'a [RecordBatch],
86 pub(crate) slots: &'a [Option<Slot>],
87}
88
89impl Rows<'_> {
90 pub(crate) fn at(&self, id: RowId) -> RowRef {
91 match self.slots.get(id as usize) {
92 Some(Some(slot)) => slot.row_ref(),
93 _ => unreachable!("row id {id} is held, but its slot is free"),
96 }
97 }
98}
99
100impl ViewState {
101 pub(crate) fn compile(spec: &ViewSpec, schema: &Schema) -> Result<Self, DataError> {
102 let sort = spec
103 .sort
104 .iter()
105 .map(|(name, order)| {
106 let (column, _, read) = resolve(schema, name)?;
107 Ok(SortColumn {
108 column,
109 read,
110 descending: *order == Order::Descending,
111 })
112 })
113 .collect::<Result<_, DataError>>()?;
114 let filter = spec
115 .filter
116 .as_ref()
117 .map(|f| Predicate::compile(f, schema))
118 .transpose()?;
119 Ok(Self {
120 sort,
121 filter,
122 rows: SortedRows::default(),
123 member: Vec::new(),
124 })
125 }
126
127 pub(crate) fn sorted(column: SortColumn) -> Self {
129 Self {
130 sort: vec![column],
131 filter: None,
132 rows: SortedRows::default(),
133 member: Vec::new(),
134 }
135 }
136
137 pub(crate) fn len(&self) -> usize {
138 self.rows.len()
139 }
140
141 pub(crate) fn partition_point(&self, pred: impl Fn(RowId) -> bool) -> usize {
143 self.rows.partition_point(pred)
144 }
145
146 pub(crate) fn get(&self, index: usize) -> Option<RowId> {
147 self.rows.get(index)
148 }
149
150 fn passes(&self, batches: &[RecordBatch], at: RowRef) -> bool {
152 self.filter
153 .as_ref()
154 .is_none_or(|f| f.eval(&batches[at.batch], at.row) == Some(true))
155 }
156
157 pub(crate) fn remove(&mut self, rows: Rows<'_>, id: RowId, at: RowRef) {
159 if !self.member.get(id as usize).copied().unwrap_or(false) {
160 return;
161 }
162 let probe = entry(&self.sort, rows.batches, id, at);
163 let sort = &self.sort;
164 let found = self
165 .rows
166 .remove(id, |other| entry_order(sort, rows, other, probe, at));
167 debug_assert!(found, "a member row is in the sorted rows");
168 self.member[id as usize] = false;
169 }
170
171 pub(crate) fn position(&self, rows: Rows<'_>, id: RowId) -> Option<usize> {
173 if !self.member.get(id as usize).copied().unwrap_or(false) {
174 return None;
175 }
176 let at = rows.at(id);
177 let probe = entry(&self.sort, rows.batches, id, at);
178 let sort = &self.sort;
179 self.rows
180 .position(id, |other| entry_order(sort, rows, other, probe, at))
181 }
182
183 pub(crate) fn insert(&mut self, rows: Rows<'_>, id: RowId, at: RowRef) {
185 if !self.passes(rows.batches, at) {
186 return;
187 }
188 let probe = entry(&self.sort, rows.batches, id, at);
189 let sort = &self.sort;
190 self.rows
191 .insert(probe, |other| entry_order(sort, rows, other, probe, at));
192 if self.member.len() <= id as usize {
193 self.member.resize(id as usize + 1, false);
194 }
195 self.member[id as usize] = true;
196 }
197
198 pub(crate) fn rebuild(&mut self, rows: Rows<'_>) {
200 let mut entries: Vec<Entry> = rows
201 .slots
202 .iter()
203 .enumerate()
204 .filter_map(|(id, slot)| Some((RowId::try_from(id).ok()?, slot.as_ref()?.row_ref())))
205 .filter(|&(_, at)| self.passes(rows.batches, at))
206 .map(|(id, at)| entry(&self.sort, rows.batches, id, at))
207 .collect();
208 entries.sort_unstable_by(|&a, &b| entry_order(&self.sort, rows, a, b, rows.at(b.id)));
209 self.member.clear();
210 self.member.resize(rows.slots.len(), false);
211 for entry in &entries {
212 self.member[entry.id as usize] = true;
213 }
214 self.rows.rebuild(&entries);
215 }
216}
217
218pub(crate) fn entry(sort: &[SortColumn], batches: &[RecordBatch], id: RowId, at: RowRef) -> Entry {
220 let key = sort.first().map_or(0, |first| {
221 let value = (first.read)(batches[at.batch].column(first.column).as_ref(), at.row);
222 prefix(value, first.descending)
223 });
224 Entry { key, id }
225}
226
227pub(crate) fn entry_order(
230 sort: &[SortColumn],
231 rows: Rows<'_>,
232 other: Entry,
233 probe: Entry,
234 probe_at: RowRef,
235) -> Ordering {
236 other.key.cmp(&probe.key).then_with(|| {
237 row_order(
238 sort,
239 rows.batches,
240 (other.id, rows.at(other.id)),
241 (probe.id, probe_at),
242 )
243 })
244}
245
246fn row_order(
249 sort: &[SortColumn],
250 batches: &[RecordBatch],
251 a: (RowId, RowRef),
252 b: (RowId, RowRef),
253) -> Ordering {
254 for key in sort {
255 let read = |at: RowRef| (key.read)(batches[at.batch].column(key.column).as_ref(), at.row);
256 let order = compare(read(a.1), read(b.1), key.descending);
257 if order.is_ne() {
258 return order;
259 }
260 }
261 a.0.cmp(&b.0)
262}