Skip to content

planner: support use_plan_cache hint and binding under hint_only plan cache strategy#67535

Merged
ti-chi-bot[bot] merged 4 commits into
pingcap:masterfrom
qw4990:codex/issue-67409
Apr 8, 2026
Merged

planner: support use_plan_cache hint and binding under hint_only plan cache strategy#67535
ti-chi-bot[bot] merged 4 commits into
pingcap:masterfrom
qw4990:codex/issue-67409

Conversation

@qw4990
Copy link
Copy Markdown
Contributor

@qw4990 qw4990 commented Apr 2, 2026

What problem does this PR solve?

Issue Number: close #67409

Problem Summary: planner: support use_plan_cache hint and binding under hint_only plan cache strategy

What changed and how does it work?

  • Added new system variable tidb_plan_cache_strategy:
    • all (default): keep current behavior
    • hint_only: only cache plans when use_plan_cache() is present
  • Added new optimizer hint: use_plan_cache().
  • Implemented hint_only behavior for:
    • prepared plan cache
    • non-prepared plan cache
  • Extended hint detection so use_plan_cache() coming from SQL binding is also honored.

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

  • New Features
    • Added tidb_plan_cache_strategy system variable ("all" or "hint_only") and the use_plan_cache() hint to control plan caching.
  • Behavior Changes
    • In "hint_only" mode, plans are cached only when the use_plan_cache() hint (or an equivalent binding) is present; missing hints cause plan-cache lookup to be skipped and produce a warning during EXPLAIN.
  • Tests
    • Added integration tests covering hint_only strategy, prepared/non-prepared statements, bindings, and warning behavior.

@ti-chi-bot ti-chi-bot Bot added the release-note-none Denotes a PR that doesn't merit a release note. label Apr 2, 2026
@pantheon-ai
Copy link
Copy Markdown

pantheon-ai Bot commented Apr 2, 2026

Review Complete

Findings: 0 issues
Posted: 0
Duplicates/Skipped: 0

ℹ️ Learn more details on Pantheon AI.

@ti-chi-bot ti-chi-bot Bot added sig/planner SIG: Planner size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Apr 2, 2026
@tiprow
Copy link
Copy Markdown

tiprow Bot commented Apr 2, 2026

Hi @qw4990. Thanks for your PR.

PRs from untrusted users cannot be marked as trusted with /ok-to-test in this repo meaning untrusted PR authors can never trigger tests themselves. Collaborators can still trigger tests on the PR using /test all.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 2, 2026

📝 Walkthrough

Walkthrough

Introduce a hint_only plan-cache strategy and a use_plan_cache() hint; plan-cache lookup and key generation are adjusted to require the hint (or a binding containing it) before using cached plans, with new vars, hint detection, and tests added.

Changes

Cohort / File(s) Summary
Hint definition & detection
pkg/util/hint/hint.go, pkg/util/hint/hint_processor.go, pkg/parser/ast/misc.go
Add HintUsePlanCache and StmtHints.UsePlanCache; add ContainTableHintInStmtNode() to detect table hints; treat use_plan_cache as an args-less hint during restore.
Plan cache config & session state
pkg/sessionctx/vardef/tidb_vars.go, pkg/sessionctx/variable/session.go, pkg/sessionctx/variable/sysvar.go
Add tidb_plan_cache_strategy sysvar with enum values all/hint_only, default all; add SessionVars.PlanCacheStrategy and wire sysvar to session field.
Plan cache core behavior & keys
pkg/planner/core/plan_cache.go, pkg/planner/core/plan_cache_utils.go, pkg/planner/optimize.go
Add detection/propagation of use_plan_cache presence (including via matched binding); refactor cache-key creation to accept matched binding info; skip plan-cache lookup when strategy is hint_only and hint absent, emitting a warning.
Tests
tests/integrationtest/t/planner/core/plan_cache.test, tests/integrationtest/r/planner/core/plan_cache.result
Add integration tests covering hint_only behavior for prepared/non-prepared statements and bindings; assert cache hits/misses and warning emission.

Sequence Diagrams

