Skip to main content

parquet/arrow/arrow_reader/selection/
selector.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! The run length backed representation of a [`RowSelection`]: [`RowSelector`]
19//! and the primitives operating on a sequence of them.
20//!
21//! This is the counterpart of the bitmap backing in the `boolean` module, and
22//! provides the same set of transforms (`split_off`, `trim`, `offset`,
23//! `limit`) over `Vec<RowSelector>` instead of a `BooleanBuffer`.
24//!
25//! [`RowSelection`]: crate::arrow::arrow_reader::RowSelection
26
27/// [`RowSelection`] is a collection of [`RowSelector`] used to skip rows when
28/// scanning a parquet file
29///
30/// [`RowSelection`]: crate::arrow::arrow_reader::RowSelection
31#[derive(Debug, Clone, Copy, Eq, PartialEq)]
32pub struct RowSelector {
33    /// The number of rows
34    pub row_count: usize,
35
36    /// If true, skip `row_count` rows
37    pub skip: bool,
38}
39
40impl RowSelector {
41    /// Select `row_count` rows
42    pub fn select(row_count: usize) -> Self {
43        Self {
44            row_count,
45            skip: false,
46        }
47    }
48
49    /// Skip `row_count` rows
50    pub fn skip(row_count: usize) -> Self {
51        Self {
52            row_count,
53            skip: true,
54        }
55    }
56}
57
58/// Borrowed iterator over the [`RowSelector`]s of a
59/// [`RowSelection`](crate::arrow::arrow_reader::RowSelection).
60#[derive(Debug)]
61pub struct RowSelectionIter<'a>(std::slice::Iter<'a, RowSelector>);
62
63impl<'a> RowSelectionIter<'a> {
64    pub(super) fn new(selectors: &'a [RowSelector]) -> Self {
65        Self(selectors.iter())
66    }
67}
68
69impl<'a> Iterator for RowSelectionIter<'a> {
70    type Item = &'a RowSelector;
71
72    #[inline]
73    fn next(&mut self) -> Option<Self::Item> {
74        self.0.next()
75    }
76
77    #[inline]
78    fn size_hint(&self) -> (usize, Option<usize>) {
79        self.0.size_hint()
80    }
81
82    #[inline]
83    fn count(self) -> usize {
84        self.0.count()
85    }
86
87    #[inline]
88    fn nth(&mut self, n: usize) -> Option<Self::Item> {
89        self.0.nth(n)
90    }
91
92    #[inline]
93    fn last(self) -> Option<Self::Item> {
94        self.0.last()
95    }
96
97    #[inline]
98    fn fold<B, F>(self, init: B, f: F) -> B
99    where
100        F: FnMut(B, Self::Item) -> B,
101    {
102        self.0.fold(init, f)
103    }
104}
105
106impl ExactSizeIterator for RowSelectionIter<'_> {}
107
108// once it returns None, it will continue returning None
109impl std::iter::FusedIterator for RowSelectionIter<'_> {}
110
111/// Splits `selectors` at the first `row_count` rows, returning `(head, tail)`.
112pub(super) fn split_off_selectors(
113    mut selectors: Vec<RowSelector>,
114    row_count: usize,
115) -> (Vec<RowSelector>, Vec<RowSelector>) {
116    let mut total_count = 0;
117
118    // Find the index where the selector exceeds the row count
119    let find = selectors.iter().position(|selector| {
120        total_count += selector.row_count;
121        total_count > row_count
122    });
123
124    let split_idx = match find {
125        Some(idx) => idx,
126        None => return (selectors, Vec::new()),
127    };
128
129    // `selectors` keeps the head, `tail` takes the rest. The selector straddling
130    // the boundary is split between the two.
131    let mut tail = selectors.split_off(split_idx);
132
133    // Always present as `split_idx < selectors.len`
134    let next = tail.first_mut().unwrap();
135    let overflow = total_count - row_count;
136
137    if next.row_count != overflow {
138        selectors.push(RowSelector {
139            row_count: next.row_count - overflow,
140            skip: next.skip,
141        })
142    }
143    next.row_count = overflow;
144
145    (selectors, tail)
146}
147
148/// Skips the first `offset` selected rows of `selectors`.
149pub(super) fn offset_selectors(mut selectors: Vec<RowSelector>, offset: usize) -> Vec<RowSelector> {
150    let mut selected_count = 0;
151    let mut skipped_count = 0;
152
153    // Find the index where the selector exceeds the row count
154    let find = selectors.iter().position(|selector| match selector.skip {
155        true => {
156            skipped_count += selector.row_count;
157            false
158        }
159        false => {
160            selected_count += selector.row_count;
161            selected_count > offset
162        }
163    });
164
165    let split_idx = match find {
166        Some(idx) => idx,
167        None => {
168            selectors.clear();
169            return selectors;
170        }
171    };
172
173    let mut new_selectors = Vec::with_capacity(selectors.len() - split_idx + 1);
174    new_selectors.push(RowSelector::skip(skipped_count + offset));
175    new_selectors.push(RowSelector::select(selected_count - offset));
176    new_selectors.extend_from_slice(&selectors[split_idx + 1..]);
177
178    new_selectors
179}
180
181/// Keeps only the first `limit` selected rows of `selectors`.
182pub(super) fn limit_selectors(
183    mut selectors: Vec<RowSelector>,
184    mut limit: usize,
185) -> Vec<RowSelector> {
186    if limit == 0 {
187        selectors.clear();
188    }
189
190    for (idx, selection) in selectors.iter_mut().enumerate() {
191        if !selection.skip {
192            if selection.row_count >= limit {
193                selection.row_count = limit;
194                selectors.truncate(idx + 1);
195                break;
196            } else {
197                limit -= selection.row_count;
198            }
199        }
200    }
201    selectors
202}
203
204#[cfg(test)]
205mod tests {
206    use super::*;
207    use crate::arrow::arrow_reader::selection::RowSelection;
208
209    #[test]
210    fn test_from_selectors_skips_empty_selectors() {
211        let selection = RowSelection::from(vec![
212            RowSelector::select(0),
213            RowSelector::skip(0),
214            RowSelector::select(2),
215            RowSelector::select(0),
216            RowSelector::skip(1),
217        ]);
218        assert_eq!(
219            selection.selectors(),
220            vec![RowSelector::select(2), RowSelector::skip(1)]
221        );
222    }
223
224    #[test]
225    fn test_split_off() {
226        let mut selection = RowSelection::from(vec![
227            RowSelector::skip(34),
228            RowSelector::select(12),
229            RowSelector::skip(3),
230            RowSelector::select(35),
231        ]);
232
233        let split = selection.split_off(34);
234        assert_eq!(split.selectors(), vec![RowSelector::skip(34)]);
235        assert_eq!(
236            selection.selectors(),
237            vec![
238                RowSelector::select(12),
239                RowSelector::skip(3),
240                RowSelector::select(35)
241            ]
242        );
243
244        let split = selection.split_off(5);
245        assert_eq!(split.selectors(), vec![RowSelector::select(5)]);
246        assert_eq!(
247            selection.selectors(),
248            vec![
249                RowSelector::select(7),
250                RowSelector::skip(3),
251                RowSelector::select(35)
252            ]
253        );
254
255        let split = selection.split_off(8);
256        assert_eq!(
257            split.selectors(),
258            vec![RowSelector::select(7), RowSelector::skip(1)]
259        );
260        assert_eq!(
261            selection.selectors(),
262            vec![RowSelector::skip(2), RowSelector::select(35)]
263        );
264
265        let split = selection.split_off(200);
266        assert_eq!(
267            split.selectors(),
268            vec![RowSelector::skip(2), RowSelector::select(35)]
269        );
270        assert!(selection.selectors().is_empty());
271    }
272
273    #[test]
274    fn test_offset() {
275        let selection = RowSelection::from(vec![
276            RowSelector::select(5),
277            RowSelector::skip(23),
278            RowSelector::select(7),
279            RowSelector::skip(33),
280            RowSelector::select(6),
281        ]);
282
283        let selection = selection.offset(2);
284        assert_eq!(
285            selection.selectors(),
286            vec![
287                RowSelector::skip(2),
288                RowSelector::select(3),
289                RowSelector::skip(23),
290                RowSelector::select(7),
291                RowSelector::skip(33),
292                RowSelector::select(6),
293            ]
294        );
295
296        let selection = selection.offset(5);
297        assert_eq!(
298            selection.selectors(),
299            vec![
300                RowSelector::skip(30),
301                RowSelector::select(5),
302                RowSelector::skip(33),
303                RowSelector::select(6),
304            ]
305        );
306
307        let selection = selection.offset(3);
308        assert_eq!(
309            selection.selectors(),
310            vec![
311                RowSelector::skip(33),
312                RowSelector::select(2),
313                RowSelector::skip(33),
314                RowSelector::select(6),
315            ]
316        );
317
318        let selection = selection.offset(2);
319        assert_eq!(
320            selection.selectors(),
321            vec![RowSelector::skip(68), RowSelector::select(6),]
322        );
323
324        let selection = selection.offset(3);
325        assert_eq!(
326            selection.selectors(),
327            vec![RowSelector::skip(71), RowSelector::select(3),]
328        );
329    }
330
331    #[test]
332    fn test_combine() {
333        let a = vec![
334            RowSelector::skip(3),
335            RowSelector::skip(3),
336            RowSelector::select(10),
337            RowSelector::skip(4),
338        ];
339
340        let b = vec![
341            RowSelector::skip(3),
342            RowSelector::skip(3),
343            RowSelector::select(10),
344            RowSelector::skip(4),
345            RowSelector::skip(0),
346        ];
347
348        let c = vec![
349            RowSelector::skip(2),
350            RowSelector::skip(4),
351            RowSelector::select(3),
352            RowSelector::select(3),
353            RowSelector::select(4),
354            RowSelector::skip(3),
355            RowSelector::skip(1),
356            RowSelector::skip(0),
357        ];
358
359        let expected = RowSelection::from(vec![
360            RowSelector::skip(6),
361            RowSelector::select(10),
362            RowSelector::skip(4),
363        ]);
364
365        assert_eq!(RowSelection::from_iter(a), expected);
366        assert_eq!(RowSelection::from_iter(b), expected);
367        assert_eq!(RowSelection::from_iter(c), expected);
368    }
369
370    #[test]
371    fn test_combine_2elements() {
372        let a = vec![RowSelector::select(10), RowSelector::select(5)];
373        let a_expect = vec![RowSelector::select(15)];
374        assert_eq!(RowSelection::from_iter(a).selectors(), a_expect);
375
376        let b = vec![RowSelector::select(10), RowSelector::skip(5)];
377        let b_expect = vec![RowSelector::select(10), RowSelector::skip(5)];
378        assert_eq!(RowSelection::from_iter(b).selectors(), b_expect);
379
380        let c = vec![RowSelector::skip(10), RowSelector::select(5)];
381        let c_expect = vec![RowSelector::skip(10), RowSelector::select(5)];
382        assert_eq!(RowSelection::from_iter(c).selectors(), c_expect);
383
384        let d = vec![RowSelector::skip(10), RowSelector::skip(5)];
385        let d_expect = vec![RowSelector::skip(15)];
386        assert_eq!(RowSelection::from_iter(d).selectors(), d_expect);
387    }
388
389    #[test]
390    fn test_from_one_and_empty() {
391        let a = vec![RowSelector::select(10)];
392        let selection1 = RowSelection::from(a.clone());
393        assert_eq!(selection1.selectors(), a);
394
395        let b = vec![];
396        let selection1 = RowSelection::from(b.clone());
397        assert_eq!(selection1.selectors(), b)
398    }
399
400    #[test]
401    fn test_limit() {
402        // Limit to existing limit should no-op
403        let selection = RowSelection::from(vec![RowSelector::select(10), RowSelector::skip(90)]);
404        let limited = selection.limit(10);
405        assert_eq!(RowSelection::from(vec![RowSelector::select(10)]), limited);
406
407        let selection = RowSelection::from(vec![
408            RowSelector::select(10),
409            RowSelector::skip(10),
410            RowSelector::select(10),
411            RowSelector::skip(10),
412            RowSelector::select(10),
413        ]);
414
415        let limited = selection.clone().limit(5);
416        let expected = vec![RowSelector::select(5)];
417        assert_eq!(limited.selectors(), expected);
418
419        let limited = selection.clone().limit(15);
420        let expected = vec![
421            RowSelector::select(10),
422            RowSelector::skip(10),
423            RowSelector::select(5),
424        ];
425        assert_eq!(limited.selectors(), expected);
426
427        let limited = selection.clone().limit(0);
428        let expected = vec![];
429        assert_eq!(limited.selectors(), expected);
430
431        let limited = selection.clone().limit(30);
432        let expected = vec![
433            RowSelector::select(10),
434            RowSelector::skip(10),
435            RowSelector::select(10),
436            RowSelector::skip(10),
437            RowSelector::select(10),
438        ];
439        assert_eq!(limited.selectors(), expected);
440
441        let limited = selection.limit(100);
442        let expected = vec![
443            RowSelector::select(10),
444            RowSelector::skip(10),
445            RowSelector::select(10),
446            RowSelector::skip(10),
447            RowSelector::select(10),
448        ];
449        assert_eq!(limited.selectors(), expected);
450    }
451
452    #[test]
453    fn test_from_ranges() {
454        let ranges = [1..3, 4..6, 6..6, 8..8, 9..10];
455        let selection = RowSelection::from_consecutive_ranges(ranges.into_iter(), 10);
456        assert_eq!(
457            selection.selectors(),
458            vec![
459                RowSelector::skip(1),
460                RowSelector::select(2),
461                RowSelector::skip(1),
462                RowSelector::select(2),
463                RowSelector::skip(3),
464                RowSelector::select(1)
465            ]
466        );
467
468        let out_of_order_ranges = [1..3, 8..10, 4..7];
469        let result = std::panic::catch_unwind(|| {
470            RowSelection::from_consecutive_ranges(out_of_order_ranges.into_iter(), 10)
471        });
472        assert!(result.is_err());
473    }
474
475    #[test]
476    fn test_empty_selector() {
477        let selection = RowSelection::from(vec![
478            RowSelector::skip(0),
479            RowSelector::select(2),
480            RowSelector::skip(0),
481            RowSelector::select(2),
482        ]);
483        assert_eq!(selection.selectors(), vec![RowSelector::select(4)]);
484
485        let selection = RowSelection::from(vec![
486            RowSelector::select(0),
487            RowSelector::skip(2),
488            RowSelector::select(0),
489            RowSelector::skip(2),
490        ]);
491        assert_eq!(selection.selectors(), vec![RowSelector::skip(4)]);
492    }
493
494    #[test]
495    fn test_trim() {
496        let selection = RowSelection::from(vec![
497            RowSelector::skip(34),
498            RowSelector::select(12),
499            RowSelector::skip(3),
500            RowSelector::select(35),
501        ]);
502
503        let expected = vec![
504            RowSelector::skip(34),
505            RowSelector::select(12),
506            RowSelector::skip(3),
507            RowSelector::select(35),
508        ];
509
510        assert_eq!(selection.trim().selectors(), expected);
511
512        let selection = RowSelection::from(vec![
513            RowSelector::skip(34),
514            RowSelector::select(12),
515            RowSelector::skip(3),
516        ]);
517
518        let expected = vec![RowSelector::skip(34), RowSelector::select(12)];
519
520        assert_eq!(selection.trim().selectors(), expected);
521    }
522}