use of org.apache.druid.segment.filter.SelectorFilter in project druid by druid-io.
the class JoinFilterAnalyzer method rewriteSelectorFilter.
/**
* Rewrites a selector filter on a join table into an IN filter on the base table.
*
* @param selectorFilter SelectorFilter to be rewritten
* @param joinFilterPreAnalysis The pre-analysis computed by {@link #computeJoinFilterPreAnalysis)}
* @param pushDownVirtualColumnsForLhsExprs See comments on {@link #analyzeJoinFilterClause}
*
* @return A JoinFilterAnalysis that indicates how to handle the potentially rewritten filter
*/
private static JoinFilterAnalysis rewriteSelectorFilter(SelectorFilter selectorFilter, JoinFilterPreAnalysis joinFilterPreAnalysis, Map<Expr, VirtualColumn> pushDownVirtualColumnsForLhsExprs) {
List<Filter> newFilters = new ArrayList<>();
String filteringColumn = selectorFilter.getDimension();
String filteringValue = selectorFilter.getValue();
if (areSomeColumnsFromPostJoinVirtualColumns(joinFilterPreAnalysis.getPostJoinVirtualColumns(), selectorFilter.getRequiredColumns())) {
return JoinFilterAnalysis.createNoPushdownFilterAnalysis(selectorFilter);
}
if (!joinFilterPreAnalysis.getJoinableClauses().areSomeColumnsFromJoin(selectorFilter.getRequiredColumns())) {
return new JoinFilterAnalysis(false, selectorFilter, selectorFilter);
}
List<JoinFilterColumnCorrelationAnalysis> correlationAnalyses = joinFilterPreAnalysis.getCorrelationsByFilteringColumn().get(filteringColumn);
if (correlationAnalyses == null) {
return JoinFilterAnalysis.createNoPushdownFilterAnalysis(selectorFilter);
}
for (JoinFilterColumnCorrelationAnalysis correlationAnalysis : correlationAnalyses) {
if (correlationAnalysis.supportsPushDown()) {
Optional<Set<String>> correlatedValues = correlationAnalysis.getCorrelatedValuesMap().get(Pair.of(filteringColumn, filteringValue));
if (!correlatedValues.isPresent()) {
return JoinFilterAnalysis.createNoPushdownFilterAnalysis(selectorFilter);
}
Set<String> newFilterValues = correlatedValues.get();
// in nothing => match nothing
if (newFilterValues.isEmpty()) {
return new JoinFilterAnalysis(true, selectorFilter, FalseFilter.instance());
}
for (String correlatedBaseColumn : correlationAnalysis.getBaseColumns()) {
Filter rewrittenFilter = new InDimFilter(correlatedBaseColumn, newFilterValues).toFilter();
newFilters.add(rewrittenFilter);
}
for (Expr correlatedBaseExpr : correlationAnalysis.getBaseExpressions()) {
// We need to create a virtual column for the expressions when pushing down
VirtualColumn pushDownVirtualColumn = pushDownVirtualColumnsForLhsExprs.computeIfAbsent(correlatedBaseExpr, (expr) -> {
String vcName = getCorrelatedBaseExprVirtualColumnName(pushDownVirtualColumnsForLhsExprs.size());
return new ExpressionVirtualColumn(vcName, correlatedBaseExpr, ColumnType.STRING);
});
Filter rewrittenFilter = new InDimFilter(pushDownVirtualColumn.getOutputName(), newFilterValues).toFilter();
newFilters.add(rewrittenFilter);
}
}
}
if (newFilters.isEmpty()) {
return JoinFilterAnalysis.createNoPushdownFilterAnalysis(selectorFilter);
}
return new JoinFilterAnalysis(true, selectorFilter, Filters.maybeAnd(newFilters).orElse(null));
}
use of org.apache.druid.segment.filter.SelectorFilter in project druid by druid-io.
the class RhsRewriteCandidates method determineRhsRewriteCandidatesForSingleFilter.
private static Optional<RhsRewriteCandidate> determineRhsRewriteCandidatesForSingleFilter(Filter orClause, Equiconditions equiconditions, JoinableClauses joinableClauses) {
// Currently, we only support rewrites of filters that operate on a single column for simplicity.
if (equiconditions.doesFilterSupportDirectJoinFilterRewrite(orClause)) {
String reqColumn = orClause.getRequiredColumns().iterator().next();
JoinableClause joinableClause = joinableClauses.getColumnFromJoinIfExists(reqColumn);
if (joinableClause != null) {
return Optional.of(new RhsRewriteCandidate(joinableClause, reqColumn, null, true));
}
} else if (orClause instanceof SelectorFilter) {
// this is a candidate for RHS filter rewrite, determine column correlations and correlated values
String reqColumn = ((SelectorFilter) orClause).getDimension();
String reqValue = ((SelectorFilter) orClause).getValue();
JoinableClause joinableClause = joinableClauses.getColumnFromJoinIfExists(reqColumn);
if (joinableClause != null) {
return Optional.of(new RhsRewriteCandidate(joinableClause, reqColumn, reqValue, false));
}
}
return Optional.empty();
}
use of org.apache.druid.segment.filter.SelectorFilter in project druid by druid-io.
the class ListFilteredVirtualColumnSelectorTest method testFilterListFilteredVirtualColumnAllowIndex.
@Test
public void testFilterListFilteredVirtualColumnAllowIndex() {
ListFilteredVirtualColumn virtualColumn = new ListFilteredVirtualColumn(ALLOW_VIRTUAL_NAME, new DefaultDimensionSpec(COLUMN_NAME, COLUMN_NAME, ColumnType.STRING), ImmutableSet.of("b", "c"), true);
ColumnSelector selector = EasyMock.createMock(ColumnSelector.class);
ColumnHolder holder = EasyMock.createMock(ColumnHolder.class);
BitmapIndex index = EasyMock.createMock(BitmapIndex.class);
ImmutableBitmap bitmap = EasyMock.createMock(ImmutableBitmap.class);
BitmapFactory bitmapFactory = EasyMock.createMock(BitmapFactory.class);
EasyMock.expect(selector.getColumnHolder(COLUMN_NAME)).andReturn(holder).atLeastOnce();
EasyMock.expect(holder.getBitmapIndex()).andReturn(index).atLeastOnce();
EasyMock.expect(index.getCardinality()).andReturn(3).atLeastOnce();
EasyMock.expect(index.getValue(0)).andReturn("a").atLeastOnce();
EasyMock.expect(index.getValue(1)).andReturn("b").atLeastOnce();
EasyMock.expect(index.getValue(2)).andReturn("c").atLeastOnce();
EasyMock.expect(index.getBitmap(2)).andReturn(bitmap).once();
EasyMock.expect(index.getBitmapFactory()).andReturn(bitmapFactory).once();
EasyMock.expect(index.hasNulls()).andReturn(true).once();
EasyMock.replay(selector, holder, index, bitmap, bitmapFactory);
ColumnSelectorBitmapIndexSelector bitmapIndexSelector = new ColumnSelectorBitmapIndexSelector(new RoaringBitmapFactory(), VirtualColumns.create(Collections.singletonList(virtualColumn)), selector);
SelectorFilter filter = new SelectorFilter(ALLOW_VIRTUAL_NAME, "a");
Assert.assertTrue(filter.shouldUseBitmapIndex(bitmapIndexSelector));
BitmapIndex listFilteredIndex = bitmapIndexSelector.getBitmapIndex(ALLOW_VIRTUAL_NAME);
Assert.assertEquals(-1, listFilteredIndex.getIndex("a"));
Assert.assertEquals(0, listFilteredIndex.getIndex("b"));
Assert.assertEquals(1, listFilteredIndex.getIndex("c"));
Assert.assertEquals(2, listFilteredIndex.getCardinality());
Assert.assertEquals("b", listFilteredIndex.getValue(0));
Assert.assertEquals("c", listFilteredIndex.getValue(1));
Assert.assertEquals(bitmap, listFilteredIndex.getBitmap(1));
Assert.assertEquals(bitmapFactory, listFilteredIndex.getBitmapFactory());
Assert.assertTrue(listFilteredIndex.hasNulls());
EasyMock.verify(selector, holder, index, bitmap, bitmapFactory);
}
Aggregations