diff --git a/hbase-mapreduce/src/main/java/org/apache/hadoop/hbase/mapreduce/TableInputFormatBase.java b/hbase-mapreduce/src/main/java/org/apache/hadoop/hbase/mapreduce/TableInputFormatBase.java index 11ea6e58770d..40e96d515168 100644 --- a/hbase-mapreduce/src/main/java/org/apache/hadoop/hbase/mapreduce/TableInputFormatBase.java +++ b/hbase-mapreduce/src/main/java/org/apache/hadoop/hbase/mapreduce/TableInputFormatBase.java @@ -407,6 +407,9 @@ protected List createNInputSplitsUniform(InputSplit split, int n) // Split Region into n chunks evenly byte[][] splitKeys = Bytes.split(startRow, endRow, true, n - 1); + // Restore the original boundaries after using synthetic ones to calculate the split keys. + splitKeys[0] = ts.getStartRow(); + splitKeys[splitKeys.length - 1] = ts.getEndRow(); for (int i = 0; i < splitKeys.length - 1; i++) { // In the table input format for single table we do not need to // store the scan object in table split because it can be memory intensive and redundant diff --git a/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestTableInputFormatBase.java b/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestTableInputFormatBase.java index 124221e44784..d13d729be498 100644 --- a/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestTableInputFormatBase.java +++ b/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestTableInputFormatBase.java @@ -17,6 +17,7 @@ */ package org.apache.hadoop.hbase.mapreduce; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -27,6 +28,7 @@ import java.net.Inet6Address; import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.concurrent.ExecutorService; @@ -52,6 +54,7 @@ import org.apache.hadoop.hbase.testclassification.SmallTests; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Pair; +import org.apache.hadoop.mapreduce.InputSplit; import org.apache.hadoop.mapreduce.JobContext; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; @@ -62,6 +65,24 @@ @Tag(SmallTests.TAG) public class TestTableInputFormatBase { + @Test + public void testCreateNInputSplitsUniformPreservesOriginalBoundaries() throws IOException { + TableInputFormat inputFormat = new TableInputFormat(); + for (byte[] startRow : new byte[][] { HConstants.EMPTY_START_ROW, Bytes.toBytes("start") }) { + TableSplit split = + new TableSplit(TableName.valueOf("test"), startRow, HConstants.EMPTY_END_ROW, "localhost"); + + List splits = inputFormat.createNInputSplitsUniform(split, 2); + + assertEquals(2, splits.size()); + TableSplit first = (TableSplit) splits.get(0); + TableSplit last = (TableSplit) splits.get(1); + assertArrayEquals(startRow, first.getStartRow()); + assertArrayEquals(first.getEndRow(), last.getStartRow()); + assertArrayEquals(HConstants.EMPTY_END_ROW, last.getEndRow()); + } + } + @Test public void testReuseRegionSizeCalculator() throws IOException { JobContext context = mock(JobContext.class);