Skip to content

[Refactor] Unify position-fallback tabletId-to-bucketSeq fill into one facade helper#76253

Open
xiangguangyxg wants to merge 1 commit into
StarRocks:mainfrom
xiangguangyxg:refactor-unify-tabletid-bucketseq-fill
Open

[Refactor] Unify position-fallback tabletId-to-bucketSeq fill into one facade helper#76253
xiangguangyxg wants to merge 1 commit into
StarRocks:mainfrom
xiangguangyxg:refactor-unify-tabletid-bucketseq-fill

Conversation

@xiangguangyxg

Copy link
Copy Markdown
Contributor

Why I'm doing:

The "position-fallback tabletId→bucketSeq fill policy" — if a RangeColocateScanDispatch is
present and the scan is range-aligned (dispatch.computeBucketSeq(selectedIndex) != null), use that
bucketSeq map; otherwise fall back to position-based bucketSeq (put(allTabletIds.get(i), i))
— was
written twice:

  • OlapScanNode.fillTabletId2BucketSeq (private, early-return form), and
  • inline inside PlanFragmentBuilder.visitPhysicalOlapScan (nested if/else form).

Two independent producers of the same policy can silently drift. Today any divergence is benign — the
dispatch-time alignment guard in OlapScanNode.getBucketNums() fails closed (worst case: one path
throws → shuffle fallback, never a wrong result) — but the duplication is unnecessary and easy to
collapse.

What I'm doing:

Extract the shared policy into a single static facade helper on the class that already owns the
policy's core:

public static void RangeColocateScanDispatch.fillTabletId2BucketSeq(
        @Nullable RangeColocateScanDispatch dispatch,
        MaterializedIndex selectedIndex,
        List<Long> allTabletIds,
        Map<Long, Integer> target)

Both call sites now route through it. RangeColocateScanDispatch is the natural home: it owns
computeBucketSeq and already hosts the sibling static scan helpers (isTabletRangesAligned,
computeAlignedTabletRanges, computeForcedAlignmentBoundaries). The helper appends to the
caller-supplied target map without clearing it, preserving the existing whole-scan accumulation
across sub-partitions.

This is a byte-for-byte behavior-preserving extraction. The two sites were already semantically
identical (early-return vs nested if/else, same outcomes); the helper reproduces both exactly for
all three cases:

case result
dispatch == null (HASH / range non-colocate) position-based fill
dispatch != null and computeBucketSeq != null (aligned) putAll(dispatch map)
dispatch != null and computeBucketSeq == null (transiently unaligned) position-based fallback

The now-dead private OlapScanNode.fillTabletId2BucketSeq is removed. No plan shape or bucketSeq
assignment changes.

What type of PR is this:

  • BugFix
  • Feature
  • Enhancement
  • Refactor
  • UT
  • Doc
  • Tool

Does this PR entail a change in behavior?

  • Yes, this PR will result in a change in behavior.
  • No, this PR will not result in a change in behavior.

Checklist:

  • I have added test cases for my bug fix or my new feature

(Added 3 focused unit tests to RangeColocateScanDispatchTest covering the three fill cases; the
existing range-colocate plan/dispatch suites — RangeColocateScanDispatchTest,
RangeColocateScanRangeDispatchTest, RangeColocateMixedJoinPlanTest,
RangeColocateNullSafeJoinPlanTest — stay green.)

  • This pr needs user documentation (for new or modified features or behaviors)
  • This is a backport pr

Bugfix cherry-pick branch check:

  • I have checked the version labels which the pr will be auto-backported to the target branch

[Refactor] is not auto-backported. The duplication exists on both main and branch-4.1 (the
range-colocate feature line), but a pure de-dup needs no backport — recommending main-only; 4.1
parity is optional and left to the maintainer's discretion.

…e facade helper

The position-fallback tabletId->bucketSeq fill policy was implemented twice:
OlapScanNode.fillTabletId2BucketSeq (early-return form) and inline in
PlanFragmentBuilder.visitPhysicalOlapScan (nested if/else form). Two independent
producers of the same policy can silently drift.

