You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ap...@apache.org on 2010/03/04 18:06:05 UTC
svn commit: r919068 [4/4] - in /hadoop/hbase/branches/0.20: ./
src/contrib/stargate/lib/
src/contrib/stargate/src/java/org/apache/hadoop/hbase/stargate/
src/contrib/stargate/src/java/org/apache/hadoop/hbase/stargate/model/
src/contrib/stargate/src/java...
Added: hadoop/hbase/branches/0.20/src/contrib/stargate/src/test/org/apache/hadoop/hbase/stargate/TestScannersWithFilters.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.20/src/contrib/stargate/src/test/org/apache/hadoop/hbase/stargate/TestScannersWithFilters.java?rev=919068&view=auto
==============================================================================
--- hadoop/hbase/branches/0.20/src/contrib/stargate/src/test/org/apache/hadoop/hbase/stargate/TestScannersWithFilters.java (added)
+++ hadoop/hbase/branches/0.20/src/contrib/stargate/src/test/org/apache/hadoop/hbase/stargate/TestScannersWithFilters.java Thu Mar 4 17:06:04 2010
@@ -0,0 +1,979 @@
+/*
+ * Copyright 2010 The Apache Software Foundation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.stargate;
+
+import java.io.ByteArrayInputStream;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.HColumnDescriptor;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.KeyValue;
+import org.apache.hadoop.hbase.client.Delete;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.client.HTable;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.filter.BinaryComparator;
+import org.apache.hadoop.hbase.filter.Filter;
+import org.apache.hadoop.hbase.filter.FilterList;
+import org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter;
+import org.apache.hadoop.hbase.filter.InclusiveStopFilter;
+import org.apache.hadoop.hbase.filter.PageFilter;
+import org.apache.hadoop.hbase.filter.PrefixFilter;
+import org.apache.hadoop.hbase.filter.QualifierFilter;
+import org.apache.hadoop.hbase.filter.RegexStringComparator;
+import org.apache.hadoop.hbase.filter.RowFilter;
+import org.apache.hadoop.hbase.filter.SkipFilter;
+import org.apache.hadoop.hbase.filter.SubstringComparator;
+import org.apache.hadoop.hbase.filter.ValueFilter;
+import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
+import org.apache.hadoop.hbase.filter.FilterList.Operator;
+import org.apache.hadoop.hbase.stargate.client.Client;
+import org.apache.hadoop.hbase.stargate.client.Cluster;
+import org.apache.hadoop.hbase.stargate.client.Response;
+import org.apache.hadoop.hbase.stargate.model.CellModel;
+import org.apache.hadoop.hbase.stargate.model.CellSetModel;
+import org.apache.hadoop.hbase.stargate.model.RowModel;
+import org.apache.hadoop.hbase.stargate.model.ScannerModel;
+import org.apache.hadoop.hbase.util.Bytes;
+
+public class TestScannersWithFilters extends MiniClusterTestCase {
+
+ private static final Log LOG =
+ LogFactory.getLog(TestScannersWithFilters.class);
+
+ private Client client;
+ private JAXBContext context;
+ private Marshaller marshaller;
+ private Unmarshaller unmarshaller;
+
+ private static final byte [][] ROWS_ONE = {
+ Bytes.toBytes("testRowOne-0"), Bytes.toBytes("testRowOne-1"),
+ Bytes.toBytes("testRowOne-2"), Bytes.toBytes("testRowOne-3")
+ };
+
+ private static final byte [][] ROWS_TWO = {
+ Bytes.toBytes("testRowTwo-0"), Bytes.toBytes("testRowTwo-1"),
+ Bytes.toBytes("testRowTwo-2"), Bytes.toBytes("testRowTwo-3")
+ };
+
+ private static final byte [][] FAMILIES = {
+ Bytes.toBytes("testFamilyOne"), Bytes.toBytes("testFamilyTwo")
+ };
+
+ private static final byte [][] QUALIFIERS_ONE = {
+ Bytes.toBytes("testQualifierOne-0"), Bytes.toBytes("testQualifierOne-1"),
+ Bytes.toBytes("testQualifierOne-2"), Bytes.toBytes("testQualifierOne-3")
+ };
+
+ private static final byte [][] QUALIFIERS_TWO = {
+ Bytes.toBytes("testQualifierTwo-0"), Bytes.toBytes("testQualifierTwo-1"),
+ Bytes.toBytes("testQualifierTwo-2"), Bytes.toBytes("testQualifierTwo-3")
+ };
+
+ private static final byte [][] VALUES = {
+ Bytes.toBytes("testValueOne"), Bytes.toBytes("testValueTwo")
+ };
+
+ private long numRows = ROWS_ONE.length + ROWS_TWO.length;
+ private long colsPerRow = FAMILIES.length * QUALIFIERS_ONE.length;
+
+ public TestScannersWithFilters() throws JAXBException {
+ super();
+ context = JAXBContext.newInstance(
+ CellModel.class,
+ CellSetModel.class,
+ RowModel.class,
+ ScannerModel.class);
+ marshaller = context.createMarshaller();
+ unmarshaller = context.createUnmarshaller();
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ client = new Client(new Cluster().add("localhost", testServletPort));
+ HBaseAdmin admin = new HBaseAdmin(conf);
+ if (!admin.tableExists(getName())) {
+ HTableDescriptor htd = new HTableDescriptor(getName());
+ htd.addFamily(new HColumnDescriptor(FAMILIES[0]));
+ htd.addFamily(new HColumnDescriptor(FAMILIES[1]));
+ admin.createTable(htd);
+ HTable table = new HTable(conf, getName());
+ // Insert first half
+ for(byte [] ROW : ROWS_ONE) {
+ Put p = new Put(ROW);
+ for(byte [] QUALIFIER : QUALIFIERS_ONE) {
+ p.add(FAMILIES[0], QUALIFIER, VALUES[0]);
+ }
+ table.put(p);
+ }
+ for(byte [] ROW : ROWS_TWO) {
+ Put p = new Put(ROW);
+ for(byte [] QUALIFIER : QUALIFIERS_TWO) {
+ p.add(FAMILIES[1], QUALIFIER, VALUES[1]);
+ }
+ table.put(p);
+ }
+
+ // Insert second half (reverse families)
+ for(byte [] ROW : ROWS_ONE) {
+ Put p = new Put(ROW);
+ for(byte [] QUALIFIER : QUALIFIERS_ONE) {
+ p.add(FAMILIES[1], QUALIFIER, VALUES[0]);
+ }
+ table.put(p);
+ }
+ for(byte [] ROW : ROWS_TWO) {
+ Put p = new Put(ROW);
+ for(byte [] QUALIFIER : QUALIFIERS_TWO) {
+ p.add(FAMILIES[0], QUALIFIER, VALUES[1]);
+ }
+ table.put(p);
+ }
+
+ // Delete the second qualifier from all rows and families
+ for(byte [] ROW : ROWS_ONE) {
+ Delete d = new Delete(ROW);
+ d.deleteColumns(FAMILIES[0], QUALIFIERS_ONE[1]);
+ d.deleteColumns(FAMILIES[1], QUALIFIERS_ONE[1]);
+ table.delete(d);
+ }
+ for(byte [] ROW : ROWS_TWO) {
+ Delete d = new Delete(ROW);
+ d.deleteColumns(FAMILIES[0], QUALIFIERS_TWO[1]);
+ d.deleteColumns(FAMILIES[1], QUALIFIERS_TWO[1]);
+ table.delete(d);
+ }
+ colsPerRow -= 2;
+
+ // Delete the second rows from both groups, one column at a time
+ for(byte [] QUALIFIER : QUALIFIERS_ONE) {
+ Delete d = new Delete(ROWS_ONE[1]);
+ d.deleteColumns(FAMILIES[0], QUALIFIER);
+ d.deleteColumns(FAMILIES[1], QUALIFIER);
+ table.delete(d);
+ }
+ for(byte [] QUALIFIER : QUALIFIERS_TWO) {
+ Delete d = new Delete(ROWS_TWO[1]);
+ d.deleteColumns(FAMILIES[0], QUALIFIER);
+ d.deleteColumns(FAMILIES[1], QUALIFIER);
+ table.delete(d);
+ }
+ numRows -= 2;
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ client.shutdown();
+ super.tearDown();
+ }
+
+ private void verifyScan(Scan s, long expectedRows, long expectedKeys)
+ throws Exception {
+ ScannerModel model = ScannerModel.fromScan(s);
+ model.setBatch(Integer.MAX_VALUE); // fetch it all at once
+ StringWriter writer = new StringWriter();
+ marshaller.marshal(model, writer);
+ LOG.debug(writer.toString());
+ byte[] body = Bytes.toBytes(writer.toString());
+ Response response = client.put("/" + getName() + "/scanner", MIMETYPE_XML,
+ body);
+ assertEquals(response.getCode(), 201);
+ String scannerURI = response.getLocation();
+ assertNotNull(scannerURI);
+
+ // get a cell set
+ response = client.get(scannerURI, MIMETYPE_XML);
+ assertEquals(response.getCode(), 200);
+ CellSetModel cells = (CellSetModel)
+ unmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
+
+ int rows = cells.getRows().size();
+ assertTrue("Scanned too many rows! Only expected " + expectedRows +
+ " total but scanned " + rows, expectedRows == rows);
+ for (RowModel row: cells.getRows()) {
+ int count = row.getCells().size();
+ assertEquals("Expected " + expectedKeys + " keys per row but " +
+ "returned " + count, expectedKeys, count);
+ }
+
+ // delete the scanner
+ response = client.delete(scannerURI);
+ assertEquals(response.getCode(), 200);
+ }
+
+ private void verifyScanFull(Scan s, KeyValue [] kvs) throws Exception {
+ ScannerModel model = ScannerModel.fromScan(s);
+ model.setBatch(Integer.MAX_VALUE); // fetch it all at once
+ StringWriter writer = new StringWriter();
+ marshaller.marshal(model, writer);
+ LOG.debug(writer.toString());
+ byte[] body = Bytes.toBytes(writer.toString());
+ Response response = client.put("/" + getName() + "/scanner", MIMETYPE_XML,
+ body);
+ assertEquals(response.getCode(), 201);
+ String scannerURI = response.getLocation();
+ assertNotNull(scannerURI);
+
+ // get a cell set
+ response = client.get(scannerURI, MIMETYPE_XML);
+ assertEquals(response.getCode(), 200);
+ CellSetModel cellSet = (CellSetModel)
+ unmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
+
+ // delete the scanner
+ response = client.delete(scannerURI);
+ assertEquals(response.getCode(), 200);
+
+ int row = 0;
+ int idx = 0;
+ Iterator<RowModel> i = cellSet.getRows().iterator();
+ for (boolean done = true; done; row++) {
+ done = i.hasNext();
+ if (!done) break;
+ RowModel rowModel = i.next();
+ List<CellModel> cells = rowModel.getCells();
+ if (cells.isEmpty()) break;
+ assertTrue("Scanned too many keys! Only expected " + kvs.length +
+ " total but already scanned " + (cells.size() + idx),
+ kvs.length >= idx + cells.size());
+ for (CellModel cell: cells) {
+ assertTrue("Row mismatch",
+ Bytes.equals(rowModel.getKey(), kvs[idx].getRow()));
+ byte[][] split = KeyValue.parseColumn(cell.getColumn());
+ assertTrue("Family mismatch",
+ Bytes.equals(split[0], kvs[idx].getFamily()));
+ assertTrue("Qualifier mismatch",
+ Bytes.equals(split[1], kvs[idx].getQualifier()));
+ assertTrue("Value mismatch",
+ Bytes.equals(cell.getValue(), kvs[idx].getValue()));
+ idx++;
+ }
+ }
+ assertEquals("Expected " + kvs.length + " total keys but scanned " + idx,
+ kvs.length, idx);
+ }
+
+ private void verifyScanNoEarlyOut(Scan s, long expectedRows, long expectedKeys)
+ throws Exception {
+ ScannerModel model = ScannerModel.fromScan(s);
+ model.setBatch(Integer.MAX_VALUE); // fetch it all at once
+ StringWriter writer = new StringWriter();
+ marshaller.marshal(model, writer);
+ LOG.debug(writer.toString());
+ byte[] body = Bytes.toBytes(writer.toString());
+ Response response = client.put("/" + getName() + "/scanner", MIMETYPE_XML,
+ body);
+ assertEquals(response.getCode(), 201);
+ String scannerURI = response.getLocation();
+ assertNotNull(scannerURI);
+
+ // get a cell set
+ response = client.get(scannerURI, MIMETYPE_XML);
+ assertEquals(response.getCode(), 200);
+ CellSetModel cellSet = (CellSetModel)
+ unmarshaller.unmarshal(new ByteArrayInputStream(response.getBody()));
+
+ // delete the scanner
+ response = client.delete(scannerURI);
+ assertEquals(response.getCode(), 200);
+
+ Iterator<RowModel> i = cellSet.getRows().iterator();
+ int j = 0;
+ for (boolean done = true; done; j++) {
+ done = i.hasNext();
+ if (!done) break;
+ RowModel rowModel = i.next();
+ List<CellModel> cells = rowModel.getCells();
+ if (cells.isEmpty()) break;
+ assertTrue("Scanned too many rows! Only expected " + expectedRows +
+ " total but already scanned " + (j+1), expectedRows > j);
+ assertEquals("Expected " + expectedKeys + " keys per row but " +
+ "returned " + cells.size(), expectedKeys, cells.size());
+ }
+ assertEquals("Expected " + expectedRows + " rows but scanned " + j +
+ " rows", expectedRows, j);
+ }
+
+ public void testNoFilter() throws Exception {
+ // No filter
+ long expectedRows = this.numRows;
+ long expectedKeys = this.colsPerRow;
+
+ // Both families
+ Scan s = new Scan();
+ verifyScan(s, expectedRows, expectedKeys);
+
+ // One family
+ s = new Scan();
+ s.addFamily(FAMILIES[0]);
+ verifyScan(s, expectedRows, expectedKeys/2);
+ }
+
+ public void testPrefixFilter() throws Exception {
+ // Grab rows from group one (half of total)
+ long expectedRows = this.numRows / 2;
+ long expectedKeys = this.colsPerRow;
+ Scan s = new Scan();
+ s.setFilter(new PrefixFilter(Bytes.toBytes("testRowOne")));
+ verifyScan(s, expectedRows, expectedKeys);
+ }
+
+ public void testPageFilter() throws Exception {
+
+ // KVs in first 6 rows
+ KeyValue [] expectedKVs = {
+ // testRowOne-0
+ new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]),
+ new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+ new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[2], VALUES[0]),
+ new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+ // testRowOne-2
+ new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]),
+ new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+ new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[2], VALUES[0]),
+ new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+ // testRowOne-3
+ new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]),
+ new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+ new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[2], VALUES[0]),
+ new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+ // testRowTwo-0
+ new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+ // testRowTwo-2
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+ // testRowTwo-3
+ new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1])
+ };
+
+ // Grab all 6 rows
+ long expectedRows = 6;
+ long expectedKeys = this.colsPerRow;
+ Scan s = new Scan();
+ s.setFilter(new PageFilter(expectedRows));
+ verifyScan(s, expectedRows, expectedKeys);
+ s.setFilter(new PageFilter(expectedRows));
+ verifyScanFull(s, expectedKVs);
+
+ // Grab first 4 rows (6 cols per row)
+ expectedRows = 4;
+ expectedKeys = this.colsPerRow;
+ s = new Scan();
+ s.setFilter(new PageFilter(expectedRows));
+ verifyScan(s, expectedRows, expectedKeys);
+ s.setFilter(new PageFilter(expectedRows));
+ verifyScanFull(s, Arrays.copyOf(expectedKVs, 24));
+
+ // Grab first 2 rows
+ expectedRows = 2;
+ expectedKeys = this.colsPerRow;
+ s = new Scan();
+ s.setFilter(new PageFilter(expectedRows));
+ verifyScan(s, expectedRows, expectedKeys);
+ s.setFilter(new PageFilter(expectedRows));
+ verifyScanFull(s, Arrays.copyOf(expectedKVs, 12));
+
+ // Grab first row
+ expectedRows = 1;
+ expectedKeys = this.colsPerRow;
+ s = new Scan();
+ s.setFilter(new PageFilter(expectedRows));
+ verifyScan(s, expectedRows, expectedKeys);
+ s.setFilter(new PageFilter(expectedRows));
+ verifyScanFull(s, Arrays.copyOf(expectedKVs, 6));
+ }
+
+ public void testInclusiveStopFilter() throws Exception {
+
+ // Grab rows from group one
+
+ // If we just use start/stop row, we get total/2 - 1 rows
+ long expectedRows = (this.numRows / 2) - 1;
+ long expectedKeys = this.colsPerRow;
+ Scan s = new Scan(Bytes.toBytes("testRowOne-0"),
+ Bytes.toBytes("testRowOne-3"));
+ verifyScan(s, expectedRows, expectedKeys);
+
+ // Now use start row with inclusive stop filter
+ expectedRows = this.numRows / 2;
+ s = new Scan(Bytes.toBytes("testRowOne-0"));
+ s.setFilter(new InclusiveStopFilter(Bytes.toBytes("testRowOne-3")));
+ verifyScan(s, expectedRows, expectedKeys);
+
+ // Grab rows from group two
+
+ // If we just use start/stop row, we get total/2 - 1 rows
+ expectedRows = (this.numRows / 2) - 1;
+ expectedKeys = this.colsPerRow;
+ s = new Scan(Bytes.toBytes("testRowTwo-0"),
+ Bytes.toBytes("testRowTwo-3"));
+ verifyScan(s, expectedRows, expectedKeys);
+
+ // Now use start row with inclusive stop filter
+ expectedRows = this.numRows / 2;
+ s = new Scan(Bytes.toBytes("testRowTwo-0"));
+ s.setFilter(new InclusiveStopFilter(Bytes.toBytes("testRowTwo-3")));
+ verifyScan(s, expectedRows, expectedKeys);
+
+ }
+
+ public void testQualifierFilter() throws Exception {
+
+ // Match two keys (one from each family) in half the rows
+ long expectedRows = this.numRows / 2;
+ long expectedKeys = 2;
+ Filter f = new QualifierFilter(CompareOp.EQUAL,
+ new BinaryComparator(Bytes.toBytes("testQualifierOne-2")));
+ Scan s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match keys less than same qualifier
+ // Expect only two keys (one from each family) in half the rows
+ expectedRows = this.numRows / 2;
+ expectedKeys = 2;
+ f = new QualifierFilter(CompareOp.LESS,
+ new BinaryComparator(Bytes.toBytes("testQualifierOne-2")));
+ s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match keys less than or equal
+ // Expect four keys (two from each family) in half the rows
+ expectedRows = this.numRows / 2;
+ expectedKeys = 4;
+ f = new QualifierFilter(CompareOp.LESS_OR_EQUAL,
+ new BinaryComparator(Bytes.toBytes("testQualifierOne-2")));
+ s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match keys not equal
+ // Expect four keys (two from each family)
+ // Only look in first group of rows
+ expectedRows = this.numRows / 2;
+ expectedKeys = 4;
+ f = new QualifierFilter(CompareOp.NOT_EQUAL,
+ new BinaryComparator(Bytes.toBytes("testQualifierOne-2")));
+ s = new Scan(HConstants.EMPTY_START_ROW, Bytes.toBytes("testRowTwo"));
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match keys greater or equal
+ // Expect four keys (two from each family)
+ // Only look in first group of rows
+ expectedRows = this.numRows / 2;
+ expectedKeys = 4;
+ f = new QualifierFilter(CompareOp.GREATER_OR_EQUAL,
+ new BinaryComparator(Bytes.toBytes("testQualifierOne-2")));
+ s = new Scan(HConstants.EMPTY_START_ROW, Bytes.toBytes("testRowTwo"));
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match keys greater
+ // Expect two keys (one from each family)
+ // Only look in first group of rows
+ expectedRows = this.numRows / 2;
+ expectedKeys = 2;
+ f = new QualifierFilter(CompareOp.GREATER,
+ new BinaryComparator(Bytes.toBytes("testQualifierOne-2")));
+ s = new Scan(HConstants.EMPTY_START_ROW, Bytes.toBytes("testRowTwo"));
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match keys not equal to
+ // Look across rows and fully validate the keys and ordering
+ // Expect varied numbers of keys, 4 per row in group one, 6 per row in group two
+ f = new QualifierFilter(CompareOp.NOT_EQUAL,
+ new BinaryComparator(QUALIFIERS_ONE[2]));
+ s = new Scan();
+ s.setFilter(f);
+
+ KeyValue [] kvs = {
+ // testRowOne-0
+ new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+ new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+ // testRowOne-2
+ new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+ new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+ // testRowOne-3
+ new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+ new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+ // testRowTwo-0
+ new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+ // testRowTwo-2
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+ // testRowTwo-3
+ new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+ };
+ verifyScanFull(s, kvs);
+
+
+ // Test across rows and groups with a regex
+ // Filter out "test*-2"
+ // Expect 4 keys per row across both groups
+ f = new QualifierFilter(CompareOp.NOT_EQUAL,
+ new RegexStringComparator("test.+-2"));
+ s = new Scan();
+ s.setFilter(f);
+
+ kvs = new KeyValue [] {
+ // testRowOne-0
+ new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+ new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+ // testRowOne-2
+ new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+ new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+ // testRowOne-3
+ new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+ new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+ // testRowTwo-0
+ new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+ // testRowTwo-2
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+ // testRowTwo-3
+ new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+ };
+ verifyScanFull(s, kvs);
+
+ }
+
+ public void testRowFilter() throws Exception {
+
+ // Match a single row, all keys
+ long expectedRows = 1;
+ long expectedKeys = this.colsPerRow;
+ Filter f = new RowFilter(CompareOp.EQUAL,
+ new BinaryComparator(Bytes.toBytes("testRowOne-2")));
+ Scan s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match a two rows, one from each group, using regex
+ expectedRows = 2;
+ expectedKeys = this.colsPerRow;
+ f = new RowFilter(CompareOp.EQUAL,
+ new RegexStringComparator("testRow.+-2"));
+ s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match rows less than
+ // Expect all keys in one row
+ expectedRows = 1;
+ expectedKeys = this.colsPerRow;
+ f = new RowFilter(CompareOp.LESS,
+ new BinaryComparator(Bytes.toBytes("testRowOne-2")));
+ s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match rows less than or equal
+ // Expect all keys in two rows
+ expectedRows = 2;
+ expectedKeys = this.colsPerRow;
+ f = new RowFilter(CompareOp.LESS_OR_EQUAL,
+ new BinaryComparator(Bytes.toBytes("testRowOne-2")));
+ s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match rows not equal
+ // Expect all keys in all but one row
+ expectedRows = this.numRows - 1;
+ expectedKeys = this.colsPerRow;
+ f = new RowFilter(CompareOp.NOT_EQUAL,
+ new BinaryComparator(Bytes.toBytes("testRowOne-2")));
+ s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match keys greater or equal
+ // Expect all keys in all but one row
+ expectedRows = this.numRows - 1;
+ expectedKeys = this.colsPerRow;
+ f = new RowFilter(CompareOp.GREATER_OR_EQUAL,
+ new BinaryComparator(Bytes.toBytes("testRowOne-2")));
+ s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match keys greater
+ // Expect all keys in all but two rows
+ expectedRows = this.numRows - 2;
+ expectedKeys = this.colsPerRow;
+ f = new RowFilter(CompareOp.GREATER,
+ new BinaryComparator(Bytes.toBytes("testRowOne-2")));
+ s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match rows not equal to testRowTwo-2
+ // Look across rows and fully validate the keys and ordering
+ // Should see all keys in all rows but testRowTwo-2
+ f = new RowFilter(CompareOp.NOT_EQUAL,
+ new BinaryComparator(Bytes.toBytes("testRowOne-2")));
+ s = new Scan();
+ s.setFilter(f);
+
+ KeyValue [] kvs = {
+ // testRowOne-0
+ new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]),
+ new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+ new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[2], VALUES[0]),
+ new KeyValue(ROWS_ONE[0], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+ // testRowOne-3
+ new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]),
+ new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+ new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[2], VALUES[0]),
+ new KeyValue(ROWS_ONE[3], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+ // testRowTwo-0
+ new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+ // testRowTwo-2
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+ // testRowTwo-3
+ new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+ };
+ verifyScanFull(s, kvs);
+
+
+ // Test across rows and groups with a regex
+ // Filter out everything that doesn't match "*-2"
+ // Expect all keys in two rows
+ f = new RowFilter(CompareOp.EQUAL,
+ new RegexStringComparator(".+-2"));
+ s = new Scan();
+ s.setFilter(f);
+
+ kvs = new KeyValue [] {
+ // testRowOne-2
+ new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0]),
+ new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[3], VALUES[0]),
+ new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[2], VALUES[0]),
+ new KeyValue(ROWS_ONE[2], FAMILIES[1], QUALIFIERS_ONE[3], VALUES[0]),
+ // testRowTwo-2
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1])
+ };
+ verifyScanFull(s, kvs);
+
+ }
+
+ public void testValueFilter() throws Exception {
+
+ // Match group one rows
+ long expectedRows = this.numRows / 2;
+ long expectedKeys = this.colsPerRow;
+ Filter f = new ValueFilter(CompareOp.EQUAL,
+ new BinaryComparator(Bytes.toBytes("testValueOne")));
+ Scan s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match group two rows
+ expectedRows = this.numRows / 2;
+ expectedKeys = this.colsPerRow;
+ f = new ValueFilter(CompareOp.EQUAL,
+ new BinaryComparator(Bytes.toBytes("testValueTwo")));
+ s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match all values using regex
+ expectedRows = this.numRows;
+ expectedKeys = this.colsPerRow;
+ f = new ValueFilter(CompareOp.EQUAL,
+ new RegexStringComparator("testValue((One)|(Two))"));
+ s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match values less than
+ // Expect group one rows
+ expectedRows = this.numRows / 2;
+ expectedKeys = this.colsPerRow;
+ f = new ValueFilter(CompareOp.LESS,
+ new BinaryComparator(Bytes.toBytes("testValueTwo")));
+ s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match values less than or equal
+ // Expect all rows
+ expectedRows = this.numRows;
+ expectedKeys = this.colsPerRow;
+ f = new ValueFilter(CompareOp.LESS_OR_EQUAL,
+ new BinaryComparator(Bytes.toBytes("testValueTwo")));
+ s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match values less than or equal
+ // Expect group one rows
+ expectedRows = this.numRows / 2;
+ expectedKeys = this.colsPerRow;
+ f = new ValueFilter(CompareOp.LESS_OR_EQUAL,
+ new BinaryComparator(Bytes.toBytes("testValueOne")));
+ s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match values not equal
+ // Expect half the rows
+ expectedRows = this.numRows / 2;
+ expectedKeys = this.colsPerRow;
+ f = new ValueFilter(CompareOp.NOT_EQUAL,
+ new BinaryComparator(Bytes.toBytes("testValueOne")));
+ s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match values greater or equal
+ // Expect all rows
+ expectedRows = this.numRows;
+ expectedKeys = this.colsPerRow;
+ f = new ValueFilter(CompareOp.GREATER_OR_EQUAL,
+ new BinaryComparator(Bytes.toBytes("testValueOne")));
+ s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match values greater
+ // Expect half rows
+ expectedRows = this.numRows / 2;
+ expectedKeys = this.colsPerRow;
+ f = new ValueFilter(CompareOp.GREATER,
+ new BinaryComparator(Bytes.toBytes("testValueOne")));
+ s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, expectedRows, expectedKeys);
+
+ // Match values not equal to testValueOne
+ // Look across rows and fully validate the keys and ordering
+ // Should see all keys in all group two rows
+ f = new ValueFilter(CompareOp.NOT_EQUAL,
+ new BinaryComparator(Bytes.toBytes("testValueOne")));
+ s = new Scan();
+ s.setFilter(f);
+
+ KeyValue [] kvs = {
+ // testRowTwo-0
+ new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+ // testRowTwo-2
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+ // testRowTwo-3
+ new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+ };
+ verifyScanFull(s, kvs);
+ }
+
+ public void testSkipFilter() throws Exception {
+
+ // Test for qualifier regex: "testQualifierOne-2"
+ // Should only get rows from second group, and all keys
+ Filter f = new SkipFilter(new QualifierFilter(CompareOp.NOT_EQUAL,
+ new BinaryComparator(Bytes.toBytes("testQualifierOne-2"))));
+ Scan s = new Scan();
+ s.setFilter(f);
+
+ KeyValue [] kvs = {
+ // testRowTwo-0
+ new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+ // testRowTwo-2
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+ // testRowTwo-3
+ new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[3], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[2], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[1], QUALIFIERS_TWO[3], VALUES[1]),
+ };
+ verifyScanFull(s, kvs);
+ }
+
+ public void testFilterList() throws Exception {
+
+ // Test getting a single row, single key using Row, Qualifier, and Value
+ // regular expression and substring filters
+ // Use must pass all
+ List<Filter> filters = new ArrayList<Filter>();
+ filters.add(new RowFilter(CompareOp.EQUAL, new RegexStringComparator(".+-2")));
+ filters.add(new QualifierFilter(CompareOp.EQUAL, new RegexStringComparator(".+-2")));
+ filters.add(new ValueFilter(CompareOp.EQUAL, new SubstringComparator("One")));
+ Filter f = new FilterList(Operator.MUST_PASS_ALL, filters);
+ Scan s = new Scan();
+ s.addFamily(FAMILIES[0]);
+ s.setFilter(f);
+ KeyValue [] kvs = {
+ new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[2], VALUES[0])
+ };
+ verifyScanFull(s, kvs);
+
+ // Test getting everything with a MUST_PASS_ONE filter including row, qf, val
+ // regular expression and substring filters
+ filters.clear();
+ filters.add(new RowFilter(CompareOp.EQUAL, new RegexStringComparator(".+Two.+")));
+ filters.add(new QualifierFilter(CompareOp.EQUAL, new RegexStringComparator(".+-2")));
+ filters.add(new ValueFilter(CompareOp.EQUAL, new SubstringComparator("One")));
+ f = new FilterList(Operator.MUST_PASS_ONE, filters);
+ s = new Scan();
+ s.setFilter(f);
+ verifyScanNoEarlyOut(s, this.numRows, this.colsPerRow);
+ }
+
+ public void testFirstKeyOnlyFilter() throws Exception {
+ Scan s = new Scan();
+ s.setFilter(new FirstKeyOnlyFilter());
+ // Expected KVs, the first KV from each of the remaining 6 rows
+ KeyValue [] kvs = {
+ new KeyValue(ROWS_ONE[0], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[2], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_ONE[3], FAMILIES[0], QUALIFIERS_ONE[0], VALUES[0]),
+ new KeyValue(ROWS_TWO[0], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[2], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1]),
+ new KeyValue(ROWS_TWO[3], FAMILIES[0], QUALIFIERS_TWO[0], VALUES[1])
+ };
+ verifyScanFull(s, kvs);
+ }
+
+}
Modified: hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/BinaryComparator.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/BinaryComparator.java?rev=919068&r1=919067&r2=919068&view=diff
==============================================================================
--- hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/BinaryComparator.java (original)
+++ hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/BinaryComparator.java Thu Mar 4 17:06:04 2010
@@ -20,46 +20,21 @@
package org.apache.hadoop.hbase.filter;
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-
-import org.apache.hadoop.hbase.util.Bytes;
-
/**
* A binary comparator which lexicographically compares against the specified
* byte array using {@link Bytes#compareTo(byte[], byte[])}.
*/
-public class BinaryComparator implements WritableByteArrayComparable {
-
- private byte [] value;
+public class BinaryComparator extends WritableByteArrayComparable {
- /**
- * Writable constructor, do not use.
- */
- public BinaryComparator() {
- }
+ /** Nullary constructor for Writable, do not use */
+ public BinaryComparator() { }
/**
- * Constructor.
- * @param value the value to compare against
+ * Constructor
+ * @param value
*/
- public BinaryComparator(byte [] value) {
- this.value = value;
+ public BinaryComparator(byte[] value) {
+ super(value);
}
- @Override
- public void readFields(DataInput in) throws IOException {
- value = Bytes.readByteArray(in);
- }
-
- @Override
- public void write(DataOutput out) throws IOException {
- Bytes.writeByteArray(out, value);
- }
-
- @Override
- public int compareTo(byte [] value) {
- return Bytes.compareTo(this.value, value);
- }
-}
\ No newline at end of file
+}
Modified: hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/BinaryPrefixComparator.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/BinaryPrefixComparator.java?rev=919068&r1=919067&r2=919068&view=diff
==============================================================================
--- hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/BinaryPrefixComparator.java (original)
+++ hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/BinaryPrefixComparator.java Thu Mar 4 17:06:04 2010
@@ -22,45 +22,28 @@
import org.apache.hadoop.hbase.util.Bytes;
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-
/**
* A comparator which compares against a specified byte array, but only compares
* up to the length of this byte array. For the rest it is similar to
* {@link BinaryComparator}.
*/
-public class BinaryPrefixComparator implements WritableByteArrayComparable {
- private byte [] value;
+public class BinaryPrefixComparator extends WritableByteArrayComparable {
- /**
- * Writable constructor, do not use.
- */
- public BinaryPrefixComparator() {
- }
+ /** Nullary constructor for Writable, do not use */
+ public BinaryPrefixComparator() { }
/**
- * Constructor.
- * @param value the value to compare against
+ * Constructor
+ * @param value
*/
- public BinaryPrefixComparator(byte [] value) {
- this.value = value;
- }
-
- @Override
- public void readFields(DataInput in) throws IOException {
- value = Bytes.readByteArray(in);
- }
-
- @Override
- public void write(DataOutput out) throws IOException {
- Bytes.writeByteArray(out, value);
+ public BinaryPrefixComparator(byte[] value) {
+ super(value);
}
@Override
public int compareTo(byte [] value) {
- return Bytes.compareTo(this.value, 0, this.value.length, value, 0, this.value.length);
+ return Bytes.compareTo(this.value, 0, this.value.length, value, 0,
+ this.value.length);
}
}
Modified: hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/ColumnCountGetFilter.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/ColumnCountGetFilter.java?rev=919068&r1=919067&r2=919068&view=diff
==============================================================================
--- hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/ColumnCountGetFilter.java (original)
+++ hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/ColumnCountGetFilter.java Thu Mar 4 17:06:04 2010
@@ -28,6 +28,10 @@
this.limit = n;
}
+ public int getLimit() {
+ return limit;
+ }
+
public boolean filterAllRemaining() {
return this.count > this.limit;
}
Modified: hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/CompareFilter.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/CompareFilter.java?rev=919068&r1=919067&r2=919068&view=diff
==============================================================================
--- hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/CompareFilter.java (original)
+++ hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/CompareFilter.java Thu Mar 4 17:06:04 2010
@@ -81,6 +81,20 @@
this.comparator = comparator;
}
+ /**
+ * @return operator
+ */
+ public CompareOp getOperator() {
+ return compareOp;
+ }
+
+ /**
+ * @return the comparator
+ */
+ public WritableByteArrayComparable getComparator() {
+ return comparator;
+ }
+
public void reset() {
}
Modified: hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/InclusiveStopFilter.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/InclusiveStopFilter.java?rev=919068&r1=919067&r2=919068&view=diff
==============================================================================
--- hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/InclusiveStopFilter.java (original)
+++ hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/InclusiveStopFilter.java Thu Mar 4 17:06:04 2010
@@ -45,6 +45,10 @@
this.stopRowKey = stopRowKey;
}
+ public byte[] getStopRowKey() {
+ return this.stopRowKey;
+ }
+
public void reset() {
// noop, no state
}
Modified: hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/PageFilter.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/PageFilter.java?rev=919068&r1=919067&r2=919068&view=diff
==============================================================================
--- hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/PageFilter.java (original)
+++ hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/PageFilter.java Thu Mar 4 17:06:04 2010
@@ -57,6 +57,10 @@
this.pageSize = pageSize;
}
+ public long getPageSize() {
+ return pageSize;
+ }
+
public void reset() {
// noop
}
Modified: hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/PrefixFilter.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/PrefixFilter.java?rev=919068&r1=919067&r2=919068&view=diff
==============================================================================
--- hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/PrefixFilter.java (original)
+++ hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/PrefixFilter.java Thu Mar 4 17:06:04 2010
@@ -42,6 +42,10 @@
super();
}
+ public byte[] getPrefix() {
+ return prefix;
+ }
+
public void reset() {
// Noop
}
Modified: hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/RegexStringComparator.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/RegexStringComparator.java?rev=919068&r1=919067&r2=919068&view=diff
==============================================================================
--- hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/RegexStringComparator.java (original)
+++ hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/RegexStringComparator.java Thu Mar 4 17:06:04 2010
@@ -49,33 +49,39 @@
* "{3}[\\d]{1,3})?)(\\/[0-9]+)?"));
* </pre>
*/
-public class RegexStringComparator implements WritableByteArrayComparable {
+public class RegexStringComparator extends WritableByteArrayComparable {
+
private Pattern pattern;
- /** Nullary constructor for Writable */
- public RegexStringComparator() {
- super();
- }
+ /** Nullary constructor for Writable, do not use */
+ public RegexStringComparator() { }
/**
* Constructor
* @param expr a valid regular expression
*/
public RegexStringComparator(String expr) {
+ super(Bytes.toBytes(expr));
this.pattern = Pattern.compile(expr);
}
+ @Override
public int compareTo(byte[] value) {
// Use find() for subsequence match instead of matches() (full sequence
// match) to adhere to the principle of least surprise.
return pattern.matcher(Bytes.toString(value)).find() ? 0 : 1;
}
+ @Override
public void readFields(DataInput in) throws IOException {
- this.pattern = Pattern.compile(in.readUTF());
+ String expr = in.readUTF();
+ this.value = Bytes.toBytes(expr);
+ this.pattern = Pattern.compile(expr);
}
+ @Override
public void write(DataOutput out) throws IOException {
out.writeUTF(pattern.toString());
}
+
}
Modified: hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/SingleColumnValueFilter.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/SingleColumnValueFilter.java?rev=919068&r1=919067&r2=919068&view=diff
==============================================================================
--- hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/SingleColumnValueFilter.java (original)
+++ hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/SingleColumnValueFilter.java Thu Mar 4 17:06:04 2010
@@ -117,6 +117,34 @@
this.comparator = comparator;
}
+ /**
+ * @return operator
+ */
+ public CompareOp getOperator() {
+ return compareOp;
+ }
+
+ /**
+ * @return the comparator
+ */
+ public WritableByteArrayComparable getComparator() {
+ return comparator;
+ }
+
+ /**
+ * @return the family
+ */
+ public byte[] getFamily() {
+ return columnFamily;
+ }
+
+ /**
+ * @return the qualifier
+ */
+ public byte[] getQualifier() {
+ return columnQualifier;
+ }
+
public boolean filterRowKey(byte[] rowKey, int offset, int length) {
// We don't filter on the row key... we filter later on column value so
// always return false.
Modified: hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/SkipFilter.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/SkipFilter.java?rev=919068&r1=919067&r2=919068&view=diff
==============================================================================
--- hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/SkipFilter.java (original)
+++ hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/SkipFilter.java Thu Mar 4 17:06:04 2010
@@ -56,6 +56,10 @@
this.filter = filter;
}
+ public Filter getFilter() {
+ return filter;
+ }
+
public void reset() {
filter.reset();
filterRow = false;
Modified: hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/SubstringComparator.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/SubstringComparator.java?rev=919068&r1=919067&r2=919068&view=diff
==============================================================================
--- hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/SubstringComparator.java (original)
+++ hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/SubstringComparator.java Thu Mar 4 17:06:04 2010
@@ -40,12 +40,13 @@
* new SubstringComparator("substr"));
* </pre>
*/
-public class SubstringComparator implements WritableByteArrayComparable {
+public class SubstringComparator extends WritableByteArrayComparable {
private String substr;
- /** Nullary constructor for Writable */
+ /** Nullary constructor for Writable, do not use */
public SubstringComparator() {
+ super();
}
/**
@@ -53,17 +54,28 @@
* @param substr the substring
*/
public SubstringComparator(String substr) {
+ super(Bytes.toBytes(substr.toLowerCase()));
this.substr = substr.toLowerCase();
}
+ @Override
+ public byte[] getValue() {
+ return Bytes.toBytes(substr);
+ }
+
+ @Override
public int compareTo(byte[] value) {
return Bytes.toString(value).toLowerCase().contains(substr) ? 0 : 1;
}
+ @Override
public void readFields(DataInput in) throws IOException {
- substr = in.readUTF();
+ String substr = in.readUTF();
+ this.value = Bytes.toBytes(substr);
+ this.substr = substr;
}
+ @Override
public void write(DataOutput out) throws IOException {
out.writeUTF(substr);
}
Modified: hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/WhileMatchFilter.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/WhileMatchFilter.java?rev=919068&r1=919067&r2=919068&view=diff
==============================================================================
--- hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/WhileMatchFilter.java (original)
+++ hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/WhileMatchFilter.java Thu Mar 4 17:06:04 2010
@@ -45,6 +45,10 @@
this.filter = filter;
}
+ public Filter getFilter() {
+ return filter;
+ }
+
public void reset() {
this.filter.reset();
}
Modified: hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/WritableByteArrayComparable.java
URL: http://svn.apache.org/viewvc/hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/WritableByteArrayComparable.java?rev=919068&r1=919067&r2=919068&view=diff
==============================================================================
--- hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/WritableByteArrayComparable.java (original)
+++ hadoop/hbase/branches/0.20/src/java/org/apache/hadoop/hbase/filter/WritableByteArrayComparable.java Thu Mar 4 17:06:04 2010
@@ -19,9 +19,48 @@
*/
package org.apache.hadoop.hbase.filter;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.Writable;
-/** Interface for both Comparable<byte []> and Writable. */
-public interface WritableByteArrayComparable extends Writable, Comparable<byte[]> {
- // Not methods, just tie the two interfaces together.
+/** Base class, combines Comparable<byte []> and Writable. */
+public abstract class WritableByteArrayComparable implements Writable, Comparable<byte[]> {
+
+ byte[] value;
+
+ /**
+ * Nullary constructor, for Writable
+ */
+ public WritableByteArrayComparable() { }
+
+ /**
+ * Constructor.
+ * @param value the value to compare against
+ */
+ public WritableByteArrayComparable(byte [] value) {
+ this.value = value;
+ }
+
+ public byte[] getValue() {
+ return value;
+ }
+
+ @Override
+ public void readFields(DataInput in) throws IOException {
+ value = Bytes.readByteArray(in);
+ }
+
+ @Override
+ public void write(DataOutput out) throws IOException {
+ Bytes.writeByteArray(out, value);
+ }
+
+ @Override
+ public int compareTo(byte [] value) {
+ return Bytes.compareTo(this.value, value);
+ }
+
}