private static void generateAllCombinations(List<ExpressionTree> result,
                                                List<ExpressionTree> andList,
                                                List<ExpressionTree> nonAndList
    ) {
      List<ExpressionTree> kids = andList.get(0).getChildren();
      if (result.isEmpty()) {
        for(ExpressionTree kid: kids) {
          ExpressionTree or = new ExpressionTree(ExpressionTree.Operator.OR);
          result.add(or);
          for(ExpressionTree node: nonAndList) {
            or.getChildren().add(new ExpressionTree(node));
          }
          or.getChildren().add(kid);
        }
      } else {
        List<ExpressionTree> work = new ArrayList<>(result);
        result.clear();
        for(ExpressionTree kid: kids) {
          for(ExpressionTree or: work) {
            ExpressionTree copy = new ExpressionTree(or);
            copy.getChildren().add(kid);
            result.add(copy);
          }
        }
      }
      if (andList.size() > 1) {
        generateAllCombinations(result, andList.subList(1, andList.size()),
            nonAndList);
      }
    }
Generate all combinations of items on the andList. For each item on the
andList, it generates all combinations of one child from each and
expression. Thus, (and a b) (and c d) will be expanded to: (or a c)
(or a d) (or b c) (or b d). If there are items on the nonAndList, they
are added to each or expression.
@param result a list to put the results onto
@param andList a list of and expressions
@param nonAndList a list of non-and expressions
storage-api/src/java/org/apache/hadoop/hive/ql/io/sarg/SearchArgumentImpl.java