docs/agents/planner/plan_cache_notes.md
NewPlanCacheKey is hot; avoid per-execution normalization/digest work.PlanCacheStmt.BindingInfo) for binding normalization.NormalizeStmtForBinding,
NormalizeDigestForBinding, and MatchSQLBinding under GetPlanFromPlanCache.pkg/planner/core/plan_cacheable_checker.go.IsASTCacheable -> cacheableChecker.NonPreparedPlanCacheableWithCtx ->
nonPreparedPlanCacheableChecker.checkTableCacheable.cacheableChecker performs AST traversal and short-circuits once
checker.cacheable becomes false.skipForSubqueryDisabled() is used by both *ast.ExistsSubqueryExpr and
*ast.SubqueryExpr to keep the subquery gating logic in one place.*ast.TableName nodes go through InfoSchema validation, partition pruning
mode checks, generated column checks, and temporary table checks.cteCanUsed stores CTE names visible in the current query block.withScopeOffset records CTE list boundaries for each SelectStmt that
has a WITH clause, and leaveWithScope() restores the outer scope.*ast.CommonTableExpression handling:
*ast.TableName with empty schema and name in cteCanUsed, skip
physical table lookup because the name refers to a CTE, not InfoSchema.pkg/planner/core/casetest/plancache/plan_cacheable_checker_test.go.CacheableWithCtx) for specific SQL shapes.@@last_plan_from_cache) for runtime effect.test.t1 instead of t1).make bazel_prepare before running tests.go test -count=1 -run TestCacheable -tags=intest,deadlock ./pkg/planner/core/casetest/plancachego test -count=1 -run TestPreparedPlanCacheWithCTE -tags=intest,deadlock ./pkg/planner/core/casetest/plancache