Skip to content

fix: DH-20318: Fix bug in UnionSourceManager pushdown estimation that caused AIOOBE in UnionRedirection#7796

Merged
rcaudy merged 6 commits intodeephaven:mainfrom
rcaudy:rwc-usm-aiobe-fix
Mar 17, 2026
Merged

fix: DH-20318: Fix bug in UnionSourceManager pushdown estimation that caused AIOOBE in UnionRedirection#7796
rcaudy merged 6 commits intodeephaven:mainfrom
rcaudy:rwc-usm-aiobe-fix

Conversation

@rcaudy
Copy link
Copy Markdown
Member

@rcaudy rcaudy commented Mar 17, 2026

No description provided.

rcaudy and others added 3 commits March 16, 2026 20:57
…nstituent row keys have gaps

When `constituentChangesPermitted=true`, removing then adding a constituent creates gaps in
`constituentRows` row keys (e.g. remove key 8, add key 15 → max key 15 with only 15 entries).
`initialize` was incorrectly using these row keys as 0-based slot positions for
`UnionRedirection` lookups, causing `currLastRowKeyForSlot(15)` to access
`currFirstRowKeys[16]` → `ArrayIndexOutOfBoundsException: Index 16 out of bounds for length 16`.

Fix uses a separate `MutableInt slotPosition` counter (0-based position) for `unionRedirection`
slot lookups, while keeping the actual `rowKey` for `constituentTables.get/getPrev`. Adds a
regression test that reproduces the exact crash scenario.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… the fix

The AIOBE in UnionSourcePushdownFilterContext.initialize propagates via
errorUpdate -> notifyListenersOnError, silently setting filtered.isFailed()=true.
Since filtered had no downstream listeners, RefreshingTableTestCase.reportUpdateError
was never called and TestCase.fail() was never triggered. filtered.size() returned
the stale count of N, so assertEquals(N, filtered.size()) passed even without the fix.

Attach an ErrorListener to filtered before the update cycle to capture the
exception delivered via notifyListenersOnError. Without the fix the assertThat
on originalException() fails showing the actual AIOBE; with the fix it is null.
Also assert !filtered.isFailed() as a belt-and-suspenders check.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rcaudy rcaudy added this to the 42.0 milestone Mar 17, 2026
@rcaudy rcaudy requested a review from Copilot March 17, 2026 02:08
@rcaudy rcaudy self-assigned this Mar 17, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 17, 2026

No docs changes detected for 03860ed

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes an ArrayIndexOutOfBoundsException in UnionSourcePushdownFilterContext.initialize that occurred when constituent changes created gaps in row keys. The bug was in the pushdown filter estimation logic, where row keys from constituentRows were incorrectly used as position-based slot indices for unionRedirection lookups.

Changes:

  • Fixed initialize() in UnionSourcePushdownFilterContext to use a 0-based position counter for unionRedirection slot lookups while using actual row keys for constituentTables lookups.
  • Added a regression test (testMergeWhereWithConstituentChangeGap) that reproduces the AIOOBE by removing a constituent (creating a gap) and adding a new one beyond the previous max key.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
engine/table/src/main/java/io/deephaven/engine/table/impl/sources/UnionSourceManager.java Decouples position-based slot index from row key in initialize(), replacing TIntArrayList of row keys with a MutableInt position counter
engine/table/src/test/java/io/deephaven/engine/table/impl/PartitionedTableTest.java Adds regression test reproducing the AIOOBE when constituent row keys have gaps

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…rContext.initialize; fix AIOOBE with constituent row-key gaps

When constituentChangesPermitted=true, removing a constituent creates a
gap in constituentRows row keys. The previous code incorrectly used those
row keys as slot indices into unionRedirection (which is position-indexed),
causing an ArrayIndexOutOfBoundsException in currLastRowKeyForSlot when
the max row key exceeded currSize-1.

Fix uses a 0-based slot counter alongside a ChunkedObjectColumnIterator
over constituentTables to avoid serial get/getPrev calls, cleanly separating
position-indexed slot lookups from row-key-indexed table lookups.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes an ArrayIndexOutOfBoundsException in UnionSourceManager's pushdown filter estimation. The bug occurred when constituentChangesPermitted=true and a constituent removal created a gap in constituentRows row keys, causing the initialize() method to incorrectly use row keys (which may have gaps) as position-based slot indices for unionRedirection lookups.

Changes:

  • Fixed UnionSourcePushdownFilterContext.initialize() to use a position-based slot counter with an iterator over constituent tables, instead of using constituentRows row keys directly as slot positions.
  • Added a regression test that reproduces the AIOOBE by removing a constituent (creating a gap) and adding a new one past the previous max key.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
engine/table/src/main/java/io/deephaven/engine/table/impl/sources/UnionSourceManager.java Replaced row-key-based slot lookup with iterator + 0-based slot counter in initialize()
engine/table/src/test/java/io/deephaven/engine/table/impl/PartitionedTableTest.java Added regression test testMergeWhereWithConstituentChangeGap

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@rcaudy rcaudy requested review from cpwright and lbooker42 March 17, 2026 02:53
cpwright
cpwright previously approved these changes Mar 17, 2026
…itionedTableTest.java

Co-authored-by: Charles P. Wright <cpwright@gmail.com>
@rcaudy rcaudy enabled auto-merge (squash) March 17, 2026 15:04
@rcaudy rcaudy requested a review from cpwright March 17, 2026 15:04
cpwright
cpwright previously approved these changes Mar 17, 2026
…ments

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rcaudy rcaudy merged commit 8e995cd into deephaven:main Mar 17, 2026
23 checks passed
@rcaudy rcaudy deleted the rwc-usm-aiobe-fix branch March 17, 2026 15:52
@github-actions github-actions Bot locked and limited conversation to collaborators Mar 17, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants