From a48dba4078623655ddfc2392765ca85bbc1ba660 Mon Sep 17 00:00:00 2001 From: AilinKid <314806019@qq.com> Date: Tue, 24 Mar 2026 22:37:31 +0800 Subject: [PATCH 1/2] . Signed-off-by: AilinKid <314806019@qq.com> --- .../casetest/correlated/correlated_test.go | 75 +++++++++++++++++++ pkg/planner/core/exhaust_physical_plans.go | 2 + .../core/operator/logicalop/logical_join.go | 5 ++ .../physicalop/physical_index_join.go | 5 ++ pkg/planner/core/rule_decorrelate.go | 4 + pkg/planner/core/task.go | 3 + pkg/planner/optimize.go | 58 +++++++++++--- pkg/sessionctx/stmtctx/stmtctx.go | 25 +++++++ pkg/sessionctx/vardef/tidb_vars.go | 6 ++ pkg/sessionctx/variable/session.go | 6 ++ pkg/sessionctx/variable/setvar_affect.go | 1 + pkg/sessionctx/variable/sysvar.go | 4 + pkg/sessionctx/variable/varsutil_test.go | 6 ++ 13 files changed, 191 insertions(+), 9 deletions(-) diff --git a/pkg/planner/core/casetest/correlated/correlated_test.go b/pkg/planner/core/casetest/correlated/correlated_test.go index 9a4e83c8a580f..34a9c4a249ec9 100644 --- a/pkg/planner/core/casetest/correlated/correlated_test.go +++ b/pkg/planner/core/casetest/correlated/correlated_test.go @@ -15,10 +15,14 @@ package correlated import ( + "fmt" + "strings" "testing" + "github.com/pingcap/failpoint" "github.com/pingcap/tidb/pkg/testkit" "github.com/pingcap/tidb/pkg/testkit/testdata" + "github.com/stretchr/testify/require" ) func TestCorrelatedSubquery(t *testing.T) { @@ -98,6 +102,68 @@ func TestNaturalJoinWithCorrelatedSubquery(tt *testing.T) { tk.MustQuery("explain format = 'plan_tree' " + sql).Check(testkit.Rows(output[i].Plan...)) tk.MustQuery(sql).Check(testkit.Rows(output[i].Result...)) } + + t.Run("AlternativeLogicalPlansChooseApply", func(t *testing.T) { + tk.MustExec("use test") + tk.MustExec("drop table if exists alt_pick_t1, alt_pick_t2, alt_pick_t3") + tk.MustExec("create table alt_pick_t1(a int primary key)") + tk.MustExec("create table alt_pick_t2(a int, b int, key idx_a(a))") + tk.MustExec("create table alt_pick_t3(a int, c int, key idx_a(a))") + tk.MustExec("insert into alt_pick_t1 values (1), (2)") + + vals2 := make([]string, 0, 200) + vals3 := make([]string, 0, 200) + for i := 0; i < 200; i++ { + vals2 = append(vals2, fmt.Sprintf("(%d, %d)", i%100, i)) + vals3 = append(vals3, fmt.Sprintf("(%d, %d)", i%100, i)) + } + tk.MustExec("insert into alt_pick_t2 values " + strings.Join(vals2, ",")) + tk.MustExec("insert into alt_pick_t3 values " + strings.Join(vals3, ",")) + tk.MustExec("analyze table alt_pick_t1, alt_pick_t2, alt_pick_t3") + + tk.MustExec("set @@tidb_opt_enable_alternative_logical_plans=off") + sql := "select alt_pick_t1.a, (select count(*) from alt_pick_t2 join alt_pick_t3 on alt_pick_t2.a = alt_pick_t3.a where alt_pick_t2.a = alt_pick_t1.a) as cnt from alt_pick_t1 order by alt_pick_t1.a" + explainSQL := "explain format = 'brief' " + sql + + offPlan := testdata.ConvertRowsToStrings(tk.MustQuery(explainSQL).Rows()) + tk.MustQuery(sql).Check(testkit.Rows("1 4", "2 4")) + require.False(t, planContainsText(offPlan, "Apply"), strings.Join(offPlan, "\n")) + + tk.MustExec("set @@tidb_opt_enable_alternative_logical_plans=on") + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/pkg/planner/failIfAlternativeLogicalPlanRoundTriggered", fmt.Sprintf("return(%q)", sql))) + err := tk.ExecToErr(sql) + stmtCtx := tk.Session().GetSessionVars().StmtCtx + require.True(t, stmtCtx.AlternativeLogicalPlanDecorrelatedApply) + require.False(t, stmtCtx.AlternativeLogicalPlanSameOrderIndexJoin) + require.ErrorContains(t, err, "unexpected alternative logical plan round") + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/pkg/planner/failIfAlternativeLogicalPlanRoundTriggered")) + + onPlan := testdata.ConvertRowsToStrings(tk.MustQuery(explainSQL).Rows()) + tk.MustQuery(sql).Check(testkit.Rows("1 4", "2 4")) + require.True(t, planContainsText(onPlan, "Apply"), strings.Join(onPlan, "\n")) + }) + + t.Run("AlternativeLogicalPlansSkipSecondRoundWhenIndexJoinExists", func(t *testing.T) { + tk.MustExec("use test") + tk.MustExec("set @@tidb_opt_enable_alternative_logical_plans=on") + tk.MustExec("drop table if exists alt_skip_t1, alt_skip_t2") + tk.MustExec("create table alt_skip_t1(a int primary key)") + tk.MustExec("create table alt_skip_t2(a int, b int, key idx_a(a))") + tk.MustExec("insert into alt_skip_t1 values (1), (2), (3)") + tk.MustExec("insert into alt_skip_t2 values (1, 1), (1, 2), (2, 3), (3, 4)") + tk.MustExec("analyze table alt_skip_t1, alt_skip_t2") + + sql := "select alt_skip_t1.a from alt_skip_t1 where exists (select 1 from alt_skip_t2 where alt_skip_t2.a = alt_skip_t1.a and alt_skip_t2.b > 0) order by alt_skip_t1.a" + require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/pkg/planner/failIfAlternativeLogicalPlanRoundTriggered", fmt.Sprintf("return(%q)", sql))) + defer func() { + require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/pkg/planner/failIfAlternativeLogicalPlanRoundTriggered")) + }() + + require.NoError(t, tk.QueryToErr(sql)) + stmtCtx := tk.Session().GetSessionVars().StmtCtx + require.True(t, stmtCtx.AlternativeLogicalPlanDecorrelatedApply) + require.True(t, stmtCtx.AlternativeLogicalPlanSameOrderIndexJoin) + }) }) } @@ -114,3 +180,12 @@ func TestWrongDecorrelate(t *testing.T) { " 30025.20000000000000000000 60121022342", "X 6.23000000000000000000 60021022342")) } + +func planContainsText(plan []string, needle string) bool { + for _, row := range plan { + if strings.Contains(row, needle) { + return true + } + } + return false +} diff --git a/pkg/planner/core/exhaust_physical_plans.go b/pkg/planner/core/exhaust_physical_plans.go index 7522c21c05b29..2d384acdae372 100644 --- a/pkg/planner/core/exhaust_physical_plans.go +++ b/pkg/planner/core/exhaust_physical_plans.go @@ -353,6 +353,8 @@ func constructIndexJoinStatic( // for static enumeration here, we just pass down the original equal condition for condition adjustment rather // depend on the original logical join node. EqualConditions: p.EqualConditions, + // Only count candidates that keep the original Apply outer/inner order. + FromDecorrelatedApply: p.FromDecorrelatedApply && outerIdx == 0, }.Init(p.SCtx(), p.StatsInfo().ScaleByExpectCnt(p.SCtx().GetSessionVars(), prop.ExpectedCnt), p.QueryBlockOffset(), chReqProps...) join.SetSchema(p.Schema()) return []base.PhysicalPlan{join} diff --git a/pkg/planner/core/operator/logicalop/logical_join.go b/pkg/planner/core/operator/logicalop/logical_join.go index 3c2fceb44f503..2303742dedb92 100644 --- a/pkg/planner/core/operator/logicalop/logical_join.go +++ b/pkg/planner/core/operator/logicalop/logical_join.go @@ -100,6 +100,11 @@ type LogicalJoin struct { // allJoinLeaf is used to identify the table where the column is located during constant propagation. allJoinLeaf []*expression.Schema + + // FromDecorrelatedApply marks joins that come from decorrelating an Apply in the + // first logical round. It is only used to decide whether an equivalent same-order + // PhysicalIndexJoin candidate has already been generated. + FromDecorrelatedApply bool } // Init initializes LogicalJoin. diff --git a/pkg/planner/core/operator/physicalop/physical_index_join.go b/pkg/planner/core/operator/physicalop/physical_index_join.go index f87ae0d99d22d..d878360c28e9c 100644 --- a/pkg/planner/core/operator/physicalop/physical_index_join.go +++ b/pkg/planner/core/operator/physicalop/physical_index_join.go @@ -66,6 +66,10 @@ type PhysicalIndexJoin struct { InnerHashKeys []*expression.Column // EqualConditions stores the equal conditions for logical join's original EqualConditions. EqualConditions []*expression.ScalarFunction `plan-cache-clone:"shallow"` + + // FromDecorrelatedApply is true only when this IndexJoin keeps the original + // Apply outer/inner order after decorrelation. + FromDecorrelatedApply bool } // Init initializes PhysicalIndexJoin. @@ -99,6 +103,7 @@ func (p *PhysicalIndexJoin) Clone(newCtx base.PlanContext) (base.PhysicalPlan, e cloned.CompareFilters = p.CompareFilters.cloneForPlanCache() cloned.OuterHashKeys = util.CloneCols(p.OuterHashKeys) cloned.InnerHashKeys = util.CloneCols(p.InnerHashKeys) + cloned.FromDecorrelatedApply = p.FromDecorrelatedApply return cloned, nil } diff --git a/pkg/planner/core/rule_decorrelate.go b/pkg/planner/core/rule_decorrelate.go index fbbfe0b6554b8..cd12a00585def 100644 --- a/pkg/planner/core/rule_decorrelate.go +++ b/pkg/planner/core/rule_decorrelate.go @@ -233,6 +233,10 @@ func (s *DecorrelateSolver) optimize(ctx context.Context, p base.LogicalPlan, gr join := &apply.LogicalJoin join.SetSelf(join) join.SetTP(plancodec.TypeJoin) + if p.SCtx().GetSessionVars().EnableAlternativeLogicalPlans { + p.SCtx().GetSessionVars().StmtCtx.MarkAlternativeLogicalPlanDecorrelatedApply() + join.FromDecorrelatedApply = true + } p = join } else if apply.NoDecorrelate { goto NoOptimize diff --git a/pkg/planner/core/task.go b/pkg/planner/core/task.go index 054c661a502c8..1c531d91a4d2f 100644 --- a/pkg/planner/core/task.go +++ b/pkg/planner/core/task.go @@ -175,6 +175,9 @@ func indexJoinAttach2Task(p *physicalop.PhysicalIndexJoin, tasks ...base.Task) b outerTask := tasks[1-p.InnerChildIdx].ConvertToRootTask(p.SCtx()) innerTask := tasks[p.InnerChildIdx].ConvertToRootTask(p.SCtx()) completePhysicalIndexJoin(p, innerTask.(*physicalop.RootTask), innerTask.Plan().Schema(), outerTask.Plan().Schema(), true) + if p.FromDecorrelatedApply { + p.SCtx().GetSessionVars().StmtCtx.MarkAlternativeLogicalPlanSameOrderIndexJoin() + } if p.InnerChildIdx == 1 { p.SetChildren(outerTask.Plan(), innerTask.Plan()) } else { diff --git a/pkg/planner/optimize.go b/pkg/planner/optimize.go index 816c5d82deb0d..f06c1cd25af71 100644 --- a/pkg/planner/optimize.go +++ b/pkg/planner/optimize.go @@ -33,6 +33,7 @@ import ( "github.com/pingcap/tidb/pkg/planner/core" "github.com/pingcap/tidb/pkg/planner/core/base" "github.com/pingcap/tidb/pkg/planner/core/resolve" + "github.com/pingcap/tidb/pkg/planner/core/rule" "github.com/pingcap/tidb/pkg/planner/indexadvisor" "github.com/pingcap/tidb/pkg/planner/planctx" "github.com/pingcap/tidb/pkg/planner/property" @@ -478,6 +479,7 @@ func buildAndOptimizeLogicalPlanRound( bestNames *types.NameSlice, bestCost *float64, bestLogicalPlanCtx *logicalPlanBuildCtx, + optFlagAdjust func(uint64) uint64, ) (base.Plan, types.NameSlice, bool, error) { builder := planBuilderPool.Get().(*core.PlanBuilder) defer planBuilderPool.Put(builder.ResetForReuse()) @@ -526,7 +528,11 @@ func buildAndOptimizeLogicalPlanRound( *optimizeStarted = true *beginOpt = time.Now() } - finalPlan, cost, err := core.DoOptimize(ctx, sctx, builder.GetOptFlag(), logic) + optFlag := builder.GetOptFlag() + if optFlagAdjust != nil { + optFlag = optFlagAdjust(optFlag) + } + finalPlan, cost, err := core.DoOptimize(ctx, sctx, optFlag, logic) if err != nil { return nil, nil, false, err } @@ -545,6 +551,12 @@ func buildAndOptimizeLogicalPlanRound( // optimizeCnt is a global variable only used for test. var optimizeCnt int +func shouldTryAlternativeLogicalPlanRound(sessVars *variable.SessionVars) bool { + return sessVars.EnableAlternativeLogicalPlans && + sessVars.StmtCtx.AlternativeLogicalPlanDecorrelatedApply && + !sessVars.StmtCtx.AlternativeLogicalPlanSameOrderIndexJoin +} + func optimize(ctx context.Context, sctx planctx.PlanContext, node *resolve.NodeW, is infoschema.InfoSchema) (base.Plan, types.NameSlice, float64, error) { failpoint.Inject("checkOptimizeCountOne", func(val failpoint.Value) { // only count the optimization for SQL with specified text @@ -577,8 +589,7 @@ func optimize(ctx context.Context, sctx planctx.PlanContext, node *resolve.NodeW // build multi logical plan from raw AST. var ( - buildRound = 1 - needRestoreLogicalPlanCtx = buildRound > 1 + needRestoreLogicalPlanCtx = sessVars.EnableAlternativeLogicalPlans bestCost = math.MaxFloat64 bestPlan base.PhysicalPlan bestNames types.NameSlice @@ -588,13 +599,42 @@ func optimize(ctx context.Context, sctx planctx.PlanContext, node *resolve.NodeW var initialLogicalPlanCtx logicalPlanBuildCtx if needRestoreLogicalPlanCtx { initialLogicalPlanCtx = saveLogicalPlanBuildCtx(sessVars) + sessVars.StmtCtx.ResetAlternativeLogicalPlanSignals() } - for i := range buildRound { - if needRestoreLogicalPlanCtx && i > 0 { - restoreLogicalPlanBuildCtx(sessVars, initialLogicalPlanCtx) - } - p, names, nonLogical, err := buildAndOptimizeLogicalPlanRound( + p, names, nonLogical, err := buildAndOptimizeLogicalPlanRound( + ctx, + sctx, + node, + is, + hintProcessor, + &checked, + &optimizeStarted, + &beginOpt, + needRestoreLogicalPlanCtx, + &bestPlan, + &bestNames, + &bestCost, + &bestLogicalPlanCtx, + nil, + ) + if err != nil { + return nil, nil, 0, err + } + if nonLogical { + // keep compatible with the old. + return p, names, 0, nil + } + + if shouldTryAlternativeLogicalPlanRound(sessVars) { + restoreLogicalPlanBuildCtx(sessVars, initialLogicalPlanCtx) + failpoint.Inject("failIfAlternativeLogicalPlanRoundTriggered", func(val failpoint.Value) { + if testSQL, ok := val.(string); ok && testSQL == node.Node.OriginalText() { + failpoint.Return(nil, nil, 0, errors.New("unexpected alternative logical plan round")) + } + }) + + p, names, nonLogical, err = buildAndOptimizeLogicalPlanRound( ctx, sctx, node, @@ -608,12 +648,12 @@ func optimize(ctx context.Context, sctx planctx.PlanContext, node *resolve.NodeW &bestNames, &bestCost, &bestLogicalPlanCtx, + func(flag uint64) uint64 { return flag &^ rule.FlagDecorrelate }, ) if err != nil { return nil, nil, 0, err } if nonLogical { - // keep compatible with the old. return p, names, 0, nil } } diff --git a/pkg/sessionctx/stmtctx/stmtctx.go b/pkg/sessionctx/stmtctx/stmtctx.go index 1fa7b5211329a..1284eddc81ea0 100644 --- a/pkg/sessionctx/stmtctx/stmtctx.go +++ b/pkg/sessionctx/stmtctx/stmtctx.go @@ -472,6 +472,12 @@ type StatementContext struct { UseDynamicPruneMode bool // ColRefFromPlan mark the column ref used by assignment in update statement. ColRefFromUpdatePlan intset.FastIntSet + // AlternativeLogicalPlanDecorrelatedApply indicates whether the current logical + // optimization round decorrelated at least one Apply into Join. + AlternativeLogicalPlanDecorrelatedApply bool + // AlternativeLogicalPlanSameOrderIndexJoin indicates whether the current first + // round already produced a same-order index join candidate for a decorrelated Apply. + AlternativeLogicalPlanSameOrderIndexJoin bool // IsExplainAnalyzeDML is true if the statement is "explain analyze DML executors", before responding the explain // results to the client, the transaction should be committed first. See issue #37373 for more details. @@ -646,6 +652,25 @@ func (sc *StatementContext) RestoreLogicalPlanBuildState(state LogicalPlanBuildS sc.RangeFallbackHandler = contextutil.NewRangeFallbackHandler(&sc.PlanCacheTracker, sc) } +// ResetAlternativeLogicalPlanSignals clears the statement-local signals used by the +// alternative logical plan feature. +func (sc *StatementContext) ResetAlternativeLogicalPlanSignals() { + sc.AlternativeLogicalPlanDecorrelatedApply = false + sc.AlternativeLogicalPlanSameOrderIndexJoin = false +} + +// MarkAlternativeLogicalPlanDecorrelatedApply records that at least one Apply has +// been decorrelated into a Join in the current round. +func (sc *StatementContext) MarkAlternativeLogicalPlanDecorrelatedApply() { + sc.AlternativeLogicalPlanDecorrelatedApply = true +} + +// MarkAlternativeLogicalPlanSameOrderIndexJoin records that the current first round +// has already produced a same-order index join candidate for a decorrelated Apply. +func (sc *StatementContext) MarkAlternativeLogicalPlanSameOrderIndexJoin() { + sc.AlternativeLogicalPlanSameOrderIndexJoin = true +} + // CtxID returns the context id of the statement func (sc *StatementContext) CtxID() uint64 { return sc.ctxID diff --git a/pkg/sessionctx/vardef/tidb_vars.go b/pkg/sessionctx/vardef/tidb_vars.go index a043652f35288..c3911f0eec06c 100644 --- a/pkg/sessionctx/vardef/tidb_vars.go +++ b/pkg/sessionctx/vardef/tidb_vars.go @@ -334,6 +334,11 @@ const ( // TiDBOptEnableNoDecorrelateInSelect is used to control whether to enable the NO_DECORRELATE hint for subqueries in the select list. TiDBOptEnableNoDecorrelateInSelect = "tidb_opt_enable_no_decorrelate_in_select" + // TiDBOptEnableAlternativeLogicalPlans controls whether the optimizer may build + // an extra non-decorrelate logical alternative when decorrelation does not + // produce an equivalent same-order index join candidate. + TiDBOptEnableAlternativeLogicalPlans = "tidb_opt_enable_alternative_logical_plans" + // TiDBEnableSemiJoinRewrite controls automatic rewrite of semi-join to // inner-join with aggregation (equivalent to SEMI_JOIN_REWRITE() hint). TiDBOptEnableSemiJoinRewrite = "tidb_opt_enable_semi_join_rewrite" @@ -1456,6 +1461,7 @@ const ( DefOptInSubqToJoinAndAgg = true DefOptPreferRangeScan = true DefOptEnableNoDecorrelateInSelect = false + DefOptEnableAlternativeLogicalPlans = false DefOptEnableSemiJoinRewrite = false DefBatchInsert = false DefBatchDelete = false diff --git a/pkg/sessionctx/variable/session.go b/pkg/sessionctx/variable/session.go index 6123684863463..58462343b64e4 100644 --- a/pkg/sessionctx/variable/session.go +++ b/pkg/sessionctx/variable/session.go @@ -1209,6 +1209,11 @@ type SessionVars struct { // EnableNoDecorrelateInSelect enables the NO_DECORRELATE hint for subqueries in the select list. EnableNoDecorrelateInSelect bool + // EnableAlternativeLogicalPlans enables building an extra non-decorrelate + // logical alternative when decorrelation does not produce an equivalent + // same-order index join candidate. + EnableAlternativeLogicalPlans bool + // EnableSemiJoinRewrite enables the SEMI_JOIN_REWRITE hint for subqueries in the where clause. EnableSemiJoinRewrite bool @@ -2332,6 +2337,7 @@ func NewSessionVars(hctx HookContext) *SessionVars { CartesianJoinOrderThreshold: vardef.DefOptCartesianJoinOrderThreshold, EnableOuterJoinReorder: vardef.DefTiDBEnableOuterJoinReorder, EnableNoDecorrelateInSelect: vardef.DefOptEnableNoDecorrelateInSelect, + EnableAlternativeLogicalPlans: vardef.DefOptEnableAlternativeLogicalPlans, EnableSemiJoinRewrite: vardef.DefOptEnableSemiJoinRewrite, RetryLimit: vardef.DefTiDBRetryLimit, DisableTxnAutoRetry: vardef.DefTiDBDisableTxnAutoRetry, diff --git a/pkg/sessionctx/variable/setvar_affect.go b/pkg/sessionctx/variable/setvar_affect.go index 46b0771c0f501..258de00d355dd 100644 --- a/pkg/sessionctx/variable/setvar_affect.go +++ b/pkg/sessionctx/variable/setvar_affect.go @@ -121,6 +121,7 @@ var isHintUpdatableVerified = map[string]struct{}{ "mpp_version": {}, "tidb_enable_inl_join_inner_multi_pattern": {}, "tidb_opt_enable_no_decorrelate_in_select": {}, + "tidb_opt_enable_alternative_logical_plans": {}, "tidb_opt_enable_late_materialization": {}, "tidb_opt_ordering_index_selectivity_threshold": {}, "tidb_opt_ordering_index_selectivity_ratio": {}, diff --git a/pkg/sessionctx/variable/sysvar.go b/pkg/sessionctx/variable/sysvar.go index 9f8ef55e2f0fa..9fcbd02b98eba 100644 --- a/pkg/sessionctx/variable/sysvar.go +++ b/pkg/sessionctx/variable/sysvar.go @@ -2528,6 +2528,10 @@ var defaultSysVars = []*SysVar{ s.EnableNoDecorrelateInSelect = TiDBOptOn(val) return nil }}, + {Scope: vardef.ScopeGlobal | vardef.ScopeSession, Name: vardef.TiDBOptEnableAlternativeLogicalPlans, Value: BoolToOnOff(vardef.DefOptEnableAlternativeLogicalPlans), Type: vardef.TypeBool, SetSession: func(s *SessionVars, val string) error { + s.EnableAlternativeLogicalPlans = TiDBOptOn(val) + return nil + }}, {Scope: vardef.ScopeGlobal | vardef.ScopeSession, Name: vardef.TiDBEnableStrictDoubleTypeCheck, Value: BoolToOnOff(vardef.DefEnableStrictDoubleTypeCheck), Type: vardef.TypeBool, SetSession: func(s *SessionVars, val string) error { s.EnableStrictDoubleTypeCheck = TiDBOptOn(val) return nil diff --git a/pkg/sessionctx/variable/varsutil_test.go b/pkg/sessionctx/variable/varsutil_test.go index a88a70789461b..16616e04174b1 100644 --- a/pkg/sessionctx/variable/varsutil_test.go +++ b/pkg/sessionctx/variable/varsutil_test.go @@ -91,6 +91,7 @@ func TestNewSessionVars(t *testing.T) { require.Equal(t, vardef.DefTiDBAnalyzeVersion, vars.AnalyzeVersion) require.Equal(t, vardef.DefCTEMaxRecursionDepth, vars.CTEMaxRecursionDepth) require.Equal(t, int64(vardef.DefTiDBTmpTableMaxSize), vars.TMPTableSize) + require.Equal(t, vardef.DefOptEnableAlternativeLogicalPlans, vars.EnableAlternativeLogicalPlans) assertFieldsGreaterThanZero(t, reflect.ValueOf(vars.MemQuota)) assertFieldsGreaterThanZero(t, reflect.ValueOf(vars.BatchSize)) @@ -210,6 +211,11 @@ func TestVarsutil(t *testing.T) { require.NoError(t, err) require.True(t, v.BatchInsert) + require.False(t, v.EnableAlternativeLogicalPlans) + err = v.SetSystemVar(vardef.TiDBOptEnableAlternativeLogicalPlans, "1") + require.NoError(t, err) + require.True(t, v.EnableAlternativeLogicalPlans) + require.Equal(t, 32, v.InitChunkSize) require.Equal(t, 1024, v.MaxChunkSize) err = v.SetSystemVar(vardef.TiDBMaxChunkSize, "2") From ae951e23ddd667ba4943c35752b2157834edae54 Mon Sep 17 00:00:00 2001 From: AilinKid <15825830+AilinKid@users.noreply.github.com> Date: Tue, 24 Mar 2026 14:42:49 +0000 Subject: [PATCH 2/2] chore: update bazel file --- pkg/planner/BUILD.bazel | 1 + pkg/planner/core/casetest/correlated/BUILD.bazel | 2 ++ 2 files changed, 3 insertions(+) diff --git a/pkg/planner/BUILD.bazel b/pkg/planner/BUILD.bazel index a9f1721d0a552..5a9830db679bc 100644 --- a/pkg/planner/BUILD.bazel +++ b/pkg/planner/BUILD.bazel @@ -14,6 +14,7 @@ go_library( "//pkg/planner/core", "//pkg/planner/core/base", "//pkg/planner/core/resolve", + "//pkg/planner/core/rule", "//pkg/planner/indexadvisor", "//pkg/planner/planctx", "//pkg/planner/property", diff --git a/pkg/planner/core/casetest/correlated/BUILD.bazel b/pkg/planner/core/casetest/correlated/BUILD.bazel index 06a1110e01407..06feeb196dc38 100644 --- a/pkg/planner/core/casetest/correlated/BUILD.bazel +++ b/pkg/planner/core/casetest/correlated/BUILD.bazel @@ -15,6 +15,8 @@ go_test( "//pkg/testkit/testdata", "//pkg/testkit/testmain", "//pkg/testkit/testsetup", + "@com_github_pingcap_failpoint//:failpoint", + "@com_github_stretchr_testify//require", "@org_uber_go_goleak//:goleak", ], )