Skip to content

Commit 9f6ce2f

Browse files
committed
Make pruning stats pluggable
Default selects based on the dtypes. Modeled in the same way that zone maps configure aggregate partials.
1 parent 3b07ff7 commit 9f6ce2f

3 files changed

Lines changed: 151 additions & 443 deletions

File tree

‎vortex-file/src/pruning.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl FileStatsBinder<'_> {
8080
fn stat_ref(&self, field_path: &FieldPath, stat: Stat) -> Option<BoundExpression> {
8181
let (field_stats, field_dtype) = self.file_stats.get_by_path(field_path)?;
8282

83-
let stat_value = field_stats.get(stat).as_exact()?;
83+
let stat_value = field_stats.get(stat).into_inner()?;
8484
let stat_dtype = stat.dtype(field_dtype)?;
8585
let stat_scalar = Scalar::try_new(stat_dtype, Some(stat_value)).ok()?;
8686

‎vortex-file/src/writer.rs‎

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ use vortex_array::dtype::FieldPath;
2525
use vortex_array::iter::ArrayIterator;
2626
use vortex_array::iter::ArrayIteratorExt;
2727
use vortex_array::session::ArraySessionExt;
28-
use vortex_array::stats::pruning_aggregate_fns;
2928
use vortex_array::stream::ArrayStream;
3029
use vortex_array::stream::ArrayStreamAdapter;
3130
use vortex_array::stream::ArrayStreamExt;
@@ -84,7 +83,10 @@ pub struct VortexWriteOptions {
8483
buffered_bytes: BufferedBytesTracker,
8584
exclude_dtype: bool,
8685
max_variable_length_statistics_size: usize,
87-
file_statistics: Vec<AggregateFnRef>,
86+
/// The aggregates to compute for file-level statistics.
87+
///
88+
/// If unset, the writer chooses pruning aggregates from the file dtype.
89+
file_statistics: Option<Vec<AggregateFnRef>>,
8890
write_legacy_statistics: bool,
8991
metadata: HashMap<String, ByteBuffer>,
9092
}
@@ -107,7 +109,7 @@ impl VortexWriteOptions {
107109
buffered_bytes: BufferedBytesTracker::new(),
108110
session,
109111
exclude_dtype: false,
110-
file_statistics: pruning_aggregate_fns(),
112+
file_statistics: None,
111113
write_legacy_statistics: true,
112114
max_variable_length_statistics_size: 64,
113115
metadata: HashMap::default(),
@@ -158,9 +160,10 @@ impl VortexWriteOptions {
158160

159161
/// Configure which statistics to compute at the file level.
160162
///
161-
/// Pass an empty vector to omit file-level statistics.
163+
/// Pass an empty vector to omit file-level statistics. If left unset, the writer chooses
164+
/// pruning aggregates from the file dtype.
162165
pub fn with_file_statistics(mut self, file_statistics: Vec<AggregateFnRef>) -> Self {
163-
self.file_statistics = file_statistics;
166+
self.file_statistics = Some(file_statistics);
164167
self
165168
}
166169

@@ -286,9 +289,12 @@ impl VortexWriteOptions {
286289
.map(move |result| result.map(|chunk| (ptr.advance(), chunk))),
287290
)
288291
.sendable();
292+
// When unset, `accumulate_stats` resolves each leaf's own default from its dtype, the way
293+
// `default_zoned_aggregate_fns` does for zoned layouts (e.g. bounded min/max for
294+
// variable-length columns), rather than a single dtype-blind default applied uniformly.
289295
let (file_stats, stream) = accumulate_stats(
290296
stream,
291-
self.file_statistics.clone().into(),
297+
self.file_statistics.clone().map(Arc::from),
292298
self.max_variable_length_statistics_size,
293299
&self.session,
294300
self.write_legacy_statistics,
@@ -334,7 +340,7 @@ impl VortexWriteOptions {
334340
let (layout, segment_specs) = layout_fut.await?;
335341

336342
// Assemble the Footer object now that we have all the segments.
337-
let statistics = if self.file_statistics.is_empty() {
343+
let statistics = if matches!(&self.file_statistics, Some(stats) if stats.is_empty()) {
338344
None
339345
} else {
340346
Some(FileStatistics::new_with_dtype(

0 commit comments

Comments
 (0)