This is an automated email from the ASF dual-hosted git repository. blue pushed a commit to branch 0.9.x in repository https://gitbox.apache.org/repos/asf/iceberg.git
commit 37a5709f5206ef84bd1b35a3a052a0c3d58355a8 Author: Ryan Blue <[email protected]> AuthorDate: Fri Jul 31 15:06:31 2020 -0700 Implement negate in bound predicates (#1282) --- .../iceberg/expressions/BoundLiteralPredicate.java | 5 ++ .../iceberg/expressions/BoundUnaryPredicate.java | 5 ++ .../iceberg/expressions/TestExpressionHelpers.java | 57 ++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/api/src/main/java/org/apache/iceberg/expressions/BoundLiteralPredicate.java b/api/src/main/java/org/apache/iceberg/expressions/BoundLiteralPredicate.java index 698b839..e0770ce 100644 --- a/api/src/main/java/org/apache/iceberg/expressions/BoundLiteralPredicate.java +++ b/api/src/main/java/org/apache/iceberg/expressions/BoundLiteralPredicate.java @@ -32,6 +32,11 @@ public class BoundLiteralPredicate<T> extends BoundPredicate<T> { this.literal = lit; } + @Override + public Expression negate() { + return new BoundLiteralPredicate<>(op().negate(), term(), literal); + } + public Literal<T> literal() { return literal; } diff --git a/api/src/main/java/org/apache/iceberg/expressions/BoundUnaryPredicate.java b/api/src/main/java/org/apache/iceberg/expressions/BoundUnaryPredicate.java index c5835ba..528dd1f 100644 --- a/api/src/main/java/org/apache/iceberg/expressions/BoundUnaryPredicate.java +++ b/api/src/main/java/org/apache/iceberg/expressions/BoundUnaryPredicate.java @@ -25,6 +25,11 @@ public class BoundUnaryPredicate<T> extends BoundPredicate<T> { } @Override + public Expression negate() { + return new BoundUnaryPredicate<>(op().negate(), term()); + } + + @Override public boolean isUnaryPredicate() { return true; } diff --git a/api/src/test/java/org/apache/iceberg/expressions/TestExpressionHelpers.java b/api/src/test/java/org/apache/iceberg/expressions/TestExpressionHelpers.java index 5bf336f..302e4a6 100644 --- a/api/src/test/java/org/apache/iceberg/expressions/TestExpressionHelpers.java +++ b/api/src/test/java/org/apache/iceberg/expressions/TestExpressionHelpers.java @@ -20,6 +20,9 @@ package org.apache.iceberg.expressions; import org.apache.iceberg.AssertHelpers; +import org.apache.iceberg.types.Types; +import org.apache.iceberg.types.Types.NestedField; +import org.apache.iceberg.types.Types.StructType; import org.junit.Assert; import org.junit.Test; @@ -29,11 +32,20 @@ import static org.apache.iceberg.expressions.Expressions.and; import static org.apache.iceberg.expressions.Expressions.bucket; import static org.apache.iceberg.expressions.Expressions.day; import static org.apache.iceberg.expressions.Expressions.equal; +import static org.apache.iceberg.expressions.Expressions.greaterThan; +import static org.apache.iceberg.expressions.Expressions.greaterThanOrEqual; import static org.apache.iceberg.expressions.Expressions.hour; +import static org.apache.iceberg.expressions.Expressions.in; +import static org.apache.iceberg.expressions.Expressions.isNull; import static org.apache.iceberg.expressions.Expressions.lessThan; +import static org.apache.iceberg.expressions.Expressions.lessThanOrEqual; import static org.apache.iceberg.expressions.Expressions.month; import static org.apache.iceberg.expressions.Expressions.not; +import static org.apache.iceberg.expressions.Expressions.notEqual; +import static org.apache.iceberg.expressions.Expressions.notIn; +import static org.apache.iceberg.expressions.Expressions.notNull; import static org.apache.iceberg.expressions.Expressions.or; +import static org.apache.iceberg.expressions.Expressions.rewriteNot; import static org.apache.iceberg.expressions.Expressions.truncate; import static org.apache.iceberg.expressions.Expressions.year; @@ -78,6 +90,51 @@ public class TestExpressionHelpers { } @Test + public void testRewriteNot() { + StructType struct = StructType.of(NestedField.optional(1, "a", Types.IntegerType.get())); + Expression[][] expressions = new Expression[][] { + // (rewritten pred, original pred) pairs + { isNull("a"), isNull("a") }, + { notNull("a"), not(isNull("a")) }, + { notNull("a"), notNull("a") }, + { isNull("a"), not(notNull("a")) }, + { equal("a", 5), equal("a", 5) }, + { notEqual("a", 5), not(equal("a", 5)) }, + { notEqual("a", 5), notEqual("a", 5) }, + { equal("a", 5), not(notEqual("a", 5)) }, + { in("a", 5, 6), in("a", 5, 6) }, + { notIn("a", 5, 6), not(in("a", 5, 6)) }, + { notIn("a", 5, 6), notIn("a", 5, 6) }, + { in("a", 5, 6), not(notIn("a", 5, 6)) }, + { lessThan("a", 5), lessThan("a", 5) }, + { greaterThanOrEqual("a", 5), not(lessThan("a", 5)) }, + { greaterThanOrEqual("a", 5), greaterThanOrEqual("a", 5) }, + { lessThan("a", 5), not(greaterThanOrEqual("a", 5)) }, + { lessThanOrEqual("a", 5), lessThanOrEqual("a", 5) }, + { greaterThan("a", 5), not(lessThanOrEqual("a", 5)) }, + { greaterThan("a", 5), greaterThan("a", 5) }, + { lessThanOrEqual("a", 5), not(greaterThan("a", 5)) }, + { or(equal("a", 5), isNull("a")), or(equal("a", 5), isNull("a")) }, + { and(notEqual("a", 5), notNull("a")), not(or(equal("a", 5), isNull("a"))) }, + { and(notEqual("a", 5), notNull("a")), and(notEqual("a", 5), notNull("a")) }, + { or(equal("a", 5), isNull("a")), not(and(notEqual("a", 5), notNull("a"))) }, + { or(equal("a", 5), notNull("a")), or(equal("a", 5), not(isNull("a"))) }, + }; + + for (Expression[] pair : expressions) { + // unbound rewrite + Assert.assertEquals(String.format("rewriteNot(%s) should be %s", pair[1], pair[0]), + pair[0].toString(), rewriteNot(pair[1]).toString()); + + // bound rewrite + Expression expectedBound = Binder.bind(struct, pair[0]); + Expression toRewriteBound = Binder.bind(struct, pair[1]); + Assert.assertEquals(String.format("rewriteNot(%s) should be %s", toRewriteBound, expectedBound), + expectedBound.toString(), rewriteNot(toRewriteBound).toString()); + } + } + + @Test public void testTransformExpressions() { Assert.assertEquals("Should produce the correct expression string", "year(ref(name=\"ts\")) == \"2019\"",
