use of io.druid.segment.data.Offset in project druid by druid-io.
the class QueryableIndexStorageAdapter method makeCursors.
@Override
public Sequence<Cursor> makeCursors(Filter filter, Interval interval, VirtualColumns virtualColumns, Granularity gran, boolean descending) {
Interval actualInterval = interval;
long minDataTimestamp = getMinTime().getMillis();
long maxDataTimestamp = getMaxTime().getMillis();
final Interval dataInterval = new Interval(minDataTimestamp, gran.bucketEnd(getMaxTime()).getMillis());
if (!actualInterval.overlaps(dataInterval)) {
return Sequences.empty();
}
if (actualInterval.getStart().isBefore(dataInterval.getStart())) {
actualInterval = actualInterval.withStart(dataInterval.getStart());
}
if (actualInterval.getEnd().isAfter(dataInterval.getEnd())) {
actualInterval = actualInterval.withEnd(dataInterval.getEnd());
}
final ColumnSelectorBitmapIndexSelector selector = new ColumnSelectorBitmapIndexSelector(index.getBitmapFactoryForDimensions(), virtualColumns, index);
/**
* 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 Offset offset;
final List<Filter> postFilters = new ArrayList<>();
if (filter == null) {
offset = new NoFilterOffset(0, index.getNumRows(), descending);
} else {
final List<Filter> 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(selector)) {
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(selector)) {
preFilters.add(filter);
} else {
postFilters.add(filter);
}
}
if (preFilters.size() == 0) {
offset = new NoFilterOffset(0, index.getNumRows(), descending);
} else {
// Use AndFilter.getBitmapIndex to intersect the preFilters to get its short-circuiting behavior.
offset = BitmapOffset.of(AndFilter.getBitmapIndex(selector, preFilters), descending, (long) getNumRows());
}
}
final Filter postFilter;
if (postFilters.size() == 0) {
postFilter = null;
} else if (postFilters.size() == 1) {
postFilter = postFilters.get(0);
} else {
postFilter = new AndFilter(postFilters);
}
return Sequences.filter(new CursorSequenceBuilder(this, actualInterval, virtualColumns, gran, offset, minDataTimestamp, maxDataTimestamp, descending, postFilter, selector).build(), Predicates.<Cursor>notNull());
}
use of io.druid.segment.data.Offset in project druid by druid-io.
the class BitmapOffsetTest method testSanity.
@Test
public void testSanity() throws Exception {
MutableBitmap mutable = factory.makeEmptyMutableBitmap();
for (int val : TEST_VALS) {
mutable.add(val);
}
ImmutableBitmap bitmap = factory.makeImmutableBitmap(mutable);
final BitmapOffset offset = BitmapOffset.of(bitmap, descending, bitmap.size());
final int[] expected = descending ? TEST_VALS_FLIP : TEST_VALS;
int count = 0;
while (offset.withinBounds()) {
Assert.assertEquals(expected[count], offset.getOffset());
int cloneCount = count;
Offset clonedOffset = offset.clone();
while (clonedOffset.withinBounds()) {
Assert.assertEquals(expected[cloneCount], clonedOffset.getOffset());
++cloneCount;
clonedOffset.increment();
}
++count;
offset.increment();
}
Assert.assertEquals(count, expected.length);
}
Aggregations