private void generateHashMapResultLargeMultiValue(VectorizedRowBatch batch,
      VectorMapJoinHashMapResult hashMapResult, int[] allMatches, int allMatchesIndex,
      int duplicateCount) throws HiveException, IOException {

    // Kick out previous overflow batch results.
    if (overflowBatch.size > 0) {
      forwardOverflow();
    }

    ByteSegmentRef byteSegmentRef = hashMapResult.first();
    while (byteSegmentRef != null) {

      // Fill up as much of the overflow batch as possible with small table values.
      while (byteSegmentRef != null) {

        if (smallTableValueVectorDeserializeRow != null) {
          doSmallTableValueDeserializeRow(overflowBatch, overflowBatch.size,
              byteSegmentRef, hashMapResult);
        }

        overflowBatch.size++;
        if (overflowBatch.size == overflowBatch.DEFAULT_SIZE) {
          break;
        }
        byteSegmentRef = hashMapResult.next();
      }

      // Forward the overflow batch over and over:
      //
      //    Reference a new one big table row's values each time
      //      cross product
      //    Current "batch" of small table values.
      //
      // TODO: This could be further optimized to copy big table (equal) keys once
      //       and only copy big table values each time...
      //       And, not set repeating every time...
      //

      for (int i = 0; i < duplicateCount; i++) {

        int batchIndex = allMatches[allMatchesIndex + i];

        if (bigTableRetainedVectorCopy != null) {

          // The one big table row's values repeat.
          bigTableRetainedVectorCopy.copyByReference(
              batch, batchIndex,
              overflowBatch, 0);
          for (int column : bigTableRetainColumnMap) {
            overflowBatch.cols[column].isRepeating = true;
          }
        }

        if (nonOuterSmallTableKeyVectorCopy != null) {

          // For non-[FULL] OUTER MapJoin, copy non-retained Big Table keys to the Big Table area
          // across to overflow batch by value so Small Key projection will see its keys...
          //
          nonOuterSmallTableKeyVectorCopy.copyByValue(
              batch, batchIndex,
              overflowBatch, 0);
          for (int column : nonOuterSmallTableKeyColumnMap) {
            overflowBatch.cols[column].isRepeating = true;
          }
        }

        int[] outerSmallTableKeyColumnMap = null;
        if (outerSmallTableKeyVectorCopy != null) {

          // For [FULL] OUTER MapJoin, copy Big Table keys to Small Table area within
          // to overflow batch by value.
          //
          outerSmallTableKeyVectorCopy.copyByValue(
              batch, batchIndex,
              overflowBatch, 0);
          outerSmallTableKeyColumnMap = outerSmallTableKeyMapping.getOutputColumns();
          for (int column : outerSmallTableKeyColumnMap) {
            overflowBatch.cols[column].isRepeating = true;
          }
        }

        // Crucial here that we don't reset the overflow batch, or we will loose the small table
        // values we put in above.
        forwardOverflowNoReset();

        // Hand reset the big table columns.
        for (int column : bigTableRetainColumnMap) {
          ColumnVector colVector = overflowBatch.cols[column];
          colVector.reset();
        }
        for (int column : nonOuterSmallTableKeyColumnMap) {
          ColumnVector colVector = overflowBatch.cols[column];
          colVector.reset();
        }
        if (outerSmallTableKeyColumnMap != null) {
          for (int column : outerSmallTableKeyColumnMap) {
            ColumnVector colVector = overflowBatch.cols[column];
            colVector.reset();
          }
        }
      }

      byteSegmentRef = hashMapResult.next();
      if (byteSegmentRef == null) {
        break;
      }

      // Get ready for a another round of small table values.
      overflowBatch.reset();
    }
    // Clear away any residue from our optimizations.
    overflowBatch.reset();
  }
Generate optimized results for a large N x M cross product using repeated vectorized row
batch optimization.

@param batch
         The big table batch.
@param hashMapResult
         The hash map results for the matching key.
@param allMatches
         The all match selected array that contains (physical) batch indices.
@param allMatchesIndex
         The index of the match key.
@param duplicateCount
         Number of equal key rows.
ql/src/java/org/apache/hadoop/hive/ql/exec/vector/mapjoin/VectorMapJoinGenerateResultOperator.java