Skip to content

fix: Joom 1.1-5 — nested booleans exported to the JVM with a non-zero bit offset (backport #6339) - #6

Merged
msafonov merged 2 commits into
branch-1.1from
joom/1.1-fix5
Oct 9, 2026
Merged

msafonov merged 2 commits into
branch-1.1from
joom/1.1-fix5

Conversation

@msafonov

@msafonov msafonov commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

A boolean nested in a struct, list or map could come back to the JVM with the values and validity of neighbouring rows (null or flipped). In production this nulled nested booleans in 19 rows of mongo.finance_order_costs_daily_snapshot. The bug is upstream, not in our fork changes. Proposed version name: joom-1.1-5.

Cause

Comet exports batches to the JVM through the Arrow C Data Interface. arrow-rs folds a slice into the buffers for every Spark type except boolean, which keeps its bit offset in ArrayData::offset, and Arrow Java 18.3 ignores the imported offset (apache/arrow-java#88). The existing workaround in prepare_output (apache#2051) only checked the top level of each column; a struct around a sliced boolean has offset 0, so the nested boolean was read from bit 0.

Changes

No upstream default is changed.

Tests

On joom-1.1-4 code the new tests fail and with this PR they pass:

test joom-1.1-4 this PR
Rust test_move_to_spark_zeroes_nested_boolean_offsets FAILED ok
CometExecSuite: 3 upstream tests + nested struct-in-struct test 4 failed (wrong results) 4 passed
CometCodegenSuite: 3 upstream UDF-bridge tests 3 failed 3 passed

Locally on this PR: cargo fmt, clippy -D warnings, spotless and scalastyle clean; Rust workspace 1918 passed, 0 failed; CometExecSuite 155, CometCodegenSuite 103, CometSmjJoinFilterFuzzSuite default part 8, CometNativeShuffleSuite 70, CometFuzzTestSuite 45, CometArrayExpressionSuite 65, CometMapExpressionSuite 20, CometUdfBridgeSuite, CometShuffleReadCoalesceSuite, CometBlockStoreShuffleReaderSuite: all passed, 0 failed.

Cluster check

BoolSliceRepro (offset slice, sliced aggregate output, row_number dedup over a struct-in-struct boolean as in production), rows with a wrong nested boolean against the top-level copy of the same value; vanilla Spark gives 0 in all three:

query joom-1.1-4 this PR
ORDER BY … LIMIT 40 OFFSET 17 12 / 40 0 / 40
GROUP BY over 100-row batches 695 / 2000 0 / 2000
row_number dedup, 20M rows 9783 / 4,948,454 0 / 4,948,454

🤖 Generated with Claude Code

andygrove and others added 2 commits October 8, 2026 22:43
…he JVM (apache#6339) (apache#6449)

Arrow Java's C Data import ignores ArrowArray.offset at every level
(apache/arrow-java#88). arrow-rs folds a slice into the buffers for every
Spark type except boolean, which keeps its bit offset, so a sliced boolean
reached the JVM read from bit 0. The fix for apache#2051 only checked the top level
of each output column, so a boolean inside a sliced struct, list or map came
back wrong, and inputs to the JVM UDF bridge were never checked at all.

Add zero_offsets to datafusion-comet-common. It returns the array unchanged
when every offset is already zero, and otherwise re-slices boolean bitmaps
to start at bit 0 at every level, sharing every other buffer. move_to_spark
now applies it to every executed batch and decoded shuffle block, replacing
the top-level take in prepare_output, and JvmScalarUdfExpr applies it to the
bridge inputs.

Closes apache#6288.

(cherry picked from commit aee5e06)
(cherry picked from commit 6680083)
Reproduces the export corruption seen in mongo.finance_order_costs_daily_snapshot:
a boolean inside a nullable struct inside a struct comes back with the values of
neighbouring rows on joom-1.1-4 and is fixed by the previous commit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added bug Something isn't working area:udf labels Oct 8, 2026
@msafonov
msafonov merged commit 17a8426 into branch-1.1 Oct 9, 2026
37 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:udf bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants