private static Expression complementIfNecessary(Expression expression, boolean complement) { return complement ? new NotExpression(expression) : expression; }
private static Expression not(Expression booleanExpression) { return new NotExpression(booleanExpression); }
private static NotExpression not(Expression expression) { return new NotExpression(expression); }
private List<Expression> extractDisjuncts(Type type, DiscreteValues discreteValues, SymbolReference reference) { List<Expression> values = discreteValues.getValues().stream() .map(object -> literalEncoder.toExpression(object, type)) .collect(toList()); // If values is empty, then the equatableValues was either ALL or NONE, both of which should already have been checked for checkState(!values.isEmpty()); Expression predicate; if (values.size() == 1) { predicate = new ComparisonExpression(EQUAL, reference, getOnlyElement(values)); } else { predicate = new InPredicate(reference, new InListExpression(values)); } if (!discreteValues.isWhiteList()) { predicate = new NotExpression(predicate); } return ImmutableList.of(predicate); }
@Override public Node visitLogicalNot(SqlBaseParser.LogicalNotContext context) { return new NotExpression(getLocation(context), (Expression) visit(context.booleanExpression())); }
@Override public Expression rewriteIsNotNullPredicate(IsNotNullPredicate node, Void context, ExpressionTreeRewriter<Void> treeRewriter) { Expression value = treeRewriter.rewrite(node.getValue(), context); return new NotExpression(new IsNullPredicate(value)); }
private Expression combineRangeWithExcludedPoints(Type type, SymbolReference reference, Range range, List<Expression> excludedPoints) { if (excludedPoints.isEmpty()) { return processRange(type, range, reference); } Expression excludedPointsExpression = new NotExpression(new InPredicate(reference, new InListExpression(excludedPoints))); if (excludedPoints.size() == 1) { excludedPointsExpression = new ComparisonExpression(NOT_EQUAL, reference, getOnlyElement(excludedPoints)); } return combineConjuncts(processRange(type, range, reference), excludedPointsExpression); }
@Override protected Object visitNotExpression(NotExpression node, Object context) { Object value = process(node.getValue(), context); if (value == null) { return null; } if (value instanceof Expression) { return new NotExpression(toExpression(value, type(node.getValue()))); } return !(Boolean) value; }
private static Expression isNotNull(Expression expression) { return new NotExpression(new IsNullPredicate(expression)); }
@Override protected ExtractionResult visitInPredicate(InPredicate node, Boolean complement) { if (!(node.getValueList() instanceof InListExpression)) { return super.visitInPredicate(node, complement); } InListExpression valueList = (InListExpression) node.getValueList(); checkState(!valueList.getValues().isEmpty(), "InListExpression should never be empty"); ImmutableList.Builder<Expression> disjuncts = ImmutableList.builder(); for (Expression expression : valueList.getValues()) { disjuncts.add(new ComparisonExpression(EQUAL, node.getValue(), expression)); } ExtractionResult extractionResult = process(or(disjuncts.build()), complement); // preserve original IN predicate as remaining predicate if (extractionResult.tupleDomain.isAll()) { Expression originalPredicate = node; if (complement) { originalPredicate = new NotExpression(originalPredicate); } return new ExtractionResult(extractionResult.tupleDomain, originalPredicate); } return extractionResult; }
@Override public Node visitDistinctFrom(SqlBaseParser.DistinctFromContext context) { Expression expression = new ComparisonExpression( getLocation(context), ComparisonExpression.Operator.IS_DISTINCT_FROM, (Expression) visit(context.value), (Expression) visit(context.right)); if (context.NOT() != null) { expression = new NotExpression(getLocation(context), expression); } return expression; }
@Override public Node visitBetween(SqlBaseParser.BetweenContext context) { Expression expression = new BetweenPredicate( getLocation(context), (Expression) visit(context.value), (Expression) visit(context.lower), (Expression) visit(context.upper)); if (context.NOT() != null) { expression = new NotExpression(getLocation(context), expression); } return expression; }
@Override public Node visitLike(SqlBaseParser.LikeContext context) { Expression result = new LikePredicate( getLocation(context), (Expression) visit(context.value), (Expression) visit(context.pattern), visitIfPresent(context.escape, Expression.class)); if (context.NOT() != null) { result = new NotExpression(getLocation(context), result); } return result; }
private Expression toPredicate(Domain domain, SymbolReference reference) { if (domain.getValues().isNone()) { return domain.isNullAllowed() ? new IsNullPredicate(reference) : FALSE_LITERAL; } if (domain.getValues().isAll()) { return domain.isNullAllowed() ? TRUE_LITERAL : new NotExpression(new IsNullPredicate(reference)); } List<Expression> disjuncts = new ArrayList<>(); disjuncts.addAll(domain.getValues().getValuesProcessor().transform( ranges -> extractDisjuncts(domain.getType(), ranges, reference), discreteValues -> extractDisjuncts(domain.getType(), discreteValues, reference), allOrNone -> { throw new IllegalStateException("Case should not be reachable"); })); // Add nullability disjuncts if (domain.isNullAllowed()) { disjuncts.add(new IsNullPredicate(reference)); } return combineDisjunctsWithDefault(disjuncts, TRUE_LITERAL); }
@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 public Node visitInList(SqlBaseParser.InListContext context) { Expression result = new InPredicate( getLocation(context), (Expression) visit(context.value), new InListExpression(getLocation(context), visit(context.expression(), Expression.class))); if (context.NOT() != null) { result = new NotExpression(getLocation(context), result); } return result; }
@Override public Node visitInSubquery(SqlBaseParser.InSubqueryContext context) { Expression result = new InPredicate( getLocation(context), (Expression) visit(context.value), new SubqueryExpression(getLocation(context), (Query) visit(context.query()))); if (context.NOT() != null) { result = new NotExpression(getLocation(context), result); } return result; }
@Test public void testNormalize() { assertNormalize(new ComparisonExpression(EQUAL, name("a"), new LongLiteral("1"))); assertNormalize(new IsNullPredicate(name("a"))); assertNormalize(new NotExpression(new LikePredicate(name("a"), new StringLiteral("x%"), Optional.empty()))); assertNormalize( new NotExpression(new ComparisonExpression(EQUAL, name("a"), new LongLiteral("1"))), new ComparisonExpression(NOT_EQUAL, name("a"), new LongLiteral("1"))); assertNormalize( new NotExpression(new ComparisonExpression(NOT_EQUAL, name("a"), new LongLiteral("1"))), new ComparisonExpression(EQUAL, name("a"), new LongLiteral("1"))); // Cannot normalize IS DISTINCT FROM yet assertNormalize(new NotExpression(new ComparisonExpression(IS_DISTINCT_FROM, name("a"), new LongLiteral("1")))); }
@Test public void testBetween() { assertExpression("1 BETWEEN 2 AND 3", new BetweenPredicate(new LongLiteral("1"), new LongLiteral("2"), new LongLiteral("3"))); assertExpression("1 NOT BETWEEN 2 AND 3", new NotExpression(new BetweenPredicate(new LongLiteral("1"), new LongLiteral("2"), new LongLiteral("3")))); }
@Test public void testExists() { assertStatement("SELECT EXISTS(SELECT 1)", simpleQuery(selectList(exists(simpleQuery(selectList(new LongLiteral("1"))))))); assertStatement( "SELECT EXISTS(SELECT 1) = EXISTS(SELECT 2)", simpleQuery( selectList(new ComparisonExpression( ComparisonExpression.Operator.EQUAL, exists(simpleQuery(selectList(new LongLiteral("1")))), exists(simpleQuery(selectList(new LongLiteral("2")))))))); assertStatement( "SELECT NOT EXISTS(SELECT 1) = EXISTS(SELECT 2)", simpleQuery( selectList( new NotExpression( new ComparisonExpression( ComparisonExpression.Operator.EQUAL, exists(simpleQuery(selectList(new LongLiteral("1")))), exists(simpleQuery(selectList(new LongLiteral("2"))))))))); assertStatement( "SELECT (NOT EXISTS(SELECT 1)) = EXISTS(SELECT 2)", simpleQuery( selectList( new ComparisonExpression( ComparisonExpression.Operator.EQUAL, new NotExpression(exists(simpleQuery(selectList(new LongLiteral("1"))))), exists(simpleQuery(selectList(new LongLiteral("2")))))))); }