Index: src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide.java =================================================================== --- src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide.java (revision 1434509) +++ src/test/java/org/apache/hadoop/hbase/client/TestFromClientSide.java (working copy) @@ -4857,6 +4857,37 @@ assertEquals(1, bar.length); } + @Test + public void testGetEmptyRow() throws Exception { + //Create a table and put in 1 row + HBaseAdmin admin = TEST_UTIL.getHBaseAdmin(); + HTableDescriptor desc = new HTableDescriptor(Bytes.toBytes("test")); + desc.addFamily(new HColumnDescriptor(FAMILY)); + admin.createTable(desc); + HTable table = new HTable(TEST_UTIL.getConfiguration(), "test"); + + Put put = new Put(ROW); + put.add(FAMILY, QUALIFIER, VALUE); + table.put(put); + table.flushCommits(); + + //Try getting the row with an empty row key and make sure the other base cases work as well + Result res = table.get(new Get(new byte[0])); + assertTrue(res.isEmpty() == true); + res = table.get(new Get(Bytes.toBytes("r1-not-exist"))); + assertTrue(res.isEmpty() == true); + res = table.get(new Get(ROW)); + assertTrue(Arrays.equals(res.getValue(FAMILY, QUALIFIER), VALUE)); + + //Now actually put in a row with an empty row key + put = new Put(new byte[0]); + put.add(FAMILY, QUALIFIER, VALUE); + table.put(put); + table.flushCommits(); + res = table.get(new Get(new byte[0])); + assertTrue(Arrays.equals(res.getValue(FAMILY, QUALIFIER), VALUE)); + } + @org.junit.Rule public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu = new org.apache.hadoop.hbase.ResourceCheckerJUnitRule(); Index: src/main/java/org/apache/hadoop/hbase/client/Scan.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/client/Scan.java (revision 1434509) +++ src/main/java/org/apache/hadoop/hbase/client/Scan.java (working copy) @@ -90,6 +90,7 @@ private byte [] stopRow = HConstants.EMPTY_END_ROW; private int maxVersions = 1; private int batch = -1; + private boolean getScan; // If application wants to collect scan metrics, it needs to // call scan.setAttribute(SCAN_ATTRIBUTES_ENABLE, Bytes.toBytes(Boolean.TRUE)) static public String SCAN_ATTRIBUTES_METRICS_ENABLE = @@ -136,6 +137,8 @@ public Scan(byte [] startRow, byte [] stopRow) { this.startRow = startRow; this.stopRow = stopRow; + //if the startRow and stopRow both are empty, it is not a Get + this.getScan = isStartRowAndEqualsStopRow(); } /** @@ -151,6 +154,7 @@ batch = scan.getBatch(); caching = scan.getCaching(); cacheBlocks = scan.getCacheBlocks(); + getScan = scan.isGetScan(); filter = scan.getFilter(); // clone? TimeRange ctr = scan.getTimeRange(); tr = new TimeRange(ctr.getMin(), ctr.getMax()); @@ -183,9 +187,14 @@ this.maxVersions = get.getMaxVersions(); this.tr = get.getTimeRange(); this.familyMap = get.getFamilyMap(); + this.getScan = true; } public boolean isGetScan() { + return this.getScan || isStartRowAndEqualsStopRow(); + } + + private boolean isStartRowAndEqualsStopRow() { return this.startRow != null && this.startRow.length > 0 && Bytes.equals(this.startRow, this.stopRow); } Index: src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java =================================================================== --- src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java (revision 1434509) +++ src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java (working copy) @@ -3534,7 +3534,7 @@ this.filter = scan.getFilter(); this.batch = scan.getBatch(); - if (Bytes.equals(scan.getStopRow(), HConstants.EMPTY_END_ROW)) { + if (Bytes.equals(scan.getStopRow(), HConstants.EMPTY_END_ROW) && !scan.isGetScan()) { this.stopRow = null; } else { this.stopRow = scan.getStopRow();