private @Nullable LcsTable validateKeys(
      RelNode factRel,
      List<Integer> leftKeys,
      List<Integer> rightKeys,
      List<Integer> actualLeftKeys) {
    int keyIdx = 0;
    RelOptTable theTable = null;
    ListIterator<Integer> keyIter = leftKeys.listIterator();
    while (keyIter.hasNext()) {
      boolean removeKey = false;
      final RelColumnOrigin colOrigin =
          mq.getColumnOrigin(factRel, keyIter.next());

      // can't use the rid column as a semijoin key
      if ((colOrigin == null || !colOrigin.isDerived())
          || LucidDbSpecialOperators.isLcsRidColumnId(
            colOrigin.getOriginColumnOrdinal())) {
        removeKey = true;
      } else {
        RelOptTable table = colOrigin.getOriginTable();
        if (theTable == null) {
          if (!(table instanceof LcsTable)) {
            // not a column store table
            removeKey = true;
          } else {
            theTable = table;
          }
        } else {
          // the tables must match because the column has
          // a simple origin
          assert table == theTable;
        }
      }
      if (colOrigin != null && !removeKey) {
        actualLeftKeys.add(colOrigin.getOriginColumnOrdinal());
        keyIdx++;
      } else {
        keyIter.remove();
        rightKeys.remove(keyIdx);
      }
    }

    // if all keys have been removed, then we don't have any valid semijoin
    // keys
    if (actualLeftKeys.isEmpty()) {
      return null;
    } else {
      return (LcsTable) theTable;
    }
  }
Validates the candidate semijoin keys corresponding to the fact table.
Ensure the keys all originate from the same underlying table, and they
all correspond to simple column references. If unsuitable keys are found,
they're removed from the key list and a new list corresponding to the
remaining valid keys is returned.

@param factRel fact table RelNode
@param leftKeys fact table semijoin keys
@param rightKeys dimension table semijoin keys
@param actualLeftKeys the remaining valid fact table semijoin keys

@return the underlying fact table if the semijoin keys are valid;
otherwise null
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveLoptSemiJoinOptimizer.java