diff --git a/executor/executor_test.go b/executor/executor_test.go index d525eefe82622..99cf682d0de01 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -8453,3 +8453,29 @@ func (s *testSerialSuite) TestIssue30289(c *C) { err := tk.QueryToErr("select /*+ hash_join(t1) */ * from t t1 join t t2 on t1.a=t2.a") c.Assert(err.Error(), Matches, "issue30289 build return error") } + +func (s *testSerialSuite) TestIssue30971(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1, t2") + tk.MustExec("create table t1 (id int);") + tk.MustExec("create table t2 (id int, c int);") + + testCases := []struct { + sql string + fields int + }{ + // Fix a bug that the column length field returned to client is incorrect using MySQL prepare protocol. + {"select * from t1 union select 1 from t1", 1}, + {"select c from t2 union select * from t1", 1}, + {"select * from t1", 1}, + {"select * from t2 where c in (select * from t1)", 2}, + {"insert into t1 values (?)", 0}, + {"update t1 set id = ?", 0}, + } + for _, test := range testCases { + _, _, fields, err := tk.Se.PrepareStmt(test.sql) + c.Assert(err, IsNil) + c.Assert(fields, HasLen, test.fields) + } +} diff --git a/executor/prepared.go b/executor/prepared.go index 832252a82ec93..00e264d3e9ad6 100644 --- a/executor/prepared.go +++ b/executor/prepared.go @@ -204,7 +204,7 @@ func (e *PrepareExec) Next(ctx context.Context, req *chunk.Chunk) error { if err != nil { return err } - if _, ok := stmt.(*ast.SelectStmt); ok { + if p.Schema().Len() > 0 { e.Fields = colNames2ResultFields(p.Schema(), p.OutputNames(), vars.CurrentDB) } if e.ID == 0 {