HBASE-21174 [REST] Failed to parse empty qualifier in TableResource#getScanResource
Signed-off-by: tedyu <yuzhihong@gmail.com>
This commit is contained in:
parent
d40348e8cd
commit
45cd6ae2d9
|
@ -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()) {
|
if (LOG.isTraceEnabled()) {
|
||||||
LOG.trace("Scan family and column : " + familysplit[0] + " " + familysplit[1]);
|
LOG.trace("Scan family : " + Bytes.toStringBinary(parts[0]));
|
||||||
}
|
}
|
||||||
tableScan.addColumn(Bytes.toBytes(familysplit[0]), Bytes.toBytes(familysplit[1]));
|
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 {
|
} else {
|
||||||
tableScan.addFamily(Bytes.toBytes(familysplit[0]));
|
throw new IllegalArgumentException("Invalid column specifier.");
|
||||||
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()) {
|
|
||||||
LOG.trace("Scan family : " + familysplit[0]);
|
|
||||||
}
|
|
||||||
tableScan.addFamily(Bytes.toBytes(familysplit[0]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FilterList filterList = new FilterList();
|
FilterList filterList = new FilterList();
|
||||||
|
|
|
@ -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();
|
||||||
|
@ -115,6 +117,7 @@ public class TestTableScan {
|
||||||
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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue