presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/ExtractCommonPredicatesExpressionRewriter.java/ExtractCommonPredicatesExpressionRewriter/distributeIfPossible
class ExtractCommonPredicatesExpressionRewriter:        private Expression distributeIfPossible(LogicalBinaryExpression expression)
        {
            if (!isDeterministic(expression, metadata)) {
                // Do not distribute boolean expressions if there are any non-deterministic elements
                // TODO: This can be optimized further if non-deterministic elements are not repeated
                return expression;
            }
            List<Set<Expression>> subPredicates = getSubPredicates(expression).stream()
                    .map(ImmutableSet::copyOf)
                    .collect(toList());

            int originalBaseExpressions = subPredicates.stream()
                    .mapToInt(Set::size)
                    .sum();

            int newBaseExpressions;
            try {
                newBaseExpressions = Math.multiplyExact(subPredicates.stream()
                        .mapToInt(Set::size)
                        .reduce(Math::multiplyExact)
                        .getAsInt(), subPredicates.size());
            }
            catch (ArithmeticException e) {
                // Integer overflow from multiplication means there are too many expressions
                return expression;
            }

            if (newBaseExpressions > originalBaseExpressions * 2) {
                // Do not distribute boolean expressions if it would create 2x more base expressions
                // (e.g. A, B, C, D from the above example). This is just an arbitrary heuristic to
                // avoid cross product expression explosion.
                return expression;
            }

            Set<List<Expression>> crossProduct = Sets.cartesianProduct(subPredicates);

            return combinePredicates(
                    metadata,
                    expression.getOperator().flip(),
                    crossProduct.stream()
                            .map(expressions -> combinePredicates(metadata, expression.getOperator(), expressions))
                            .collect(toImmutableList()));
        }