executor: HashJoinExec checks the buildError even if the probeSide is empty (#30471)
This commit is contained in:
@ -9487,3 +9487,17 @@ func (s *testSerialSuite) TestIssue28650(c *C) {
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *testSerialSuite) TestIssue30289(c *C) {
|
||||
tk := testkit.NewTestKit(c, s.store)
|
||||
tk.MustExec("use test")
|
||||
fpName := "github.com/pingcap/tidb/executor/issue30289"
|
||||
c.Assert(failpoint.Enable(fpName, `return(true)`), IsNil)
|
||||
defer func() {
|
||||
c.Assert(failpoint.Disable(fpName), IsNil)
|
||||
}()
|
||||
tk.MustExec("drop table if exists t")
|
||||
tk.MustExec("create table t(a int)")
|
||||
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")
|
||||
}
|
||||
|
||||
@ -214,9 +214,13 @@ func (e *HashJoinExec) fetchProbeSideChunks(ctx context.Context) {
|
||||
return
|
||||
}
|
||||
if !hasWaitedForBuild {
|
||||
failpoint.Inject("issue30289", func(val failpoint.Value) {
|
||||
if val.(bool) {
|
||||
probeSideResult.Reset()
|
||||
}
|
||||
})
|
||||
if probeSideResult.NumRows() == 0 && !e.useOuterToBuild {
|
||||
e.finished.Store(true)
|
||||
return
|
||||
}
|
||||
emptyBuild, buildErr := e.wait4BuildSide()
|
||||
if buildErr != nil {
|
||||
@ -258,6 +262,13 @@ func (e *HashJoinExec) wait4BuildSide() (emptyBuild bool, err error) {
|
||||
func (e *HashJoinExec) fetchBuildSideRows(ctx context.Context, chkCh chan<- *chunk.Chunk, doneCh <-chan struct{}) {
|
||||
defer close(chkCh)
|
||||
var err error
|
||||
failpoint.Inject("issue30289", func(val failpoint.Value) {
|
||||
if val.(bool) {
|
||||
err = errors.Errorf("issue30289 build return error")
|
||||
e.buildFinished <- errors.Trace(err)
|
||||
return
|
||||
}
|
||||
})
|
||||
for {
|
||||
if e.finished.Load().(bool) {
|
||||
return
|
||||
|
||||
@ -142,17 +142,29 @@ func (e *ShuffleExec) Close() error {
|
||||
if !e.prepared {
|
||||
for _, w := range e.workers {
|
||||
for _, r := range w.receivers {
|
||||
close(r.inputHolderCh)
|
||||
close(r.inputCh)
|
||||
if r.inputHolderCh != nil {
|
||||
close(r.inputHolderCh)
|
||||
}
|
||||
if r.inputCh != nil {
|
||||
close(r.inputCh)
|
||||
}
|
||||
}
|
||||
if w.outputHolderCh != nil {
|
||||
close(w.outputHolderCh)
|
||||
}
|
||||
close(w.outputHolderCh)
|
||||
}
|
||||
close(e.outputCh)
|
||||
if e.outputCh != nil {
|
||||
close(e.outputCh)
|
||||
}
|
||||
}
|
||||
if e.finishCh != nil {
|
||||
close(e.finishCh)
|
||||
}
|
||||
close(e.finishCh)
|
||||
for _, w := range e.workers {
|
||||
for _, r := range w.receivers {
|
||||
for range r.inputCh {
|
||||
if r.inputCh != nil {
|
||||
for range r.inputCh {
|
||||
}
|
||||
}
|
||||
}
|
||||
// close child executor of each worker
|
||||
@ -160,7 +172,9 @@ func (e *ShuffleExec) Close() error {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
for range e.outputCh { // workers exit before `e.outputCh` is closed.
|
||||
if e.outputCh != nil {
|
||||
for range e.outputCh { // workers exit before `e.outputCh` is closed.
|
||||
}
|
||||
}
|
||||
e.executed = false
|
||||
|
||||
|
||||
Reference in New Issue
Block a user