@Override public RowFilter adapt(FilterAdapterContext context, ColumnRangeFilter filter) throws IOException { byte[] familyName = getSingleFamily(context.getScan()); ColumnRange.Builder rangeBuilder = ColumnRange.newBuilder(); rangeBuilder.setFamilyName(Bytes.toString(familyName)); ByteString startQualifier = ByteString.copyFrom(filter.getMinColumn()); if (filter.getMinColumnInclusive()) { rangeBuilder.setStartQualifierInclusive(startQualifier); } else { rangeBuilder.setStartQualifierExclusive(startQualifier); } ByteString endQualifier = ByteString.copyFrom(filter.getMaxColumn()); if (filter.getMaxColumnInclusive()) { rangeBuilder.setEndQualifierInclusive(endQualifier); } else { rangeBuilder.setEndQualifierExclusive(endQualifier); } return RowFilter.newBuilder() .setColumnRangeFilter(rangeBuilder) .build(); }
@Test public void testColumnRangeFilterWithASingleFamily() throws IOException { ColumnRangeFilter filter = new ColumnRangeFilter( Bytes.toBytes("a"), true, Bytes.toBytes("b"), false); Scan familyScan = new Scan().addFamily(Bytes.toBytes("foo")); RowFilter rowFilter = filterAdapter.adapt( new FilterAdapterContext(familyScan), filter); Assert.assertEquals( "a", Bytes.toString( rowFilter .getColumnRangeFilter() .getStartQualifierInclusive() .toByteArray())); Assert.assertEquals( "b", Bytes.toString( rowFilter .getColumnRangeFilter() .getEndQualifierExclusive() .toByteArray())); }
@Test public void testToConcreteFilters() throws IOException { FiltersCounter counter = new FiltersCounter(); ThemisCpUtil.processFilters(null, counter); Assert.assertEquals(0, counter.concreteFilterCount); counter = new FiltersCounter(); ThemisCpUtil.processFilters(new ColumnRangeFilter(), counter); Assert.assertEquals(1, counter.concreteFilterCount); counter = new FiltersCounter(); FilterList filterList = new FilterList(); filterList.addFilter(new ColumnRangeFilter()); filterList.addFilter(new ColumnCountGetFilter()); ThemisCpUtil.processFilters(filterList, counter); Assert.assertEquals(2, counter.concreteFilterCount); // test process filterlist operator counter = new ConcreteFiltersCounter(); ThemisCpUtil.processFilters(new ColumnRangeFilter(), counter); Assert.assertEquals(1, counter.concreteFilterCount); counter = new ConcreteFiltersCounter(); ThemisCpUtil.processFilters(filterList, counter); Assert.assertEquals(0, counter.concreteFilterCount); }
/** * Scan data inside single row (intraScan) without transaction. * {@link HaeinsaTransaction#commit()} to check or mutate lock column of the row scanned by this method. * This method can be used when read performance is important or strict consistency of the result is not matter. * * @throws IOException IOException from HBase. */ private HaeinsaResultScanner getScannerWithoutTx(HaeinsaIntraScan intraScan) throws IOException { Scan hScan = new Scan(intraScan.getRow(), Bytes.add(intraScan.getRow(), new byte[]{0x00})); hScan.setBatch(intraScan.getBatch()); for (byte[] family : intraScan.getFamilies()) { hScan.addFamily(family); } ColumnRangeFilter rangeFilter = new ColumnRangeFilter( intraScan.getMinColumn(), intraScan.isMinColumnInclusive(), intraScan.getMaxColumn(), intraScan.isMaxColumnInclusive()); hScan.setFilter(rangeFilter); final ResultScanner scanner = table.getScanner(hScan); return new SimpleClientScanner(scanner); }
/** * Test partial Result re-assembly in the presence of different filters. The Results from the * partial scanner should match the Results returned from a scanner that receives all of the * results in one RPC to the server. The partial scanner is tested with a variety of different * result sizes (all of which are less than the size necessary to fetch an entire row) * @throws Exception */ @Test public void testPartialResultsWithColumnFilter() throws Exception { testPartialResultsWithColumnFilter(new FirstKeyOnlyFilter()); testPartialResultsWithColumnFilter(new ColumnPrefixFilter(Bytes.toBytes("testQualifier5"))); testPartialResultsWithColumnFilter(new ColumnRangeFilter(Bytes.toBytes("testQualifer1"), true, Bytes.toBytes("testQualifier7"), true)); Set<byte[]> qualifiers = new LinkedHashSet<>(); qualifiers.add(Bytes.toBytes("testQualifier5")); testPartialResultsWithColumnFilter(new FirstKeyValueMatchingQualifiersFilter(qualifiers)); }
@Override public FilterSupportStatus isFilterSupported( FilterAdapterContext context, ColumnRangeFilter filter) { // We require a single column family to be specified: int familyCount = context.getScan().numFamilies(); if (familyCount != 1) { return UNSUPPORTED_STATUS; } return FilterSupportStatus.SUPPORTED; }
/** * Haeinsa implementation of {@link ColumnRangeFilter}. * Scan range of column inside single row defined by {@link HaeinsaIntraScan} in the context of transaction(tx). * Return {@link ClientScanner} which related to {@link HaeinsaTable} and {@link HaeinsaTransaction}. * <p> * Return {@link SimpleClientScanner} which do not support transaction if tx is null. * User can use this feature if specific intra-scan operation does not require strong consistency. * <p> * Haeinsa does not support column-range scan over multiple row in this version. */ @Override public HaeinsaResultScanner getScanner(@Nullable HaeinsaTransaction tx, HaeinsaIntraScan intraScan) throws IOException { Preconditions.checkNotNull(intraScan); if (tx == null) { return getScannerWithoutTx(intraScan); } // scan from startRow ( inclusive ) to startRow + 0x00 ( exclusive ) Scan hScan = new Scan(intraScan.getRow(), Bytes.add(intraScan.getRow(), new byte[]{0x00})); hScan.setBatch(intraScan.getBatch()); hScan.setCacheBlocks(intraScan.getCacheBlocks()); for (byte[] family : intraScan.getFamilies()) { hScan.addFamily(family); } ColumnRangeFilter rangeFilter = new ColumnRangeFilter( intraScan.getMinColumn(), intraScan.isMinColumnInclusive(), intraScan.getMaxColumn(), intraScan.isMaxColumnInclusive()); hScan.setFilter(rangeFilter); HaeinsaTableTransaction tableState = tx.createOrGetTableState(getTableName()); HaeinsaRowTransaction rowState = tableState.getRowStates().get(intraScan.getRow()); if (rowState == null) { rowState = checkOrRecoverLock(tx, intraScan.getRow(), tableState, rowState); } List<HaeinsaKeyValueScanner> scanners = Lists.newArrayList(); if (rowState != null) { scanners.addAll(rowState.getScanners()); } scanners.add(new HBaseScanScanner(table.getScanner(hScan))); // scanners at this moment is: // union( muationScanners from RowTransaction, Scanner of intraScan ) return new ClientScanner(tx, scanners, hScan.getFamilyMap(), intraScan, false); }
/** * Create a new FilterAdapter */ public static FilterAdapter buildAdapter() { FilterAdapter adapter = new FilterAdapter(); adapter.addFilterAdapter( ColumnPrefixFilter.class, new ColumnPrefixFilterAdapter()); adapter.addFilterAdapter( ColumnRangeFilter.class, new ColumnRangeFilterAdapter()); adapter.addFilterAdapter( KeyOnlyFilter.class, new KeyOnlyFilterAdapter()); adapter.addFilterAdapter( MultipleColumnPrefixFilter.class, new MultipleColumnPrefixFilterAdapter()); adapter.addFilterAdapter( TimestampsFilter.class, new TimestampsFilterAdapter()); ValueFilterAdapter valueFilterAdapter = new ValueFilterAdapter(); adapter.addFilterAdapter( ValueFilter.class, valueFilterAdapter); SingleColumnValueFilterAdapter scvfa = new SingleColumnValueFilterAdapter(valueFilterAdapter); adapter.addFilterAdapter( SingleColumnValueFilter.class, scvfa); adapter.addFilterAdapter( SingleColumnValueExcludeFilter.class, new SingleColumnValueExcludeFilterAdapter(scvfa)); adapter.addFilterAdapter( ColumnPaginationFilter.class, new ColumnPaginationFilterAdapter()); adapter.addFilterAdapter( FirstKeyOnlyFilter.class, new FirstKeyOnlyFilterAdapter()); adapter.addFilterAdapter( ColumnCountGetFilter.class, new ColumnCountGetFilterAdapter()); adapter.addFilterAdapter( RandomRowFilter.class, new RandomRowFilterAdapter()); adapter.addFilterAdapter( PrefixFilter.class, new PrefixFilterAdapter()); adapter.addFilterAdapter( QualifierFilter.class, new QualifierFilterAdapter()); // Passing the FilterAdapter in to the FilterListAdapter is a bit // unfortunate, but makes adapting the FilterList's subfilters simpler. FilterListAdapter filterListAdapter = new FilterListAdapter(adapter); // FilterList implements UnsupportedStatusCollector so it should // be used when possible (third parameter to addFilterAdapter()). adapter.addFilterAdapter( FilterList.class, filterListAdapter, filterListAdapter); return adapter; }
@Test public void testColumnRangeFilterThrowsWithNoFamilies() throws IOException { ColumnRangeFilter filter = new ColumnRangeFilter( Bytes.toBytes("a"), true, Bytes.toBytes("b"), true); Assert.assertFalse(filterAdapter.isFilterSupported(emptyScanContext, filter).isSupported()); }