public static ImmutableList<RexNode> getPredsNotPushedAlready(Set<String> predicatesToExclude,
          RelNode inp, List<RexNode> predsToPushDown) {
    // Bail out if there is nothing to push
    if (predsToPushDown.isEmpty()) {
      return ImmutableList.of();
    }
    // Build map to not convert multiple times, further remove already included predicates
    Map<String,RexNode> stringToRexNode = Maps.newLinkedHashMap();
    for (RexNode r : predsToPushDown) {
      String rexNodeString = r.toString();
      if (predicatesToExclude.add(rexNodeString)) {
        stringToRexNode.put(rexNodeString, r);
      }
    }
    if (stringToRexNode.isEmpty()) {
      return ImmutableList.of();
    }
    // Finally exclude preds that are already in the subtree as given by the metadata provider
    // Note: this is the last step, trying to avoid the expensive call to the metadata provider
    //       if possible
    Set<String> predicatesInSubtree = Sets.newHashSet();
    final RelMetadataQuery mq = inp.getCluster().getMetadataQuery();
    for (RexNode pred : mq.getPulledUpPredicates(inp).pulledUpPredicates) {
      predicatesInSubtree.add(pred.toString());
      predicatesInSubtree.addAll(Lists.transform(RelOptUtil.conjunctions(pred), REX_STR_FN));
    }
    final ImmutableList.Builder<RexNode> newConjuncts = ImmutableList.builder();
    for (Entry<String,RexNode> e : stringToRexNode.entrySet()) {
      if (predicatesInSubtree.add(e.getKey())) {
        newConjuncts.add(e.getValue());
      }
    }
    predicatesToExclude.addAll(predicatesInSubtree);
    return newConjuncts.build();
  }
Given a list of predicates to push down, this methods returns the set of predicates
that still need to be pushed. Predicates need to be pushed because 1) their String
representation is not included in input set of predicates to exclude, or 2) they are
already in the subtree rooted at the input node.
This method updates the set of predicates to exclude with the String representation
of the predicates in the output and in the subtree.

@param predicatesToExclude String representation of predicates that should be excluded
@param inp root of the subtree
@param predsToPushDown candidate predicates to push down through the subtree
@return list of predicates to push down
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/HiveCalciteUtil.java