Skip to content

fix(container): bound external null bitmap merge - #27444

Merged
mergify[bot] merged 12 commits into
matrixorigin:mainfrom
Lundomn:fix/nulls-or-external-bitmap-27432
Aug 25, 2026
Merged

fix(container): bound external null bitmap merge#27444
mergify[bot] merged 12 commits into
matrixorigin:mainfrom
Lundomn:fix/nulls-or-external-bitmap-27432

Conversation

@Lundomn

@Lundomn Lundomn commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

What type of PR is this?

  • API-change
  • BUG
  • Improvement
  • Documentation
  • Feature
  • Test and CI
  • Code Refactoring

Which issue(s) this PR fixes:

Fixes #27432

What this PR does / why we need it:

nulls.Or could panic when a source bitmap retained a longer logical length than an externally allocated result bitmap. This occurred while evaluating a nullable VARCHAR comparison inside a CASE aggregate over a large Kafka-loaded table, producing:

internal error: panic bitmap external storage capacity exceeded

This change keeps externally backed result bitmap storage bounded to its visible logical length and copies only source NULL bits within that bound. It adds regression coverage for one and two long source bitmaps, including in-range and out-of-range bits.

Tests completed locally:

  • go test -mod=readonly -vet=off -count=1 ./pkg/container/nulls ./pkg/common/bitmap
  • go test -mod=readonly -vet=off -short -race -tags matrixone_test -p 1 ./pkg/container/nulls ./pkg/common/bitmap
  • go vet -mod=readonly ./pkg/common/bitmap ./pkg/container/nulls
  • latest-main MatrixOne build
  • 590,187-row Kafka/GH Archive regression, including CASE/SUM, NULL semantics, transactions, index equivalence, updates, and deletes

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@aunjgr aunjgr 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.

[P1] Do not clip allocation-accounted function-result NULLs when the bitmap's logical length is reset. At f7197fe, FunctionExpressionExecutor preallocates external NULL storage, then PreExtendAndReset calls ResetWithSameType, leaving its bitmap length zero while capacity still covers the result rows. Built-ins such as lower propagate source NULLs through nulls.Or; the new external-result branch sees source length greater than zero, sets its limit to zero, and returns without copying any NULLs.\n\nReproduced with an allocation-accounted expression executor over lower(varchar): input values AA, NULL, CC return a non-NULL value at row 1 on this head. The identical isolated test passes at merge base 344d852.\n\nPreserve the normal OR path whenever the external destination capacity can represent the source; only use a bounded copy when growth would exceed that capacity, or pass the output's visible row bound explicitly. Add an allocation-accounted function-expression regression alongside the bitmap tests.

@aptend aptend 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.

Deep re-review of exact head 74489d3df71b63a42f9b39b92db1739cd0273b97. I read the full prior review/history, audited the complete four-file diff, and focused on the increment after the changes-requested head f7197fe8c539126e9258820420d5c75f182f0809. The allocation-accounted expression NULL-loss case is fixed, and the hash-join empty-bucket caller now establishes its row bound. However, the generic nulls.Or fallback now uses physical capacity as a logical row bound and reintroduces the PR's original out-of-range NULL leak whenever the longer source still fits spare external capacity; the deterministic counterexample is inline. Unmodified nulls/bitmap/colexec/hashjoin suites, focused race runs, vet, and diff checks pass; the added exact-head counterexample fails as described and was removed afterward.

Comment thread pkg/container/nulls/nulls.go Outdated

@aunjgr aunjgr 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.

Deep re-reviewed exact head a3f6dcf63913be198a60d4a940912720b1820d56 against merge base dc403fbac6a09c77ac93bb023fe83056308a038b and the full prior review history.

The result owner now publishes the current visible row domain after reset; external physical capacity is never inferred as logical length. All Nulls union entry points route through the same word-wise bounded merge, preserve in-range NULLs, exclude stale out-of-range bits, handle aliases/empty/zero-row generations, and retain destination length. External expansion failure is failure-atomic, and the hash-join empty-bucket path establishes its result bound before propagation.

This closes the original panic, the spare-capacity leak, and reset-result NULL loss without adding per-row work or allocations. No remaining correctness, ownership, or boundedness blocker found.

@aptend aptend 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.

Re-reviewed exact head a3f6dcf after reading the full review/thread history and checking both the rewritten delta and complete diff. The prior blocker is closed: external NULL unions are bounded by the destination logical row domain rather than spare backing capacity; allocation-accounted function results republish that domain after reset; the empty-spill MARK join establishes it before propagation; and capacity failure is now state-atomic. Exact-head list/build/vet/full package tests passed, focused race tests passed 20 iterations, and an allocation-accounted MARK-join counterexample passed 20 iterations. No blocking issues found.

@Lundomn

Lundomn commented Aug 25, 2026

Copy link
Copy Markdown
Contributor Author

@Mergifyio queue

@mergify

mergify Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

  • Entered queue2026-08-25 11:43 UTC · Rule: main · triggered by @Lundomn with the @mergifyio queue command
  • Checks passed · in-place
  • Merged2026-08-25 13:10 UTC · at f47b6b866ad485ec304186ca7929bc2bc62c225f · squash

This pull request spent 1 hour 26 minutes 56 seconds in the queue, including 50 minutes 39 seconds running CI.

Required conditions to merge
  • #review-threads-unresolved = 0 [🛡 GitHub branch protection]
  • github-review-approved [🛡 GitHub branch protection]
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone CI / UT Test on Ubuntu/x86
    • check-neutral = Matrixone CI / UT Test on Ubuntu/x86
    • check-skipped = Matrixone CI / UT Test on Ubuntu/x86
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone CI / SCA Test on Linux/arm64
    • check-neutral = Matrixone CI / SCA Test on Linux/arm64
    • check-skipped = Matrixone CI / SCA Test on Linux/arm64
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
    • check-neutral = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
    • check-skipped = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Utils CI / Coverage
    • check-neutral = Matrixone Utils CI / Coverage
    • check-skipped = Matrixone Utils CI / Coverage
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone UT Coverage / UT Coverage on Ubuntu/x86
    • check-neutral = Matrixone UT Coverage / UT Coverage on Ubuntu/x86
    • check-skipped = Matrixone UT Coverage / UT Coverage on Ubuntu/x86
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Standlone CI / multi CN e2e BVT Test on Linux/x64(COMPOSE, PESSIMISTIC)
    • check-neutral = Matrixone Standlone CI / multi CN e2e BVT Test on Linux/x64(COMPOSE, PESSIMISTIC)
    • check-skipped = Matrixone Standlone CI / multi CN e2e BVT Test on Linux/x64(COMPOSE, PESSIMISTIC)

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

Labels

kind/bug Something isn't working kind/test-ci size/M Denotes a PR that changes [100,499] lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: nullable VARCHAR CASE aggregate panics with bitmap external storage capacity exceeded

5 participants