/**
   * Returns the comparison result of the next row from each cursor. If one cursor has no more rows
   * but the other does then subsequent calls to this will indicate that the remaining rows are
   * unique.
   *
   * <p>The caller must check that hasNext() returns true before calling this.
   *
   * <p>Once next() has been called the cursors specified in the result of the call to next() are
   * guaranteed to point to the row that was indicated. Reading values from the cursor that was not
   * indicated in the call to next() will result in undefined behavior.
   *
   * @return LEFT, if the row pointed to by the left cursor is unique, RIGHT if the row pointed to
   *     by the right cursor is unique, BOTH if the rows in both cursors are the same.
   */
  public Result next() {
    if (!hasNext()) {
      throw new IllegalStateException("you must only call next() when hasNext() is true");
    }
    incrementCursors();
    assert hasNext();

    boolean hasLeft = !mCursorLeft.isAfterLast();
    boolean hasRight = !mCursorRight.isAfterLast();

    if (hasLeft && hasRight) {
      populateValues(mValues, mCursorLeft, mColumnsLeft, 0 /* start filling at index 0 */);
      populateValues(mValues, mCursorRight, mColumnsRight, 1 /* start filling at index 1 */);
      switch (compareStrings(mValues)) {
        case -1:
          mCompareResult = Result.LEFT;
          break;
        case 0:
          mCompareResult = Result.BOTH;
          break;
        case 1:
          mCompareResult = Result.RIGHT;
          break;
      }
    } else if (hasLeft) {
      mCompareResult = Result.LEFT;
    } else {
      assert hasRight;
      mCompareResult = Result.RIGHT;
    }
    mCompareResultIsValid = true;
    return mCompareResult;
  }
  /**
   * Returns whether or not there are more rows to compare using next().
   *
   * @return true if there are more rows to compare
   */
  public boolean hasNext() {
    if (mCompareResultIsValid) {
      switch (mCompareResult) {
        case BOTH:
          return !mCursorLeft.isLast() || !mCursorRight.isLast();

        case LEFT:
          return !mCursorLeft.isLast() || !mCursorRight.isAfterLast();

        case RIGHT:
          return !mCursorLeft.isAfterLast() || !mCursorRight.isLast();

        default:
          throw new IllegalStateException("bad value for mCompareResult, " + mCompareResult);
      }
    } else {
      return !mCursorLeft.isAfterLast() || !mCursorRight.isAfterLast();
    }
  }