You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by hi...@apache.org on 2020/04/06 05:29:54 UTC
[druid] branch master updated: Eliminate common subfilters when
converting it to a CNF (#9608)
This is an automated email from the ASF dual-hosted git repository.
himanshug pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/master by this push:
new 40e84a1 Eliminate common subfilters when converting it to a CNF (#9608)
40e84a1 is described below
commit 40e84a171b8be8e87db20b0c5c189aef1b860f41
Author: Jihoon Son <ji...@apache.org>
AuthorDate: Sun Apr 5 22:29:41 2020 -0700
Eliminate common subfilters when converting it to a CNF (#9608)
---
.../druid/benchmark/FilterPartitionBenchmark.java | 4 +-
.../apache/druid/query/filter/BooleanFilter.java | 5 +-
.../apache/druid/query/filter/DimFilterUtils.java | 4 +-
.../apache/druid/query/filter/TrueDimFilter.java | 8 +-
.../segment/QueryableIndexStorageAdapter.java | 9 +-
.../org/apache/druid/segment/filter/AndFilter.java | 33 ++--
.../org/apache/druid/segment/filter/Filters.java | 56 +++---
.../org/apache/druid/segment/filter/NotFilter.java | 32 +++-
.../org/apache/druid/segment/filter/OrFilter.java | 28 ++-
.../apache/druid/segment/filter/TrueFilter.java | 9 +-
.../segment/join/filter/JoinFilterAnalyzer.java | 8 +-
.../druid/query/filter/AndDimFilterTest.java | 29 ++-
...dDimFilterTest.java => DimFilterTestUtils.java} | 34 ++--
.../apache/druid/query/filter/OrDimFilterTest.java | 53 +++++
.../druid/segment/filter/BaseFilterTest.java | 2 +-
.../druid/segment/filter/FilterPartitionTest.java | 4 +-
.../filter/FilterTestUtils.java} | 38 ++--
.../apache/druid/segment/filter/FiltersTest.java | 213 ++++++++++++++++++++-
...tFilterTest.java => NotFilterEvaluateTest.java} | 6 +-
.../apache/druid/segment/filter/NotFilterTest.java | 84 ++------
20 files changed, 473 insertions(+), 186 deletions(-)
diff --git a/benchmarks/src/test/java/org/apache/druid/benchmark/FilterPartitionBenchmark.java b/benchmarks/src/test/java/org/apache/druid/benchmark/FilterPartitionBenchmark.java
index b52cde1..547784e 100644
--- a/benchmarks/src/test/java/org/apache/druid/benchmark/FilterPartitionBenchmark.java
+++ b/benchmarks/src/test/java/org/apache/druid/benchmark/FilterPartitionBenchmark.java
@@ -377,7 +377,7 @@ public class FilterPartitionBenchmark
Filter orFilter = new OrFilter(Arrays.asList(filter, filter2));
StorageAdapter sa = new QueryableIndexStorageAdapter(qIndex);
- Sequence<Cursor> cursors = makeCursors(sa, Filters.convertToCNF(orFilter));
+ Sequence<Cursor> cursors = makeCursors(sa, Filters.toCNF(orFilter));
readCursors(cursors, blackhole);
}
@@ -451,7 +451,7 @@ public class FilterPartitionBenchmark
);
StorageAdapter sa = new QueryableIndexStorageAdapter(qIndex);
- Sequence<Cursor> cursors = makeCursors(sa, Filters.convertToCNF(dimFilter3.toFilter()));
+ Sequence<Cursor> cursors = makeCursors(sa, Filters.toCNF(dimFilter3.toFilter()));
readCursors(cursors, blackhole);
}
diff --git a/processing/src/main/java/org/apache/druid/query/filter/BooleanFilter.java b/processing/src/main/java/org/apache/druid/query/filter/BooleanFilter.java
index 9bbbdb6..e11153e 100644
--- a/processing/src/main/java/org/apache/druid/query/filter/BooleanFilter.java
+++ b/processing/src/main/java/org/apache/druid/query/filter/BooleanFilter.java
@@ -23,12 +23,13 @@ import org.apache.druid.segment.ColumnSelector;
import org.apache.druid.segment.ColumnSelectorFactory;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
public interface BooleanFilter extends Filter
{
- List<Filter> getFilters();
+ ValueMatcher[] EMPTY_VALUE_MATCHER_ARRAY = new ValueMatcher[0];
+
+ Set<Filter> getFilters();
/**
* Get a ValueMatcher that applies this filter to row values.
diff --git a/processing/src/main/java/org/apache/druid/query/filter/DimFilterUtils.java b/processing/src/main/java/org/apache/druid/query/filter/DimFilterUtils.java
index 00a84fc..c980adb 100644
--- a/processing/src/main/java/org/apache/druid/query/filter/DimFilterUtils.java
+++ b/processing/src/main/java/org/apache/druid/query/filter/DimFilterUtils.java
@@ -52,9 +52,9 @@ public class DimFilterUtils
static final byte COLUMN_COMPARISON_CACHE_ID = 0xD;
static final byte EXPRESSION_CACHE_ID = 0xE;
static final byte TRUE_CACHE_ID = 0xF;
- public static byte BLOOM_DIM_FILTER_CACHE_ID = 0x10;
- public static final byte STRING_SEPARATOR = (byte) 0xFF;
+ public static final byte BLOOM_DIM_FILTER_CACHE_ID = 0x10;
+ public static final byte STRING_SEPARATOR = (byte) 0xFF;
static byte[] computeCacheKey(byte cacheIdKey, List<DimFilter> filters)
{
diff --git a/processing/src/main/java/org/apache/druid/query/filter/TrueDimFilter.java b/processing/src/main/java/org/apache/druid/query/filter/TrueDimFilter.java
index d10e6d9..2254358 100644
--- a/processing/src/main/java/org/apache/druid/query/filter/TrueDimFilter.java
+++ b/processing/src/main/java/org/apache/druid/query/filter/TrueDimFilter.java
@@ -20,9 +20,9 @@
package org.apache.druid.query.filter;
import com.google.common.collect.RangeSet;
+import org.apache.druid.query.cache.CacheKeyBuilder;
import org.apache.druid.segment.filter.TrueFilter;
-import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.Set;
@@ -32,8 +32,8 @@ public class TrueDimFilter implements DimFilter
{
@Override
public byte[] getCacheKey()
- {
- return ByteBuffer.allocate(1).put(DimFilterUtils.TRUE_CACHE_ID).array();
+ {
+ return new CacheKeyBuilder(DimFilterUtils.TRUE_CACHE_ID).build();
}
@Override
@@ -45,7 +45,7 @@ public class TrueDimFilter implements DimFilter
@Override
public Filter toFilter()
{
- return new TrueFilter();
+ return TrueFilter.instance();
}
@Override
diff --git a/processing/src/main/java/org/apache/druid/segment/QueryableIndexStorageAdapter.java b/processing/src/main/java/org/apache/druid/segment/QueryableIndexStorageAdapter.java
index cbb6446..70f4c9c 100644
--- a/processing/src/main/java/org/apache/druid/segment/QueryableIndexStorageAdapter.java
+++ b/processing/src/main/java/org/apache/druid/segment/QueryableIndexStorageAdapter.java
@@ -54,6 +54,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
/**
*
@@ -384,13 +385,13 @@ public class QueryableIndexStorageAdapter implements StorageAdapter
*
* Any subfilters that cannot be processed entirely with bitmap indexes will be moved to the post-filtering stage.
*/
- final List<Filter> preFilters;
+ final Set<Filter> preFilters;
final List<Filter> postFilters = new ArrayList<>();
int preFilteredRows = totalRows;
if (filter == null) {
- preFilters = Collections.emptyList();
+ preFilters = Collections.emptySet();
} else {
- preFilters = new ArrayList<>();
+ preFilters = new HashSet<>();
if (filter instanceof AndFilter) {
// If we get an AndFilter, we can split the subfilters across both filtering stages
@@ -432,7 +433,7 @@ public class QueryableIndexStorageAdapter implements StorageAdapter
}
if (queryMetrics != null) {
- queryMetrics.preFilters(preFilters);
+ queryMetrics.preFilters(new ArrayList<>(preFilters));
queryMetrics.postFilters(postFilters);
queryMetrics.reportSegmentRows(totalRows);
queryMetrics.reportPreFilteredRows(preFilteredRows);
diff --git a/processing/src/main/java/org/apache/druid/segment/filter/AndFilter.java b/processing/src/main/java/org/apache/druid/segment/filter/AndFilter.java
index 93c890a..696bd8b 100644
--- a/processing/src/main/java/org/apache/druid/segment/filter/AndFilter.java
+++ b/processing/src/main/java/org/apache/druid/segment/filter/AndFilter.java
@@ -19,8 +19,10 @@
package org.apache.druid.segment.filter;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import org.apache.druid.collections.bitmap.ImmutableBitmap;
import org.apache.druid.java.util.common.StringUtils;
@@ -38,20 +40,27 @@ import org.apache.druid.segment.ColumnSelectorFactory;
import org.apache.druid.segment.vector.VectorColumnSelectorFactory;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
/**
*/
public class AndFilter implements BooleanFilter
{
private static final Joiner AND_JOINER = Joiner.on(" && ");
- static final ValueMatcher[] EMPTY_VALUE_MATCHER_ARRAY = new ValueMatcher[0];
- private final List<Filter> filters;
+ private final Set<Filter> filters;
+ @VisibleForTesting
public AndFilter(List<Filter> filters)
{
+ this(new HashSet<>(filters));
+ }
+
+ public AndFilter(Set<Filter> filters)
+ {
Preconditions.checkArgument(filters.size() > 0, "Can't construct empty AndFilter");
this.filters = filters;
}
@@ -59,7 +68,7 @@ public class AndFilter implements BooleanFilter
public static <T> ImmutableBitmap getBitmapIndex(
BitmapIndexSelector selector,
BitmapResultFactory<T> bitmapResultFactory,
- List<Filter> filters
+ Set<Filter> filters
)
{
return bitmapResultFactory.toImmutableBitmap(getBitmapResult(selector, bitmapResultFactory, filters));
@@ -68,11 +77,11 @@ public class AndFilter implements BooleanFilter
private static <T> T getBitmapResult(
BitmapIndexSelector selector,
BitmapResultFactory<T> bitmapResultFactory,
- List<Filter> filters
+ Set<Filter> filters
)
{
if (filters.size() == 1) {
- return filters.get(0).getBitmapResult(selector, bitmapResultFactory);
+ return Iterables.getOnlyElement(filters).getBitmapResult(selector, bitmapResultFactory);
}
final List<T> bitmapResults = Lists.newArrayListWithCapacity(filters.size());
@@ -102,8 +111,9 @@ public class AndFilter implements BooleanFilter
{
final ValueMatcher[] matchers = new ValueMatcher[filters.size()];
- for (int i = 0; i < filters.size(); i++) {
- matchers[i] = filters.get(i).makeMatcher(factory);
+ int i = 0;
+ for (Filter filter : filters) {
+ matchers[i++] = filter.makeMatcher(factory);
}
return makeMatcher(matchers);
}
@@ -113,8 +123,9 @@ public class AndFilter implements BooleanFilter
{
final VectorValueMatcher[] matchers = new VectorValueMatcher[filters.size()];
- for (int i = 0; i < filters.size(); i++) {
- matchers[i] = filters.get(i).makeVectorMatcher(factory);
+ int i = 0;
+ for (Filter filter : filters) {
+ matchers[i++] = filter.makeVectorMatcher(factory);
}
return makeVectorMatcher(matchers);
}
@@ -150,11 +161,11 @@ public class AndFilter implements BooleanFilter
matchers.add(0, offsetMatcher);
}
- return makeMatcher(matchers.toArray(EMPTY_VALUE_MATCHER_ARRAY));
+ return makeMatcher(matchers.toArray(BooleanFilter.EMPTY_VALUE_MATCHER_ARRAY));
}
@Override
- public List<Filter> getFilters()
+ public Set<Filter> getFilters()
{
return filters;
}
diff --git a/processing/src/main/java/org/apache/druid/segment/filter/Filters.java b/processing/src/main/java/org/apache/druid/segment/filter/Filters.java
index 4e865f6..2328dfb 100644
--- a/processing/src/main/java/org/apache/druid/segment/filter/Filters.java
+++ b/processing/src/main/java/org/apache/druid/segment/filter/Filters.java
@@ -19,16 +19,14 @@
package org.apache.druid.segment.filter;
-import com.google.common.base.Function;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
import it.unimi.dsi.fastutil.ints.IntIterable;
import it.unimi.dsi.fastutil.ints.IntIterator;
import it.unimi.dsi.fastutil.ints.IntList;
import org.apache.druid.collections.bitmap.ImmutableBitmap;
-import org.apache.druid.java.util.common.guava.FunctionalIterable;
import org.apache.druid.query.BitmapResultFactory;
import org.apache.druid.query.Query;
import org.apache.druid.query.filter.BitmapIndexSelector;
@@ -51,9 +49,12 @@ import javax.annotation.Nullable;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.stream.Collectors;
/**
*
@@ -69,22 +70,9 @@ public class Filters
*
* @return list of Filters
*/
- public static List<Filter> toFilters(List<DimFilter> dimFilters)
+ public static Set<Filter> toFilters(List<DimFilter> dimFilters)
{
- return ImmutableList.copyOf(
- FunctionalIterable
- .create(dimFilters)
- .transform(
- new Function<DimFilter, Filter>()
- {
- @Override
- public Filter apply(DimFilter input)
- {
- return input.toFilter();
- }
- }
- )
- );
+ return dimFilters.stream().map(DimFilter::toFilter).collect(Collectors.toSet());
}
/**
@@ -438,10 +426,10 @@ public class Filters
return null;
}
boolean useCNF = query.getContextBoolean(CTX_KEY_USE_FILTER_CNF, false);
- return useCNF ? convertToCNF(filter) : filter;
+ return useCNF ? toCNF(filter) : filter;
}
- public static Filter convertToCNF(Filter current)
+ public static Filter toCNF(Filter current)
{
current = pushDownNot(current);
current = flatten(current);
@@ -452,7 +440,8 @@ public class Filters
// CNF conversion functions were adapted from Apache Hive, see:
// https://github.com/apache/hive/blob/branch-2.0/storage-api/src/java/org/apache/hadoop/hive/ql/io/sarg/SearchArgumentImpl.java
- private static Filter pushDownNot(Filter current)
+ @VisibleForTesting
+ static Filter pushDownNot(Filter current)
{
if (current instanceof NotFilter) {
Filter child = ((NotFilter) current).getBaseFilter();
@@ -460,14 +449,14 @@ public class Filters
return pushDownNot(((NotFilter) child).getBaseFilter());
}
if (child instanceof AndFilter) {
- List<Filter> children = new ArrayList<>();
+ Set<Filter> children = new HashSet<>();
for (Filter grandChild : ((AndFilter) child).getFilters()) {
children.add(pushDownNot(new NotFilter(grandChild)));
}
return new OrFilter(children);
}
if (child instanceof OrFilter) {
- List<Filter> children = new ArrayList<>();
+ Set<Filter> children = new HashSet<>();
for (Filter grandChild : ((OrFilter) child).getFilters()) {
children.add(pushDownNot(new NotFilter(grandChild)));
}
@@ -477,7 +466,7 @@ public class Filters
if (current instanceof AndFilter) {
- List<Filter> children = new ArrayList<>();
+ Set<Filter> children = new HashSet<>();
for (Filter child : ((AndFilter) current).getFilters()) {
children.add(pushDownNot(child));
}
@@ -486,7 +475,7 @@ public class Filters
if (current instanceof OrFilter) {
- List<Filter> children = new ArrayList<>();
+ Set<Filter> children = new HashSet<>();
for (Filter child : ((OrFilter) current).getFilters()) {
children.add(pushDownNot(child));
}
@@ -503,7 +492,7 @@ public class Filters
return new NotFilter(convertToCNFInternal(((NotFilter) current).getBaseFilter()));
}
if (current instanceof AndFilter) {
- List<Filter> children = new ArrayList<>();
+ Set<Filter> children = new HashSet<>();
for (Filter child : ((AndFilter) current).getFilters()) {
children.add(convertToCNFInternal(child));
}
@@ -525,7 +514,7 @@ public class Filters
}
}
if (!andList.isEmpty()) {
- List<Filter> result = new ArrayList<>();
+ Set<Filter> result = new HashSet<>();
generateAllCombinations(result, andList, nonAndList);
return new AndFilter(result);
}
@@ -535,7 +524,8 @@ public class Filters
// CNF conversion functions were adapted from Apache Hive, see:
// https://github.com/apache/hive/blob/branch-2.0/storage-api/src/java/org/apache/hadoop/hive/ql/io/sarg/SearchArgumentImpl.java
- private static Filter flatten(Filter root)
+ @VisibleForTesting
+ static Filter flatten(Filter root)
{
if (root instanceof BooleanFilter) {
List<Filter> children = new ArrayList<>(((BooleanFilter) root).getFilters());
@@ -546,7 +536,7 @@ public class Filters
// do we need to flatten?
if (child.getClass() == root.getClass() && !(child instanceof NotFilter)) {
boolean first = true;
- List<Filter> grandKids = ((BooleanFilter) child).getFilters();
+ Set<Filter> grandKids = ((BooleanFilter) child).getFilters();
for (Filter grandkid : grandKids) {
// for the first grandkid replace the original parent
if (first) {
@@ -577,15 +567,15 @@ public class Filters
// CNF conversion functions were adapted from Apache Hive, see:
// https://github.com/apache/hive/blob/branch-2.0/storage-api/src/java/org/apache/hadoop/hive/ql/io/sarg/SearchArgumentImpl.java
private static void generateAllCombinations(
- List<Filter> result,
+ Set<Filter> result,
List<Filter> andList,
List<Filter> nonAndList
)
{
- List<Filter> children = ((AndFilter) andList.get(0)).getFilters();
+ Set<Filter> children = ((AndFilter) andList.get(0)).getFilters();
if (result.isEmpty()) {
for (Filter child : children) {
- List<Filter> a = Lists.newArrayList(nonAndList);
+ Set<Filter> a = new HashSet<>(nonAndList);
a.add(child);
result.add(new OrFilter(a));
}
@@ -594,7 +584,7 @@ public class Filters
result.clear();
for (Filter child : children) {
for (Filter or : work) {
- List<Filter> a = Lists.newArrayList((((OrFilter) or).getFilters()));
+ Set<Filter> a = new HashSet<>((((OrFilter) or).getFilters()));
a.add(child);
result.add(new OrFilter(a));
}
diff --git a/processing/src/main/java/org/apache/druid/segment/filter/NotFilter.java b/processing/src/main/java/org/apache/druid/segment/filter/NotFilter.java
index 3a39e2f..a82a57f 100644
--- a/processing/src/main/java/org/apache/druid/segment/filter/NotFilter.java
+++ b/processing/src/main/java/org/apache/druid/segment/filter/NotFilter.java
@@ -19,6 +19,7 @@
package org.apache.druid.segment.filter;
+import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.query.BitmapResultFactory;
import org.apache.druid.query.filter.BitmapIndexSelector;
import org.apache.druid.query.filter.Filter;
@@ -32,6 +33,7 @@ import org.apache.druid.segment.ColumnSelector;
import org.apache.druid.segment.ColumnSelectorFactory;
import org.apache.druid.segment.vector.VectorColumnSelectorFactory;
+import java.util.Objects;
import java.util.Set;
/**
@@ -40,9 +42,7 @@ public class NotFilter implements Filter
{
private final Filter baseFilter;
- public NotFilter(
- Filter baseFilter
- )
+ public NotFilter(Filter baseFilter)
{
this.baseFilter = baseFilter;
}
@@ -135,6 +135,32 @@ public class NotFilter implements Filter
return 1. - baseFilter.estimateSelectivity(indexSelector);
}
+ @Override
+ public String toString()
+ {
+ return StringUtils.format("~(%s)", baseFilter);
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ NotFilter notFilter = (NotFilter) o;
+ return Objects.equals(baseFilter, notFilter.baseFilter);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ // to return a different hash from baseFilter
+ return Objects.hash(1, baseFilter);
+ }
+
public Filter getBaseFilter()
{
return baseFilter;
diff --git a/processing/src/main/java/org/apache/druid/segment/filter/OrFilter.java b/processing/src/main/java/org/apache/druid/segment/filter/OrFilter.java
index 9e5314b..46cd9e2 100644
--- a/processing/src/main/java/org/apache/druid/segment/filter/OrFilter.java
+++ b/processing/src/main/java/org/apache/druid/segment/filter/OrFilter.java
@@ -19,8 +19,10 @@
package org.apache.druid.segment.filter;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
import org.apache.druid.collections.bitmap.ImmutableBitmap;
import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.query.BitmapResultFactory;
@@ -38,8 +40,10 @@ import org.apache.druid.segment.ColumnSelectorFactory;
import org.apache.druid.segment.vector.VectorColumnSelectorFactory;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
/**
*/
@@ -47,10 +51,16 @@ public class OrFilter implements BooleanFilter
{
private static final Joiner OR_JOINER = Joiner.on(" || ");
- private final List<Filter> filters;
+ private final Set<Filter> filters;
+ @VisibleForTesting
public OrFilter(List<Filter> filters)
{
+ this(new HashSet<>(filters));
+ }
+
+ public OrFilter(Set<Filter> filters)
+ {
Preconditions.checkArgument(filters.size() > 0, "Can't construct empty OrFilter (the universe does not exist)");
this.filters = filters;
@@ -60,7 +70,7 @@ public class OrFilter implements BooleanFilter
public <T> T getBitmapResult(BitmapIndexSelector selector, BitmapResultFactory<T> bitmapResultFactory)
{
if (filters.size() == 1) {
- return filters.get(0).getBitmapResult(selector, bitmapResultFactory);
+ return Iterables.getOnlyElement(filters).getBitmapResult(selector, bitmapResultFactory);
}
List<T> bitmapResults = new ArrayList<>();
@@ -76,8 +86,9 @@ public class OrFilter implements BooleanFilter
{
final ValueMatcher[] matchers = new ValueMatcher[filters.size()];
- for (int i = 0; i < filters.size(); i++) {
- matchers[i] = filters.get(i).makeMatcher(factory);
+ int i = 0;
+ for (Filter filter : filters) {
+ matchers[i++] = filter.makeMatcher(factory);
}
return makeMatcher(matchers);
}
@@ -87,8 +98,9 @@ public class OrFilter implements BooleanFilter
{
final VectorValueMatcher[] matchers = new VectorValueMatcher[filters.size()];
- for (int i = 0; i < filters.size(); i++) {
- matchers[i] = filters.get(i).makeVectorMatcher(factory);
+ int i = 0;
+ for (Filter filter : filters) {
+ matchers[i++] = filter.makeVectorMatcher(factory);
}
return makeVectorMatcher(matchers);
}
@@ -124,11 +136,11 @@ public class OrFilter implements BooleanFilter
matchers.add(0, offsetMatcher);
}
- return makeMatcher(matchers.toArray(AndFilter.EMPTY_VALUE_MATCHER_ARRAY));
+ return makeMatcher(matchers.toArray(BooleanFilter.EMPTY_VALUE_MATCHER_ARRAY));
}
@Override
- public List<Filter> getFilters()
+ public Set<Filter> getFilters()
{
return filters;
}
diff --git a/processing/src/main/java/org/apache/druid/segment/filter/TrueFilter.java b/processing/src/main/java/org/apache/druid/segment/filter/TrueFilter.java
index 2ae0edf..58cda8c 100644
--- a/processing/src/main/java/org/apache/druid/segment/filter/TrueFilter.java
+++ b/processing/src/main/java/org/apache/druid/segment/filter/TrueFilter.java
@@ -33,7 +33,14 @@ import java.util.Set;
*/
public class TrueFilter implements Filter
{
- public TrueFilter()
+ private static final TrueFilter INSTANCE = new TrueFilter();
+
+ public static TrueFilter instance()
+ {
+ return INSTANCE;
+ }
+
+ private TrueFilter()
{
}
diff --git a/processing/src/main/java/org/apache/druid/segment/join/filter/JoinFilterAnalyzer.java b/processing/src/main/java/org/apache/druid/segment/join/filter/JoinFilterAnalyzer.java
index d8cd4f6..892fcb3 100644
--- a/processing/src/main/java/org/apache/druid/segment/join/filter/JoinFilterAnalyzer.java
+++ b/processing/src/main/java/org/apache/druid/segment/join/filter/JoinFilterAnalyzer.java
@@ -128,17 +128,17 @@ public class JoinFilterAnalyzer
);
}
- Filter normalizedFilter = Filters.convertToCNF(originalFilter);
+ Filter normalizedFilter = Filters.toCNF(originalFilter);
// List of candidates for pushdown
// CNF normalization will generate either
// - an AND filter with multiple subfilters
// - or a single non-AND subfilter which cannot be split further
- List<Filter> normalizedOrClauses;
+ Set<Filter> normalizedOrClauses;
if (normalizedFilter instanceof AndFilter) {
normalizedOrClauses = ((AndFilter) normalizedFilter).getFilters();
} else {
- normalizedOrClauses = Collections.singletonList(normalizedFilter);
+ normalizedOrClauses = Collections.singleton(normalizedFilter);
}
List<Filter> normalizedBaseTableClauses = new ArrayList<>();
@@ -422,7 +422,7 @@ public class JoinFilterAnalyzer
)
{
boolean retainRhs = false;
- List<Filter> newFilters = new ArrayList<>();
+ Set<Filter> newFilters = new HashSet<>();
for (Filter filter : orFilter.getFilters()) {
if (!areSomeColumnsFromJoin(joinFilterPreAnalysis.getJoinableClauses(), filter.getRequiredColumns())) {
newFilters.add(filter);
diff --git a/processing/src/test/java/org/apache/druid/query/filter/AndDimFilterTest.java b/processing/src/test/java/org/apache/druid/query/filter/AndDimFilterTest.java
index f2d6c43..7aeae01 100644
--- a/processing/src/test/java/org/apache/druid/query/filter/AndDimFilterTest.java
+++ b/processing/src/test/java/org/apache/druid/query/filter/AndDimFilterTest.java
@@ -21,10 +21,12 @@ package org.apache.druid.query.filter;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
+import org.apache.druid.segment.filter.FilterTestUtils;
+import org.apache.druid.testing.InitializedNullHandlingTest;
import org.junit.Assert;
import org.junit.Test;
-public class AndDimFilterTest
+public class AndDimFilterTest extends InitializedNullHandlingTest
{
@Test
public void testGetRequiredColumns()
@@ -38,4 +40,29 @@ public class AndDimFilterTest
);
Assert.assertEquals(andDimFilter.getRequiredColumns(), Sets.newHashSet("a", "b", "c"));
}
+
+ @Test
+ public void testToFilterWithDuplicateFilters()
+ {
+ DimFilter dimFilter = DimFilterTestUtils.and(
+ DimFilterTestUtils.or(
+ DimFilterTestUtils.selector("col1", "1"),
+ DimFilterTestUtils.selector("col2", "2")
+ ),
+ DimFilterTestUtils.or(
+ // duplicate but different order
+ DimFilterTestUtils.selector("col2", "2"),
+ DimFilterTestUtils.selector("col1", "1")
+ ),
+ DimFilterTestUtils.selector("col3", "3")
+ );
+ Filter expected = FilterTestUtils.and(
+ FilterTestUtils.or(
+ FilterTestUtils.selector("col1", "1"),
+ FilterTestUtils.selector("col2", "2")
+ ),
+ FilterTestUtils.selector("col3", "3")
+ );
+ Assert.assertEquals(expected, dimFilter.toFilter());
+ }
}
diff --git a/processing/src/test/java/org/apache/druid/query/filter/AndDimFilterTest.java b/processing/src/test/java/org/apache/druid/query/filter/DimFilterTestUtils.java
similarity index 61%
copy from processing/src/test/java/org/apache/druid/query/filter/AndDimFilterTest.java
copy to processing/src/test/java/org/apache/druid/query/filter/DimFilterTestUtils.java
index f2d6c43..87fa026 100644
--- a/processing/src/test/java/org/apache/druid/query/filter/AndDimFilterTest.java
+++ b/processing/src/test/java/org/apache/druid/query/filter/DimFilterTestUtils.java
@@ -19,23 +19,27 @@
package org.apache.druid.query.filter;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.junit.Assert;
-import org.junit.Test;
+import java.util.Arrays;
-public class AndDimFilterTest
+public class DimFilterTestUtils
{
- @Test
- public void testGetRequiredColumns()
+ public static AndDimFilter and(DimFilter... filters)
{
- AndDimFilter andDimFilter = new AndDimFilter(
- Lists.newArrayList(
- new SelectorDimFilter("a", "d", null),
- new SelectorDimFilter("b", "d", null),
- new SelectorDimFilter("c", "d", null)
- )
- );
- Assert.assertEquals(andDimFilter.getRequiredColumns(), Sets.newHashSet("a", "b", "c"));
+ return new AndDimFilter(Arrays.asList(filters));
+ }
+
+ public static OrDimFilter or(DimFilter... filters)
+ {
+ return new OrDimFilter(Arrays.asList(filters));
+ }
+
+ public static NotDimFilter not(DimFilter filter)
+ {
+ return new NotDimFilter(filter);
+ }
+
+ public static SelectorDimFilter selector(final String fieldName, final String value)
+ {
+ return new SelectorDimFilter(fieldName, value, null);
}
}
diff --git a/processing/src/test/java/org/apache/druid/query/filter/OrDimFilterTest.java b/processing/src/test/java/org/apache/druid/query/filter/OrDimFilterTest.java
new file mode 100644
index 0000000..9f02194
--- /dev/null
+++ b/processing/src/test/java/org/apache/druid/query/filter/OrDimFilterTest.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.query.filter;
+
+import org.apache.druid.segment.filter.FilterTestUtils;
+import org.apache.druid.testing.InitializedNullHandlingTest;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class OrDimFilterTest extends InitializedNullHandlingTest
+{
+ @Test
+ public void testToFilterWithDuplicateFilters()
+ {
+ DimFilter dimFilter = DimFilterTestUtils.or(
+ DimFilterTestUtils.and(
+ DimFilterTestUtils.selector("col1", "1"),
+ DimFilterTestUtils.selector("col2", "2")
+ ),
+ DimFilterTestUtils.and(
+ // duplicate but different order
+ DimFilterTestUtils.selector("col2", "2"),
+ DimFilterTestUtils.selector("col1", "1")
+ ),
+ DimFilterTestUtils.selector("col3", "3")
+ );
+ Filter expected = FilterTestUtils.or(
+ FilterTestUtils.and(
+ FilterTestUtils.selector("col1", "1"),
+ FilterTestUtils.selector("col2", "2")
+ ),
+ FilterTestUtils.selector("col3", "3")
+ );
+ Assert.assertEquals(expected, dimFilter.toFilter());
+ }
+}
diff --git a/processing/src/test/java/org/apache/druid/segment/filter/BaseFilterTest.java b/processing/src/test/java/org/apache/druid/segment/filter/BaseFilterTest.java
index 8a704d2..5700458 100644
--- a/processing/src/test/java/org/apache/druid/segment/filter/BaseFilterTest.java
+++ b/processing/src/test/java/org/apache/druid/segment/filter/BaseFilterTest.java
@@ -336,7 +336,7 @@ public abstract class BaseFilterTest extends InitializedNullHandlingTest
final DimFilter maybeOptimized = optimize ? dimFilter.optimize() : dimFilter;
final Filter filter = maybeOptimized.toFilter();
- return cnf ? Filters.convertToCNF(filter) : filter;
+ return cnf ? Filters.toCNF(filter) : filter;
}
private DimFilter maybeOptimize(final DimFilter dimFilter)
diff --git a/processing/src/test/java/org/apache/druid/segment/filter/FilterPartitionTest.java b/processing/src/test/java/org/apache/druid/segment/filter/FilterPartitionTest.java
index bb76c54..5ffd167 100644
--- a/processing/src/test/java/org/apache/druid/segment/filter/FilterPartitionTest.java
+++ b/processing/src/test/java/org/apache/druid/segment/filter/FilterPartitionTest.java
@@ -621,7 +621,7 @@ public class FilterPartitionTest extends BaseFilterTest
);
Filter filter1 = dimFilter1.toFilter();
- Filter filter1CNF = Filters.convertToCNF(filter1);
+ Filter filter1CNF = Filters.toCNF(filter1);
Assert.assertEquals(AndFilter.class, filter1CNF.getClass());
Assert.assertEquals(2, ((AndFilter) filter1CNF).getFilters().size());
@@ -675,7 +675,7 @@ public class FilterPartitionTest extends BaseFilterTest
);
Filter filter1 = dimFilter1.toFilter();
- Filter filter1CNF = Filters.convertToCNF(filter1);
+ Filter filter1CNF = Filters.toCNF(filter1);
Assert.assertEquals(AndFilter.class, filter1CNF.getClass());
Assert.assertEquals(2, ((AndFilter) filter1CNF).getFilters().size());
diff --git a/processing/src/test/java/org/apache/druid/query/filter/AndDimFilterTest.java b/processing/src/test/java/org/apache/druid/segment/filter/FilterTestUtils.java
similarity index 58%
copy from processing/src/test/java/org/apache/druid/query/filter/AndDimFilterTest.java
copy to processing/src/test/java/org/apache/druid/segment/filter/FilterTestUtils.java
index f2d6c43..003d8d8 100644
--- a/processing/src/test/java/org/apache/druid/query/filter/AndDimFilterTest.java
+++ b/processing/src/test/java/org/apache/druid/segment/filter/FilterTestUtils.java
@@ -17,25 +17,31 @@
* under the License.
*/
-package org.apache.druid.query.filter;
+package org.apache.druid.segment.filter;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import org.junit.Assert;
-import org.junit.Test;
+import org.apache.druid.query.filter.Filter;
-public class AndDimFilterTest
+import java.util.Arrays;
+
+public class FilterTestUtils
{
- @Test
- public void testGetRequiredColumns()
+ public static AndFilter and(Filter... filters)
+ {
+ return new AndFilter(Arrays.asList(filters));
+ }
+
+ public static OrFilter or(Filter... filters)
+ {
+ return new OrFilter(Arrays.asList(filters));
+ }
+
+ public static NotFilter not(Filter filter)
+ {
+ return new NotFilter(filter);
+ }
+
+ public static SelectorFilter selector(final String fieldName, final String value)
{
- AndDimFilter andDimFilter = new AndDimFilter(
- Lists.newArrayList(
- new SelectorDimFilter("a", "d", null),
- new SelectorDimFilter("b", "d", null),
- new SelectorDimFilter("c", "d", null)
- )
- );
- Assert.assertEquals(andDimFilter.getRequiredColumns(), Sets.newHashSet("a", "b", "c"));
+ return new SelectorFilter(fieldName, value, null);
}
}
diff --git a/processing/src/test/java/org/apache/druid/segment/filter/FiltersTest.java b/processing/src/test/java/org/apache/druid/segment/filter/FiltersTest.java
index 56b993c..70b527d 100644
--- a/processing/src/test/java/org/apache/druid/segment/filter/FiltersTest.java
+++ b/processing/src/test/java/org/apache/druid/segment/filter/FiltersTest.java
@@ -25,14 +25,16 @@ import org.apache.druid.collections.bitmap.BitmapFactory;
import org.apache.druid.collections.bitmap.ConciseBitmapFactory;
import org.apache.druid.collections.bitmap.ImmutableBitmap;
import org.apache.druid.collections.bitmap.MutableBitmap;
+import org.apache.druid.query.filter.Filter;
import org.apache.druid.segment.IntIteratorUtils;
import org.apache.druid.segment.column.BitmapIndex;
+import org.apache.druid.testing.InitializedNullHandlingTest;
import org.junit.Assert;
import org.junit.Test;
import java.util.List;
-public class FiltersTest
+public class FiltersTest extends InitializedNullHandlingTest
{
@Test
public void testEstimateSelectivityOfBitmapList()
@@ -50,6 +52,215 @@ public class FiltersTest
Assert.assertEquals(expected, estimated, 0.00001);
}
+ @Test
+ public void testPushDownNot()
+ {
+ final Filter filter = FilterTestUtils.not(
+ FilterTestUtils.and(
+ FilterTestUtils.selector("col1", "1"),
+ FilterTestUtils.selector("col2", "2"),
+ FilterTestUtils.not(FilterTestUtils.selector("col3", "3"))
+ )
+ );
+ final Filter expected = FilterTestUtils.or(
+ FilterTestUtils.not(FilterTestUtils.selector("col1", "1")),
+ FilterTestUtils.not(FilterTestUtils.selector("col2", "2")),
+ FilterTestUtils.selector("col3", "3")
+ );
+ Assert.assertEquals(expected, Filters.pushDownNot(filter));
+ }
+
+ @Test
+ public void testPushDownNotLeafNot()
+ {
+ final Filter filter = FilterTestUtils.and(
+ FilterTestUtils.selector("col1", "1"),
+ FilterTestUtils.selector("col2", "2"),
+ FilterTestUtils.not(FilterTestUtils.selector("col3", "3"))
+ );
+ Assert.assertEquals(filter, Filters.pushDownNot(filter));
+ }
+
+ @Test
+ public void testFlatten()
+ {
+ final Filter filter = FilterTestUtils.and(
+ FilterTestUtils.and(
+ FilterTestUtils.and(
+ FilterTestUtils.selector("col1", "1"),
+ FilterTestUtils.selector("col2", "2")
+ )
+ ),
+ FilterTestUtils.selector("col3", "3")
+ );
+ final Filter expected = FilterTestUtils.and(
+ FilterTestUtils.selector("col1", "1"),
+ FilterTestUtils.selector("col2", "2"),
+ FilterTestUtils.selector("col3", "3")
+ );
+ Assert.assertEquals(expected, Filters.flatten(filter));
+ }
+
+ @Test
+ public void testFlattenUnflattenable()
+ {
+ final Filter filter = FilterTestUtils.and(
+ FilterTestUtils.or(
+ FilterTestUtils.selector("col1", "1"),
+ FilterTestUtils.selector("col2", "2")
+ ),
+ FilterTestUtils.selector("col3", "3")
+ );
+ Assert.assertEquals(filter, Filters.flatten(filter));
+ }
+
+ @Test
+ public void testToCNFWithMuchReducibleFilter()
+ {
+ final Filter muchReducible = FilterTestUtils.and(
+ // should be flattened
+ FilterTestUtils.and(
+ FilterTestUtils.and(
+ FilterTestUtils.and(FilterTestUtils.selector("col1", "val1"))
+ )
+ ),
+ // should be flattened
+ FilterTestUtils.and(
+ FilterTestUtils.or(
+ FilterTestUtils.and(FilterTestUtils.selector("col1", "val1"))
+ )
+ ),
+ // should be flattened
+ FilterTestUtils.or(
+ FilterTestUtils.and(
+ FilterTestUtils.or(FilterTestUtils.selector("col1", "val1"))
+ )
+ ),
+ // should eliminate duplicate filters
+ FilterTestUtils.selector("col1", "val1"),
+ FilterTestUtils.selector("col2", "val2"),
+ FilterTestUtils.and(
+ FilterTestUtils.selector("col1", "val1"),
+ FilterTestUtils.selector("col2", "val2")
+ ),
+ FilterTestUtils.and(
+ FilterTestUtils.selector("col1", "val1"),
+ FilterTestUtils.and(
+ FilterTestUtils.selector("col2", "val2"),
+ FilterTestUtils.selector("col1", "val1")
+ )
+ )
+ );
+ final Filter expected = FilterTestUtils.and(
+ FilterTestUtils.selector("col1", "val1"),
+ FilterTestUtils.selector("col2", "val2")
+ );
+ Assert.assertEquals(expected, Filters.toCNF(muchReducible));
+ }
+
+ @Test
+ public void testToCNFWithComplexFilterIncludingNotAndOr()
+ {
+ final Filter filter = FilterTestUtils.and(
+ FilterTestUtils.or(
+ FilterTestUtils.and(
+ FilterTestUtils.selector("col1", "val1"),
+ FilterTestUtils.selector("col2", "val2")
+ ),
+ FilterTestUtils.not(
+ FilterTestUtils.and(
+ FilterTestUtils.selector("col4", "val4"),
+ FilterTestUtils.selector("col5", "val5")
+ )
+ )
+ ),
+ FilterTestUtils.or(
+ FilterTestUtils.not(
+ FilterTestUtils.or(
+ FilterTestUtils.selector("col2", "val2"),
+ FilterTestUtils.selector("col4", "val4"),
+ FilterTestUtils.selector("col5", "val5")
+ )
+ ),
+ FilterTestUtils.and(
+ FilterTestUtils.selector("col1", "val1"),
+ FilterTestUtils.selector("col3", "val3")
+ )
+ ),
+ FilterTestUtils.and(
+ FilterTestUtils.or(
+ FilterTestUtils.selector("col1", "val1"),
+ FilterTestUtils.selector("col2", "val22"), // selecting different value
+ FilterTestUtils.selector("col3", "val3")
+ ),
+ FilterTestUtils.not(
+ FilterTestUtils.selector("col1", "val11")
+ )
+ ),
+ FilterTestUtils.and(
+ FilterTestUtils.or(
+ FilterTestUtils.selector("col1", "val1"),
+ FilterTestUtils.selector("col2", "val22"),
+ FilterTestUtils.selector("col3", "val3")
+ ),
+ FilterTestUtils.not(
+ FilterTestUtils.selector("col1", "val11") // selecting different value
+ )
+ )
+ );
+ final Filter expected = FilterTestUtils.and(
+ FilterTestUtils.or(
+ FilterTestUtils.selector("col1", "val1"),
+ FilterTestUtils.selector("col2", "val22"),
+ FilterTestUtils.selector("col3", "val3")
+ ),
+ FilterTestUtils.or(
+ FilterTestUtils.selector("col1", "val1"),
+ FilterTestUtils.not(FilterTestUtils.selector("col2", "val2"))
+ ),
+ FilterTestUtils.or(
+ FilterTestUtils.not(FilterTestUtils.selector("col2", "val2")),
+ FilterTestUtils.selector("col3", "val3")
+ ),
+ FilterTestUtils.or(
+ FilterTestUtils.selector("col1", "val1"),
+ FilterTestUtils.not(FilterTestUtils.selector("col4", "val4"))
+ ),
+ FilterTestUtils.or(
+ FilterTestUtils.selector("col3", "val3"),
+ FilterTestUtils.not(FilterTestUtils.selector("col4", "val4"))
+ ),
+ FilterTestUtils.or(
+ FilterTestUtils.selector("col1", "val1"),
+ FilterTestUtils.not(FilterTestUtils.selector("col5", "val5"))
+ ),
+ FilterTestUtils.or(
+ FilterTestUtils.selector("col3", "val3"),
+ FilterTestUtils.not(FilterTestUtils.selector("col5", "val5"))
+ ),
+ FilterTestUtils.not(FilterTestUtils.selector("col1", "val11")),
+ // The below OR filter could be eliminated because this filter also has
+ // (col1 = val1 || ~(col4 = val4)) && (col1 = val1 || ~(col5 = val5)).
+ // The reduction process would be
+ // (col1 = val1 || ~(col4 = val4)) && (col1 = val1 || ~(col5 = val5)) && (col1 = val1 || ~(col4 = val4) || ~(col5 = val5))
+ // => (col1 = val1 && ~(col4 = val4) || ~(col5 = val5)) && (col1 = val1 || ~(col4 = val4) || ~(col5 = val5))
+ // => (col1 = val1 && ~(col4 = val4) || ~(col5 = val5))
+ // => (col1 = val1 || ~(col4 = val4)) && (col1 = val1 || ~(col5 = val5)).
+ // However, we don't have this reduction now, so we have a filter in a suboptimized CNF.
+ FilterTestUtils.or(
+ FilterTestUtils.selector("col1", "val1"),
+ FilterTestUtils.not(FilterTestUtils.selector("col4", "val4")),
+ FilterTestUtils.not(FilterTestUtils.selector("col5", "val5"))
+ ),
+ FilterTestUtils.or(
+ FilterTestUtils.selector("col2", "val2"),
+ FilterTestUtils.not(FilterTestUtils.selector("col4", "val4")),
+ FilterTestUtils.not(FilterTestUtils.selector("col5", "val5"))
+ )
+ );
+ Assert.assertEquals(expected, Filters.toCNF(filter));
+ }
+
private static BitmapIndex getBitmapIndex(final List<ImmutableBitmap> bitmapList)
{
return new BitmapIndex()
diff --git a/processing/src/test/java/org/apache/druid/segment/filter/NotFilterTest.java b/processing/src/test/java/org/apache/druid/segment/filter/NotFilterEvaluateTest.java
similarity index 95%
copy from processing/src/test/java/org/apache/druid/segment/filter/NotFilterTest.java
copy to processing/src/test/java/org/apache/druid/segment/filter/NotFilterEvaluateTest.java
index f512d70..a2f073c 100644
--- a/processing/src/test/java/org/apache/druid/segment/filter/NotFilterTest.java
+++ b/processing/src/test/java/org/apache/druid/segment/filter/NotFilterEvaluateTest.java
@@ -44,7 +44,7 @@ import java.util.List;
import java.util.Map;
@RunWith(Parameterized.class)
-public class NotFilterTest extends BaseFilterTest
+public class NotFilterEvaluateTest extends BaseFilterTest
{
private static final String TIMESTAMP_COLUMN = "timestamp";
@@ -64,7 +64,7 @@ public class NotFilterTest extends BaseFilterTest
PARSER.parseBatch(ImmutableMap.of("dim0", "5")).get(0)
);
- public NotFilterTest(
+ public NotFilterEvaluateTest(
String testName,
IndexBuilder indexBuilder,
Function<IndexBuilder, Pair<StorageAdapter, Closeable>> finisher,
@@ -78,7 +78,7 @@ public class NotFilterTest extends BaseFilterTest
@AfterClass
public static void tearDown() throws Exception
{
- BaseFilterTest.tearDown(NotFilterTest.class.getName());
+ BaseFilterTest.tearDown(NotFilterEvaluateTest.class.getName());
}
@Test
diff --git a/processing/src/test/java/org/apache/druid/segment/filter/NotFilterTest.java b/processing/src/test/java/org/apache/druid/segment/filter/NotFilterTest.java
index f512d70..d3f34e1 100644
--- a/processing/src/test/java/org/apache/druid/segment/filter/NotFilterTest.java
+++ b/processing/src/test/java/org/apache/druid/segment/filter/NotFilterTest.java
@@ -19,86 +19,24 @@
package org.apache.druid.segment.filter;
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import org.apache.druid.data.input.InputRow;
-import org.apache.druid.data.input.impl.DimensionsSpec;
-import org.apache.druid.data.input.impl.InputRowParser;
-import org.apache.druid.data.input.impl.MapInputRowParser;
-import org.apache.druid.data.input.impl.TimeAndDimsParseSpec;
-import org.apache.druid.data.input.impl.TimestampSpec;
-import org.apache.druid.java.util.common.DateTimes;
-import org.apache.druid.java.util.common.Pair;
-import org.apache.druid.query.filter.NotDimFilter;
-import org.apache.druid.query.filter.SelectorDimFilter;
-import org.apache.druid.segment.IndexBuilder;
-import org.apache.druid.segment.StorageAdapter;
-import org.junit.AfterClass;
+import nl.jqno.equalsverifier.EqualsVerifier;
+import org.apache.druid.query.filter.Filter;
+import org.junit.Assert;
import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import java.io.Closeable;
-import java.util.List;
-import java.util.Map;
-
-@RunWith(Parameterized.class)
-public class NotFilterTest extends BaseFilterTest
+public class NotFilterTest
{
- private static final String TIMESTAMP_COLUMN = "timestamp";
-
- private static final InputRowParser<Map<String, Object>> PARSER = new MapInputRowParser(
- new TimeAndDimsParseSpec(
- new TimestampSpec(TIMESTAMP_COLUMN, "iso", DateTimes.of("2000")),
- new DimensionsSpec(null, null, null)
- )
- );
-
- private static final List<InputRow> ROWS = ImmutableList.of(
- PARSER.parseBatch(ImmutableMap.of("dim0", "0")).get(0),
- PARSER.parseBatch(ImmutableMap.of("dim0", "1")).get(0),
- PARSER.parseBatch(ImmutableMap.of("dim0", "2")).get(0),
- PARSER.parseBatch(ImmutableMap.of("dim0", "3")).get(0),
- PARSER.parseBatch(ImmutableMap.of("dim0", "4")).get(0),
- PARSER.parseBatch(ImmutableMap.of("dim0", "5")).get(0)
- );
-
- public NotFilterTest(
- String testName,
- IndexBuilder indexBuilder,
- Function<IndexBuilder, Pair<StorageAdapter, Closeable>> finisher,
- boolean cnf,
- boolean optimize
- )
- {
- super(testName, ROWS, indexBuilder, finisher, cnf, optimize);
- }
-
- @AfterClass
- public static void tearDown() throws Exception
+ @Test
+ public void testEquals()
{
- BaseFilterTest.tearDown(NotFilterTest.class.getName());
+ EqualsVerifier.forClass(NotFilter.class).usingGetClass().withNonnullFields("baseFilter").verify();
}
@Test
- public void testNotSelector()
+ public void testHashCodeCompareWithBaseFilter()
{
- assertFilterMatches(
- new NotDimFilter(new SelectorDimFilter("dim0", null, null)),
- ImmutableList.of("0", "1", "2", "3", "4", "5")
- );
- assertFilterMatches(
- new NotDimFilter(new SelectorDimFilter("dim0", "", null)),
- ImmutableList.of("0", "1", "2", "3", "4", "5")
- );
- assertFilterMatches(
- new NotDimFilter(new SelectorDimFilter("dim0", "0", null)),
- ImmutableList.of("1", "2", "3", "4", "5")
- );
- assertFilterMatches(
- new NotDimFilter(new SelectorDimFilter("dim0", "1", null)),
- ImmutableList.of("0", "2", "3", "4", "5")
- );
+ final Filter baseFilter = FilterTestUtils.selector("col1", "1");
+ final Filter notFilter = FilterTestUtils.not(baseFilter);
+ Assert.assertNotEquals(notFilter.hashCode(), baseFilter.hashCode());
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org