HBASE-26901 delete with null columnQualifier occurs NullPointerException when NewVersionBehavior is on (#4295)

Signed-off-by: Duo Zhang <zhangduo@apache.org>
This commit is contained in:
eomiks 2022-04-12 21:26:36 +09:00 committed by GitHub
parent 1d8a5bf0e3
commit 7ac9e0be27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 5 deletions

View File

@ -165,9 +165,7 @@ public class NewVersionBehaviorTracker implements ColumnTracker, DeleteTracker {
* Else return MAX_VALUE. * Else return MAX_VALUE.
*/ */
protected long prepare(Cell cell) { protected long prepare(Cell cell) {
boolean matchCq = if (isColumnQualifierChanged(cell)) {
PrivateCellUtil.matchingQualifier(cell, lastCqArray, lastCqOffset, lastCqLength);
if (!matchCq) {
// The last cell is family-level delete and this is not, or the cq is changed, // The last cell is family-level delete and this is not, or the cq is changed,
// we should construct delColMap as a deep copy of delFamMap. // we should construct delColMap as a deep copy of delFamMap.
delColMap.clear(); delColMap.clear();
@ -175,8 +173,7 @@ public class NewVersionBehaviorTracker implements ColumnTracker, DeleteTracker {
delColMap.put(e.getKey(), e.getValue().getDeepCopy()); delColMap.put(e.getKey(), e.getValue().getDeepCopy());
} }
countCurrentCol = 0; countCurrentCol = 0;
} } else if (!PrivateCellUtil.isDelete(lastCqType) && lastCqType == cell.getTypeByte()
if (matchCq && !PrivateCellUtil.isDelete(lastCqType) && lastCqType == cell.getTypeByte()
&& lastCqTs == cell.getTimestamp()) { && lastCqTs == cell.getTimestamp()) {
// Put with duplicate timestamp, ignore. // Put with duplicate timestamp, ignore.
return lastCqMvcc; return lastCqMvcc;
@ -190,6 +187,15 @@ public class NewVersionBehaviorTracker implements ColumnTracker, DeleteTracker {
return Long.MAX_VALUE; return Long.MAX_VALUE;
} }
private boolean isColumnQualifierChanged(Cell cell) {
if (delColMap.isEmpty() && lastCqArray == null && cell.getQualifierLength() == 0
&& (PrivateCellUtil.isDeleteColumns(cell) || PrivateCellUtil.isDeleteColumnVersion(cell))) {
// for null columnQualifier
return true;
}
return !PrivateCellUtil.matchingQualifier(cell, lastCqArray, lastCqOffset, lastCqLength);
}
// DeleteTracker // DeleteTracker
@Override @Override
public void add(Cell cell) { public void add(Cell cell) {

View File

@ -19,6 +19,7 @@ package org.apache.hadoop.hbase.regionserver;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException; import java.io.IOException;
import org.apache.hadoop.hbase.HBaseClassTestRule; import org.apache.hadoop.hbase.HBaseClassTestRule;
@ -358,4 +359,14 @@ public class TestNewVersionBehaviorFromClientSide {
} }
} }
@Test
public void testNullColumnQualifier() throws IOException {
try (Table t = createTable()) {
Delete del = new Delete(ROW);
del.addColumn(FAMILY, null);
t.delete(del);
Result r = t.get(new Get(ROW)); //NPE
assertTrue(r.isEmpty());
}
}
} }