diff --git a/executor/explain.go b/executor/explain.go index 2e12fd9d417b2..6747a130f2c26 100644 --- a/executor/explain.go +++ b/executor/explain.go @@ -71,6 +71,7 @@ func (e *ExplainExec) Next(ctx context.Context, req *chunk.Chunk) error { return nil } +<<<<<<< HEAD func (e *ExplainExec) generateExplainInfo(ctx context.Context) (rows [][]string, err error) { closed := false defer func() { @@ -80,28 +81,35 @@ func (e *ExplainExec) generateExplainInfo(ctx context.Context) (rows [][]string, } }() if e.analyzeExec != nil { +======= +func (e *ExplainExec) executeAnalyzeExec(ctx context.Context) (err error) { + if e.analyzeExec != nil && !e.executed { + defer func() { + err1 := e.analyzeExec.Close() + if err1 != nil { + if err != nil { + err = errors.New(err.Error() + ", " + err1.Error()) + } else { + err = err1 + } + } + }() + e.executed = true +>>>>>>> 875cf6dfb... executor: fix analyze update panic cause by duplicate call analyze executor Close method (#20390) chk := newFirstChunk(e.analyzeExec) - var nextErr, closeErr error for { - nextErr = Next(ctx, e.analyzeExec, chk) - if nextErr != nil || chk.NumRows() == 0 { + err = Next(ctx, e.analyzeExec, chk) + if err != nil || chk.NumRows() == 0 { break } } - closeErr = e.analyzeExec.Close() - closed = true - if nextErr != nil { - if closeErr != nil { - err = errors.New(nextErr.Error() + ", " + closeErr.Error()) - } else { - err = nextErr - } - } else if closeErr != nil { - err = closeErr - } - if err != nil { - return nil, err - } + } + return err +} + +func (e *ExplainExec) generateExplainInfo(ctx context.Context) (rows [][]string, err error) { + if err = e.executeAnalyzeExec(ctx); err != nil { + return nil, err } if err = e.explain.RenderResult(); err != nil { return nil, err diff --git a/executor/explain_test.go b/executor/explain_test.go index 57a3c5ed5d265..0965a0a9f9ee0 100644 --- a/executor/explain_test.go +++ b/executor/explain_test.go @@ -97,14 +97,15 @@ func (s *testSuite1) TestExplainWrite(c *C) { tk := testkit.NewTestKitWithInit(c, s.store) tk.MustExec("drop table if exists t") tk.MustExec("create table t (a int)") - tk.MustExec("explain analyze insert into t select 1") + tk.MustQuery("explain analyze insert into t select 1") tk.MustQuery("select * from t").Check(testkit.Rows("1")) - tk.MustExec("explain analyze update t set a=2 where a=1") + tk.MustQuery("explain analyze update t set a=2 where a=1") tk.MustQuery("select * from t").Check(testkit.Rows("2")) - tk.MustExec("explain insert into t select 1") + tk.MustQuery("explain insert into t select 1") tk.MustQuery("select * from t").Check(testkit.Rows("2")) - tk.MustExec("explain analyze insert into t select 1") - tk.MustQuery("select * from t order by a").Check(testkit.Rows("1", "2")) + tk.MustQuery("explain analyze insert into t select 1") + tk.MustQuery("explain analyze replace into t values (3)") + tk.MustQuery("select * from t order by a").Check(testkit.Rows("1", "2", "3")) } func (s *testSuite1) TestExplainAnalyzeMemory(c *C) { diff --git a/executor/explain_unit_test.go b/executor/explain_unit_test.go index fa9b13bc66e48..1276575f47c28 100644 --- a/executor/explain_unit_test.go +++ b/executor/explain_unit_test.go @@ -81,6 +81,10 @@ func TestExplainAnalyzeInvokeNextAndClose(t *testing.T) { t.Errorf(err.Error()) } // mockErrorOperator panic + explainExec = &ExplainExec{ + baseExecutor: baseExec, + explain: nil, + } mockOpr = mockErrorOperator{baseExec, true, false} explainExec.analyzeExec = &mockOpr defer func() {