SEPURI-SAI-KRISHNA opened a new pull request, #19646:
URL: https://github.com/apache/hudi/pull/19646

   ### Describe the issue this Pull Request addresses
   
   Data skipping prunes files it must keep when a query filters on `IS NULL` 
(or `<=> null`)
   and the column-stats index holds no stats for that column in that file. 
Closes #19645.
   
   `DataSkippingUtils` translated:
   
   * `colA is null` → `colA_nullCount > 0`
   * `colA <=> null` → `colA_nullCount = null`
   
   The transposed column-stats index fills `min`/`max`/`nullCount` with `null` 
when a file has
   no stats record for a column — a column added by schema evolution (older 
files hold no
   record for it) or a column whose type the index does not support. For such 
rows the first
   predicate evaluates to `null` and the second is `null` for every row, so
   `indexDf.where(indexFilter)` drops them and the corresponding files are 
pruned. Records in
   those files are all null for that column, i.e. exactly the rows the query 
asks for, so the
   query silently returns fewer rows than it should.
   
   The `is not null` translation right below already handles the unknown-stats 
case
   (`colA_nullCount = null or colA_valueCount = null or ...`), and the fill-in 
code in
   `ColumnStatsIndexSupport#transpose` assumes "the filter includes an isNull 
check" — which
   held only for `is not null`.
   
   ### Summary and Changelog
   
   * `DataSkippingUtils`: `IsNull` and `EqualNullSafe(col, null)` now translate 
to
     `colA_nullCount is null OR colA_nullCount > 0`, via a new
     `ColumnStatsExpressionUtils#genColumnIsNullExpression` helper. A file 
whose null-count is
     unknown is kept instead of being pruned; when the null-count is known the 
pruning
     decision is unchanged.
   * `EqualNullSafe(col, null)` previously produced `colA_nullCount = null`, an 
always-null
     predicate that prunes every indexed file; it now shares the `IS NULL` 
translation, which
     is what `<=> null` means. (Spark's `NullPropagation` usually rewrites `col 
<=> null` into
     `col is null` before the filter reaches `HoodieFileIndex`, so this arm is 
mostly latent —
     but it is reached by callers that translate un-optimized expressions.)
   * Comments on both arms (and the mirrored ones in 
`containsNullOrValueCountBasedFilters`)
     now describe the actual translation.
   * `TestDataSkippingUtils`: three cases added to
     `testSupportedAndUnsupportedDataSkippingColumnsSource` (the suite that 
covers columns
     without stats) — `B is null`, `B <=> null` and `A = 1 and B is null` over 
an index where
     one file has no stats for `B`. All three fail on master and pass with this 
change.
   
   No code was copied.
   
   ### Impact
   
   Fixes silently incomplete results for `IS NULL` / `<=> null` queries on 
Spark when data
   skipping is enabled and the queried column has no stats in some files (most 
commonly after
   `ADD COLUMN` schema evolution). Files with unknown null-counts are now 
scanned, so such
   queries read a few more files than before — a correctness-required 
trade-off; queries on
   columns that are fully indexed are unaffected.
   
   No public API, config or storage-format change.
   
   ### Risk Level
   
   low
   
   The change only relaxes a pruning predicate (strictly fewer files are 
pruned), so it cannot
   introduce new false pruning. Verified with the new and existing 
`TestDataSkippingUtils`
   cases.
   
   ### Documentation Update
   
   none
   
   ### Contributor's checklist
   
   - [x] Read through [contributor's 
guide](https://hudi.apache.org/contribute/how-to-contribute)
   - [x] Enough context is provided in the sections above
   - [x] Adequate tests were added if applicable
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to