Skip to content

refactor(parquet): split arrow_reader/selection into smaller modules - #10434

Merged
alamb merged 5 commits into
apache:mainfrom
haohuaijin:split-selection-modules
Jul 25, 2026
Merged

refactor(parquet): split arrow_reader/selection into smaller modules#10434
alamb merged 5 commits into
apache:mainfrom
haohuaijin:split-selection-modules

Conversation

@haohuaijin

@haohuaijin haohuaijin commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

Rationale for this change

Follow up to #10141. selection/mod.rs had grown past 2200 lines and mixed the RowSelection type and its public API, the set algebra, the page range mapping, the cursor machinery and a large test module. This is a reorganization to make the code easier to navigate; there is no functional change.

What changes are included in this PR?

The module is split by concern, and mod.rs goes from 2219 to 947 lines:

module contents
mod.rs RowSelection, RowSelectionInner and the public API
selector.rs run length backing: RowSelector, RowSelectionIter, and the split_off / offset / limit primitives
boolean.rs bitmap backing: MaskSelection, MaskRunIter and the mask primitives
algebra.rs and_then, intersection and union for both backings
ranges.rs page byte ranges and batch boundary expansion
cursor.rs RowSelectionCursor, MaskCursor, SelectorsCursor, LoadedRowRanges, RowSelectionPolicy / RowSelectionStrategy

Are these changes tested?

Yes, by the existing tests, moved next to the code they now cover. No test was added, removed or renamed: the set of test names under arrow::arrow_reader::selection is identical before and after this PR, and the split_off / trim / offset / limit tests still go through the RowSelection methods rather than the extracted helpers.

Are there any user-facing changes?

No. The public API (parquet::arrow::arrow_reader::{RowSelection, RowSelector, RowSelectionCursor, RowSelectionPolicy, RowSelectionIter, MaskRunIter}) is unchanged, and no call site outside selection/ needed modification.

One internal note: SelectorsCursor and MaskChunk are no longer nameable outside selection/, as they moved into the private cursor module and are not re-exported. Neither was reachable from outside the crate before, since selection is pub(crate).

`selection/mod.rs` had grown past 2100 lines and mixed the `RowSelection`
type, the set algebra, the page range mapping and the cursor machinery.

Split it by concern, with one module per selection backing:

* `mod.rs`      - `RowSelection` and its public API, dispatching on backing
* `selector.rs` - run length backing: `RowSelector` and its primitives
* `boolean.rs`  - bitmap backing: `MaskSelection` and its primitives
* `algebra.rs`  - `and_then`, `intersection` and `union`
* `ranges.rs`   - page byte ranges and batch boundary expansion
* `cursor.rs`   - `RowSelectionCursor` and the policy / strategy types

No functional change: bodies are moved verbatim and the public API is
unchanged.
@github-actions github-actions Bot added the parquet Changes to the parquet crate label Jul 25, 2026
@haohuaijin
haohuaijin marked this pull request as draft July 25, 2026 07:05
…ction

Follow up cleanup on the module split, in `selection/mod.rs`:

* `trim` and `split_off` dispatched on the backing with `if let` /
  `matches!` plus an early return, and had to re-destructure the taken
  `RowSelectionInner` behind `unreachable!()`. Both now `match` on
  `self.inner` directly, which drops all three `unreachable!()` arms.
* `RowSelection::selectors_mut` is removed. Its only two callers were
  `trim` and `split_off`, and both returned early on the mask backing,
  so the `Mask` -> `Selectors` promotion inside it was unreachable.
* `split_off_selectors` now takes the `Vec<RowSelector>` by value and
  returns `(head, tail)`, mirroring `split_off_mask`. The `mem::take`
  and the trailing `mem::swap` it needed to write the tail back through
  `&mut` are gone.
* `trim_selectors` is inlined back into `trim`: a four line loop only
  extracted to mirror `trim_mask`.

No behavior change; the set of test names is still identical.
@haohuaijin
haohuaijin marked this pull request as ready for review July 25, 2026 11:59
@haohuaijin

Copy link
Copy Markdown
Contributor Author

Pure reorganization of arrow_reader/selection: mod.rs had grown past 2200 lines and is now split by concern. Bodies are moved verbatim, the public API is unchanged — the diff should read as a move.

cc @alamb @hhhizzz — follow up to #10141, would appreciate a look when you have time.

Comment on lines -494 to -508
/// Promote a mask-backed selection to selector backing in place.
fn selectors_mut(&mut self) -> &mut Vec<RowSelector> {
if let RowSelectionInner::Mask(_) = &self.inner {
let mask = match std::mem::take(&mut self.inner) {
RowSelectionInner::Mask(m) => m,
RowSelectionInner::Selectors(_) => unreachable!(),
};
self.inner = RowSelectionInner::Selectors(mask_to_selectors(mask.mask()));
}
match &mut self.inner {
RowSelectionInner::Selectors(s) => s,
RowSelectionInner::Mask(_) => unreachable!(),
}
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove those code as it only use in trim and split_off, but current trim and split_off now match on self.inner instead of dispatching with if let / matches! plus an early return;

@alamb alamb left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you -- This is great @haohuaijin

//! This module holds [`RowSelection`] and its public API, which dispatches to
//! one of the two backings depending on how the selection is stored:
//!
//! * `selector`: the run length backing, [`RowSelector`] and its primitives

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

@alamb
alamb merged commit b1ca9c4 into apache:main Jul 25, 2026
1 check passed
@haohuaijin
haohuaijin deleted the split-selection-modules branch July 26, 2026 00:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

parquet Changes to the parquet crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Split parquet/src/arrow/arrow_reader/selection/mod.rs into smaller modules

2 participants