private boolean createDerivatives(final List<ExprNodeDesc> resultExprs, final Operator<?> op,
        final ExprNodeDesc currentNode, final ExprNodeDesc sourceKey) throws SemanticException {
      // 1. Obtain join operator upstream
      Operator<?> currentOp = op;
      while (!(currentOp instanceof CommonJoinOperator)) {
        if (currentOp.getParentOperators() == null || currentOp.getParentOperators().size() != 1) {
          // Cannot backtrack
          currentOp = null;
          break;
        }
        if (!(currentOp instanceof FilterOperator) &&
            !(currentOp instanceof SelectOperator) &&
            !(currentOp instanceof ReduceSinkOperator) &&
            !(currentOp instanceof GroupByOperator)) {
          // Operator not supported
          currentOp = null;
          break;
        }
        // Move the pointer
        currentOp = currentOp.getParentOperators().get(0);
      }
      if (currentOp == null) {
        // We did not find any join, we are done
        return true;
      }
      CommonJoinOperator<JoinDesc> joinOp = (CommonJoinOperator) currentOp;

      // 2. Backtrack expression to join output
      ExprNodeDesc expr = currentNode;
      if (currentOp != op) {
        if (expr instanceof ExprNodeColumnDesc) {
          // Expression refers to output of current operator, but backtrack methods works
          // from the input columns, hence we need to make resolution for current operator
          // here. If the operator was already the join, there is nothing to do
          if (op.getColumnExprMap() != null) {
            expr = op.getColumnExprMap().get(((ExprNodeColumnDesc) expr).getColumn());
          }
        } else {
          // TODO: We can extend to other expression types
          // We are done
          return true;
        }
      }
      final ExprNodeDesc joinExprNode = ExprNodeDescUtils.backtrack(expr, op, joinOp);
      if (joinExprNode == null || !(joinExprNode instanceof ExprNodeColumnDesc)) {
        // TODO: We can extend to other expression types
        // We are done
        return true;
      }
      final String columnRefJoinInput = ((ExprNodeColumnDesc)joinExprNode).getColumn();

      // 3. Find input position in join for expression obtained
      String columnOutputName = null;
      for (Map.Entry<String, ExprNodeDesc> e : joinOp.getColumnExprMap().entrySet()) {
        if (e.getValue() == joinExprNode) {
          columnOutputName = e.getKey();
          break;
        }
      }
      if (columnOutputName == null) {
        // Maybe the join is pruning columns, though it should not.
        // In any case, we are done
        return true;
      }
      final int srcPos = joinOp.getConf().getReversedExprs().get(columnOutputName);
      final int[][] targets = getTargets(joinOp);
      final ReduceSinkOperator rsOp = (ReduceSinkOperator) joinOp.getParentOperators().get(srcPos);

      // 4. Find expression in input RS operator.
      final Operator<?> rsOpInput = rsOp.getParentOperators().get(0);
      final ExprNodeDesc rsOpInputExprNode = rsOp.getColumnExprMap().get(columnRefJoinInput);
      if (rsOpInputExprNode == null) {
        // Unexpected, we just bail out and we do not infer additional predicates
        return false;
      }
      int posInRSOpKeys = -1;
      for (int i = 0; i < rsOp.getConf().getKeyCols().size(); i++) {
        if (rsOpInputExprNode.isSame(rsOp.getConf().getKeyCols().get(i))) {
          posInRSOpKeys = i;
          break;
        }
      }

      // 5. If it is part of the key, we can create a new semijoin.
      // In addition, we can do the same for siblings
      if (posInRSOpKeys >= 0) {
        // We pass the tests, we add it to the args for the AND expression
        addParentReduceSink(resultExprs, rsOp, posInRSOpKeys, sourceKey);
        for (int targetPos: targets[srcPos]) {
          if (srcPos == targetPos) {
            continue;
          }
          final ReduceSinkOperator otherRsOp = (ReduceSinkOperator) joinOp.getParentOperators().get(targetPos);
          final Operator<?> otherRsOpInput = otherRsOp.getParentOperators().get(0);
          // We pass the tests, we add it to the args for the AND expression
          addParentReduceSink(resultExprs, otherRsOp, posInRSOpKeys, sourceKey);
          // We propagate to operator below
          boolean success = createDerivatives(
              resultExprs, otherRsOpInput, otherRsOp.getConf().getKeyCols().get(posInRSOpKeys), sourceKey);
          if (!success) {
            // Something went wrong, bail out
            return false;
          }
        }
      }

      // 6. Whether it was part of the key or of the value, if we reach here, we can at least
      // continue propagating to operators below
      boolean success = createDerivatives(
          resultExprs, rsOpInput, rsOpInputExprNode, sourceKey);
      if (!success) {
        // Something went wrong, bail out
        return false;
      }

      // 7. We are done, success
      return true;
    }
creates synthetic predicates that represent "IN (keylist other table)"
ql/src/java/org/apache/hadoop/hive/ql/ppd/SyntheticJoinPredicate.java