diff --git a/pkg/planner/optimize.go b/pkg/planner/optimize.go index 733b6e80f0bc3..127819a3c322e 100644 --- a/pkg/planner/optimize.go +++ b/pkg/planner/optimize.go @@ -239,9 +239,6 @@ func Optimize(ctx context.Context, sctx sessionctx.Context, node *resolve.NodeW, return fp, fp.OutputNames(), nil } } - if err := pctx.AdviseTxnWarmup(); err != nil { - return nil, nil, err - } enableUseBinding := sessVars.UsePlanBaselines stmtNode, isStmtNode := node.Node.(ast.StmtNode) @@ -322,6 +319,11 @@ func Optimize(ctx context.Context, sctx sessionctx.Context, node *resolve.NodeW, hint.BindHint(stmtNode, originHints) } + // postpone Warmup because binding may change the behaviour, like pipelined DML + if err = pctx.AdviseTxnWarmup(); err != nil { + return nil, nil, err + } + if sessVars.StmtCtx.EnableOptimizerDebugTrace && bestPlanFromBind != nil { core.DebugTraceBestBinding(pctx, chosenBinding.Hint) } diff --git a/tests/realtikvtest/pipelineddmltest/pipelineddml_test.go b/tests/realtikvtest/pipelineddmltest/pipelineddml_test.go index 211b6e86db12c..45d48ef626e7c 100644 --- a/tests/realtikvtest/pipelineddmltest/pipelineddml_test.go +++ b/tests/realtikvtest/pipelineddmltest/pipelineddml_test.go @@ -218,15 +218,36 @@ func TestPipelinedDMLPositive(t *testing.T) { // enable by hint // Hint works for DELETE and UPDATE, but not for INSERT if the hint is in its select clause. tk.MustExec("set @@tidb_dml_type = standard") - err = panicToErr( - func() error { - _, err := tk.Exec("delete /*+ SET_VAR(tidb_dml_type=bulk) */ from t") - // "insert into t select /*+ SET_VAR(tidb_dml_type=bulk) */ * from t" won't work - return err - }, - ) - require.Error(t, err) - require.True(t, strings.Contains(err.Error(), "pipelined memdb is enabled"), err.Error()) + dmls := [][2]string{ + {"update t set b = b + 1", "update /*+ SET_VAR(tidb_dml_type=bulk) */ t set b = b + 1"}, + {"insert into t select * from t", "insert /*+ SET_VAR(tidb_dml_type=bulk) */ into t select * from t"}, + {"delete from t", "delete /*+ SET_VAR(tidb_dml_type=bulk) */ from t"}, + } + for _, dmlPair := range dmls { + err := panicToErr( + func() error { + _, err := tk.Exec(dmlPair[1]) + return err + }, + ) + require.Error(t, err) + require.True(t, strings.Contains(err.Error(), "pipelined memdb is enabled"), err.Error()) + } + + // test global binding + for _, dmlPair := range dmls { + tk.MustExec("create global binding for " + dmlPair[0] + " using " + dmlPair[1]) + } + for _, dmlPair := range dmls { + err := panicToErr( + func() error { + _, err := tk.Exec(dmlPair[0]) + return err + }, + ) + require.Error(t, err, dmlPair[0]) + require.True(t, strings.Contains(err.Error(), "pipelined memdb is enabled"), err.Error()) + } } func TestPipelinedDMLNegative(t *testing.T) {