HBASE-25533 The metadata of the table and family should not be an empty string (#2914) (#2906)

Signed-off-by: Viraj Jasani <vjasani@apache.org>
Signed-off-by: Geoffrey Jacoby <gjacoby@apache.org>
This commit is contained in:
Baiqiang Zhao 2021-01-29 23:30:30 +08:00 committed by GitHub
parent 2c72225d13
commit 3b43df68e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 91 additions and 5 deletions

View File

@ -679,7 +679,7 @@ public class ColumnFamilyDescriptorBuilder {
* @return this (for chained invocation)
*/
private ModifyableColumnFamilyDescriptor setValue(Bytes key, Bytes value) {
if (value == null) {
if (value == null || value.getLength() == 0) {
values.remove(key);
} else {
values.put(key, value);
@ -1241,7 +1241,7 @@ public class ColumnFamilyDescriptorBuilder {
* @return this (for chained invocation)
*/
public ModifyableColumnFamilyDescriptor setConfiguration(String key, String value) {
if (value == null) {
if (value == null || value.length() == 0) {
configuration.remove(key);
} else {
configuration.put(key, value);

View File

@ -736,7 +736,7 @@ public class TableDescriptorBuilder {
toBytesOrNull(value, Bytes::toBytes));
}
/*
/**
* @param key The key.
* @param value The value. If null, removes the setting.
*/
@ -745,14 +745,14 @@ public class TableDescriptorBuilder {
return setValue(key, toBytesOrNull(value, Bytes::toBytes));
}
/*
/**
* Setter for storing metadata as a (key, value) pair in {@link #values} map
*
* @param key The key.
* @param value The value. If null, removes the setting.
*/
public ModifyableTableDescriptor setValue(final Bytes key, final Bytes value) {
if (value == null) {
if (value == null || value.getLength() == 0) {
values.remove(key);
} else {
values.put(key, value);

View File

@ -18,6 +18,7 @@
package org.apache.hadoop.hbase.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.apache.hadoop.hbase.HBaseClassTestRule;
@ -222,6 +223,24 @@ public class TestColumnFamilyDescriptorBuilder {
KeepDeletedCells.FALSE.toString());
assertEquals(defaultValueMap.get(ColumnFamilyDescriptorBuilder.DATA_BLOCK_ENCODING),
DataBlockEncoding.NONE.toString());
}
@Test
public void testSetEmptyValue() {
ColumnFamilyDescriptorBuilder builder =
ColumnFamilyDescriptorBuilder.newBuilder(HConstants.CATALOG_FAMILY);
String testConf = "TestConfiguration";
String testValue = "TestValue";
// test set value
builder.setValue(testValue, "2");
assertEquals("2", Bytes.toString(builder.build().getValue(Bytes.toBytes(testValue))));
builder.setValue(testValue, "");
assertNull(builder.build().getValue(Bytes.toBytes(testValue)));
// test set configuration
builder.setConfiguration(testConf, "1");
assertEquals("1", builder.build().getConfigurationValue(testConf));
builder.setConfiguration(testConf, "");
assertNull(builder.build().getConfigurationValue(testConf));
}
}

View File

@ -19,6 +19,7 @@ package org.apache.hadoop.hbase.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@ -393,4 +394,22 @@ public class TestTableDescriptorBuilder {
+ "MEMSTORE_FLUSHSIZE => '268435456 B (256MB)'}}, {NAME => 'cf', BLOCKSIZE => '1000'}",
htd.toStringCustomizedValues());
}
@Test
public void testSetEmptyValue() {
TableDescriptorBuilder builder =
TableDescriptorBuilder.newBuilder(TableName.valueOf(name.getMethodName()));
String testValue = "TestValue";
// test setValue
builder.setValue(testValue, "2");
assertEquals("2", builder.build().getValue(testValue));
builder.setValue(testValue, "");
assertNull(builder.build().getValue(Bytes.toBytes(testValue)));
// test setFlushPolicyClassName
builder.setFlushPolicyClassName("class");
assertEquals("class", builder.build().getFlushPolicyClassName());
builder.setFlushPolicyClassName("");
assertNull(builder.build().getFlushPolicyClassName());
}
}

View File

@ -980,6 +980,22 @@ module Hbase
assert_no_match(eval("/" + key_2 + "/"), admin.describe(@test_name))
end
define_test "alter should be able to remove a list of table attributes when value is empty" do
drop_test_table(@test_name)
key_1 = "TestAttr1"
key_2 = "TestAttr2"
command(:create, @test_name, { NAME => 'i'}, METADATA => { key_1 => 1, key_2 => 2 })
# eval() is used to convert a string to regex
assert_match(eval("/" + key_1 + "/"), admin.describe(@test_name))
assert_match(eval("/" + key_2 + "/"), admin.describe(@test_name))
command(:alter, @test_name, METADATA => { key_1 => '', key_2 => '' })
assert_no_match(eval("/" + key_1 + "/"), admin.describe(@test_name))
assert_no_match(eval("/" + key_2 + "/"), admin.describe(@test_name))
end
define_test "alter should be able to remove a table configuration" do
drop_test_table(@test_name)
create_test_table(@test_name)
@ -1010,6 +1026,38 @@ module Hbase
assert_no_match(eval("/" + key_2 + "/"), admin.describe(@test_name))
end
define_test "alter should be able to remove a list of table configuration when value is empty" do
drop_test_table(@test_name)
key_1 = "TestConf1"
key_2 = "TestConf2"
command(:create, @test_name, { NAME => 'i'}, CONFIGURATION => { key_1 => 1, key_2 => 2 })
# eval() is used to convert a string to regex
assert_match(eval("/" + key_1 + "/"), admin.describe(@test_name))
assert_match(eval("/" + key_2 + "/"), admin.describe(@test_name))
command(:alter, @test_name, CONFIGURATION => { key_1 => '', key_2 => '' })
assert_no_match(eval("/" + key_1 + "/"), admin.describe(@test_name))
assert_no_match(eval("/" + key_2 + "/"), admin.describe(@test_name))
end
define_test "alter should be able to remove a list of column family configuration when value is empty" do
drop_test_table(@test_name)
key_1 = "TestConf1"
key_2 = "TestConf2"
command(:create, @test_name, { NAME => 'i', CONFIGURATION => { key_1 => 1, key_2 => 2 }})
# eval() is used to convert a string to regex
assert_match(eval("/" + key_1 + "/"), admin.describe(@test_name))
assert_match(eval("/" + key_2 + "/"), admin.describe(@test_name))
command(:alter, @test_name, { NAME => 'i', CONFIGURATION => { key_1 => '', key_2 => '' }})
assert_no_match(eval("/" + key_1 + "/"), admin.describe(@test_name))
assert_no_match(eval("/" + key_2 + "/"), admin.describe(@test_name))
end
define_test "get_table should get a real table" do
drop_test_table(@test_name)
create_test_table(@test_name)