Skip to content

planner, executor: code preparation for supporting access path keep order with IN Conditions using merge sort#66713

Merged
ti-chi-bot[bot] merged 3 commits into
pingcap:release-8.5from
time-and-fate:cherry-pick-63457-to-release-8.5
Mar 6, 2026
Merged

planner, executor: code preparation for supporting access path keep order with IN Conditions using merge sort#66713
ti-chi-bot[bot] merged 3 commits into
pingcap:release-8.5from
time-and-fate:cherry-pick-63457-to-release-8.5

Conversation

@time-and-fate
Copy link
Copy Markdown
Member

@time-and-fate time-and-fate commented Mar 5, 2026

Manual cherry-pick of #63457


What problem does this PR solve?

Issue Number: ref #63449

Problem Summary:

This PR doesn't contain actual logic changes. It's for reducing modifications for the next PR.

What changed and how does it work?

  • planner
    • isMatchProp() (pkg/planner/core/find_best_task.go)
      • Renamed to matchProperty()
      • Return type changed from a bool to PhysicalPropMatchResult, which is a newly introduced enum.
      • Slightly refactor the current code to make it cleaner without modifying the actual logic.
    • New enum PhysicalPropMatchResult (pkg/planner/property/physical_property.go)
      • PropNotMatched: corresponds to previous isMatchProp() == false.
      • PropMatched: corresponds to previous isMatchProp() == true.
  • executor
    • Extract function collectColIdxFromByItems() for later use.
    • Add assertion that expressions in ByItems must be Columns.
  • tests
    • Added the integration tests so that we can see the plan changes and also make sure there are no correctness issues in the next PR.

Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No need to test
    • I checked and no code files have been changed.

Side effects

  • Performance regression: Consumes more CPU
  • Performance regression: Consumes more Memory
  • Breaking backward compatibility

Documentation

  • Affects user behaviors
  • Contains syntax changes
  • Contains variable changes
  • Contains experimental features
  • Changes MySQL compatibility

Release note

Please refer to Release Notes Language Style Guide to write a quality release note.

None

Summary by CodeRabbit

  • Bug Fixes

    • Strengthened validation of ordering keys to ensure consistent, column-only ordering across readers.
  • Performance

    • Improved merge-sort decision logic to better preserve ordering and reduce unnecessary work.
  • Refactor

    • Simplified property matching flow for planner decisions, improving correctness of plan selection.
  • Tests

    • Added extensive integration tests covering grouped ranges and order-by scenarios.

@ti-chi-bot ti-chi-bot Bot added release-note-none Denotes a PR that doesn't merit a release note. do-not-merge/cherry-pick-not-approved size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. sig/planner SIG: Planner labels Mar 5, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 5, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 650cd9ac-fdd5-4267-8502-38c027df54ba

📥 Commits

Reviewing files that changed from the base of the PR and between 1cb44f1 and ce1024f.

📒 Files selected for processing (2)
  • tests/integrationtest/r/planner/core/grouped_ranges_order_by.result
  • tests/integrationtest/t/planner/core/grouped_ranges_order_by.test
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/integrationtest/t/planner/core/grouped_ranges_order_by.test

📝 Walkthrough

Walkthrough

Adds runtime validation that ByItems are Column expressions in multiple executor readers, extracts merge-sort decision logic into a shared helper used by index readers, replaces boolean property-matching with an explicit enum result, and adds extensive integration tests for grouped range order-by scenarios.

Changes

Cohort / File(s) Summary
Executor validation
pkg/executor/builder.go
Added collectColIdxFromByItems and assertByItemsAreColumns; centralized ByItems → column-index collection and runtime assertions across reader constructors.
Merge-sort decision
pkg/executor/distsql.go
Introduced needMergeSort(byItems, kvRangesCount) and replaced inline heuristics in IndexReaderExecutor / IndexLookUpExecutor paths to conditionally wrap partitioned results with a sorted result wrapper.
Planner property matching
pkg/planner/core/find_best_task.go, pkg/planner/property/physical_property.go
Added exported PhysicalPropMatchResult with PropNotMatched/PropMatched and Matched(); replaced boolean matching with matchProperty returning the enum and updated call sites to use .Matched().
Integration tests
tests/integrationtest/t/planner/core/grouped_ranges_order_by.test, tests/integrationtest/r/planner/core/grouped_ranges_order_by.result
Added comprehensive test cases and expected results exercising grouped range ordering, partitioned/indexed tables, prepared statements, transactions, and various query patterns.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Suggested labels

type/cherry-pick-for-release-8.5, ok-to-test

Suggested reviewers

  • mjonss
  • AilinKid

Poem

