Search in sources :

Example 1 with Offset

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());
}
Also used : AndFilter(io.druid.segment.filter.AndFilter) AndFilter(io.druid.segment.filter.AndFilter) BooleanFilter(io.druid.query.filter.BooleanFilter) Filter(io.druid.query.filter.Filter) ArrayList(java.util.ArrayList) Interval(org.joda.time.Interval) Offset(io.druid.segment.data.Offset)

Example 2 with Offset

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);
}
Also used : ImmutableBitmap(io.druid.collections.bitmap.ImmutableBitmap) MutableBitmap(io.druid.collections.bitmap.MutableBitmap) Offset(io.druid.segment.data.Offset) Test(org.junit.Test)

Aggregations

Offset (io.druid.segment.data.Offset)2 ImmutableBitmap (io.druid.collections.bitmap.ImmutableBitmap)1 MutableBitmap (io.druid.collections.bitmap.MutableBitmap)1 BooleanFilter (io.druid.query.filter.BooleanFilter)1 Filter (io.druid.query.filter.Filter)1 AndFilter (io.druid.segment.filter.AndFilter)1 ArrayList (java.util.ArrayList)1 Interval (org.joda.time.Interval)1 Test (org.junit.Test)1