Skip to content

Commit 83660ba

Browse files
committed
extend Stat with from_aggregate_fn_partial
1 parent 0f7315b commit 83660ba

2 files changed

Lines changed: 20 additions & 25 deletions

File tree

‎vortex-array/src/expr/stats/mod.rs‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub use stat_bound::*;
2525

2626
use crate::aggregate_fn;
2727
use crate::aggregate_fn::AggregateFnRef;
28+
use crate::aggregate_fn::AggregateFnSatisfaction;
2829
use crate::aggregate_fn::AggregateFnVTable;
2930
use crate::aggregate_fn::AggregateFnVTableExt;
3031
use crate::aggregate_fn::EmptyOptions;
@@ -239,6 +240,18 @@ impl Stat {
239240
None
240241
}
241242

243+
pub fn from_aggregate_fn_partial(
244+
aggregate_fn: &AggregateFnRef,
245+
) -> Option<(Self, AggregateFnSatisfaction)> {
246+
Self::all().find_map(|stat| {
247+
let requested = stat.aggregate_fn()?;
248+
match aggregate_fn.can_satisfy(&requested) {
249+
AggregateFnSatisfaction::No => None,
250+
satisfaction => Some((stat, satisfaction)),
251+
}
252+
})
253+
}
254+
242255
pub fn name(&self) -> &str {
243256
match self {
244257
Self::IsConstant => "is_constant",

‎vortex-layout/src/layouts/file_stats.rs‎

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -124,20 +124,13 @@ impl StatsAccumulator {
124124
let mut stats_set = StatsSet::default();
125125

126126
for (aggregate_fn, accumulator) in &self.aggregates {
127-
let Some(stat) = file_stat_for_aggregate_fn(aggregate_fn) else {
127+
let Some((stat, satisfaction)) = Stat::from_aggregate_fn_partial(aggregate_fn) else {
128128
continue;
129129
};
130130
let Some(v) = accumulator.final_scalar()?.into_value() else {
131131
continue;
132132
};
133-
134-
// `BoundedMax`/`BoundedMin` (this module's own default variable-length aggregates)
135-
// can never exactly satisfy a request for the plain `Max`/`Min` they stand in for, so
136-
// their result is always recorded as an approximate bound.
137-
let requested = stat
138-
.aggregate_fn()
139-
.vortex_expect("a stat resolved from an aggregate fn has its own aggregate fn");
140-
let precision = if aggregate_fn.can_satisfy(&requested).is_exact() {
133+
let precision = if satisfaction.is_exact() {
141134
Precision::exact(v)
142135
} else {
143136
Precision::inexact(v)
@@ -187,21 +180,6 @@ fn default_max_variable_length_statistics_size() -> NonZeroUsize {
187180
unsafe { NonZeroUsize::new_unchecked(64) }
188181
}
189182

190-
/// Maps `aggregate_fn` to the legacy [`Stat`] slot its result belongs in.
191-
///
192-
/// Unlike [`Stat::from_aggregate_fn`], this also recognizes [`BoundedMax`]/[`BoundedMin`] — this
193-
/// module's own default variable-length aggregates — which fill the `Max`/`Min` slots as an
194-
/// approximate bound rather than an exact value.
195-
fn file_stat_for_aggregate_fn(aggregate_fn: &AggregateFnRef) -> Option<Stat> {
196-
if aggregate_fn.is::<BoundedMax>() {
197-
return Some(Stat::Max);
198-
}
199-
if aggregate_fn.is::<BoundedMin>() {
200-
return Some(Stat::Min);
201-
}
202-
Stat::from_aggregate_fn(aggregate_fn)
203-
}
204-
205183
/// Computes the post-order sequence of `(FieldPath, DType)` entries that file-level statistics
206184
/// are stored against.
207185
///
@@ -807,7 +785,11 @@ mod tests {
807785

808786
let acc = FileStatsAccumulator::new(
809787
&dtype,
810-
Some(Arc::from([agg(Stat::NullCount), agg(Stat::Min), agg(Stat::Max)])),
788+
Some(Arc::from([
789+
agg(Stat::NullCount),
790+
agg(Stat::Min),
791+
agg(Stat::Max),
792+
])),
811793
1024,
812794
&session,
813795
true,

0 commit comments

Comments
 (0)