Aggregate sum of zero valid values is null#8705
Conversation
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
Merging this PR will not alter performance
Warning Please fix the performance issues or acknowledge them on CodSpeed. Performance Changes
Tip Investigate this regression by commenting Comparing Footnotes
|
Signed-off-by: Matt Katz <mhkatz97@gmail.com>
gatesn
left a comment
There was a problem hiding this comment.
I think... with the new Zoned layout, the aggregate partial has become a wire API.
That said, we haven't updated FileStats to use aggregate partials. And I don't believe zone maps use Sum?
A safer option would be to add a separate Sum function with this new behavior and different partial. @robert3005 any thoughts on a preferred direction?
Either way, we should separately make sure we have forward/backward compatibility tests for zoned statistics!
…s and dead code Signed-off-by: Matt Katz <mhkatz97@gmail.com>
|
we have SUM in zonemaps |
|
@mhk197 I think simpler would be to add another function. Maybe even rename them such that the new sql semantic sum is called |
SUMof zero valid values now yields null , as per SQL standard (SQLSUM, ISO 9075-2 §10.9). This replaces he previous "all-invalid sums to zero" contract. Overflow still yields null. This matches arrow-rs (sumreturnsNonefor empty/all-null), DuckDB (SumState.isset), and DataFusion (SumAccumulator { sum: Option }).The blocker for doing this at the root was that a null partial already means overflow and must poison merges, while "empty" must be the merge identity — one nullable scalar can't encode both, and Sum partials cross persisted merge boundaries (zoned layout stats). So
SumPartialnow carries aseenflag (DuckDB'sisset), and the partial dtype becomes{sum, seen}.Stat::Sumretains original behavior because persisted stat merging requires identity-on-empty.Side Effects:
meanof all-null input is now nullColumnStatistics::sum_valueis only exported whennull_count < row_countStructGetItemRuleto handle struct partials.get_itemon a nullable struct withNonNullable/AllValidvalidity previously returned the raw non-nullable field.