sequenceDiagram
    participant Client
    participant Session as SessionVars
    participant Optimizer
    participant Binding as BindInfo
    participant Cache as PlanCache

    Client->>Session: Execute SQL (strategy=hint_only)
    Session->>Optimizer: Provide stmt + strategy
    Optimizer->>Optimizer: Check AST for use_plan_cache hint
    alt hint present in AST
        Optimizer->>Cache: newPlanCacheKeyWithMatchedBinding(...)
        Cache->>Optimizer: Lookup plan
    else hint absent
        Optimizer->>Binding: MatchSQLBindingWithCache(...)
        Binding->>Optimizer: matchedBinding (may contain hint)
        alt matched binding has use_plan_cache
            Optimizer->>Cache: newPlanCacheKeyWithMatchedBinding(...)
            Cache->>Optimizer: Lookup plan
        else no hint anywhere
            Optimizer->>Session: WarnSkipPlanCache("hint_only no hint")
            Optimizer->>Optimizer: Generate plan without cache
        end
    end
    Optimizer->>Client: Return plan/result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

size/M

Suggested reviewers

  • hawkingrei
  • terry1purcell

Poem

🐰 A hint tucked in SQL, a whisper to cache,
I hop through bindings, avoiding the splash.
With use_plan_cache() I choose what to keep,
Small, clever caches — no memory heap! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding support for use_plan_cache hint and binding under a hint_only plan cache strategy.
Description check ✅ Passed The description includes the required issue reference (close #67409) and provides a clear summary of changes (new system variable, new hint, implementation scope, and SQL binding support).
Linked Issues check ✅ Passed The PR successfully implements the hint_only strategy from #67409 with use_plan_cache hint support and SQL binding detection, addressing the core objective of selective plan caching.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the hint_only plan cache strategy, use_plan_cache hint, and SQL binding detection as specified in #67409.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@pantheon-ai pantheon-ai Bot left a comment

Choose a reason for hiding this comment

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

✅ Code looks good. No issues found.

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.

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

315-330: Consider splitting “binding matched” from “binding match already computed” in helper args.

At Line 324, bindingMatched currently controls both rematch behavior and match-result semantics. That contract is easy to misuse at call sites and can reintroduce duplicate matching.

♻️ Suggested refactor
-func newPlanCacheKeyWithMatchedBinding(
+func newPlanCacheKeyWithMatchedBinding(
 	sctx sessionctx.Context,
 	stmt *PlanCacheStmt,
 	matchedBinding *bindinfo.Binding,
-	bindingMatched bool,
+	bindingMatchComputed bool,
+	bindingMatched bool,
 ) (key, binding string, cacheable bool, reason string, err error) {
-	if !bindingMatched && stmt.PreparedAst != nil {
+	if !bindingMatchComputed && stmt.PreparedAst != nil {
 		matchedBinding, bindingMatched, _ = bindinfo.MatchSQLBindingWithCache(sctx, stmt.PreparedAst.Stmt, &stmt.BindingInfo)
 	}
 	if bindingMatched && matchedBinding != nil {
 		binding = matchedBinding.BindSQL
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/planner/core/plan_cache_utils.go` around lines 315 - 330, The helper
newPlanCacheKeyWithMatchedBinding conflates "should attempt rematch" with the
"bindingMatched result" via the bindingMatched parameter, causing misuse and
duplicate matching; change the function signature to accept two distinct
booleans (e.g., rematch bool and bindingMatched bool or preMatched bool and
doRematch bool), update the internal logic to only call
bindinfo.MatchSQLBindingWithCache when the rematch/doRematch flag is true, and
treat bindingMatched strictly as the match-result to decide setting binding =
matchedBinding.BindSQL; then propagate this new signature to all callers
(including the wrapper newPlanCacheKey) and update their call sites to pass the
appropriate rematch flag versus the prior match-result so rematching behavior is
explicit and no duplicate matching occurs.
pkg/planner/core/plan_cache.go (1)

63-73: Consider centralizing the hint_only gate.

This file now has its own helper and reason string for the same use_plan_cache()/binding policy that pkg/planner/optimize.go already enforces for the non-prepared entry point. Pulling that predicate/reason into one shared helper would make future plan-cache-hint changes less likely to drift between the two paths.

As per coding guidelines "Code SHOULD remain maintainable for future readers with basic TiDB familiarity, including readers who are not experts in the specific subsystem/feature."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/planner/core/plan_cache.go` around lines 63 - 73, The new helper
containUsePlanCacheHintInPreparedSQLOrBinding and planCacheHintOnlyNoHintReason
duplicate the same "hint_only" predicate used in the non-prepared path; extract
that predicate and its reason string into a single shared helper (e.g., Move or
create a centralized function like
IsUsePlanCacheAllowedOrReason/GetUsePlanCacheHintReason) and replace the local
planCacheHintOnlyNoHintReason and containUsePlanCacheHintInPreparedSQLOrBinding
with calls to that shared helper from both this file and the code in
optimize.go; ensure the shared helper accepts a PlanCacheStmt, bindinfo.Binding,
and bindingMatched bool and returns the boolean (and/or reason string) so both
prepared and non-prepared entry points use the exact same logic.
tests/integrationtest/r/planner/core/plan_cache.result (1)

2737-2738: Add one post-drop execution before resetting hint_only.

These blocks prove that a binding can turn caching on, but they stop before checking the inverse transition. Please keep tidb_plan_cache_strategy='hint_only' for one more execute/select after drop binding; otherwise a stale binding-match cache in the prepared or non-prepared path would still pass here.

Also applies to: 2763-2765

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/integrationtest/r/planner/core/plan_cache.result` around lines 2737 -
2738, After the "drop binding for select * from t where a=1;" step, run one more
execute/select of the same statement to validate the transition before changing
plan cache strategy back to default; specifically, insert an extra "select *
from t where a=1;" (or the matching prepared execute) between the "drop binding
for select * from t where a=1;" and "set tidb_plan_cache_strategy = default;"
lines. Do the same fix for the analogous block around the "drop binding" at the
2763-2765 area so each drop is followed by one more execute/select before
resetting tidb_plan_cache_strategy.
pkg/util/hint/hint_processor.go (1)

132-132: Optional hardening: normalize hintName at API boundary.

HintName.L is lowercase; normalizing input once would make this exported function more robust for future callers.

♻️ Suggested tweak
 func ContainTableHintInStmtNode(node ast.Node, hintName string) bool {
+	hintName = strings.ToLower(hintName)
 	switch x := node.(type) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/util/hint/hint_processor.go` at line 132, The exported function
ContainTableHintInStmtNode should normalize the incoming hintName at the API
boundary because HintName.L is stored lowercase; update
ContainTableHintInStmtNode to canonicalize hintName (e.g., to lower-case or the
same normalization used by HintName.L) before any comparisons so callers passing
different-cased strings still match reliably.
tests/integrationtest/t/planner/core/plan_cache.test (1)

1735-1736: Consider adding post-drop binding assertions to lock in fallback behavior.

A quick re-execution after dropping the binding would ensure cache gating reverts immediately when the hint source is removed.

🧪 Suggested additions
 drop binding for select * from t where a=1;
+execute st using `@a`;
+execute st using `@a`;
+select @@last_plan_from_binding, @@last_plan_from_cache;
 set tidb_plan_cache_strategy = default;
 drop binding for select * from t where a=1;
+select * from t where a = 1;
+select * from t where a = 1;
+select @@last_plan_from_binding, @@last_plan_from_cache;
 set tidb_enable_non_prepared_plan_cache = default;
 set tidb_plan_cache_strategy = default;

Also applies to: 1751-1753

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/integrationtest/t/planner/core/plan_cache.test` around lines 1735 -
1736, After the "drop binding for select * from t where a=1;" and "set
tidb_plan_cache_strategy = default;" statements, re-run the same query ("select
* from t where a=1") and add assertions that verify the binding no longer gates
the plan/cache (e.g., assert the plan fingerprint or that the plan_cache does
not contain the binding and the execution uses the default strategy), ensuring
the test immediately observes fallback behavior; apply the same post-drop
re-execution and assertions at the other occurrence around the 1751-1753 block.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/planner/core/plan_cache_utils.go`:
- Around line 315-330: The helper newPlanCacheKeyWithMatchedBinding conflates
"should attempt rematch" with the "bindingMatched result" via the bindingMatched
parameter, causing misuse and duplicate matching; change the function signature
to accept two distinct booleans (e.g., rematch bool and bindingMatched bool or
preMatched bool and doRematch bool), update the internal logic to only call
bindinfo.MatchSQLBindingWithCache when the rematch/doRematch flag is true, and
treat bindingMatched strictly as the match-result to decide setting binding =
matchedBinding.BindSQL; then propagate this new signature to all callers
(including the wrapper newPlanCacheKey) and update their call sites to pass the
appropriate rematch flag versus the prior match-result so rematching behavior is
explicit and no duplicate matching occurs.

In `@pkg/planner/core/plan_cache.go`:
- Around line 63-73: The new helper
containUsePlanCacheHintInPreparedSQLOrBinding and planCacheHintOnlyNoHintReason
duplicate the same "hint_only" predicate used in the non-prepared path; extract
that predicate and its reason string into a single shared helper (e.g., Move or
create a centralized function like
IsUsePlanCacheAllowedOrReason/GetUsePlanCacheHintReason) and replace the local
planCacheHintOnlyNoHintReason and containUsePlanCacheHintInPreparedSQLOrBinding
with calls to that shared helper from both this file and the code in
optimize.go; ensure the shared helper accepts a PlanCacheStmt, bindinfo.Binding,
and bindingMatched bool and returns the boolean (and/or reason string) so both
prepared and non-prepared entry points use the exact same logic.

In `@pkg/util/hint/hint_processor.go`:
- Line 132: The exported function ContainTableHintInStmtNode should normalize
the incoming hintName at the API boundary because HintName.L is stored
lowercase; update ContainTableHintInStmtNode to canonicalize hintName (e.g., to
lower-case or the same normalization used by HintName.L) before any comparisons
so callers passing different-cased strings still match reliably.

In `@tests/integrationtest/r/planner/core/plan_cache.result`:
- Around line 2737-2738: After the "drop binding for select * from t where a=1;"
step, run one more execute/select of the same statement to validate the
transition before changing plan cache strategy back to default; specifically,
insert an extra "select * from t where a=1;" (or the matching prepared execute)
between the "drop binding for select * from t where a=1;" and "set
tidb_plan_cache_strategy = default;" lines. Do the same fix for the analogous
block around the "drop binding" at the 2763-2765 area so each drop is followed
by one more execute/select before resetting tidb_plan_cache_strategy.

In `@tests/integrationtest/t/planner/core/plan_cache.test`:
- Around line 1735-1736: After the "drop binding for select * from t where a=1;"
and "set tidb_plan_cache_strategy = default;" statements, re-run the same query
("select * from t where a=1") and add assertions that verify the binding no
longer gates the plan/cache (e.g., assert the plan fingerprint or that the
plan_cache does not contain the binding and the execution uses the default
strategy), ensuring the test immediately observes fallback behavior; apply the
same post-drop re-execution and assertions at the other occurrence around the
1751-1753 block.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2047313c-f69c-4612-a680-3f3b9c1befce

📥 Commits

Reviewing files that changed from the base of the PR and between d66a662 and 17f7912.

📒 Files selected for processing (11)
  • pkg/parser/ast/misc.go
  • pkg/planner/core/plan_cache.go
  • pkg/planner/core/plan_cache_utils.go
  • pkg/planner/optimize.go
  • pkg/sessionctx/vardef/tidb_vars.go
  • pkg/sessionctx/variable/session.go
  • pkg/sessionctx/variable/sysvar.go
  • pkg/util/hint/hint.go
  • pkg/util/hint/hint_processor.go
  • tests/integrationtest/r/planner/core/plan_cache.result
  • tests/integrationtest/t/planner/core/plan_cache.test

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 2, 2026

Codecov Report

❌ Patch coverage is 89.53488% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 77.8731%. Comparing base (90dda82) to head (cf6eb6e).
⚠️ Report is 13 commits behind head on master.

Additional details and impacted files
@@               Coverage Diff                @@
##             master     #67535        +/-   ##
================================================
+ Coverage   77.5423%   77.8731%   +0.3307%     
================================================
  Files          1962       1965         +3     
  Lines        544528     551311      +6783     
================================================
+ Hits         422240     429323      +7083     
- Misses       121478     121966       +488     
+ Partials        810         22       -788     
Flag Coverage Δ
integration 41.4046% <85.7142%> (+7.0648%) ⬆️
unit 77.1070% <59.3023%> (+0.7245%) ⬆️

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

Components Coverage Δ
dumpling 61.5065% <ø> (ø)
parser ∅ <ø> (∅)
br 50.4079% <ø> (-8.9804%) ⬇️
🚀 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.

@qw4990
Copy link
Copy Markdown
Contributor Author

qw4990 commented Apr 3, 2026

/test unit-test

@tiprow
Copy link
Copy Markdown

tiprow Bot commented Apr 3, 2026

@qw4990: PRs from untrusted users cannot be marked as trusted with /ok-to-test in this repo meaning untrusted PR authors can never trigger tests themselves. Collaborators can still trigger tests on the PR using /test.

Details

In response to this:

/test unit-test

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@qw4990
Copy link
Copy Markdown
Contributor Author

qw4990 commented Apr 3, 2026

/ok-to-test

@ti-chi-bot ti-chi-bot Bot added the ok-to-test Indicates a PR is ready to be tested. label Apr 3, 2026
@qw4990
Copy link
Copy Markdown
Contributor Author

qw4990 commented Apr 3, 2026

/retest

1 similar comment
@hawkingrei
Copy link
Copy Markdown
Member

/retest

@ti-chi-bot ti-chi-bot Bot added the needs-1-more-lgtm Indicates a PR needs 1 more LGTM. label Apr 3, 2026
Comment thread pkg/planner/optimize.go
if sctx.GetSessionVars().PlanCacheStrategy == vardef.TiDBPlanCacheStrategyHintOnly &&
!containUsePlanCacheHintInSQLOrBinding(sctx, stmt) {
if !isExplain && stmtCtx.InExplainStmt && stmtCtx.ExplainFormat == types.ExplainFormatPlanCache {
stmtCtx.AppendWarning(errors.NewNoStackErrorf("skip non-prepared plan-cache: %s", nonPreparedPlanCacheHintOnlyNoHintReason))
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.

can we add warning test about this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sure, the new test case has been added:
image

Copy link
Copy Markdown
Contributor

@AilinKid AilinKid left a comment

Choose a reason for hiding this comment

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

rest LGTM

}
if cacheEnabled && stmt.UncacheableReason == "" &&
sessVars.PlanCacheStrategy == vardef.TiDBPlanCacheStrategyHintOnly &&
!stmt.HasUsePlanCacheHint {
Copy link
Copy Markdown
Contributor

@AilinKid AilinKid Apr 3, 2026

Choose a reason for hiding this comment

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

!stmt.HasUsePlanCacheHint may overlap with !containUsePlanCacheHintInPreparedSQLOrBinding check below?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No, stmt.HasUsePlanCacheHint is from the statement directly, but containUsePlanCacheHintInPreparedSQLOrBinding is from the binding.

prepare st1 from "select /*+ use_plan_cache() */ * from t1";
prepare st2 from "select * from t2";
create global binding using select /*+ use_plan_cache() */ * from t2

In the case above, st1.HasUsePlanCacheHint is true, but st2.HashUsePlanCacheHint is false, st2 has to get the use_plan_cache from binding, which is what containUsePlanCacheHintInPreparedSQLOrBinding for.

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.

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

66-74: Consider centralizing the use_plan_cache() detection.

This file now has its own binding-aware hint_only check, while the non-prepared path enforces the same rule in pkg/planner/optimize.go. Moving that logic behind one helper would make it easier to keep the prepared and non-prepared cache paths in sync as hint sources evolve.

As per coding guidelines, "Code SHOULD remain maintainable for future readers with basic TiDB familiarity, including readers who are not experts in the specific subsystem/feature."

Also applies to: 226-236

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/planner/core/plan_cache.go` around lines 66 - 74, Extract the duplicated
detection logic into a single helper function (e.g., IsUsePlanCacheHintPresent)
that accepts the prepared statement (PlanCacheStmt), optional bindinfo.Binding
and bindingMatched flag and returns whether use_plan_cache() is present from
either stmt.HasUsePlanCacheHint or the matchedBinding.Hint. Replace the body of
containUsePlanCacheHintInPreparedSQLOrBinding and the corresponding check in
pkg/planner/optimize.go (and the other occurrence at lines ~226-236) to call
this new helper so both prepared and non-prepared code paths share the same
source of truth and preserve current semantics (null checks and
Hint.ContainTableHint(hint.HintUsePlanCache)). Ensure the helper is placed in a
package accessible to both call sites and keep parameter names and null-safety
consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/planner/core/plan_cache.go`:
- Around line 66-74: Extract the duplicated detection logic into a single helper
function (e.g., IsUsePlanCacheHintPresent) that accepts the prepared statement
(PlanCacheStmt), optional bindinfo.Binding and bindingMatched flag and returns
whether use_plan_cache() is present from either stmt.HasUsePlanCacheHint or the
matchedBinding.Hint. Replace the body of
containUsePlanCacheHintInPreparedSQLOrBinding and the corresponding check in
pkg/planner/optimize.go (and the other occurrence at lines ~226-236) to call
this new helper so both prepared and non-prepared code paths share the same
source of truth and preserve current semantics (null checks and
Hint.ContainTableHint(hint.HintUsePlanCache)). Ensure the helper is placed in a
package accessible to both call sites and keep parameter names and null-safety
consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 9bc5b9ff-5a66-4032-863c-fc53a3a2c279

📥 Commits

Reviewing files that changed from the base of the PR and between 17f7912 and cf6eb6e.

📒 Files selected for processing (4)
  • pkg/planner/core/plan_cache.go
  • pkg/planner/optimize.go
  • tests/integrationtest/r/planner/core/plan_cache.result
  • tests/integrationtest/t/planner/core/plan_cache.test
✅ Files skipped from review due to trivial changes (2)
  • pkg/planner/optimize.go
  • tests/integrationtest/t/planner/core/plan_cache.test
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/integrationtest/r/planner/core/plan_cache.result

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

ti-chi-bot Bot commented Apr 7, 2026

[LGTM Timeline notifier]

Timeline:

  • 2026-04-03 10:11:55.079926331 +0000 UTC m=+519120.285286387: ☑️ agreed by hawkingrei.
  • 2026-04-07 13:39:23.115656658 +0000 UTC m=+877168.321016715: ☑️ agreed by AilinKid.

@qw4990
Copy link
Copy Markdown
Contributor Author

qw4990 commented Apr 7, 2026

/retest

1 similar comment
@qw4990
Copy link
Copy Markdown
Contributor Author

qw4990 commented Apr 7, 2026

/retest

@qw4990
Copy link
Copy Markdown
Contributor Author

qw4990 commented Apr 7, 2026

/retest

2 similar comments
@hawkingrei
Copy link
Copy Markdown
Member

/retest

@hawkingrei
Copy link
Copy Markdown
Member

/retest

@hawkingrei
Copy link
Copy Markdown
Member

/retest

1 similar comment
@hawkingrei
Copy link
Copy Markdown
Member

/retest

Copy link
Copy Markdown
Contributor

@D3Hunter D3Hunter left a comment

Choose a reason for hiding this comment

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

/approve

@ti-chi-bot
Copy link
Copy Markdown

ti-chi-bot Bot commented Apr 8, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: AilinKid, D3Hunter, hawkingrei, terry1purcell

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 the approved label Apr 8, 2026
@qw4990
Copy link
Copy Markdown
Contributor Author

qw4990 commented Apr 8, 2026

/retest

2 similar comments
@hawkingrei
Copy link
Copy Markdown
Member

/retest

@hawkingrei
Copy link
Copy Markdown
Member

/retest

@qw4990
Copy link
Copy Markdown
Contributor Author

qw4990 commented Apr 8, 2026

/test pull-unit-test-next-gen

@tiprow
Copy link
Copy Markdown

tiprow Bot commented Apr 8, 2026

@qw4990: The specified target(s) for /test were not found.
The following commands are available to trigger required jobs:

/test fast_test_tiprow
/test tidb_parser_test

Use /test all to run the following jobs that were automatically triggered:

tidb_parser_test
Details

In response to this:

/test pull-unit-test-next-gen

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@qw4990
Copy link
Copy Markdown
Contributor Author

qw4990 commented Apr 8, 2026

/test pull-integration-e2e-test

@tiprow
Copy link
Copy Markdown

tiprow Bot commented Apr 8, 2026

@qw4990: The specified target(s) for /test were not found.
The following commands are available to trigger required jobs:

/test fast_test_tiprow
/test tidb_parser_test

Use /test all to run the following jobs that were automatically triggered:

tidb_parser_test
Details

In response to this:

/test pull-integration-e2e-test

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@hawkingrei
Copy link
Copy Markdown
Member

/retest

5 similar comments
@hawkingrei
Copy link
Copy Markdown
Member

/retest

@hawkingrei
Copy link
Copy Markdown
Member

/retest

@hawkingrei
Copy link
Copy Markdown
Member

/retest

@hawkingrei
Copy link
Copy Markdown
Member

/retest

@hawkingrei
Copy link
Copy Markdown
Member

/retest

@ti-chi-bot ti-chi-bot Bot merged commit c245042 into pingcap:master Apr 8, 2026
35 checks passed
premal pushed a commit to premal/tidb that referenced this pull request Apr 30, 2026
@coderabbitai coderabbitai Bot mentioned this pull request May 9, 2026
13 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved lgtm ok-to-test Indicates a PR is ready to be tested. release-note-none Denotes a PR that doesn't merit a release note. sig/planner SIG: Planner size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

planner: white-list based Plan Cache strategy

5 participants