HBASE-21174 [REST] Failed to parse empty qualifier in TableResource#getScanResource

Signed-off-by: tedyu <yuzhihong@gmail.com>
This commit is contained in:
Guangxu Cheng 2018-09-10 23:30:21 +08:00
parent 75a7643b11
commit 15842109c0
2 changed files with 64 additions and 25 deletions

View File

@ -27,6 +27,7 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.TableName;
import org.apache.yetus.audience.InterfaceAudience; import org.apache.yetus.audience.InterfaceAudience;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -123,7 +124,7 @@ public class TableResource extends ResourceBase {
@QueryParam(Constants.SCAN_LIMIT) int userRequestedLimit, @QueryParam(Constants.SCAN_LIMIT) int userRequestedLimit,
@DefaultValue("") @QueryParam(Constants.SCAN_START_ROW) String startRow, @DefaultValue("") @QueryParam(Constants.SCAN_START_ROW) String startRow,
@DefaultValue("") @QueryParam(Constants.SCAN_END_ROW) String endRow, @DefaultValue("") @QueryParam(Constants.SCAN_END_ROW) String endRow,
@DefaultValue("") @QueryParam(Constants.SCAN_COLUMN) List<String> column, @QueryParam(Constants.SCAN_COLUMN) List<String> column,
@DefaultValue("1") @QueryParam(Constants.SCAN_MAX_VERSIONS) int maxVersions, @DefaultValue("1") @QueryParam(Constants.SCAN_MAX_VERSIONS) int maxVersions,
@DefaultValue("-1") @QueryParam(Constants.SCAN_BATCH_SIZE) int batchSize, @DefaultValue("-1") @QueryParam(Constants.SCAN_BATCH_SIZE) int batchSize,
@DefaultValue("0") @QueryParam(Constants.SCAN_START_TIME) long startTime, @DefaultValue("0") @QueryParam(Constants.SCAN_START_TIME) long startTime,
@ -156,26 +157,21 @@ public class TableResource extends ResourceBase {
tableScan.setStartRow(Bytes.toBytes(startRow)); tableScan.setStartRow(Bytes.toBytes(startRow));
} }
tableScan.setStopRow(Bytes.toBytes(endRow)); tableScan.setStopRow(Bytes.toBytes(endRow));
for (String csplit : column) { for (String col : column) {
String[] familysplit = csplit.trim().split(":"); byte [][] parts = CellUtil.parseColumn(Bytes.toBytes(col.trim()));
if (familysplit.length == 2) { if (parts.length == 1) {
if (familysplit[1].length() > 0) {
if (LOG.isTraceEnabled()) {
LOG.trace("Scan family and column : " + familysplit[0] + " " + familysplit[1]);
}
tableScan.addColumn(Bytes.toBytes(familysplit[0]), Bytes.toBytes(familysplit[1]));
} else {
tableScan.addFamily(Bytes.toBytes(familysplit[0]));
if (LOG.isTraceEnabled()) {
LOG.trace("Scan family : " + familysplit[0] + " and empty qualifier.");
}
tableScan.addColumn(Bytes.toBytes(familysplit[0]), null);
}
} else if (StringUtils.isNotEmpty(familysplit[0])) {
if (LOG.isTraceEnabled()) { if (LOG.isTraceEnabled()) {
LOG.trace("Scan family : " + familysplit[0]); LOG.trace("Scan family : " + Bytes.toStringBinary(parts[0]));
} }
tableScan.addFamily(Bytes.toBytes(familysplit[0])); tableScan.addFamily(parts[0]);
} else if (parts.length == 2) {
if (LOG.isTraceEnabled()) {
LOG.trace("Scan family and column : " + Bytes.toStringBinary(parts[0])
+ " " + Bytes.toStringBinary(parts[1]));
}
tableScan.addColumn(parts[0], parts[1]);
} else {
throw new IllegalArgumentException("Invalid column specifier.");
} }
} }
FilterList filterList = new FilterList(); FilterList filterList = new FilterList();

