use of org.apache.druid.segment.filter.AndFilter in project druid by druid-io.
the class HiveCnfHelper method generateAllCombinations.
// A helper function 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, List<Filter> andList, List<Filter> nonAndList) {
List<Filter> children = new ArrayList<>(((AndFilter) andList.get(0)).getFilters());
if (result.isEmpty()) {
for (Filter child : children) {
List<Filter> a = new ArrayList<>(nonAndList);
a.add(child);
// Result must receive an actual OrFilter, so wrap if Filters.or managed to un-OR it.
result.add(idempotentOr(Filters.or(a)));
}
} else {
List<Filter> work = new ArrayList<>(result);
result.clear();
for (Filter child : children) {
for (Filter or : work) {
List<Filter> a = new ArrayList<>((((OrFilter) or).getFilters()));
a.add(child);
// Result must receive an actual OrFilter.
result.add(idempotentOr(Filters.or(a)));
}
}
}
if (andList.size() > 1) {
generateAllCombinations(result, andList.subList(1, andList.size()), nonAndList);
}
}
use of org.apache.druid.segment.filter.AndFilter in project druid by druid-io.
the class HiveCnfHelper method flatten.
public static Filter flatten(Filter root) {
if (root instanceof BooleanFilter) {
List<Filter> children = new ArrayList<>(((BooleanFilter) root).getFilters());
// they don't get re-visited
for (int i = 0; i < children.size(); ++i) {
Filter child = flatten(children.get(i));
// do we need to flatten?
if (child.getClass() == root.getClass() && !(child instanceof NotFilter)) {
boolean first = true;
List<Filter> grandKids = new ArrayList<>(((BooleanFilter) child).getFilters());
for (Filter grandkid : grandKids) {
// for the first grandkid replace the original parent
if (first) {
first = false;
children.set(i, grandkid);
} else {
children.add(++i, grandkid);
}
}
} else {
children.set(i, child);
}
}
// if we have a singleton AND or OR, just return the child
if (children.size() == 1 && (root instanceof AndFilter || root instanceof OrFilter)) {
return children.get(0);
}
if (root instanceof AndFilter) {
return new AndFilter(children);
} else if (root instanceof OrFilter) {
return new OrFilter(children);
}
}
return root;
}
use of org.apache.druid.segment.filter.AndFilter in project druid by druid-io.
the class HiveCnfHelper method convertToCnf.
public static Filter convertToCnf(Filter current) {
if (current instanceof NotFilter) {
return new NotFilter(convertToCnf(((NotFilter) current).getBaseFilter()));
}
if (current instanceof AndFilter) {
List<Filter> children = new ArrayList<>();
for (Filter child : ((AndFilter) current).getFilters()) {
children.add(convertToCnf(child));
}
return Filters.and(children);
}
if (current instanceof OrFilter) {
// a list of leaves that weren't under AND expressions
List<Filter> nonAndList = new ArrayList<>();
// a list of AND expressions that we need to distribute
List<Filter> andList = new ArrayList<>();
for (Filter child : ((OrFilter) current).getFilters()) {
if (child instanceof AndFilter) {
andList.add(child);
} else if (child instanceof OrFilter) {
// pull apart the kids of the OR expression
nonAndList.addAll(((OrFilter) child).getFilters());
} else {
nonAndList.add(child);
}
}
if (!andList.isEmpty()) {
List<Filter> result = new ArrayList<>();
generateAllCombinations(result, andList, nonAndList);
return Filters.and(result);
}
}
return current;
}
use of org.apache.druid.segment.filter.AndFilter in project druid by druid-io.
the class QueryableIndexStorageAdapter method analyzeFilter.
@VisibleForTesting
public FilterAnalysis analyzeFilter(@Nullable final Filter filter, ColumnSelectorBitmapIndexSelector indexSelector, @Nullable QueryMetrics queryMetrics) {
final int totalRows = index.getNumRows();
/*
* Filters can be applied in two stages:
* pre-filtering: Use bitmap indexes to prune the set of rows to be scanned.
* post-filtering: Iterate through rows and apply the filter to the row values
*
* The pre-filter and post-filter step have an implicit AND relationship. (i.e., final rows are those that
* were not pruned AND those that matched the filter during row scanning)
*
* An AND filter can have its subfilters partitioned across the two steps. The subfilters that can be
* processed entirely with bitmap indexes (subfilter returns true for supportsBitmapIndex())
* will be moved to the pre-filtering stage.
*
* Any subfilters that cannot be processed entirely with bitmap indexes will be moved to the post-filtering stage.
*/
final List<Filter> preFilters;
final List<Filter> postFilters = new ArrayList<>();
int preFilteredRows = totalRows;
if (filter == null) {
preFilters = Collections.emptyList();
} else {
preFilters = new ArrayList<>();
if (filter instanceof AndFilter) {
// If we get an AndFilter, we can split the subfilters across both filtering stages
for (Filter subfilter : ((AndFilter) filter).getFilters()) {
if (subfilter.supportsBitmapIndex(indexSelector) && subfilter.shouldUseBitmapIndex(indexSelector)) {
preFilters.add(subfilter);
} else {
postFilters.add(subfilter);
}
}
} else {
// If we get an OrFilter or a single filter, handle the filter in one stage
if (filter.supportsBitmapIndex(indexSelector) && filter.shouldUseBitmapIndex(indexSelector)) {
preFilters.add(filter);
} else {
postFilters.add(filter);
}
}
}
final ImmutableBitmap preFilterBitmap;
if (preFilters.isEmpty()) {
preFilterBitmap = null;
} else {
if (queryMetrics != null) {
BitmapResultFactory<?> bitmapResultFactory = queryMetrics.makeBitmapResultFactory(indexSelector.getBitmapFactory());
long bitmapConstructionStartNs = System.nanoTime();
// Use AndFilter.getBitmapResult to intersect the preFilters to get its short-circuiting behavior.
preFilterBitmap = AndFilter.getBitmapIndex(indexSelector, bitmapResultFactory, preFilters);
preFilteredRows = preFilterBitmap.size();
queryMetrics.reportBitmapConstructionTime(System.nanoTime() - bitmapConstructionStartNs);
} else {
BitmapResultFactory<?> bitmapResultFactory = new DefaultBitmapResultFactory(indexSelector.getBitmapFactory());
preFilterBitmap = AndFilter.getBitmapIndex(indexSelector, bitmapResultFactory, preFilters);
}
}
if (queryMetrics != null) {
queryMetrics.preFilters(new ArrayList<>(preFilters));
queryMetrics.postFilters(postFilters);
queryMetrics.reportSegmentRows(totalRows);
queryMetrics.reportPreFilteredRows(preFilteredRows);
}
return new FilterAnalysis(preFilterBitmap, Filters.maybeAnd(postFilters).orElse(null));
}
Aggregations