Skip to content

Order -0.0 below 0.0 in data file metrics bounds - #4331

Open
AP24110011695 wants to merge 1 commit into
apache:mainfrom
AP24110011695:fix/stats-aggregator-negative-zero-bounds
Open

AP24110011695 wants to merge 1 commit into
apache:mainfrom
AP24110011695:fix/stats-aggregator-negative-zero-bounds

Conversation

@AP24110011695

Copy link
Copy Markdown

What's changed

StatsAggregator.update_min/update_max aggregate parquet row-group statistics into DataFile.lower_bounds/upper_bounds. On a tie between +0.0 and -0.0, min(val, current) and max(val, current) keep the first argument — so whichever zero arrives last wins:

  • a late -0.0 lowers an existing +0.0 upper bound (e.g. row group 1 contains +0.0, a later row group's max is -0.0),
  • a late +0.0 raises an existing -0.0 lower bound.

The serialized bounds then order above a value that is present in the file, violating the two's-comparable bound ordering.

#4324 fixed the same class in the partition-field summary path (PartitionFieldStats.update in manifest.py); this applies the equivalent guard to the data-file metrics path. The argument order here is flipped (min(val, current) vs min(self._min, value)), so the guarded directions are mirrored, and the guard is split across the two update methods. Verified against #4324's pinned bar: for both arrival orders the bounds must serialize as lower = to_bytes(-0.0), upper = to_bytes(+0.0).

NaN needs no handling here: pyarrow row-group statistics exclude NaN (has_min_max is False for all-NaN chunks), so the aggregator never sees it on this path.

Test

test_stats_aggregator_orders_negative_zero_below_zero — parametrized over both arrival orders and FloatType/DoubleType, asserting the serialized bounds match the #4324 canonical pair. Verified failing-first: 4/4 fail on main (533a617) and pass with the guard; the existing StatsAggregator tests (18) still pass.

AI disclosure: code and tests drafted with AI assistance, verified locally by running the full failing-first cycle.

StatsAggregator.update_min/update_max feed DataFile lower/upper bounds,
but min(val, current) and max(val, current) keep the first argument on a
tie, so whichever zero arrives last wins: a late -0.0 lowers an existing
+0.0 upper bound, and a late +0.0 raises an existing -0.0 lower bound.
The serialized bounds then order above a value present in the file.

Mirror the fix that apache#4324 applied to partition field summaries: restore
the stored bound when a zero arrives that would invert the -0.0 < 0.0
ordering. The argument order here (val first) flips which direction
needs the guard compared to manifest.py.

Verified failing-first: the new tests fail on main for both arrival
orders and both float types, and pass with the guard.

Signed-off-by: Ayush Kumar Saha <225407166+AP24110011695@users.noreply.github.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant