private static boolean isEqualComparisonExpression(Expression conjunct) { return conjunct instanceof ComparisonExpression && ((ComparisonExpression) conjunct).getOperator() == ComparisonExpression.Operator.EQUAL; }
private static boolean isJoinEqualityCondition(Expression expression) { return expression instanceof ComparisonExpression && ((ComparisonExpression) expression).getOperator() == EQUAL && ((ComparisonExpression) expression).getLeft() instanceof SymbolReference && ((ComparisonExpression) expression).getRight() instanceof SymbolReference; }
@Override protected Void visitComparisonExpression(ComparisonExpression node, Integer indentLevel) { print(indentLevel, node.getOperator().toString()); super.visitComparisonExpression(node, indentLevel + 1); return null; }
@Override protected Optional<SortExpressionContext> visitComparisonExpression(ComparisonExpression comparison, Void context) { switch (comparison.getOperator()) { case GREATER_THAN: case GREATER_THAN_OR_EQUAL: case LESS_THAN: case LESS_THAN_OR_EQUAL: Optional<SymbolReference> sortChannel = asBuildSymbolReference(buildSymbols, comparison.getRight()); boolean hasBuildReferencesOnOtherSide = hasBuildSymbolReference(buildSymbols, comparison.getLeft()); if (!sortChannel.isPresent()) { sortChannel = asBuildSymbolReference(buildSymbols, comparison.getLeft()); hasBuildReferencesOnOtherSide = hasBuildSymbolReference(buildSymbols, comparison.getRight()); } if (sortChannel.isPresent() && !hasBuildReferencesOnOtherSide) { return sortChannel.map(symbolReference -> new SortExpressionContext(symbolReference, singletonList(comparison))); } return Optional.empty(); default: return Optional.empty(); } } }
private Multimap<Symbol, Symbol> extractCorrelatedSymbolsMapping(List<Expression> correlatedConjuncts) { // TODO: handle coercions and non-direct column references ImmutableMultimap.Builder<Symbol, Symbol> mapping = ImmutableMultimap.builder(); for (Expression conjunct : correlatedConjuncts) { if (!(conjunct instanceof ComparisonExpression)) { continue; } ComparisonExpression comparison = (ComparisonExpression) conjunct; if (!(comparison.getLeft() instanceof SymbolReference && comparison.getRight() instanceof SymbolReference && comparison.getOperator().equals(EQUAL))) { continue; } Symbol left = Symbol.from(comparison.getLeft()); Symbol right = Symbol.from(comparison.getRight()); if (correlation.contains(left) && !correlation.contains(right)) { mapping.put(left, right); } if (correlation.contains(right) && !correlation.contains(left)) { mapping.put(right, left); } } return mapping.build(); }
private static Predicate<Expression> joinEqualityExpression(final Collection<Symbol> leftSymbols) { return expression -> { // At this point in time, our join predicates need to be deterministic if (isDeterministic(expression) && expression instanceof ComparisonExpression) { ComparisonExpression comparison = (ComparisonExpression) expression; if (comparison.getOperator() == ComparisonExpression.Operator.EQUAL) { Set<Symbol> symbols1 = SymbolsExtractor.extractUnique(comparison.getLeft()); Set<Symbol> symbols2 = SymbolsExtractor.extractUnique(comparison.getRight()); if (symbols1.isEmpty() || symbols2.isEmpty()) { return false; } return (Iterables.all(symbols1, in(leftSymbols)) && Iterables.all(symbols2, not(in(leftSymbols)))) || (Iterables.all(symbols2, in(leftSymbols)) && Iterables.all(symbols1, not(in(leftSymbols)))); } } return false; }; }
@Override public PhysicalOperation visitSpatialJoin(SpatialJoinNode node, LocalExecutionPlanContext context) { Expression filterExpression = node.getFilter(); List<FunctionCall> spatialFunctions = extractSupportedSpatialFunctions(filterExpression); for (FunctionCall spatialFunction : spatialFunctions) { Optional<PhysicalOperation> operation = tryCreateSpatialJoin(context, node, removeExpressionFromFilter(filterExpression, spatialFunction), spatialFunction, Optional.empty(), Optional.empty()); if (operation.isPresent()) { return operation.get(); } } List<ComparisonExpression> spatialComparisons = extractSupportedSpatialComparisons(filterExpression); for (ComparisonExpression spatialComparison : spatialComparisons) { if (spatialComparison.getOperator() == LESS_THAN || spatialComparison.getOperator() == LESS_THAN_OR_EQUAL) { // ST_Distance(a, b) <= r Expression radius = spatialComparison.getRight(); if (radius instanceof SymbolReference && getSymbolReferences(node.getRight().getOutputSymbols()).contains(radius)) { FunctionCall spatialFunction = (FunctionCall) spatialComparison.getLeft(); Optional<PhysicalOperation> operation = tryCreateSpatialJoin(context, node, removeExpressionFromFilter(filterExpression, spatialComparison), spatialFunction, Optional.of(radius), Optional.of(spatialComparison.getOperator())); if (operation.isPresent()) { return operation.get(); } } } } throw new VerifyException("No valid spatial relationship found for spatial join"); }
private static Set<Expression> equalityAsSet(Expression expression) { Preconditions.checkArgument(expression instanceof ComparisonExpression); ComparisonExpression comparisonExpression = (ComparisonExpression) expression; Preconditions.checkArgument(comparisonExpression.getOperator() == EQUAL); return ImmutableSet.of(comparisonExpression.getLeft(), comparisonExpression.getRight()); }
@Override protected String visitComparisonExpression(ComparisonExpression node, Void context) { return formatBinaryExpression(node.getOperator().getValue(), node.getLeft(), node.getRight()); }
private static boolean isSupportedSpatialComparison(ComparisonExpression expression) { switch (expression.getOperator()) { case LESS_THAN: case LESS_THAN_OR_EQUAL: return isSTDistance(expression.getLeft()); case GREATER_THAN: case GREATER_THAN_OR_EQUAL: return isSTDistance(expression.getRight()); default: return false; } }
public static boolean isSpatialJoinFilter(PlanNode left, PlanNode right, Expression filterExpression) { List<FunctionCall> functionCalls = extractSupportedSpatialFunctions(filterExpression); for (FunctionCall functionCall : functionCalls) { if (isSpatialJoinFilter(left, right, functionCall)) { return true; } } List<ComparisonExpression> spatialComparisons = extractSupportedSpatialComparisons(filterExpression); for (ComparisonExpression spatialComparison : spatialComparisons) { if (spatialComparison.getOperator() == LESS_THAN || spatialComparison.getOperator() == LESS_THAN_OR_EQUAL) { // ST_Distance(a, b) <= r Expression radius = spatialComparison.getRight(); if (radius instanceof Literal || (radius instanceof SymbolReference && getSymbolReferences(right.getOutputSymbols()).contains(radius))) { if (isSpatialJoinFilter(left, right, (FunctionCall) spatialComparison.getLeft())) { return true; } } } } return false; }
@Override protected Type visitComparisonExpression(ComparisonExpression node, StackableAstVisitorContext<Context> context) { OperatorType operatorType = OperatorType.valueOf(node.getOperator().name()); return getOperator(context, node, operatorType, node.getLeft(), node.getRight()); }
public static Expression normalize(Expression expression) { if (expression instanceof NotExpression) { NotExpression not = (NotExpression) expression; if (not.getValue() instanceof ComparisonExpression && ((ComparisonExpression) not.getValue()).getOperator() != IS_DISTINCT_FROM) { ComparisonExpression comparison = (ComparisonExpression) not.getValue(); return new ComparisonExpression(comparison.getOperator().negate(), comparison.getLeft(), comparison.getRight()); } if (not.getValue() instanceof NotExpression) { return normalize(((NotExpression) not.getValue()).getValue()); } } return expression; }
@Override protected Boolean visitComparisonExpression(ComparisonExpression actual, Node expectedExpression) { if (expectedExpression instanceof ComparisonExpression) { ComparisonExpression expected = (ComparisonExpression) expectedExpression; if (actual.getOperator() == expected.getOperator()) { return process(actual.getLeft(), expected.getLeft()) && process(actual.getRight(), expected.getRight()); } } return false; }
comparisonOperator = comparison.getOperator(); value = new NullableValue(rightType, right); comparisonOperator = comparison.getOperator().flip(); value = new NullableValue(leftType, left);
/** * Determines whether an Expression may be successfully applied to the equality inference */ public static Predicate<Expression> isInferenceCandidate() { return expression -> { expression = normalizeInPredicateToEquality(expression); if (expression instanceof ComparisonExpression && isDeterministic(expression) && !mayReturnNullOnNonNullInput(expression)) { ComparisonExpression comparison = (ComparisonExpression) expression; if (comparison.getOperator() == ComparisonExpression.Operator.EQUAL) { // We should only consider equalities that have distinct left and right components return !comparison.getLeft().equals(comparison.getRight()); } } return false; }; }
@Override protected RowExpression visitComparisonExpression(ComparisonExpression node, Void context) { RowExpression left = process(node.getLeft(), context); RowExpression right = process(node.getRight(), context); return call( comparisonExpressionSignature(node.getOperator(), left.getType(), right.getType()), BOOLEAN, left, right); }
@Override public Expression rewriteNotExpression(NotExpression node, Void context, ExpressionTreeRewriter<Void> treeRewriter) { if (node.getValue() instanceof LogicalBinaryExpression) { LogicalBinaryExpression child = (LogicalBinaryExpression) node.getValue(); List<Expression> predicates = extractPredicates(child); List<Expression> negatedPredicates = predicates.stream().map(predicate -> treeRewriter.rewrite((Expression) new NotExpression(predicate), context)).collect(toImmutableList()); return combinePredicates(child.getOperator().flip(), negatedPredicates); } else if (node.getValue() instanceof ComparisonExpression && ((ComparisonExpression) node.getValue()).getOperator() != IS_DISTINCT_FROM) { ComparisonExpression child = (ComparisonExpression) node.getValue(); return new ComparisonExpression(child.getOperator().negate(), treeRewriter.rewrite(child.getLeft(), context), treeRewriter.rewrite(child.getRight(), context)); } else if (node.getValue() instanceof NotExpression) { NotExpression child = (NotExpression) node.getValue(); return treeRewriter.rewrite(child.getValue(), context); } return new NotExpression(treeRewriter.rewrite(node.getValue(), context)); } }
@Override protected PlanNodeStatsEstimate visitComparisonExpression(ComparisonExpression node, Void context) ComparisonExpression.Operator operator = node.getOperator(); Expression left = node.getLeft(); Expression right = node.getRight();
@Override protected Object visitComparisonExpression(ComparisonExpression node, Object context) { ComparisonExpression.Operator operator = node.getOperator(); Object left = process(node.getLeft(), context); if (left == null && operator != ComparisonExpression.Operator.IS_DISTINCT_FROM) { return null; } Object right = process(node.getRight(), context); if (operator == ComparisonExpression.Operator.IS_DISTINCT_FROM) { if (left == null && right == null) { return false; } else if (left == null || right == null) { return true; } } else if (right == null) { return null; } if (hasUnresolvedValue(left, right)) { return new ComparisonExpression(operator, toExpression(left, type(node.getLeft())), toExpression(right, type(node.getRight()))); } return invokeOperator(OperatorType.valueOf(operator.name()), types(node.getLeft(), node.getRight()), ImmutableList.of(left, right)); }