[java-client] IN-list predicate Change-Id: Ia556196963153f9db64d67bc699f96cb920ecac6 Reviewed-on: http://gerrit.cloudera.org:8080/4530 Tested-by: Kudu Jenkins Reviewed-by: Jean-Daniel Cryans <jdcry...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/kudu/repo Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/cb92799b Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/cb92799b Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/cb92799b Branch: refs/heads/master Commit: cb92799baf195d70b80535d11e54447e25b71c42 Parents: 9b50bd5 Author: Dan Burkert <d...@cloudera.com> Authored: Fri Sep 23 13:50:58 2016 -0700 Committer: Dan Burkert <d...@cloudera.com> Committed: Thu Sep 29 01:30:31 2016 +0000 ---------------------------------------------------------------------- .../org/apache/kudu/client/KuduPredicate.java | 298 ++++++++++++++++--- .../org/apache/kudu/client/PartitionPruner.java | 19 +- .../org/apache/kudu/client/TestKuduClient.java | 17 ++ .../apache/kudu/client/TestKuduPredicate.java | 206 +++++++++++++ .../apache/kudu/client/TestPartitionPruner.java | 192 +++++++----- 5 files changed, 615 insertions(+), 117 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kudu/blob/cb92799b/java/kudu-client/src/main/java/org/apache/kudu/client/KuduPredicate.java ---------------------------------------------------------------------- diff --git a/java/kudu-client/src/main/java/org/apache/kudu/client/KuduPredicate.java b/java/kudu-client/src/main/java/org/apache/kudu/client/KuduPredicate.java index 03a6004..a78d63d 100644 --- a/java/kudu-client/src/main/java/org/apache/kudu/client/KuduPredicate.java +++ b/java/kudu-client/src/main/java/org/apache/kudu/client/KuduPredicate.java @@ -18,6 +18,7 @@ package org.apache.kudu.client; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Joiner; import com.google.common.base.Objects; import com.google.common.base.Preconditions; import com.google.common.primitives.UnsignedBytes; @@ -30,7 +31,13 @@ import org.apache.kudu.Type; import org.apache.kudu.annotations.InterfaceAudience; import org.apache.kudu.annotations.InterfaceStability; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; /** * A predicate which can be used to filter rows based on the value of a column. @@ -52,6 +59,8 @@ public class KuduPredicate { RANGE, /** A predicate which filters all null rows. */ IS_NOT_NULL, + /** A predicate which filters all rows not matching a list of values. */ + IN_LIST, } /** @@ -79,6 +88,9 @@ public class KuduPredicate { /** The exclusive upper bound value if this is a Range predicate. */ private final byte[] upper; + /** IN-list values. */ + private final byte[][] inListValues; + /** * Creates a new {@code KuduPredicate} on a boolean column. * @param column the column schema @@ -316,6 +328,80 @@ public class KuduPredicate { } /** + * Creates a new IN list predicate. + * + * The list must contain values of the correct type for the column. + * + * @param column the column that the predicate applies to + * @param values list of values which the column values must match + * @param <T> the type of values, must match the type of the column + * @return an IN list predicate + */ + public static <T> KuduPredicate newInListPredicate(final ColumnSchema column, List<T> values) { + if (values.isEmpty()) return none(column); + T t = values.get(0); + + SortedSet<byte[]> vals = new TreeSet<>(new Comparator<byte[]>() { + @Override + public int compare(byte[] a, byte[] b) { + return KuduPredicate.compare(column, a, b); + } + }); + + if (t instanceof Boolean) { + checkColumn(column, Type.BOOL); + for (T value : values) { + vals.add(Bytes.fromBoolean((Boolean) value)); + } + } else if (t instanceof Byte) { + checkColumn(column, Type.INT8); + for (T value : values) { + vals.add(new byte[] {(Byte) value}); + } + } else if (t instanceof Short) { + checkColumn(column, Type.INT16); + for (T value : values) { + vals.add(Bytes.fromShort((Short) value)); + } + } else if (t instanceof Integer) { + checkColumn(column, Type.INT32); + for (T value : values) { + vals.add(Bytes.fromInt((Integer) value)); + } + } else if (t instanceof Long) { + checkColumn(column, Type.INT64, Type.UNIXTIME_MICROS); + for (T value : values) { + vals.add(Bytes.fromLong((Long) value)); + } + } else if (t instanceof Float) { + checkColumn(column, Type.FLOAT); + for (T value : values) { + vals.add(Bytes.fromFloat((Float) value)); + } + } else if (t instanceof Double) { + checkColumn(column, Type.DOUBLE); + for (T value : values) { + vals.add(Bytes.fromDouble((Double) value)); + } + } else if (t instanceof String) { + checkColumn(column, Type.STRING); + for (T value : values) { + vals.add(Bytes.fromString((String) value)); + } + } else if (t instanceof byte[]) { + checkColumn(column, Type.BINARY); + for (T value : values) { + vals.add((byte[]) value); + } + } else { + throw new IllegalArgumentException(String.format("illegal type for IN list values: %s", + t.getClass().getName())); + } + + return buildInList(column, vals); + } + + /** * @param type the predicate type * @param column the column to which the predicate applies * @param lower the lower bound serialized value if this is a Range predicate, @@ -328,6 +414,20 @@ public class KuduPredicate { this.column = column; this.lower = lower; this.upper = upper; + this.inListValues = null; + } + + /** + * Constructor for IN list predicate. + * @param column the column to which the predicate applies + * @param inListValues the encoded IN list values + */ + private KuduPredicate(ColumnSchema column, byte[][] inListValues) { + this.column = column; + this.type = PredicateType.IN_LIST; + this.lower = null; + this.upper = null; + this.inListValues = inListValues; } /** @@ -367,57 +467,132 @@ public class KuduPredicate { KuduPredicate merge(KuduPredicate other) { Preconditions.checkArgument(column.equals(other.column), "predicates from different columns may not be merged"); - if (type == PredicateType.NONE || other.type == PredicateType.NONE) { - return none(column); - } - if (type == PredicateType.IS_NOT_NULL) { - // NOT NULL is less selective than all other predicate types, so the - // intersection of NOT NULL with any other predicate is just the other - // predicate. - // - // Note: this will no longer be true when an IS NULL predicate type is - // added. - return other; - } + // NONE predicates dominate. + if (other.type == PredicateType.NONE) return other; + + // NOT NULL is dominated by all other predicates. + // Note: this will no longer be true when an IS NULL predicate type is + // added. + if (other.type == PredicateType.IS_NOT_NULL) return this; - if (type == PredicateType.EQUALITY) { - if (other.type == PredicateType.EQUALITY) { - if (compare(lower, other.lower) != 0) { - return none(this.column); + switch (type) { + case NONE: return this; + case IS_NOT_NULL: return other; + case EQUALITY: { + if (other.type == PredicateType.EQUALITY) { + if (compare(column, lower, other.lower) != 0) { + return none(this.column); + } else { + return this; + } + } else if (other.type == PredicateType.RANGE) { + if (other.rangeContains(lower)) { + return this; + } else { + return none(this.column); + } } else { - return this; + Preconditions.checkState(other.type == PredicateType.IN_LIST); + return other.merge(this); } - } else { - if ((other.lower == null || compare(lower, other.lower) >= 0) && - (other.upper == null || compare(lower, other.upper) < 0)) { - return this; + } + case RANGE: { + if (other.type == PredicateType.EQUALITY || other.type == PredicateType.IN_LIST) { + return other.merge(this); } else { - return none(this.column); + Preconditions.checkState(other.type == PredicateType.RANGE); + byte[] newLower = other.lower == null || + (lower != null && compare(column, lower, other.lower) >= 0) ? lower : other.lower; + byte[] newUpper = other.upper == null || + (upper != null && compare(column, upper, other.upper) <= 0) ? upper : other.upper; + if (newLower != null && newUpper != null && compare(column, newLower, newUpper) >= 0) { + return none(column); + } else { + if (newLower != null && newUpper != null && areConsecutive(newLower, newUpper)) { + return new KuduPredicate(PredicateType.EQUALITY, column, newLower, null); + } else { + return new KuduPredicate(PredicateType.RANGE, column, newLower, newUpper); + } + } } } - } else { - if (other.type == PredicateType.EQUALITY) { - return other.merge(this); - } else { - byte[] newLower = other.lower == null || - (lower != null && compare(lower, other.lower) >= 0) ? lower : other.lower; - byte[] newUpper = other.upper == null || - (upper != null && compare(upper, other.upper) <= 0) ? upper : other.upper; - if (newLower != null && newUpper != null && compare(newLower, newUpper) >= 0) { - return none(column); - } else { - if (newLower != null && newUpper != null && areConsecutive(newLower, newUpper)) { - return new KuduPredicate(PredicateType.EQUALITY, column, newLower, null); + case IN_LIST: { + if (other.type == PredicateType.EQUALITY) { + if (this.inListContains(other.lower)) { + return other; } else { - return new KuduPredicate(PredicateType.RANGE, column, newLower, newUpper); + return none(column); + } + } else if (other.type == PredicateType.RANGE) { + List<byte[]> values = new ArrayList<>(); + for (byte[] value : inListValues) { + if (other.rangeContains(value)) { + values.add(value); + } } + return buildInList(column, values); + } else { + Preconditions.checkState(other.type == PredicateType.IN_LIST); + List<byte[]> values = new ArrayList<>(); + for (byte[] value : inListValues) { + if (other.inListContains(value)) { + values.add(value); + } + } + return buildInList(column, values); } } + default: throw new IllegalStateException(String.format("unknown predicate type %s", this)); } } /** + * Builds an IN list predicate from a collection of raw values. The collection + * must be sorted and deduplicated. + * + * @param column the column + * @param values the IN list values + * @return an IN list predicate + */ + private static KuduPredicate buildInList(ColumnSchema column, Collection<byte[]> values) { + // IN (true, false) predicates can be simplified to IS NOT NULL. + if (column.getType().getDataType() == Common.DataType.BOOL && values.size() > 1) { + return KuduPredicate.newIsNotNullPredicate(column); + } + + switch (values.size()) { + case 0: return KuduPredicate.none(column); + case 1: return new KuduPredicate(PredicateType.EQUALITY, column, + values.iterator().next(), null); + default: return new KuduPredicate(column, values.toArray(new byte[values.size()][])); + } + } + + /** + * @param value the value to check for + * @return {@code true} if this IN list predicate contains the value + */ + boolean inListContains(byte[] value) { + final Comparator<byte[]> comparator = new Comparator<byte[]>() { + @Override + public int compare(byte[] a, byte[] b) { + return KuduPredicate.compare(column, a, b); + } + }; + return Arrays.binarySearch(inListValues, value, comparator) >= 0; + } + + /** + * @param value the value to check + * @return {@code true} if this RANGE predicate contains the value + */ + boolean rangeContains(byte[] value) { + return (lower == null || compare(column, value, lower) >= 0) && + (upper == null || compare(column, value, upper) < 0); + } + + /** * @return the schema of the predicate column */ ColumnSchema getColumn() { @@ -426,7 +601,7 @@ public class KuduPredicate { /** * Convert the predicate to the protobuf representation. - * @return the protobuf message for this predicate. + * @return the protobuf message for this predicate */ @InterfaceAudience.Private public Common.ColumnPredicatePB toPB() { @@ -452,6 +627,13 @@ public class KuduPredicate { builder.setIsNotNull(builder.getIsNotNullBuilder()); break; } + case IN_LIST: { + Common.ColumnPredicatePB.InList.Builder inListBuilder = builder.getInListBuilder(); + for (byte[] value : inListValues) { + inListBuilder.addValues(ByteString.copyFrom(value)); + } + break; + } case NONE: throw new IllegalStateException( "can not convert None predicate to protobuf message"); default: throw new IllegalArgumentException( @@ -466,7 +648,7 @@ public class KuduPredicate { */ @InterfaceAudience.Private public static KuduPredicate fromPB(Schema schema, Common.ColumnPredicatePB pb) { - ColumnSchema column = schema.getColumn(pb.getColumn()); + final ColumnSchema column = schema.getColumn(pb.getColumn()); switch (pb.getPredicateCase()) { case EQUALITY: return new KuduPredicate(PredicateType.EQUALITY, column, @@ -479,18 +661,34 @@ public class KuduPredicate { } case IS_NOT_NULL: return newIsNotNullPredicate(column); + case IN_LIST: { + Common.ColumnPredicatePB.InList inList = pb.getInList(); + + SortedSet<byte[]> values = new TreeSet<>(new Comparator<byte[]>() { + @Override + public int compare(byte[] a, byte[] b) { + return KuduPredicate.compare(column, a, b); + } + }); + + for (ByteString value : inList.getValuesList()) { + values.add(value.toByteArray()); + } + return buildInList(column, values); + } default: throw new IllegalArgumentException("unknown predicate type"); } } /** - * Compares two bounds based on the type of this predicate's column. + * Compares two bounds based on the type of the column. + * @param column the column which the values belong to * @param a the first serialized value * @param b the second serialized value * @return the comparison of the serialized values based on the column type */ - private int compare(byte[] a, byte[] b) { + private static int compare(ColumnSchema column, byte[] a, byte[] b) { switch (column.getType().getDataType()) { case BOOL: return Boolean.compare(Bytes.getBoolean(a), Bytes.getBoolean(b)); @@ -583,6 +781,13 @@ public class KuduPredicate { } /** + * @return the IN list values. Always kept sorted and de-duplicated. + */ + byte[][] getInListValues() { + return inListValues; + } + + /** * Returns the maximum value for the integer type. * @param type an integer type * @return the maximum value @@ -674,6 +879,13 @@ public class KuduPredicate { column.getName(), valueToString(upper)); } } + case IN_LIST: { + List<String> strings = new ArrayList<>(inListValues.length); + for (byte[] value : inListValues) { + strings.add(valueToString(value)); + } + return String.format("`%s` IN (%s)", column.getName(), Joiner.on(", ").join(strings)); + } case IS_NOT_NULL: return String.format("`%s` IS NOT NULL", column.getName()); case NONE: return String.format("`%s` NONE", column.getName()); default: throw new IllegalArgumentException(String.format("unknown predicate type %s", type)); @@ -688,11 +900,13 @@ public class KuduPredicate { return type == that.type && column.equals(that.column) && Arrays.equals(lower, that.lower) && - Arrays.equals(upper, that.upper); + Arrays.equals(upper, that.upper) && + Arrays.deepEquals(inListValues, that.inListValues); } @Override public int hashCode() { - return Objects.hashCode(type, column, Arrays.hashCode(lower), Arrays.hashCode(upper)); + return Objects.hashCode(type, column, Arrays.hashCode(lower), + Arrays.hashCode(upper), Arrays.deepHashCode(inListValues)); } } http://git-wip-us.apache.org/repos/asf/kudu/blob/cb92799b/java/kudu-client/src/main/java/org/apache/kudu/client/PartitionPruner.java ---------------------------------------------------------------------- diff --git a/java/kudu-client/src/main/java/org/apache/kudu/client/PartitionPruner.java b/java/kudu-client/src/main/java/org/apache/kudu/client/PartitionPruner.java index 910083f..59c85d5 100644 --- a/java/kudu-client/src/main/java/org/apache/kudu/client/PartitionPruner.java +++ b/java/kudu-client/src/main/java/org/apache/kudu/client/PartitionPruner.java @@ -373,7 +373,12 @@ public class PartitionPruner { row.setRaw(idx, predicate.getLower()); pushedPredicates++; break; - case IS_NOT_NULL: break loop; + case IS_NOT_NULL: + break loop; + case IN_LIST: + row.setRaw(idx, predicate.getInListValues()[0]); + pushedPredicates++; + break; default: throw new IllegalArgumentException( String.format("unexpected predicate type can not be pushed into key: %s", predicate)); @@ -435,6 +440,13 @@ public class PartitionPruner { break loop; case IS_NOT_NULL: break loop; + case IN_LIST: { + byte[][] values = predicate.getInListValues(); + row.setRaw(idx, values[values.length - 1]); + pushedPredicates++; + finalPredicate = predicate; + break; + } default: throw new IllegalArgumentException( String.format("unexpected predicate type can not be pushed into key: %s", predicate)); @@ -444,9 +456,10 @@ public class PartitionPruner { // If no predicates were pushed, no need to do any more work. if (pushedPredicates == 0) return AsyncKuduClient.EMPTY_ARRAY; - // Step 2: If the final predicate is an equality predicate, increment the + // Step 2: If the final predicate is an equality or IN-list predicate, increment the // key to convert it to an exclusive upper bound. - if (finalPredicate.getType() == KuduPredicate.PredicateType.EQUALITY) { + if (finalPredicate.getType() == KuduPredicate.PredicateType.EQUALITY || + finalPredicate.getType() == KuduPredicate.PredicateType.IN_LIST) { incrementKey(row, rangePartitionColumnIdxs.subList(0, pushedPredicates)); } http://git-wip-us.apache.org/repos/asf/kudu/blob/cb92799b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduClient.java ---------------------------------------------------------------------- diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduClient.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduClient.java index e59ea8e..d78a433 100644 --- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduClient.java +++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduClient.java @@ -337,6 +337,23 @@ public class TestKuduClient extends BaseKuduTest { KuduPredicate.newIsNotNullPredicate(schema.getColumn("c2")), KuduPredicate.newIsNotNullPredicate(schema.getColumn("key")) ).size()); + + // IN list + assertEquals(3, scanTableToStrings(table, + KuduPredicate.newInListPredicate(schema.getColumn("key"), + ImmutableList.of("key_30", "key_01", "invalid", "key_99")) + ).size()); + assertEquals(3, scanTableToStrings(table, + KuduPredicate.newInListPredicate(schema.getColumn("c2"), + ImmutableList.of("c2_30", "c2_1", "invalid", "c2_99")) + ).size()); + assertEquals(2, scanTableToStrings(table, + KuduPredicate.newInListPredicate(schema.getColumn("c2"), + ImmutableList.of("c2_30", "c2_1", "invalid", "c2_99")), + KuduPredicate.newIsNotNullPredicate(schema.getColumn("c2")), + KuduPredicate.newInListPredicate(schema.getColumn("key"), + ImmutableList.of("key_30", "key_45", "invalid", "key_99")) + ).size()); } /** http://git-wip-us.apache.org/repos/asf/kudu/blob/cb92799b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduPredicate.java ---------------------------------------------------------------------- diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduPredicate.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduPredicate.java index 3ad39fe..785594f 100644 --- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduPredicate.java +++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestKuduPredicate.java @@ -18,11 +18,15 @@ package org.apache.kudu.client; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + import org.junit.Assert; import org.junit.Test; import org.apache.kudu.ColumnSchema; import org.apache.kudu.Type; +import java.util.Arrays; + import static org.apache.kudu.client.KuduPredicate.ComparisonOp.EQUAL; import static org.apache.kudu.client.KuduPredicate.ComparisonOp.GREATER; import static org.apache.kudu.client.KuduPredicate.ComparisonOp.GREATER_EQUAL; @@ -64,6 +68,18 @@ public class TestKuduPredicate { return new KuduPredicate(RANGE, intCol, Bytes.fromInt(lower), Bytes.fromInt(upper)); } + private static KuduPredicate intInList(Integer... values) { + return KuduPredicate.newInListPredicate(intCol, Arrays.asList(values)); + } + + private static KuduPredicate boolInList(Boolean... values) { + return KuduPredicate.newInListPredicate(boolCol, Arrays.asList(values)); + } + + private static KuduPredicate stringInList(String... values) { + return KuduPredicate.newInListPredicate(stringCol, Arrays.asList(values)); + } + private void testMerge(KuduPredicate a, KuduPredicate b, KuduPredicate expected) { @@ -351,6 +367,113 @@ public class TestKuduPredicate { KuduPredicate.newComparisonPredicate(intCol, EQUAL, 7), KuduPredicate.none(intCol)); + // IN list + IN list + + // | | | + // | | | + testMerge(intInList(0, 10, 20), + intInList(20, 10, 20, 30), + intInList(10, 20)); + + // | | + // | | + testMerge(intInList(0, 20), + intInList(15, 30), + KuduPredicate.none(intCol)); + + // IN list + NOT NULL + testMerge(intInList(10), + KuduPredicate.newIsNotNullPredicate(intCol), + KuduPredicate.newComparisonPredicate(intCol, EQUAL, 10)); + + testMerge(intInList(10, -100), + KuduPredicate.newIsNotNullPredicate(intCol), + intInList(-100, 10)); + + // IN list + Equality + + // | | | + // | + // = + // | + testMerge(intInList(0, 10, 20), + KuduPredicate.newComparisonPredicate(intCol, EQUAL, 10), + KuduPredicate.newComparisonPredicate(intCol, EQUAL, 10)); + + // | | | + // | + // = + // none + testMerge(intInList(0, 10, 20), + KuduPredicate.newComparisonPredicate(intCol, EQUAL, 30), + KuduPredicate.none(intCol)); + + // IN list + Range + + // | | | | | + // [---) + // = + // | | + testMerge(intInList(0, 10, 20, 30, 40), + intRange(10, 30), + intInList(10, 20)); + + // | | | | + // [--) + // = + // none + testMerge(intInList(0, 10, 20, 30), + intRange(25, 30), + KuduPredicate.none(intCol)); + + // | | | | + // [------> + // = + // | | + testMerge(intInList(0, 10, 20, 30), + KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 15), + intInList(20, 30)); + + // | | | + // [------> + // = + // | + testMerge(intInList(0, 10, 20), + KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 15), + KuduPredicate.newComparisonPredicate(intCol, EQUAL, 20)); + + // | | + // [------> + // = + // none + testMerge(intInList(0, 10), + KuduPredicate.newComparisonPredicate(intCol, GREATER_EQUAL, 15), + KuduPredicate.none(intCol)); + + // | | | | + // <--) + // = + // | | + testMerge(intInList(0, 10, 20, 30), + KuduPredicate.newComparisonPredicate(intCol, LESS, 15), + intInList(0, 10)); + + // | | | + // <--) + // = + // | + testMerge(intInList(0, 10, 20), + KuduPredicate.newComparisonPredicate(intCol, LESS, 10), + KuduPredicate.newComparisonPredicate(intCol, EQUAL, 0)); + + // | | + // <--) + // = + // none + testMerge(intInList(10, 20), + KuduPredicate.newComparisonPredicate(intCol, LESS, 5), + KuduPredicate.none(intCol)); + // None // None AND @@ -431,6 +554,22 @@ public class TestKuduPredicate { KuduPredicate.newComparisonPredicate(stringCol, LESS, "a\0\0"), new KuduPredicate(RANGE, stringCol, Bytes.fromString("a"), Bytes.fromString("a\0\0"))); + + // [-----> + // | | | | + // = + // [--) + testMerge(KuduPredicate.newComparisonPredicate(stringCol, GREATER_EQUAL, "a"), + stringInList("a", "c", "b", ""), + stringInList("a", "b", "c")); + + // IS NOT NULL + // | | | | + // = + // [--) + testMerge(KuduPredicate.newIsNotNullPredicate(stringCol), + stringInList("a", "c", "b", ""), + stringInList("", "a", "b", "c")); } @Test @@ -467,6 +606,21 @@ public class TestKuduPredicate { // b <= true Assert.assertEquals(KuduPredicate.newIsNotNullPredicate(boolCol), KuduPredicate.newComparisonPredicate(boolCol, LESS_EQUAL, true)); + + // b IN () + Assert.assertEquals(KuduPredicate.none(boolCol), boolInList()); + + // b IN (true) + Assert.assertEquals(KuduPredicate.newComparisonPredicate(boolCol, EQUAL, true), + boolInList(true, true, true)); + + // b IN (false) + Assert.assertEquals(KuduPredicate.newComparisonPredicate(boolCol, EQUAL, false), + boolInList(false)); + + // b IN (false, true) + Assert.assertEquals(KuduPredicate.newIsNotNullPredicate(boolCol), + boolInList(false, true, false, true)); } /** @@ -493,6 +647,10 @@ public class TestKuduPredicate { new byte[] { (byte) 0 }, new byte[] { (byte) 10 })); + testMerge(KuduPredicate.newInListPredicate(byteCol, ImmutableList.of((byte) 12, (byte) 14, (byte) 16, (byte) 18)), + KuduPredicate.newInListPredicate(byteCol, ImmutableList.of((byte) 14, (byte) 18, (byte) 20)), + KuduPredicate.newInListPredicate(byteCol, ImmutableList.of((byte) 14, (byte) 18))); + testMerge(KuduPredicate.newComparisonPredicate(shortCol, GREATER_EQUAL, 0), KuduPredicate.newComparisonPredicate(shortCol, LESS, 10), new KuduPredicate(RANGE, @@ -500,6 +658,10 @@ public class TestKuduPredicate { Bytes.fromShort((short) 0), Bytes.fromShort((short) 10))); + testMerge(KuduPredicate.newInListPredicate(shortCol, ImmutableList.of((short) 12, (short) 14, (short) 16, (short) 18)), + KuduPredicate.newInListPredicate(shortCol, ImmutableList.of((short) 14, (short) 18, (short) 20)), + KuduPredicate.newInListPredicate(shortCol, ImmutableList.of((short) 14, (short) 18))); + testMerge(KuduPredicate.newComparisonPredicate(longCol, GREATER_EQUAL, 0), KuduPredicate.newComparisonPredicate(longCol, LESS, 10), new KuduPredicate(RANGE, @@ -507,6 +669,10 @@ public class TestKuduPredicate { Bytes.fromLong(0), Bytes.fromLong(10))); + testMerge(KuduPredicate.newInListPredicate(longCol, ImmutableList.of(12L, 14L, 16L, 18L)), + KuduPredicate.newInListPredicate(longCol, ImmutableList.of(14L, 18L, 20L)), + KuduPredicate.newInListPredicate(longCol, ImmutableList.of(14L, 18L))); + testMerge(KuduPredicate.newComparisonPredicate(floatCol, GREATER_EQUAL, 123.45f), KuduPredicate.newComparisonPredicate(floatCol, LESS, 678.90f), new KuduPredicate(RANGE, @@ -514,6 +680,10 @@ public class TestKuduPredicate { Bytes.fromFloat(123.45f), Bytes.fromFloat(678.90f))); + testMerge(KuduPredicate.newInListPredicate(floatCol, ImmutableList.of(12f, 14f, 16f, 18f)), + KuduPredicate.newInListPredicate(floatCol, ImmutableList.of(14f, 18f, 20f)), + KuduPredicate.newInListPredicate(floatCol, ImmutableList.of(14f, 18f))); + testMerge(KuduPredicate.newComparisonPredicate(doubleCol, GREATER_EQUAL, 123.45), KuduPredicate.newComparisonPredicate(doubleCol, LESS, 678.90), new KuduPredicate(RANGE, @@ -521,6 +691,10 @@ public class TestKuduPredicate { Bytes.fromDouble(123.45), Bytes.fromDouble(678.90))); + testMerge(KuduPredicate.newInListPredicate(doubleCol, ImmutableList.of(12d, 14d, 16d, 18d)), + KuduPredicate.newInListPredicate(doubleCol, ImmutableList.of(14d, 18d, 20d)), + KuduPredicate.newInListPredicate(doubleCol, ImmutableList.of(14d, 18d))); + testMerge(KuduPredicate.newComparisonPredicate(binaryCol, GREATER_EQUAL, new byte[] { 0, 1, 2, 3, 4, 5, 6 }), KuduPredicate.newComparisonPredicate(binaryCol, LESS, new byte[] { 10 }), @@ -528,6 +702,10 @@ public class TestKuduPredicate { binaryCol, new byte[] { 0, 1, 2, 3, 4, 5, 6 }, new byte[] { 10 })); + + testMerge(KuduPredicate.newInListPredicate(binaryCol, ImmutableList.of("a".getBytes(), "b".getBytes(), "c".getBytes(), "d".getBytes())), + KuduPredicate.newInListPredicate(binaryCol, ImmutableList.of("b".getBytes(), "d".getBytes(), "e".getBytes())), + KuduPredicate.newInListPredicate(binaryCol, ImmutableList.of("b".getBytes(), "d".getBytes()))); } @Test @@ -624,5 +802,33 @@ public class TestKuduPredicate { KuduPredicate.newComparisonPredicate(stringCol, EQUAL, "my string").toString()); Assert.assertEquals("`binary` = 0xAB01CD", KuduPredicate.newComparisonPredicate( binaryCol, EQUAL, new byte[] { (byte) 0xAB, (byte) 0x01, (byte) 0xCD }).toString()); + Assert.assertEquals("`int` IN (-10, 0, 10)", + intInList(10, 0, -10).toString()); + Assert.assertEquals("`string` IS NOT NULL", + KuduPredicate.newIsNotNullPredicate(stringCol).toString()); + + Assert.assertEquals("`bool` = true", KuduPredicate.newInListPredicate( + boolCol, ImmutableList.of(true)).toString()); + Assert.assertEquals("`bool` = false", KuduPredicate.newInListPredicate( + boolCol, ImmutableList.of(false)).toString()); + Assert.assertEquals("`bool` IS NOT NULL", KuduPredicate.newInListPredicate( + boolCol, ImmutableList.of(false, true, true)).toString()); + Assert.assertEquals("`byte` IN (1, 10, 100)", KuduPredicate.newInListPredicate( + byteCol, ImmutableList.of((byte) 1, (byte) 10, (byte) 100)).toString()); + Assert.assertEquals("`short` IN (1, 10, 100)", KuduPredicate.newInListPredicate( + shortCol, ImmutableList.of((short) 1, (short) 100, (short) 10)).toString()); + Assert.assertEquals("`int` IN (1, 10, 100)", KuduPredicate.newInListPredicate( + intCol, ImmutableList.of(1, 100, 10)).toString()); + Assert.assertEquals("`long` IN (1, 10, 100)", KuduPredicate.newInListPredicate( + longCol, ImmutableList.of(1L, 100L, 10L)).toString()); + Assert.assertEquals("`float` IN (78.9, 123.456)", KuduPredicate.newInListPredicate( + floatCol, ImmutableList.of(123.456f, 78.9f)).toString()); + Assert.assertEquals("`double` IN (78.9, 123.456)", KuduPredicate.newInListPredicate( + doubleCol, ImmutableList.of(123.456d, 78.9d)).toString()); + Assert.assertEquals("`string` IN (\"a\", \"my string\")", + KuduPredicate.newInListPredicate(stringCol, ImmutableList.of("my string", "a")).toString()); + Assert.assertEquals("`binary` IN (0x00, 0xAB01CD)", KuduPredicate.newInListPredicate( + binaryCol, ImmutableList.of(new byte[] { (byte) 0xAB, (byte) 0x01, (byte) 0xCD }, + new byte[] { (byte) 0x00 })).toString()); } } http://git-wip-us.apache.org/repos/asf/kudu/blob/cb92799b/java/kudu-client/src/test/java/org/apache/kudu/client/TestPartitionPruner.java ---------------------------------------------------------------------- diff --git a/java/kudu-client/src/test/java/org/apache/kudu/client/TestPartitionPruner.java b/java/kudu-client/src/test/java/org/apache/kudu/client/TestPartitionPruner.java index 6c3faff..3a5610f 100644 --- a/java/kudu-client/src/test/java/org/apache/kudu/client/TestPartitionPruner.java +++ b/java/kudu-client/src/test/java/org/apache/kudu/client/TestPartitionPruner.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableList; import org.apache.kudu.ColumnSchema; import org.apache.kudu.Schema; import org.apache.kudu.Type; +import org.apache.kudu.client.KuduPredicate.ComparisonOp; import org.junit.Test; import java.util.ArrayList; @@ -277,124 +278,144 @@ public class TestPartitionPruner extends BaseKuduTest { // c < -10 assertEquals(1, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.LESS, -10))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.LESS, -10))); // c = -10 assertEquals(1, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.EQUAL, -10))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.EQUAL, -10))); // c < 10 assertEquals(2, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.LESS, 10))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.LESS, 10))); // c < 100 assertEquals(3, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.LESS, 100))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.LESS, 100))); // c >= -10 assertEquals(3, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.GREATER_EQUAL, -10))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.GREATER_EQUAL, -10))); // c >= 0 assertEquals(3, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.GREATER_EQUAL, -10))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.GREATER_EQUAL, -10))); // c >= 5 assertEquals(2, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.GREATER_EQUAL, 5))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.GREATER_EQUAL, 5))); // c >= 10 assertEquals(2, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.GREATER_EQUAL, 10))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.GREATER_EQUAL, 10))); // c >= 100 assertEquals(1, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.GREATER_EQUAL, 100))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.GREATER_EQUAL, 100))); // c >= -10 // c < 0 assertEquals(1, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.GREATER_EQUAL, -10), - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.LESS, 0))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.GREATER_EQUAL, -10), + KuduPredicate.newComparisonPredicate(c, ComparisonOp.LESS, 0))); // c >= 5 // c < 100 assertEquals(2, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.GREATER_EQUAL, 5), - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.LESS, 100))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.GREATER_EQUAL, 5), + KuduPredicate.newComparisonPredicate(c, ComparisonOp.LESS, 100))); // b = "" assertEquals(3, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(b, KuduPredicate.ComparisonOp.EQUAL, ""))); + KuduPredicate.newComparisonPredicate(b, ComparisonOp.EQUAL, ""))); // b >= "z" assertEquals(3, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(b, KuduPredicate.ComparisonOp.GREATER_EQUAL, "z"))); + KuduPredicate.newComparisonPredicate(b, ComparisonOp.GREATER_EQUAL, "z"))); // b < "a" assertEquals(3, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(b, KuduPredicate.ComparisonOp.LESS, "a"))); + KuduPredicate.newComparisonPredicate(b, ComparisonOp.LESS, "a"))); // b >= "m" // b < "z" assertEquals(3, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(b, KuduPredicate.ComparisonOp.GREATER_EQUAL, "m"), - KuduPredicate.newComparisonPredicate(b, KuduPredicate.ComparisonOp.LESS, "z"))); + KuduPredicate.newComparisonPredicate(b, ComparisonOp.GREATER_EQUAL, "m"), + KuduPredicate.newComparisonPredicate(b, ComparisonOp.LESS, "z"))); // c >= 10 // b >= "r" assertEquals(1, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.GREATER_EQUAL, 10), - KuduPredicate.newComparisonPredicate(b, KuduPredicate.ComparisonOp.GREATER_EQUAL, "r"))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.GREATER_EQUAL, 10), + KuduPredicate.newComparisonPredicate(b, ComparisonOp.GREATER_EQUAL, "r"))); // c >= 10 // b < "r" assertEquals(2, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.GREATER_EQUAL, 10), - KuduPredicate.newComparisonPredicate(b, KuduPredicate.ComparisonOp.LESS, "r"))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.GREATER_EQUAL, 10), + KuduPredicate.newComparisonPredicate(b, ComparisonOp.LESS, "r"))); // c = 10 // b < "r" assertEquals(1, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.EQUAL, 10), - KuduPredicate.newComparisonPredicate(b, KuduPredicate.ComparisonOp.LESS, "r"))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.EQUAL, 10), + KuduPredicate.newComparisonPredicate(b, ComparisonOp.LESS, "r"))); // c < 0 // b < "m" assertEquals(1, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.EQUAL, 0), - KuduPredicate.newComparisonPredicate(b, KuduPredicate.ComparisonOp.LESS, "m"))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.EQUAL, 0), + KuduPredicate.newComparisonPredicate(b, ComparisonOp.LESS, "m"))); // c < 0 // b < "z" assertEquals(1, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.LESS, 0), - KuduPredicate.newComparisonPredicate(b, KuduPredicate.ComparisonOp.LESS, "z"))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.LESS, 0), + KuduPredicate.newComparisonPredicate(b, ComparisonOp.LESS, "z"))); // c = 0 // b = "m\0" assertEquals(1, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.EQUAL, 0), - KuduPredicate.newComparisonPredicate(b, KuduPredicate.ComparisonOp.EQUAL, "m\0"))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.EQUAL, 0), + KuduPredicate.newComparisonPredicate(b, ComparisonOp.EQUAL, "m\0"))); // c = 0 // b < "m" assertEquals(1, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.EQUAL, 0), - KuduPredicate.newComparisonPredicate(b, KuduPredicate.ComparisonOp.LESS, "m"))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.EQUAL, 0), + KuduPredicate.newComparisonPredicate(b, ComparisonOp.LESS, "m"))); // c = 0 // b < "m\0" assertEquals(2, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.EQUAL, 0), - KuduPredicate.newComparisonPredicate(b, KuduPredicate.ComparisonOp.LESS, "m\0"))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.EQUAL, 0), + KuduPredicate.newComparisonPredicate(b, ComparisonOp.LESS, "m\0"))); // c = 0 // c = 2 assertEquals(0, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.EQUAL, 0), - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.EQUAL, 2))); + KuduPredicate.newComparisonPredicate(c, ComparisonOp.EQUAL, 0), + KuduPredicate.newComparisonPredicate(c, ComparisonOp.EQUAL, 2))); + + // a IN (1, 2) + assertEquals(1, countPartitions(table, partitions, + KuduPredicate.newInListPredicate(c, ImmutableList.of((byte) 1, (byte) 2)))); + + // a IN (0, 1, 2) + assertEquals(2, countPartitions(table, partitions, + KuduPredicate.newInListPredicate(c, ImmutableList.of((byte) 0, (byte) 1, (byte) 2)))); + + // a IN (-10, 0) + // B < "m" + assertEquals(1, countPartitions(table, partitions, + KuduPredicate.newInListPredicate(c, ImmutableList.of((byte) -10, (byte) 0)), + KuduPredicate.newComparisonPredicate(b, ComparisonOp.LESS, "m"))); + + // a IN (-10, 0) + // B < "m\0" + assertEquals(2, countPartitions(table, partitions, + KuduPredicate.newInListPredicate(c, ImmutableList.of((byte) -10, (byte) 0)), + KuduPredicate.newComparisonPredicate(b, ComparisonOp.LESS, "m\0"))); } @Test @@ -425,41 +446,45 @@ public class TestPartitionPruner extends BaseKuduTest { // a = 0; assertEquals(2, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(a, KuduPredicate.ComparisonOp.EQUAL, 0))); + KuduPredicate.newComparisonPredicate(a, ComparisonOp.EQUAL, 0))); // a >= 0; assertEquals(4, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(a, KuduPredicate.ComparisonOp.GREATER_EQUAL, 0))); + KuduPredicate.newComparisonPredicate(a, ComparisonOp.GREATER_EQUAL, 0))); // a >= 0; // a < 1; assertEquals(2, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(a, KuduPredicate.ComparisonOp.GREATER_EQUAL, 0), - KuduPredicate.newComparisonPredicate(a, KuduPredicate.ComparisonOp.LESS, 1))); + KuduPredicate.newComparisonPredicate(a, ComparisonOp.GREATER_EQUAL, 0), + KuduPredicate.newComparisonPredicate(a, ComparisonOp.LESS, 1))); // a >= 0; // a < 2; assertEquals(4, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(a, KuduPredicate.ComparisonOp.GREATER_EQUAL, 0), - KuduPredicate.newComparisonPredicate(a, KuduPredicate.ComparisonOp.LESS, 2))); + KuduPredicate.newComparisonPredicate(a, ComparisonOp.GREATER_EQUAL, 0), + KuduPredicate.newComparisonPredicate(a, ComparisonOp.LESS, 2))); // b = 1; assertEquals(4, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(b, KuduPredicate.ComparisonOp.EQUAL, 1))); + KuduPredicate.newComparisonPredicate(b, ComparisonOp.EQUAL, 1))); // b = 1; // c = 2; assertEquals(2, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(b, KuduPredicate.ComparisonOp.EQUAL, 1), - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.EQUAL, 2))); + KuduPredicate.newComparisonPredicate(b, ComparisonOp.EQUAL, 1), + KuduPredicate.newComparisonPredicate(c, ComparisonOp.EQUAL, 2))); // a = 0; // b = 1; // c = 2; assertEquals(1, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(a, KuduPredicate.ComparisonOp.EQUAL, 0), - KuduPredicate.newComparisonPredicate(b, KuduPredicate.ComparisonOp.EQUAL, 1), - KuduPredicate.newComparisonPredicate(c, KuduPredicate.ComparisonOp.EQUAL, 2))); + KuduPredicate.newComparisonPredicate(a, ComparisonOp.EQUAL, 0), + KuduPredicate.newComparisonPredicate(b, ComparisonOp.EQUAL, 1), + KuduPredicate.newComparisonPredicate(c, ComparisonOp.EQUAL, 2))); + + // a IN (0, 10) + assertEquals(4, countPartitions(table, partitions, + KuduPredicate.newInListPredicate(c, ImmutableList.of((byte) 0, (byte) 10)))); } @Test @@ -468,9 +493,9 @@ public class TestPartitionPruner extends BaseKuduTest { // (host STRING, metric STRING, timestamp UNIXTIME_MICROS, value DOUBLE) // PRIMARY KEY (host, metric, time) // DISTRIBUTE BY - // RANGE(time) SPLIT ROWS [(10)], - // (PARTITION VALUES < 10, - // PARTITION 10 <= VALUES); + // RANGE(time) + // (PARTITION VALUES < 10, + // PARTITION VALUES >= 10); // HASH (host, metric) 2 PARTITIONS; ColumnSchema host = new ColumnSchema.ColumnSchemaBuilder("host", Type.STRING).key(true).build(); @@ -498,55 +523,55 @@ public class TestPartitionPruner extends BaseKuduTest { // host = "a" assertEquals(4, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(host, KuduPredicate.ComparisonOp.EQUAL, "a"))); + KuduPredicate.newComparisonPredicate(host, ComparisonOp.EQUAL, "a"))); // host = "a" // metric = "a" assertEquals(2, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(host, KuduPredicate.ComparisonOp.EQUAL, "a"), - KuduPredicate.newComparisonPredicate(metric, KuduPredicate.ComparisonOp.EQUAL, "a"))); + KuduPredicate.newComparisonPredicate(host, ComparisonOp.EQUAL, "a"), + KuduPredicate.newComparisonPredicate(metric, ComparisonOp.EQUAL, "a"))); // host = "a" // metric = "a" // timestamp >= 9; assertEquals(2, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(host, KuduPredicate.ComparisonOp.EQUAL, "a"), - KuduPredicate.newComparisonPredicate(metric, KuduPredicate.ComparisonOp.EQUAL, "a"), - KuduPredicate.newComparisonPredicate(timestamp, KuduPredicate.ComparisonOp.GREATER_EQUAL, 9))); + KuduPredicate.newComparisonPredicate(host, ComparisonOp.EQUAL, "a"), + KuduPredicate.newComparisonPredicate(metric, ComparisonOp.EQUAL, "a"), + KuduPredicate.newComparisonPredicate(timestamp, ComparisonOp.GREATER_EQUAL, 9))); // host = "a" // metric = "a" // timestamp >= 10; // timestamp < 20; assertEquals(1, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(host, KuduPredicate.ComparisonOp.EQUAL, "a"), - KuduPredicate.newComparisonPredicate(metric, KuduPredicate.ComparisonOp.EQUAL, "a"), - KuduPredicate.newComparisonPredicate(timestamp, KuduPredicate.ComparisonOp.GREATER_EQUAL, 10), - KuduPredicate.newComparisonPredicate(timestamp, KuduPredicate.ComparisonOp.LESS, 20))); + KuduPredicate.newComparisonPredicate(host, ComparisonOp.EQUAL, "a"), + KuduPredicate.newComparisonPredicate(metric, ComparisonOp.EQUAL, "a"), + KuduPredicate.newComparisonPredicate(timestamp, ComparisonOp.GREATER_EQUAL, 10), + KuduPredicate.newComparisonPredicate(timestamp, ComparisonOp.LESS, 20))); // host = "a" // metric = "a" // timestamp < 10; assertEquals(1, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(host, KuduPredicate.ComparisonOp.EQUAL, "a"), - KuduPredicate.newComparisonPredicate(metric, KuduPredicate.ComparisonOp.EQUAL, "a"), - KuduPredicate.newComparisonPredicate(timestamp, KuduPredicate.ComparisonOp.LESS, 10))); + KuduPredicate.newComparisonPredicate(host, ComparisonOp.EQUAL, "a"), + KuduPredicate.newComparisonPredicate(metric, ComparisonOp.EQUAL, "a"), + KuduPredicate.newComparisonPredicate(timestamp, ComparisonOp.LESS, 10))); // host = "a" // metric = "a" // timestamp >= 10; assertEquals(1, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(host, KuduPredicate.ComparisonOp.EQUAL, "a"), - KuduPredicate.newComparisonPredicate(metric, KuduPredicate.ComparisonOp.EQUAL, "a"), - KuduPredicate.newComparisonPredicate(timestamp, KuduPredicate.ComparisonOp.GREATER_EQUAL, 10))); + KuduPredicate.newComparisonPredicate(host, ComparisonOp.EQUAL, "a"), + KuduPredicate.newComparisonPredicate(metric, ComparisonOp.EQUAL, "a"), + KuduPredicate.newComparisonPredicate(timestamp, ComparisonOp.GREATER_EQUAL, 10))); // host = "a" // metric = "a" // timestamp = 10; assertEquals(1, countPartitions(table, partitions, - KuduPredicate.newComparisonPredicate(host, KuduPredicate.ComparisonOp.EQUAL, "a"), - KuduPredicate.newComparisonPredicate(metric, KuduPredicate.ComparisonOp.EQUAL, "a"), - KuduPredicate.newComparisonPredicate(timestamp, KuduPredicate.ComparisonOp.EQUAL, 10))); + KuduPredicate.newComparisonPredicate(host, ComparisonOp.EQUAL, "a"), + KuduPredicate.newComparisonPredicate(metric, ComparisonOp.EQUAL, "a"), + KuduPredicate.newComparisonPredicate(timestamp, ComparisonOp.EQUAL, 10))); // partition key < (hash=1) assertEquals(2, countPartitions(table, partitions, new byte[] {}, new byte[] { 0, 0, 0, 1 })); @@ -557,11 +582,34 @@ public class TestPartitionPruner extends BaseKuduTest { // timestamp = 10 // partition key < (hash=1) assertEquals(1, countPartitions(table, partitions, new byte[] {}, new byte[] { 0, 0, 0, 1 }, - KuduPredicate.newComparisonPredicate(timestamp, KuduPredicate.ComparisonOp.EQUAL, 10))); + KuduPredicate.newComparisonPredicate(timestamp, ComparisonOp.EQUAL, 10))); // timestamp = 10 // partition key >= (hash=1) assertEquals(1, countPartitions(table, partitions, new byte[] { 0, 0, 0, 1 }, new byte[] {}, - KuduPredicate.newComparisonPredicate(timestamp, KuduPredicate.ComparisonOp.EQUAL, 10))); + KuduPredicate.newComparisonPredicate(timestamp, ComparisonOp.EQUAL, 10))); + + // timestamp IN (0, 9) + // host = "a" + // metric IN ("foo", "bar") + // + // We do not prune hash partitions based on IN list predicates (yet), + // so the IN list on the hash columns is really just testing that it doesn't fail. + assertEquals(2, countPartitions(table, partitions, + KuduPredicate.newInListPredicate(timestamp, ImmutableList.of(0L, 9L)), + KuduPredicate.newComparisonPredicate(host, ComparisonOp.EQUAL, "a"), + KuduPredicate.newInListPredicate(metric, ImmutableList.of("foo", "bar")))); + + // timestamp IN (10, 100) + assertEquals(2, countPartitions(table, partitions, + KuduPredicate.newInListPredicate(timestamp, ImmutableList.of(10L, 100L)))); + + // timestamp IN (9, 10) + assertEquals(4, countPartitions(table, partitions, + KuduPredicate.newInListPredicate(timestamp, ImmutableList.of(9L, 10L)))); + + // timestamp IS NOT NULL + assertEquals(4, countPartitions(table, partitions, + KuduPredicate.newIsNotNullPredicate(timestamp))); } }