fix(datafusion): report an unconvertible column statistic as absent - #9973
Conversation
`stats_set_to_df` ran the stored statistic and the column dtype through two `vortex_expect`s per statistic. Both sides come from the file -- the value out of the footer's stats set, the dtype off the column -- so both can legitimately fail on a file we did not write: - `Stat::dtype` returns `None` where the statistic does not apply, which is `Min`/`Max` of a null column and `Sum` of a string, list or struct column; - `Scalar::try_new` rejects a stored value that does not match the column dtype. Either one panicked inside DataFusion planning rather than returning an error or simply forgoing the statistic. Forgoing it is what the end of the same chain already did: `try_to_df().ok()` drops a scalar DataFusion cannot represent. This extends that to the whole conversion and collapses the three near-identical blocks into one helper, which is also what the `TODO(connor)` above them asked for. The statistic's `Precision` is preserved, so an exact statistic stays exact and only the unconvertible ones become `Absent`. Signed-off-by: jackylee-ch <qcsd2011@gmail.com>
myrrc
left a comment
There was a problem hiding this comment.
LGTM, let's fix overly verbose comments
Merging this PR will degrade performance by 4.25%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ❌ | Simulation | decode_primitives[f32, (1000, 512)] |
42 µs | 64.1 µs | -34.49% |
| ❌ | Simulation | take_fsl_u32_random[256, 10] |
124.3 µs | 159.5 µs | -22.05% |
| ❌ | WallTime | dbp_assemble_kernel_avx512[(I128, 1024)] |
463 ns | 551 ns | -15.97% |
| ❌ | WallTime | dbp_assemble_kernel_narrow_msp_avx2[(I128, 1024)] |
629 ns | 700 ns | -10.14% |
| ⚡ | Simulation | take_fsl_f16_random[16, 100] |
179.5 µs | 119.4 µs | +50.31% |
| ⚡ | Simulation | take_fsl_nullable_random[16, 100] |
188 µs | 165.7 µs | +13.43% |
| ⚡ | Simulation | take_fsl_random[64, 100] |
227.6 µs | 202.7 µs | +12.26% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing jackylee-ch:fix/df-stats-no-panic (dc840ae) with develop (a542cbd)
Footnotes
-
293 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
Per myrrc's review. The rationale now lives in the PR description, not the code. Signed-off-by: jackylee-ch <qcsd2011@gmail.com>
|
Trimmed the "why" from both the helper doc and the test comments. |
stats_set_to_df(vortex-datafusion/src/convert/stats.rs:30-66) ran each statistic through twovortex_expects. Both sides of that conversion come from the file — the stored value out of thefooter's stats set, the dtype off the column — so both can legitimately fail on a file we did not
write:
Stat::dtypereturnsNonewhere the statistic does not apply:vortex-array/src/expr/stats/mod.rs:173,175returnNoneforMax/Minof aDType::Nullcolumn, and
Sum::return_dtypedoes the same for string, binary, list and struct columns. That hitvortex_expect("must have a valid dtype").Scalar::try_newrejects a stored value that does not match the column dtype, hittingvortex_expect("Stat::Minsomehow had an incompatibleDType").Either one panicked inside DataFusion planning instead of returning an error or simply forgoing the
statistic.
Fix
Forgoing it is what the end of the same chain already chose:
try_to_df().ok()drops a scalarDataFusion cannot represent. This extends that to the whole conversion, which also lets the three
near-identical blocks collapse into one helper — and is what the
TODO(connor)above them("There's a lot that can go wrong here, should probably handle this more gracefully") asked for, so
that comment goes too.
The statistic's
Precisionis preserved rather than flattened: an exact statistic staysPrecision::Exact, and only the unconvertible ones becomeAbsent. That distinction is easy to losehere, since
StatsSet::getreturns Vortex'sPrecisionand not anOption.Tests
cargo test --release -p vortex-datafusion: 341 passed, 335 before. Four cases cover theunconvertible shapes —
Min/Maxof a null column,Sumof a string column, and a stored valuethat disagrees with the column dtype — and two more pin that a convertible statistic keeps its exact
or inexact precision.
Restoring the
vortex_expects fails all four unconvertible cases, on both panic sites(
vortex-error/src/lib.rs:666for theOptionand:659for theResult), and leaves theprecision and
distinct_countcases green.AI assistance
Written with agentic AI assistance; my first version returned
Optioninstead ofPrecisionandwould have silently flattened every statistic's precision — the compiler caught it, and the two
precision cases above exist so a reviewer does not have to.