Tinysql Proj5 part2 Hash Join Implementation

Hi, I’m trying to finish the Proj5 part2 tinysql. I followed instructions step by step but always fail in some test.

Here is my first function fetchAndBuildHashTable:

概要
func (e *HashJoinExec) fetchAndBuildHashTable(ctx context.Context) error {
	// TODO: Implementing the building hash table stage.

	// In this stage, you'll read the data from the inner side executor of the join operator and
	// then use its data to build hash table.

	// You'll need to store the hash table in `e.rowContainer`
	// and you can call `newHashRowContainer` in `executor/hash_table.go` to build it.
	// In this stage you can only assign value for `e.rowContainer` without changing any value of the `HashJoinExec`.


	// init a new list for chunk
	innerResult := chunk.NewList(e.innerSideExec.base().retFieldTypes, e.ctx.GetSessionVars().InitChunkSize, e.maxChunkSize)

	for {
		
		chk := chunk.New(e.innerSideExec.base().retFieldTypes, e.ctx.GetSessionVars().InitChunkSize,  e.ctx.GetSessionVars().MaxChunkSize)

		err := e.innerSideExec.Next(ctx, chk)
		if err != nil {
			return errors.Trace(err)
		}
		if chk.NumRows() == 0 {
			break
		}


		innerResult.Add(chk)
	}

	buildKeyColIdx := make([]int, len(e.innerKeys))
	for i := range e.innerKeys {
		buildKeyColIdx[i] = e.innerKeys[i].Index
	}
	hCtx := &hashContext{
		allTypes:  e.innerSideExec.base().retFieldTypes,
		keyColIdx: buildKeyColIdx,
	}
	
	e.rowContainer= newHashRowContainer(e.innerSideExec.base().ctx, int(e.innerSideEstCount), hCtx, innerResult)
	return nil
}

My another function runJoinWorkers

概要
func (e *HashJoinExec) runJoinWorker(workerID uint, outerKeyColIdx []int) {
	// TODO: Implement the worker of probing stage.

	// In this method, you read the data from the channel e.outerResultChs[workerID].
	// Then use `e.join2Chunk` method get the joined result `joinResult`,
	// and put the `joinResult` into the channel `e.joinResultCh`.

	// You may pay attention to:
	
	// - e.closeCh, this is a channel tells that the join can be terminated as soon as possible.
	// Read and filter outerResult, and join the outerResult with the inner rows.

	emptyOuterResult := &outerChkResource{
		dest: e.outerResultChs[workerID],
	}

	hCtx := &hashContext{
		allTypes:  e.outerSideExec.base().retFieldTypes,
		keyColIdx: outerKeyColIdx,
	}

	var (
		outerChunk *chunk.Chunk
		selected    = make([]bool, 0, chunk.InitialCapacity)
	)

	// reuse JoinResult Chk from main goroutine
	ok, joinResult := e.getNewJoinResult(workerID)
	if !ok {
		return
	}

	for ok = true; ok;{
	


		select{
		case <-e.closeCh:
			return 
		
		// get outerChunk from Outer Fetcher Goroutine
		case outerChunk, ok = <-e.outerResultChs[workerID]:
		}

		if !ok{
			break
		}
		

		// look up in hash table and compare different rows
		ok, joinResult = e.join2Chunk(workerID, outerChunk, hCtx, joinResult, selected)
		if !ok{
			break
		}
		
		// send back info to outerChkResou
		outerChunk.Reset()
		emptyOuterResult.chk = outerChunk
		e.outerChkResourceCh <- emptyOuterResult
		
	}
	
	// send result to joinResultCh
	if joinResult == nil {
		return
	} else if joinResult.err != nil || (joinResult.chk != nil && joinResult.chk.NumRows() > 0) {
		e.joinResultCh <- joinResult
	} else if joinResult.chk != nil && joinResult.chk.NumRows() == 0 {
		e.joinChkResourceCh[workerID] <- joinResult.chk
	}
}

Can you give me some advice on debugging/ Am I misunderstanding the instructions somewhere? I have looked at some source code and master branch code, but they are not so fit. Some procedures are totally different.

The test failed at join result. For example, TestJoin case:

... obtained string = ""
... expected string = "[1]\n"
... sql:select 1 from t as a join t as b on 1

One more thing, seems that the function name NextChunk is no longer used but github tutorial is still using it. I can only find Next.