🐰 I hopped through ByItems, checking each name,
Columns lined up, no expr left to blame.
Merge-sorts now choose when partitions align,
Planner says match or not — the result’s a sign.
Tests bloom like carrots — crunchy, robust, and fine! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main focus: preparatory code changes for supporting 'keep order' with 'IN' conditions using merge sort in planner and executor.
Description check ✅ Passed The PR description is well-structured with clear sections on problem statement, changes made, and testing. All required template sections are addressed with appropriate details about the code refactoring.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
pkg/planner/core/find_best_task.go (1)

883-886: Remove unreachable nil-check in vector property matching.

Line 883 already guarantees path.Index and path.Index.VectorInfo are non-nil, so the guard at Line 884 can never execute. This dead branch makes future vector-path edits harder to reason about.

♻️ Proposed cleanup
-	if prop.VectorProp.VectorHelper != nil && path.Index != nil && path.Index.VectorInfo != nil {
-		if path.Index == nil || path.Index.VectorInfo == nil {
-			return property.PropNotMatched
-		}
+	if prop.VectorProp.VectorHelper != nil && path.Index != nil && path.Index.VectorInfo != nil {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/planner/core/find_best_task.go` around lines 883 - 886, The inner
nil-check is unreachable because the outer condition already ensures
prop.VectorProp.VectorHelper != nil && path.Index != nil &&
path.Index.VectorInfo != nil; remove the redundant guard that checks "if
path.Index == nil || path.Index.VectorInfo == nil" and its early return of
property.PropNotMatched from the block in find_best_task.go so the vector
property matching branch is simplified (identify the block by the symbols
prop.VectorProp.VectorHelper, path.Index, path.Index.VectorInfo, and the return
property.PropNotMatched).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/executor/builder.go`:
- Around line 1377-1392: The function collectColIdxFromByItems currently builds
colIdxs but silently ignores ByItems whose column IDs aren't found in cols;
change it to fail fast by detecting when a column from byItems (item.Expr as
*expression.Column) has no matching c.ID in cols and immediately return an error
(include the missing column ID or another identifying detail in the message)
instead of returning a partial colIdxs; update the loop in
collectColIdxFromByItems to check after scanning cols and return an
errors.Errorf when not found.

In `@tests/integrationtest/t/planner/core/grouped_ranges_order_by.test`:
- Around line 63-70: The EXPLAIN queries reference table t2 but the subsequent
SELECTs query table t, breaking the plan/result pairing; update the three SELECT
statements that currently use "from t" to use "from t2" so each "explain format
= 'brief' select ... from t2 ..." is executed against the same table (e.g.
change the SELECTs for "select a,c from t", "select a,c from t" (with d > 60)
and "select b,c from t" to use t2).

---

Nitpick comments:
In `@pkg/planner/core/find_best_task.go`:
- Around line 883-886: The inner nil-check is unreachable because the outer
condition already ensures prop.VectorProp.VectorHelper != nil && path.Index !=
nil && path.Index.VectorInfo != nil; remove the redundant guard that checks "if
path.Index == nil || path.Index.VectorInfo == nil" and its early return of
property.PropNotMatched from the block in find_best_task.go so the vector
property matching branch is simplified (identify the block by the symbols
prop.VectorProp.VectorHelper, path.Index, path.Index.VectorInfo, and the return
property.PropNotMatched).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a38ba854-a5f7-48cc-99c0-d2013be66cdb

📥 Commits

Reviewing files that changed from the base of the PR and between c76abe1 and 1cb44f1.

📒 Files selected for processing (6)
  • pkg/executor/builder.go
  • pkg/executor/distsql.go
  • pkg/planner/core/find_best_task.go
  • pkg/planner/property/physical_property.go
  • tests/integrationtest/r/planner/core/grouped_ranges_order_by.result
  • tests/integrationtest/t/planner/core/grouped_ranges_order_by.test

Comment thread pkg/executor/builder.go
Comment on lines +1377 to +1392
func collectColIdxFromByItems(byItems []*plannerutil.ByItems, cols []*model.ColumnInfo) ([]int, error) {
var colIdxs []int
for _, item := range byItems {
col, ok := item.Expr.(*expression.Column)
if !ok {
return nil, errors.Errorf("Not support non-column in orderBy pushed down")
}
for i, c := range cols {
if c.ID == col.ID {
colIdxs = append(colIdxs, i)
break
}
}
}
return colIdxs, nil
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fail fast when a ByItems column ID is not present in cols.

This helper currently returns partial colIdxs if a column is not found, which can silently degrade ordering (downstream compare iterates usedIndex, see pkg/executor/union_scan.go Line 305). Return an explicit error on the first missing mapping.

💡 Proposed fix
 func collectColIdxFromByItems(byItems []*plannerutil.ByItems, cols []*model.ColumnInfo) ([]int, error) {
-	var colIdxs []int
+	colIdxs := make([]int, 0, len(byItems))
 	for _, item := range byItems {
 		col, ok := item.Expr.(*expression.Column)
 		if !ok {
 			return nil, errors.Errorf("Not support non-column in orderBy pushed down")
 		}
+		found := false
 		for i, c := range cols {
 			if c.ID == col.ID {
 				colIdxs = append(colIdxs, i)
+				found = true
 				break
 			}
 		}
+		if !found {
+			return nil, errors.Errorf("Not found order by related columns in indexMerge.columns")
+		}
 	}
 	return colIdxs, nil
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func collectColIdxFromByItems(byItems []*plannerutil.ByItems, cols []*model.ColumnInfo) ([]int, error) {
var colIdxs []int
for _, item := range byItems {
col, ok := item.Expr.(*expression.Column)
if !ok {
return nil, errors.Errorf("Not support non-column in orderBy pushed down")
}
for i, c := range cols {
if c.ID == col.ID {
colIdxs = append(colIdxs, i)
break
}
}
}
return colIdxs, nil
}
func collectColIdxFromByItems(byItems []*plannerutil.ByItems, cols []*model.ColumnInfo) ([]int, error) {
colIdxs := make([]int, 0, len(byItems))
for _, item := range byItems {
col, ok := item.Expr.(*expression.Column)
if !ok {
return nil, errors.Errorf("Not support non-column in orderBy pushed down")
}
found := false
for i, c := range cols {
if c.ID == col.ID {
colIdxs = append(colIdxs, i)
found = true
break
}
}
if !found {
return nil, errors.Errorf("Not found order by related columns in indexMerge.columns")
}
}
return colIdxs, nil
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/executor/builder.go` around lines 1377 - 1392, The function
collectColIdxFromByItems currently builds colIdxs but silently ignores ByItems
whose column IDs aren't found in cols; change it to fail fast by detecting when
a column from byItems (item.Expr as *expression.Column) has no matching c.ID in
cols and immediately return an error (include the missing column ID or another
identifying detail in the message) instead of returning a partial colIdxs;
update the loop in collectColIdxFromByItems to check after scanning cols and
return an errors.Errorf when not found.

Comment thread tests/integrationtest/t/planner/core/grouped_ranges_order_by.test Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 5, 2026

Codecov Report

❌ Patch coverage is 88.75000% with 9 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (release-8.5@c76abe1). Learn more about missing BASE report.

Additional details and impacted files
@@               Coverage Diff                @@
##             release-8.5     #66713   +/-   ##
================================================
  Coverage               ?   55.1250%           
================================================
  Files                  ?       1819           
  Lines                  ?     653808           
  Branches               ?          0           
================================================
  Hits                   ?     360412           
  Misses                 ?     266697           
  Partials               ?      26699           
Flag Coverage Δ
integration 38.4513% <85.0000%> (?)
unit 64.9764% <69.7368%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
dumpling 52.9278% <0.0000%> (?)
parser ∅ <0.0000%> (?)
br 55.6397% <0.0000%> (?)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@time-and-fate
Copy link
Copy Markdown
Member Author

/retest

@ti-chi-bot ti-chi-bot Bot added cherry-pick-approved Cherry pick PR approved by release team. and removed do-not-merge/cherry-pick-not-approved labels Mar 5, 2026
@time-and-fate
Copy link
Copy Markdown
Member Author

/retest

5 similar comments
@time-and-fate
Copy link
Copy Markdown
Member Author

/retest

@time-and-fate
Copy link
Copy Markdown
Member Author

/retest

@time-and-fate
Copy link
Copy Markdown
Member Author

/retest

@time-and-fate
Copy link
Copy Markdown
Member Author

/retest

@time-and-fate
Copy link
Copy Markdown
Member Author

/retest

@ti-chi-bot ti-chi-bot Bot added approved needs-1-more-lgtm Indicates a PR needs 1 more LGTM. labels Mar 6, 2026
@ti-chi-bot
Copy link
Copy Markdown

ti-chi-bot Bot commented Mar 6, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: qw4990, winoros

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@ti-chi-bot ti-chi-bot Bot added lgtm and removed needs-1-more-lgtm Indicates a PR needs 1 more LGTM. labels Mar 6, 2026
@ti-chi-bot
Copy link
Copy Markdown

ti-chi-bot Bot commented Mar 6, 2026

[LGTM Timeline notifier]

Timeline:

  • 2026-03-06 07:48:02.074962969 +0000 UTC m=+517126.653042153: ☑️ agreed by qw4990.
  • 2026-03-06 08:50:12.477051619 +0000 UTC m=+520857.055130803: ☑️ agreed by winoros.

@ti-chi-bot ti-chi-bot Bot merged commit 3a27621 into pingcap:release-8.5 Mar 6, 2026
20 checks passed
@ti-chi-bot ti-chi-bot Bot removed the cherry-pick-approved Cherry pick PR approved by release team. label Mar 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved cherry-pick-approved Cherry pick PR approved by release team. lgtm release-note-none Denotes a PR that doesn't merit a release note. sig/planner SIG: Planner size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants