Skip to content

[core] Keep FLOAT/DOUBLE files whose NaN rows are left out of stats - #1160

Closed
JeonDaehong wants to merge 1 commit into
apache:mainfrom
JeonDaehong:fix-float-nan-stats
Closed

JeonDaehong wants to merge 1 commit into
apache:mainfrom
JeonDaehong:fix-float-nan-stats

Conversation

@JeonDaehong

Copy link
Copy Markdown
Contributor

Purpose

Linked issue: close #1159

Brief change log

The writer leaves NaN out of FLOAT/DOUBLE min/max, so max can't be trusted to rule out a NaN row. >, >=, NOT BETWEEN, and NOT of <, <=, BETWEEN now keep FLOAT/DOUBLE files instead of pruning them by max. Same idea as #926 did for NOT(=).

The cost is that FLOAT/DOUBLE columns no longer prune on these operators. Other types are unchanged.

Tests

  • range_predicates_on_float_keep_files_that_may_hold_nan (unit)
  • float_nan_stats_pruning_test: files [0.0, NaN] and [2.0], f > 1.0 returned [2] before, [1, 2] now
  • equality_exclusion_falls_open_for_floats (fix(scan): prune NOT IN predicates using file stats #795) expected Gt to keep pruning a FLOAT file. Changed that line; Lt still prunes.

Ran the ci.yml steps locally (fmt, clippy, msrv, unit, rest-server, integration, datafusion, python, go).

API and Format

None.

Documentation

None.

@JeonDaehong

Copy link
Copy Markdown
Contributor Author

@JingsongLi @leaves12138 could you take a look when you have time? Small fix in stats pruning, same kind as #926.

@JingsongLi

Copy link
Copy Markdown
Contributor

The declared positive-NaN fix has end-to-end value. Local validation passed 93 checks across statistics, Arrow residuals, PK value statistics, predicate deletes, the added native Parquet test, and an additional FLOAT32 version. The positive-NaN Parquet regression fails on base 46e6871 and passes here for both FLOAT and DOUBLE; I found no introduced correctness regression in the diff.

A separate pre-existing boundary surfaced during production-path validation: negative NaNs do not currently behave like Java's canonical NaN in the Arrow residual. With FLOAT f32::from_bits(0xffc00000), files [(0, 0.0), (1, negative_nan)] and [(2, -2.0)], filtering f < -1.0 returns [2], but putting the same rows in one file returns [1, 2]. An actual native write/plan/read test reproduces this on both base 46e6871 and this head, so this is not introduced by this PR and is distinct from partition pruning. Arrow's total ordering puts negative NaN below finite values, while the untouched Lt/min pruning assumes otherwise. This should be tracked separately (or covered if broadening this fix); the new comments saying every NaN sorts above numbers are too broad for the current residual implementation.

The writer leaves NaN out of FLOAT/DOUBLE min/max without counting it null,
and NaN orders above every number in Java and in the row filter. So a file
holding [0.0, NaN] reports max == 0.0, and f > 1.0, f >= 1.0, NOT BETWEEN and
the negation of <, <= and BETWEEN pruned it, dropping the NaN row. These now
keep FLOAT/DOUBLE files, as the NotEq/NotIn arms already do (apache#926).
@JeonDaehong

Copy link
Copy Markdown
Contributor Author

Thanks for checking this. I confirmed it with a Java probe: Float.compare / Double.compare treat every NaN as equal to NaN and above +Inf. The residual compares by bits, so a NaN with the sign bit set goes below -Inf instead. That's the NaN x86 produces for 0.0 / 0.0, so it's worth fixing.

In this PR I narrowed the comments to say "Java's ordering" (665ce3d), with no code change. I opened #1174 for the residual and will send a PR for it.

@JingsongLi JingsongLi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #1177

@JeonDaehong

Copy link
Copy Markdown
Contributor Author

Closing along with #1177, see the note there.

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.

[Bug] FLOAT/DOUBLE stats pruning drops NaN rows for >, >=

2 participants