func (e *HashJoinExec) Close() error {
	close(e.closeCh)
	if e.prepared {
		if e.joinResultCh != nil {
			for range e.joinResultCh {
			}
		}
		if e.outerChkResourceCh != nil {
			close(e.outerChkResourceCh)
			for range e.outerChkResourceCh {
			}
		}
		for i := range e.outerResultChs {
			for range e.outerResultChs[i] {
			}
		}
		for i := range e.joinChkResourceCh {
			close(e.joinChkResourceCh[i])
			for range e.joinChkResourceCh[i] {
			}
		}
		e.outerChkResourceCh = nil
		e.joinChkResourceCh = nil
	}
	err := e.baseExecutor.Close()
	return err
}
Close implements the Executor Close interface.
package executor
import (
	"context"
	"sync"
	"github.com/pingcap/errors"
	"github.com/pingcap/tidb/expression"
	plannercore "github.com/pingcap/tidb/planner/core"
	"github.com/pingcap/tidb/util"
	"github.com/pingcap/tidb/util/chunk"
	"github.com/pingcap/tidb/util/codec"
)
var _ Executor = &HashJoinExec{}
type HashJoinExec struct {
	baseExecutor
	outerSideExec     Executor
	innerSideExec     Executor
	innerSideEstCount float64
	outerSideFilter   expression.CNFExprs
	outerKeys         []*expression.Column
	innerKeys         []*expression.Column
	concurrency  uint
	rowContainer *hashRowContainer
	joinWorkerWaitGroup sync.WaitGroup
	closeCh  chan struct{}
	joinType plannercore.JoinType
	joiners []joiner
	outerChkResourceCh chan *outerChkResource
	outerResultChs     []chan *chunk.Chunk
	joinChkResourceCh  []chan *chunk.Chunk
	joinResultCh       chan *hashjoinWorkerResult
	prepared bool
}
type outerChkResource struct {
	chk  *chunk.Chunk
	dest chan<- *chunk.Chunk
}
type hashjoinWorkerResult struct {
	chk *chunk.Chunk
	err error
	src chan<- *chunk.Chunk
}