Index: hbase-client/src/main/java/org/apache/hadoop/hbase/client/HTable.java =================================================================== --- hbase-client/src/main/java/org/apache/hadoop/hbase/client/HTable.java (revision 1450599) +++ hbase-client/src/main/java/org/apache/hadoop/hbase/client/HTable.java (working copy) @@ -529,10 +529,34 @@ 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} */ Index: hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java =================================================================== --- hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java (revision 1450599) +++ hbase-common/src/main/java/org/apache/hadoop/hbase/HConstants.java (working copy) @@ -358,6 +358,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: hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin.java =================================================================== --- hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin.java (revision 1450599) +++ hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAdmin.java (working copy) @@ -536,7 +536,39 @@ assertTrue(regionList.size() == min || regionList.size() == max); } } + + @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); + } + } + @Test public void testCreateTableWithRegions() throws IOException, InterruptedException {