Collapse both into a single static helper
RangeColocateScanDispatch.fillTabletId2BucketSeq that writes into a
caller-supplied target map, and route both call sites through it.
RangeColocateScanDispatch already owns computeBucketSeq and the sibling
range-colocate scan helpers, so it is the natural home.

This is a behavior-preserving extraction: the helper reproduces both sites
exactly for dispatch absent, dispatch present + aligned, and dispatch present +
transiently unaligned. Add focused unit tests for the three cases.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: xiangguangyxg <xiangguangyxg@gmail.com>
@CelerData-Reviewer

Copy link
Copy Markdown

@codex review

@github-actions

Copy link
Copy Markdown
Contributor

Module-risk briefing for Codex review

This is review focus, not a finding list. Validate against the diff.

High-confidence risks

  • Module: planner
    Changed files: fe/fe-core/src/main/java/com/starrocks/planner/OlapScanNode.java, fe/fe-core/src/main/java/com/starrocks/planner/RangeColocateScanDispatch.java, fe/fe-core/src/test/java/com/starrocks/planner/RangeColocateScanDispatchTest.java
    Historical failure pattern: "Positional list index correspondence breaks silently under pruning" — the same OlapScanNode class previously crashed ([BugFix] Fix query cache normalization crash for tables with sub-partitions #75789) when a positionally-zipped partition-id/version-list pair diverged in length after sub-partition pruning.
    Review focus: The new RangeColocateScanDispatch.fillTabletId2BucketSeq still assigns bucketSeq by raw list position (allTabletIds.get(i) -> i) and accumulates into the caller-supplied target map via putAll without clearing. Confirm this accumulate-without-clear semantics is truly identical at both call sites when invoked repeatedly across multiple partitions/sub-partitions in OlapScanNode.computeTabletInfo's loop, and that allTabletIds ordering can't drift between the two producers now that the logic is shared.
    Evidence: [BugFix] Fix query cache normalization crash for tables with sub-partitions #75789 (from 20 merged bugfixes)
  • Module: sql/plan
    Changed files: fe/fe-core/src/main/java/com/starrocks/sql/plan/PlanFragmentBuilder.java
    Historical failure pattern: PlanFragmentBuilder's recurring "positional pairing of independently-computed lists" bug class ([BugFix] Fix query cache normalization crash for tables with sub-partitions #75789) — intermediate state built during fragment/scan construction must stay in exact sync across producers, since PlanFragmentBuilder sits at the seam between optimizer output and executable fragments.
    Review focus: This PR removes the inline nested if/else bucketSeq-fill logic from visitPhysicalOlapScan and routes it through the new shared static facade — verify the replacement produces byte-identical tabletId2BucketSeq contents (same fallback ordering, same accumulation across selectedIndex/sub-partition iterations) as the removed inline version, since this is exactly the second of two producers the PR itself says must never drift from each other.
    Evidence: [BugFix] Fix query cache normalization crash for tables with sub-partitions #75789 (from 7 merged bugfixes)

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

Reviewed commit: ee5b2e8b6d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@github-actions github-actions Bot requested review from ZiheLiu and satanson July 13, 2026 04:31
@github-actions

Copy link
Copy Markdown
Contributor

[Java-Extensions Incremental Coverage Report]

pass : 0 / 0 (0%)

@github-actions

Copy link
Copy Markdown
Contributor

[FE Incremental Coverage Report]

pass : 10 / 10 (100.00%)

file detail

path covered_line new_line coverage not_covered_line_detail
🔵 com/starrocks/planner/OlapScanNode.java 1 1 100.00% []
🔵 com/starrocks/planner/RangeColocateScanDispatch.java 8 8 100.00% []
🔵 com/starrocks/sql/plan/PlanFragmentBuilder.java 1 1 100.00% []

@github-actions

Copy link
Copy Markdown
Contributor

[BE Incremental Coverage Report]

pass : 0 / 0 (0%)

@sonarqubecloud

Copy link
Copy Markdown

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.

2 participants