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); }
@Override protected Type visitQuantifiedComparisonExpression(QuantifiedComparisonExpression node, StackableAstVisitorContext<Context> context) { Expression value = node.getValue(); process(value, context); Expression subquery = node.getSubquery(); process(subquery, context); Type comparisonType = coerceToSingleType(context, node, "Value expression and result of subquery must be of the same type for quantified comparison: %s vs %s", value, subquery); switch (node.getOperator()) { case LESS_THAN: case LESS_THAN_OR_EQUAL: case GREATER_THAN: case GREATER_THAN_OR_EQUAL: if (!comparisonType.isOrderable()) { throw new SemanticException(TYPE_MISMATCH, node, "Type [%s] must be orderable in order to be used in quantified comparison", comparisonType); } break; case EQUAL: case NOT_EQUAL: if (!comparisonType.isComparable()) { throw new SemanticException(TYPE_MISMATCH, node, "Type [%s] must be comparable in order to be used in quantified comparison", comparisonType); } break; default: throw new IllegalStateException(format("Unexpected comparison type: %s", node.getOperator())); } return setExpressionType(node, BOOLEAN); }
@Override protected Type visitQuantifiedComparisonExpression(QuantifiedComparisonExpression node, StackableAstVisitorContext<Context> context) { Expression value = node.getValue(); process(value, context); Expression subquery = node.getSubquery(); process(subquery, context); Type comparisonType = coerceToSingleType(context, node, "Value expression and result of subquery must be of the same type for quantified comparison: %s vs %s", value, subquery); switch (node.getOperator()) { case LESS_THAN: case LESS_THAN_OR_EQUAL: case GREATER_THAN: case GREATER_THAN_OR_EQUAL: if (!comparisonType.isOrderable()) { throw new SemanticException(TYPE_MISMATCH, node, "Type [%s] must be orderable in order to be used in quantified comparison", comparisonType); } break; case EQUAL: case NOT_EQUAL: if (!comparisonType.isComparable()) { throw new SemanticException(TYPE_MISMATCH, node, "Type [%s] must be comparable in order to be used in quantified comparison", comparisonType); } break; default: throw new IllegalStateException(format("Unexpected comparison type: %s", node.getOperator())); } return setExpressionType(node, BOOLEAN); }
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.getOperator()) { case EQUAL: switch (quantifiedComparison.getQuantifier()) { format("Unexpected quantified comparison: '%s %s'", quantifiedComparison.getOperator().getValue(), quantifiedComparison.getQuantifier()));
switch (quantifiedComparison.getOperator()) { case EQUAL: switch (quantifiedComparison.getQuantifier()) { format("Unexpected quantified comparison: '%s %s'", quantifiedComparison.getOperator().getValue(), quantifiedComparison.getQuantifier()));