private static boolean shouldCompareValueWithLowerBound(QuantifiedComparisonExpression quantifiedComparison) { switch (quantifiedComparison.getQuantifier()) { case ALL: switch (quantifiedComparison.getOperator()) { case LESS_THAN: case LESS_THAN_OR_EQUAL: return true; case GREATER_THAN: case GREATER_THAN_OR_EQUAL: return false; } break; case ANY: case SOME: switch (quantifiedComparison.getOperator()) { case LESS_THAN: case LESS_THAN_OR_EQUAL: return false; case GREATER_THAN: case GREATER_THAN_OR_EQUAL: return true; } break; } throw new IllegalArgumentException("Unexpected quantifier: " + quantifiedComparison.getQuantifier()); }
private static boolean shouldCompareValueWithLowerBound(QuantifiedComparisonExpression quantifiedComparison) { switch (quantifiedComparison.getQuantifier()) { case ALL: switch (quantifiedComparison.getOperator()) { case LESS_THAN: case LESS_THAN_OR_EQUAL: return true; case GREATER_THAN: case GREATER_THAN_OR_EQUAL: return false; } break; case ANY: case SOME: switch (quantifiedComparison.getOperator()) { case LESS_THAN: case LESS_THAN_OR_EQUAL: return false; case GREATER_THAN: case GREATER_THAN_OR_EQUAL: return true; } break; } throw new IllegalArgumentException("Unexpected quantifier: " + quantifiedComparison.getQuantifier()); }
@Override protected String visitQuantifiedComparisonExpression(QuantifiedComparisonExpression node, Void context) { return new StringBuilder() .append("(") .append(process(node.getValue(), context)) .append(' ') .append(node.getOperator().getValue()) .append(' ') .append(node.getQuantifier().toString()) .append(' ') .append(process(node.getSubquery(), context)) .append(")") .toString(); }
@Override protected String visitQuantifiedComparisonExpression(QuantifiedComparisonExpression node, Void context) { return new StringBuilder() .append("(") .append(process(node.getValue(), context)) .append(' ') .append(node.getOperator().getValue()) .append(' ') .append(node.getQuantifier().toString()) .append(' ') .append(process(node.getSubquery(), context)) .append(")") .toString(); }
private Expression getBoundComparisons(QuantifiedComparisonExpression quantifiedComparison, Symbol minValue, Symbol maxValue) { if (quantifiedComparison.getOperator() == EQUAL && quantifiedComparison.getQuantifier() == ALL) { // A = ALL B <=> min B = max B && A = min B return combineConjuncts( new ComparisonExpression(EQUAL, minValue.toSymbolReference(), maxValue.toSymbolReference()), new ComparisonExpression(EQUAL, quantifiedComparison.getValue(), maxValue.toSymbolReference())); } if (EnumSet.of(LESS_THAN, LESS_THAN_OR_EQUAL, GREATER_THAN, GREATER_THAN_OR_EQUAL).contains(quantifiedComparison.getOperator())) { // A < ALL B <=> A < min B // A > ALL B <=> A > max B // A < ANY B <=> A < max B // A > ANY B <=> A > min B Symbol boundValue = shouldCompareValueWithLowerBound(quantifiedComparison) ? minValue : maxValue; return new ComparisonExpression(quantifiedComparison.getOperator(), quantifiedComparison.getValue(), boundValue.toSymbolReference()); } throw new IllegalArgumentException("Unsupported quantified comparison: " + quantifiedComparison); }
private Expression getBoundComparisons(QuantifiedComparisonExpression quantifiedComparison, Symbol minValue, Symbol maxValue) { if (quantifiedComparison.getOperator() == EQUAL && quantifiedComparison.getQuantifier() == ALL) { // A = ALL B <=> min B = max B && A = min B return combineConjuncts( new ComparisonExpression(EQUAL, minValue.toSymbolReference(), maxValue.toSymbolReference()), new ComparisonExpression(EQUAL, quantifiedComparison.getValue(), maxValue.toSymbolReference())); } if (EnumSet.of(LESS_THAN, LESS_THAN_OR_EQUAL, GREATER_THAN, GREATER_THAN_OR_EQUAL).contains(quantifiedComparison.getOperator())) { // A < ALL B <=> A < min B // A > ALL B <=> A > max B // A < ANY B <=> A < max B // A > ANY B <=> A > min B Symbol boundValue = shouldCompareValueWithLowerBound(quantifiedComparison) ? minValue : maxValue; return new ComparisonExpression(quantifiedComparison.getOperator(), quantifiedComparison.getValue(), boundValue.toSymbolReference()); } throw new IllegalArgumentException("Unsupported quantified comparison: " + quantifiedComparison); }
public Expression rewriteUsingBounds(QuantifiedComparisonExpression quantifiedComparison, Symbol minValue, Symbol maxValue, Symbol countAllValue, Symbol countNonNullValue) { BooleanLiteral emptySetResult = quantifiedComparison.getQuantifier().equals(ALL) ? TRUE_LITERAL : FALSE_LITERAL; Function<List<Expression>, Expression> quantifier = quantifiedComparison.getQuantifier().equals(ALL) ? ExpressionUtils::combineConjuncts : ExpressionUtils::combineDisjuncts; Expression comparisonWithExtremeValue = getBoundComparisons(quantifiedComparison, minValue, maxValue); return new SimpleCaseExpression( countAllValue.toSymbolReference(), ImmutableList.of(new WhenClause( new GenericLiteral("bigint", "0"), emptySetResult)), Optional.of(quantifier.apply(ImmutableList.of( comparisonWithExtremeValue, new SearchedCaseExpression( ImmutableList.of( new WhenClause( new ComparisonExpression(NOT_EQUAL, countAllValue.toSymbolReference(), countNonNullValue.toSymbolReference()), new Cast(new NullLiteral(), BooleanType.BOOLEAN.toString()))), Optional.of(emptySetResult)))))); }
public Expression rewriteUsingBounds(QuantifiedComparisonExpression quantifiedComparison, Symbol minValue, Symbol maxValue, Symbol countAllValue, Symbol countNonNullValue) { BooleanLiteral emptySetResult = quantifiedComparison.getQuantifier().equals(ALL) ? TRUE_LITERAL : FALSE_LITERAL; Function<List<Expression>, Expression> quantifier = quantifiedComparison.getQuantifier().equals(ALL) ? ExpressionUtils::combineConjuncts : ExpressionUtils::combineDisjuncts; Expression comparisonWithExtremeValue = getBoundComparisons(quantifiedComparison, minValue, maxValue); return new SimpleCaseExpression( countAllValue.toSymbolReference(), ImmutableList.of(new WhenClause( new GenericLiteral("bigint", "0"), emptySetResult)), Optional.of(quantifier.apply(ImmutableList.of( comparisonWithExtremeValue, new SearchedCaseExpression( ImmutableList.of( new WhenClause( new ComparisonExpression(NOT_EQUAL, countAllValue.toSymbolReference(), countNonNullValue.toSymbolReference()), new Cast(new NullLiteral(), BooleanType.BOOLEAN.toString()))), Optional.of(emptySetResult)))))); }
private PlanBuilder planQuantifiedApplyNode(PlanBuilder subPlan, QuantifiedComparisonExpression quantifiedComparison, boolean correlationAllowed) { subPlan = subPlan.appendProjections(ImmutableList.of(quantifiedComparison.getValue()), symbolAllocator, idAllocator); checkState(quantifiedComparison.getSubquery() instanceof SubqueryExpression); SubqueryExpression quantifiedSubquery = (SubqueryExpression) quantifiedComparison.getSubquery(); SubqueryExpression uncoercedQuantifiedSubquery = uncoercedSubquery(quantifiedSubquery); PlanBuilder subqueryPlan = createPlanBuilder(uncoercedQuantifiedSubquery); subqueryPlan = subqueryPlan.appendProjections(ImmutableList.of(quantifiedSubquery), symbolAllocator, idAllocator); QuantifiedComparisonExpression coercedQuantifiedComparison = new QuantifiedComparisonExpression( quantifiedComparison.getOperator(), quantifiedComparison.getQuantifier(), subPlan.translate(quantifiedComparison.getValue()).toSymbolReference(), subqueryPlan.translate(quantifiedSubquery).toSymbolReference()); Symbol coercedQuantifiedComparisonSymbol = symbolAllocator.newSymbol(coercedQuantifiedComparison, BOOLEAN); subPlan.getTranslations().put(quantifiedComparison, coercedQuantifiedComparisonSymbol); return appendApplyNode( subPlan, quantifiedComparison.getSubquery(), subqueryPlan.getRoot(), Assignments.of(coercedQuantifiedComparisonSymbol, coercedQuantifiedComparison), correlationAllowed); }
private PlanBuilder planQuantifiedApplyNode(PlanBuilder subPlan, QuantifiedComparisonExpression quantifiedComparison, boolean correlationAllowed) { subPlan = subPlan.appendProjections(ImmutableList.of(quantifiedComparison.getValue()), symbolAllocator, idAllocator); checkState(quantifiedComparison.getSubquery() instanceof SubqueryExpression); SubqueryExpression quantifiedSubquery = (SubqueryExpression) quantifiedComparison.getSubquery(); SubqueryExpression uncoercedQuantifiedSubquery = uncoercedSubquery(quantifiedSubquery); PlanBuilder subqueryPlan = createPlanBuilder(uncoercedQuantifiedSubquery); subqueryPlan = subqueryPlan.appendProjections(ImmutableList.of(quantifiedSubquery), symbolAllocator, idAllocator); QuantifiedComparisonExpression coercedQuantifiedComparison = new QuantifiedComparisonExpression( quantifiedComparison.getOperator(), quantifiedComparison.getQuantifier(), subPlan.translate(quantifiedComparison.getValue()).toSymbolReference(), subqueryPlan.translate(quantifiedSubquery).toSymbolReference()); Symbol coercedQuantifiedComparisonSymbol = symbolAllocator.newSymbol(coercedQuantifiedComparison, BOOLEAN); subPlan.getTranslations().put(quantifiedComparison, coercedQuantifiedComparisonSymbol); return appendApplyNode( subPlan, quantifiedComparison.getSubquery(), subqueryPlan.getRoot(), Assignments.of(coercedQuantifiedComparisonSymbol, coercedQuantifiedComparison), correlationAllowed); }
switch (quantifiedComparison.getQuantifier()) { case ALL: return planQuantifiedApplyNode(subPlan, quantifiedComparison, correlationAllowed); switch (quantifiedComparison.getQuantifier()) { case ALL: format("Unexpected quantified comparison: '%s %s'", quantifiedComparison.getOperator().getValue(), quantifiedComparison.getQuantifier()));
switch (quantifiedComparison.getQuantifier()) { case ALL: return planQuantifiedApplyNode(subPlan, quantifiedComparison, correlationAllowed); switch (quantifiedComparison.getQuantifier()) { case ALL: format("Unexpected quantified comparison: '%s %s'", quantifiedComparison.getOperator().getValue(), quantifiedComparison.getQuantifier()));