@Override protected PlanNodeStatsEstimate visitLogicalBinaryExpression(LogicalBinaryExpression node, Void context) { switch (node.getOperator()) { case AND: return estimateLogicalAnd(node.getLeft(), node.getRight()); case OR: return estimateLogicalOr(node.getLeft(), node.getRight()); default: throw new IllegalArgumentException("Unexpected binary operator: " + node.getOperator()); } }
@Override protected Object visitLogicalBinaryExpression(LogicalBinaryExpression node, Object context) Object left = process(node.getLeft(), context); Object right; switch (node.getOperator()) { case AND: { if (Boolean.FALSE.equals(left)) { right = process(node.getRight(), context); right = process(node.getRight(), context); return new LogicalBinaryExpression(node.getOperator(), toExpression(left, type(node.getLeft())), toExpression(right, type(node.getRight())));
@Override protected Object visitLogicalBinaryExpression(LogicalBinaryExpression node, Object context) Object left = process(node.getLeft(), context); Object right = process(node.getRight(), context); switch (node.getType()) { case AND: { return new LogicalBinaryExpression(node.getType(), toExpression(left, expressionTypes.get(node.getLeft())), toExpression(right, expressionTypes.get(node.getRight())));
public static Expression logicalAnd(Expression left, Expression right) { return new LogicalBinaryExpression(LogicalBinaryExpression.Operator.AND, left, right); }
public static List<Expression> extractPredicates(LogicalBinaryExpression expression) { return extractPredicates(expression.getType(), expression); }
public static List<Expression> extractPredicates(LogicalBinaryExpression expression) { return extractPredicates(expression.getOperator(), expression); }
public static LogicalBinaryExpression or(Expression left, Expression right) { return new LogicalBinaryExpression(Optional.empty(), Operator.OR, left, right); }
@Override protected Void visitLogicalBinaryExpression(LogicalBinaryExpression node, Integer indentLevel) { print(indentLevel, node.getType().toString()); super.visitLogicalBinaryExpression(node, indentLevel + 1); return null; }
private static List<List<Expression>> getSubPredicates(LogicalBinaryExpression expression) { return extractPredicates(expression.getOperator(), expression).stream() .map(predicate -> predicate instanceof LogicalBinaryExpression ? extractPredicates((LogicalBinaryExpression) predicate) : ImmutableList.of(predicate)) .collect(toImmutableList()); }
@Override protected String visitLogicalBinaryExpression(LogicalBinaryExpression node, Void context) { return formatBinaryExpression(node.getOperator().toString(), node.getLeft(), node.getRight()); }
@Override protected Type visitLogicalBinaryExpression(LogicalBinaryExpression node, StackableAstVisitorContext<Context> context) { coerceType(context, node.getLeft(), BOOLEAN, "Left side of logical expression"); coerceType(context, node.getRight(), BOOLEAN, "Right side of logical expression"); return setExpressionType(node, BOOLEAN); }
public static LogicalBinaryExpression and(Expression left, Expression right) { return new LogicalBinaryExpression(Optional.empty(), Operator.AND, left, right); }
@Override public Expression rewriteLogicalBinaryExpression(LogicalBinaryExpression node, NodeContext context, ExpressionTreeRewriter<NodeContext> treeRewriter) { List<Expression> predicates = extractPredicates(node.getType(), node).stream() .map(expression -> treeRewriter.rewrite(expression, NodeContext.NOT_ROOT_NODE)) .collect(toImmutableList()); List<List<Expression>> subPredicates = getSubPredicates(predicates); Set<Expression> commonPredicates = ImmutableSet.copyOf(subPredicates.stream() .map(this::filterDeterministicPredicates) .reduce(Sets::intersection) .orElse(emptySet())); List<List<Expression>> uncorrelatedSubPredicates = subPredicates.stream() .map(predicateList -> removeAll(predicateList, commonPredicates)) .collect(toImmutableList()); LogicalBinaryExpression.Type flippedNodeType = node.getType().flip(); List<Expression> uncorrelatedPredicates = uncorrelatedSubPredicates.stream() .map(predicate -> combinePredicates(flippedNodeType, predicate)) .collect(toImmutableList()); Expression combinedUncorrelatedPredicates = combinePredicates(node.getType(), uncorrelatedPredicates); // Do not simplify top level conjuncts if it would result in top level disjuncts // Conjuncts are easier to process when pushing down predicates. if (context.isRootNode() && flippedNodeType == OR && !combinedUncorrelatedPredicates.equals(FALSE_LITERAL)) { return combinePredicates(node.getType(), predicates); } return combinePredicates(flippedNodeType, ImmutableList.<Expression>builder() .addAll(commonPredicates) .add(combinedUncorrelatedPredicates) .build()); }
@Override protected Void visitLogicalBinaryExpression(LogicalBinaryExpression node, Integer indentLevel) { print(indentLevel, node.getOperator().toString()); super.visitLogicalBinaryExpression(node, indentLevel + 1); return null; }
@Override protected String visitLogicalBinaryExpression(LogicalBinaryExpression node, Boolean negate) { LogicalBinaryExpression.Type type = node.getType(); if (type == AND) { // TODO find a better way // Optimization for the case when one hand or binary expression is IS NOT NULL predicate if (node.getRight() instanceof IsNotNullPredicate && !(node.getLeft() instanceof IsNotNullPredicate) || node.getLeft() instanceof IsNotNullPredicate && !(node.getRight() instanceof IsNotNullPredicate)) { Expression isNotNull = node.getRight() instanceof IsNotNullPredicate ? node.getRight() : node.getLeft(); Expression setExpression = isNotNull == node.getRight() ? node.getLeft() : node.getRight(); String excludeQuery = process(new IsNullPredicate(((IsNotNullPredicate) isNotNull).getValue()), negate); return "SELECT l.date, l.dimension, l._user_set FROM (" + process(setExpression, negate) + ") l LEFT JOIN (" + excludeQuery + ") r ON (r.date = l.date AND l.dimension = r.dimension) WHERE r.date IS NULL"; } String right = process(node.getRight(), negate); String left = process(node.getLeft(), negate); // TODO: use INTERSECT when it's implemented in Presto. return "SELECT l.date, l.dimension, l._user_set FROM (" + left + ") l JOIN (" + right + ") r ON (r.date = l.date)"; } else if (type == OR) { return "SELECT date, dimension, _user_set FROM (" + process(node.getLeft(), negate) + " UNION ALL " + process(node.getRight(), negate) + ")"; } else { throw new IllegalStateException(); } }