Index: src/main/java/org/apache/hadoop/hbase/client/HTable.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/HTable.java (revision 1450599) +++ src/main/java/org/apache/hadoop/hbase/client/HTable.java (working copy) @@ -625,11 +625,35 @@ if (scan.getCaching() <= 0) { scan.setCaching(getScannerCaching()); } + if (Bytes.equals(this.getTableName(), HConstants.META_TABLE_NAME)) { + changeStartAndStopRowIfMeta(scan); + } return new ClientScanner(getConfiguration(), scan, getTableName(), this.connection); } - /** + + private void changeStartAndStopRowIfMeta(final Scan scan) { + if (scan.getStartRow() != null && scan.getStartRow().length != 0 + && !isValidMetaTableRow(Bytes.toString(scan.getStartRow()))) { + String startRow = Bytes.toString(scan.getStartRow()); + startRow += HConstants.META_ROW_DELIMITER_STR + HConstants.META_ROW_DELIMITER_STR + HConstants.ZEROES; + scan.setStartRow(Bytes.toBytes(startRow)); + } + if (scan.getStopRow() != null && scan.getStopRow().length != 0 + && !isValidMetaTableRow(Bytes.toString(scan.getStopRow()))) { + String stopRow = Bytes.toString(scan.getStopRow()); + stopRow += HConstants.META_ROW_DELIMITER_STR + HConstants.META_ROW_DELIMITER_STR + HConstants.NINES; + scan.setStopRow(Bytes.toBytes(stopRow)); + } + } + + private boolean isValidMetaTableRow(String metaRow) { + return metaRow.indexOf(HConstants.META_ROW_DELIMITER_STR) != -1; + } + + +/** * {@inheritDoc} */ @Override Index: src/main/java/org/apache/hadoop/hbase/HConstants.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/HConstants.java (revision 1450599) +++ src/main/java/org/apache/hadoop/hbase/HConstants.java (working copy) @@ -305,6 +305,8 @@ /** delimiter used between portions of a region name */ public static final int META_ROW_DELIMITER = ','; + + public static final String META_ROW_DELIMITER_STR = ","; /** The catalog family as a string*/ public static final String CATALOG_FAMILY_STR = "info"; Index: src/test/java/org/apache/hadoop/hbase/client/TestAdmin.java =================================================================== --- src/test/java/org/apache/hadoop/hbase/client/TestAdmin.java (revision 1450599) +++ src/test/java/org/apache/hadoop/hbase/client/TestAdmin.java (working copy) @@ -345,6 +345,39 @@ assertTrue(exceptionThrown); } } + + @Test + public void testHBASE7928() throws Exception { + final byte[] tableName = Bytes.toBytes("a"); + final byte[] tableName1 = Bytes.toBytes("b"); + final byte[] tableName2 = Bytes.toBytes("c"); + try { + + TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY).close(); + + TEST_UTIL.createTable(tableName1, HConstants.CATALOG_FAMILY).close(); + + TEST_UTIL.createTable(tableName2, HConstants.CATALOG_FAMILY).close(); + while (!admin.isTableAvailable(tableName2)) { + Thread.sleep(1); + } + Scan s = new Scan(); + s.setStartRow(Bytes.toBytes("a1")); + s.setStopRow(Bytes.toBytes("b1")); + HTable table = new HTable(admin.getConfiguration(), HConstants.META_TABLE_NAME); + ResultScanner scanner = table.getScanner(s); + Result[] result = scanner.next(5); + assertEquals("Only one row should be selected", 1, result.length); + } finally { + admin.disableTable(tableName); + admin.deleteTable(tableName); + admin.disableTable(tableName1); + admin.deleteTable(tableName1); + admin.disableTable(tableName2); + admin.deleteTable(tableName2); + } + } + /** * Verify schema modification takes. * @throws IOException