View File

@ -90,9 +90,11 @@ public class TestTableScan {
private static final String CFB = "b"; private static final String CFB = "b";
private static final String COLUMN_1 = CFA + ":1"; private static final String COLUMN_1 = CFA + ":1";
private static final String COLUMN_2 = CFB + ":2"; private static final String COLUMN_2 = CFB + ":2";
private static final String COLUMN_EMPTY = CFA + ":";
private static Client client; private static Client client;
private static int expectedRows1; private static int expectedRows1;
private static int expectedRows2; private static int expectedRows2;
private static int expectedRows3;
private static Configuration conf; private static Configuration conf;
private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
@ -109,12 +111,13 @@ public class TestTableScan {
REST_TEST_UTIL.getServletPort())); REST_TEST_UTIL.getServletPort()));
Admin admin = TEST_UTIL.getAdmin(); Admin admin = TEST_UTIL.getAdmin();
if (!admin.tableExists(TABLE)) { if (!admin.tableExists(TABLE)) {
HTableDescriptor htd = new HTableDescriptor(TABLE); HTableDescriptor htd = new HTableDescriptor(TABLE);
htd.addFamily(new HColumnDescriptor(CFA)); htd.addFamily(new HColumnDescriptor(CFA));
htd.addFamily(new HColumnDescriptor(CFB)); htd.addFamily(new HColumnDescriptor(CFB));
admin.createTable(htd); admin.createTable(htd);
expectedRows1 = TestScannerResource.insertData(conf, TABLE, COLUMN_1, 1.0); expectedRows1 = TestScannerResource.insertData(conf, TABLE, COLUMN_1, 1.0);
expectedRows2 = TestScannerResource.insertData(conf, TABLE, COLUMN_2, 0.5); expectedRows2 = TestScannerResource.insertData(conf, TABLE, COLUMN_2, 0.5);
expectedRows3 = TestScannerResource.insertData(conf, TABLE, COLUMN_EMPTY, 1.0);
} }
} }
@ -598,6 +601,46 @@ public class TestTableScan {
} }
} }
@Test
public void testColumnWithEmptyQualifier() throws IOException, JAXBException {
// Test scanning with empty qualifier
StringBuilder builder = new StringBuilder();
builder.append("/*");
builder.append("?");
builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_EMPTY);
Response response = client.get("/" + TABLE + builder.toString(),
Constants.MIMETYPE_JSON);
assertEquals(200, response.getCode());
assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
ObjectMapper mapper = new JacksonJaxbJsonProvider()
.locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE);
CellSetModel model = mapper.readValue(response.getStream(), CellSetModel.class);
int count = TestScannerResource.countCellSet(model);
assertEquals(expectedRows3, count);
checkRowsNotNull(model);
RowModel startRow = model.getRows().get(0);
assertEquals("aaa", Bytes.toString(startRow.getKey()));
assertEquals(1, startRow.getCells().size());
// Test scanning with empty qualifier and normal qualifier
builder = new StringBuilder();
builder.append("/*");
builder.append("?");
builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_1);
builder.append("&");
builder.append(Constants.SCAN_COLUMN + "=" + COLUMN_EMPTY);
response = client.get("/" + TABLE + builder.toString(),
Constants.MIMETYPE_JSON);
assertEquals(200, response.getCode());
assertEquals(Constants.MIMETYPE_JSON, response.getHeader("content-type"));
mapper = new JacksonJaxbJsonProvider()
.locateMapper(CellSetModel.class, MediaType.APPLICATION_JSON_TYPE);
model = mapper.readValue(response.getStream(), CellSetModel.class);
count = TestScannerResource.countCellSet(model);
assertEquals(expectedRows1 + expectedRows3, count);
checkRowsNotNull(model);
}
public static class CustomFilter extends PrefixFilter { public static class CustomFilter extends PrefixFilter {
private byte[] key = null; private byte[] key = null;