code: func (e *RadixHashJoinExec) Next(ctx context.Context, req *chunk.RecordBatch) (err error) {
  	if e.runtimeStats != nil {
  		start := time.Now()
  		defer func() { e.runtimeStats.Record(time.Now().Sub(start), req.NumRows()) }()
  	}
  	if !e.prepared {
  		e.innerFinished = make(chan error, 1)
  		go util.WithRecovery(func() { e.partitionInnerAndBuildHashTables(ctx) }, e.handleFetchInnerAndBuildHashTablePanic)
  		// TODO: parallel fetch outer rows, partition them and do parallel join
  		e.prepared = true
  	}
  	return <-e.innerFinished
  }
docs: // Next implements the Executor Next interface.
  // radix hash join constructs the result following these steps:
  // step 1. fetch data from inner child
  // step 2. parallel partition the inner relation into sub-relations and build an
  // individual hash table for every partition
  // step 3. fetch data from outer child in a background goroutine and partition
  // it into sub-relations
  // step 4. probe the corresponded sub-hash-table for every sub-outer-relation in
  // multiple join workers