private void buildHashTable(QueryIterator iter1) {
   state = Phase.HASH;
   for (; iter1.hasNext(); ) {
     Binding row1 = iter1.next();
     s_countProbe++;
     hashTable.put(row1);
   }
   iter1.close();
   state = Phase.STREAM;
 }
  protected Binding moveToNextBindingOrNull() {
    // iterCurrent is the iterator of entries in the
    // probe hashed table for the current stream row.
    // iterStream is the stream of incoming rows.

    switch (state) {
      case DONE:
        return null;
      case HASH:
      case INIT:
        throw new IllegalStateException();
      case TRAILER:
        return doOneTail();
      case STREAM:
    }

    for (; ; ) {
      // Ensure we are processing a row.
      while (iterCurrent == null) {
        // Move on to the next row from the right.
        if (!iterStream.hasNext()) {
          state = Phase.TRAILER;
          iterTail = joinFinished();
          if (iterTail != null) return doOneTail();
          return null;
        }
        rowStream = iterStream.next();
        s_countScan++;
        iterCurrent = hashTable.getCandidates(rowStream);
        yielded = false;
      }

      // Emit one row using the rightRow and the current matched left rows.
      if (!iterCurrent.hasNext()) {
        iterCurrent = null;
        if (!yielded) {
          Binding b = noYieldedRows(rowStream);
          if (b != null) {
            s_countScan++;
            return b;
          }
        }
        continue;
      }

      // Nested loop join, only on less.
      // Iterator<Binding> iter = nestedLoop(iterCurrent, rowStream) ;

      Binding rowCurrentProbe = iterCurrent.next();
      Binding r = Algebra.merge(rowCurrentProbe, rowStream);
      Binding r2 = null;

      if (r != null) r2 = yieldOneResult(rowCurrentProbe, rowStream, r);
      if (r2 == null) {
        // Reject
      } else {
        yielded = true;
        s_countResults++;
        return r2;
      }
    }
  }