HBASE-19103 Add BigDecimalComparator for filter
Signed-off-by: Jan Hentschel <jan.hentschel@ultratendency.com>
This commit is contained in:
parent
d1b6d8c906
commit
0356674cd1
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.hadoop.hbase.filter;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import org.apache.hadoop.hbase.exceptions.DeserializationException;
|
||||||
|
import org.apache.hadoop.hbase.shaded.com.google.protobuf.InvalidProtocolBufferException;
|
||||||
|
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
|
||||||
|
import org.apache.hadoop.hbase.shaded.protobuf.generated.ComparatorProtos;
|
||||||
|
import org.apache.hadoop.hbase.util.ByteBufferUtils;
|
||||||
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
|
|
||||||
|
import org.apache.yetus.audience.InterfaceAudience;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A BigDecimal comparator which numerical compares against the specified byte array
|
||||||
|
*/
|
||||||
|
@InterfaceAudience.Public
|
||||||
|
public class BigDecimalComparator extends ByteArrayComparable {
|
||||||
|
private BigDecimal bigDecimal;
|
||||||
|
|
||||||
|
public BigDecimalComparator(BigDecimal value) {
|
||||||
|
super(Bytes.toBytes(value));
|
||||||
|
this.bigDecimal = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == null || !(obj instanceof BigDecimalComparator)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
BigDecimalComparator bdc = (BigDecimalComparator) obj;
|
||||||
|
return this.bigDecimal.equals(bdc.bigDecimal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(this.bigDecimal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(byte[] value, int offset, int length) {
|
||||||
|
BigDecimal that = Bytes.toBigDecimal(value, offset, length);
|
||||||
|
return this.bigDecimal.compareTo(that);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(ByteBuffer value, int offset, int length) {
|
||||||
|
BigDecimal that = ByteBufferUtils.toBigDecimal(value, offset, length);
|
||||||
|
return this.bigDecimal.compareTo(that);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The comparator serialized using pb
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public byte[] toByteArray() {
|
||||||
|
ComparatorProtos.BigDecimalComparator.Builder builder =
|
||||||
|
ComparatorProtos.BigDecimalComparator.newBuilder();
|
||||||
|
builder.setComparable(ProtobufUtil.toByteArrayComparable(this.value));
|
||||||
|
return builder.build().toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param pbBytes A pb serialized {@link BigDecimalComparator} instance
|
||||||
|
* @return An instance of {@link BigDecimalComparator} made from <code>bytes</code>
|
||||||
|
* @throws DeserializationException A deserialization exception
|
||||||
|
* @see #toByteArray
|
||||||
|
*/
|
||||||
|
public static BigDecimalComparator parseFrom(final byte[] pbBytes)
|
||||||
|
throws DeserializationException {
|
||||||
|
ComparatorProtos.BigDecimalComparator proto;
|
||||||
|
try {
|
||||||
|
proto = ComparatorProtos.BigDecimalComparator.parseFrom(pbBytes);
|
||||||
|
} catch (InvalidProtocolBufferException e) {
|
||||||
|
throw new DeserializationException(e);
|
||||||
|
}
|
||||||
|
return new BigDecimalComparator(Bytes.toBigDecimal(proto.getComparable().getValue()
|
||||||
|
.toByteArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param other the other comparator
|
||||||
|
* @return true if and only if the fields of the comparator that are serialized are equal to the
|
||||||
|
* corresponding fields in other. Used for testing.
|
||||||
|
*/
|
||||||
|
boolean areSerializedFieldsEqual(BigDecimalComparator other) {
|
||||||
|
if (other == this) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.areSerializedFieldsEqual(other);
|
||||||
|
}
|
||||||
|
}
|
|
@ -73,3 +73,7 @@ message RegexStringComparator {
|
||||||
message SubstringComparator {
|
message SubstringComparator {
|
||||||
required string substr = 1;
|
required string substr = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message BigDecimalComparator {
|
||||||
|
required ByteArrayComparable comparable = 1;
|
||||||
|
}
|
||||||
|
|
|
@ -72,3 +72,7 @@ message RegexStringComparator {
|
||||||
message SubstringComparator {
|
message SubstringComparator {
|
||||||
required string substr = 1;
|
required string substr = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message BigDecimalComparator {
|
||||||
|
required ByteArrayComparable comparable = 1;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.hadoop.hbase.filter;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.apache.hadoop.hbase.testclassification.FilterTests;
|
||||||
|
import org.apache.hadoop.hbase.testclassification.SmallTests;
|
||||||
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.experimental.categories.Category;
|
||||||
|
|
||||||
|
@Category({ FilterTests.class, SmallTests.class })
|
||||||
|
public class TestBigDecimalComparator {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testObjectEquals() {
|
||||||
|
BigDecimal bd = new BigDecimal(Double.MIN_VALUE);
|
||||||
|
// Check that equals returns true for identical objects
|
||||||
|
final BigDecimalComparator bdc = new BigDecimalComparator(bd);
|
||||||
|
Assert.assertTrue(bdc.equals(bdc));
|
||||||
|
Assert.assertEquals(bdc.hashCode(), bdc.hashCode());
|
||||||
|
|
||||||
|
// Check that equals returns true for the same object
|
||||||
|
final BigDecimalComparator bdc1 = new BigDecimalComparator(bd);
|
||||||
|
final BigDecimalComparator bdc2 = new BigDecimalComparator(bd);
|
||||||
|
Assert.assertTrue(bdc1.equals(bdc2));
|
||||||
|
Assert.assertEquals(bdc1.hashCode(), bdc2.hashCode());
|
||||||
|
|
||||||
|
// Check that equals returns false for different objects
|
||||||
|
final BigDecimalComparator bdc3 = new BigDecimalComparator(bd);
|
||||||
|
final BigDecimalComparator bdc4 = new BigDecimalComparator(new BigDecimal(Long.MIN_VALUE));
|
||||||
|
Assert.assertFalse(bdc3.equals(bdc4));
|
||||||
|
Assert.assertNotEquals(bdc3.hashCode(), bdc4.hashCode());
|
||||||
|
|
||||||
|
// Check that equals returns false for a different type
|
||||||
|
final BigDecimalComparator bdc5 = new BigDecimalComparator(bd);
|
||||||
|
Assert.assertFalse(bdc5.equals(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEqualsValue() {
|
||||||
|
// given
|
||||||
|
BigDecimal bd1 = new BigDecimal(Double.MAX_VALUE);
|
||||||
|
BigDecimal bd2 = new BigDecimal(Double.MIN_VALUE);
|
||||||
|
byte[] value1 = Bytes.toBytes(bd1);
|
||||||
|
byte[] value2 = Bytes.toBytes(bd2);
|
||||||
|
BigDecimalComparator comparator1 = new BigDecimalComparator(bd1);
|
||||||
|
BigDecimalComparator comparator2 = new BigDecimalComparator(bd2);
|
||||||
|
|
||||||
|
// when
|
||||||
|
int comp1 = comparator1.compareTo(value1);
|
||||||
|
int comp2 = comparator2.compareTo(value2);
|
||||||
|
|
||||||
|
// then
|
||||||
|
Assert.assertEquals(0, comp1);
|
||||||
|
Assert.assertEquals(0, comp2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGreaterThanValue() {
|
||||||
|
// given
|
||||||
|
byte[] val1 = Bytes.toBytes(new BigDecimal("1000000000000000000000000000000.9999999999999999"));
|
||||||
|
byte[] val2 = Bytes.toBytes(new BigDecimal(0));
|
||||||
|
byte[] val3 = Bytes.toBytes(new BigDecimal(Double.MIN_VALUE));
|
||||||
|
BigDecimal bd = new BigDecimal(Double.MAX_VALUE);
|
||||||
|
BigDecimalComparator comparator = new BigDecimalComparator(bd);
|
||||||
|
|
||||||
|
// when
|
||||||
|
int comp1 = comparator.compareTo(val1);
|
||||||
|
int comp2 = comparator.compareTo(val2);
|
||||||
|
int comp3 = comparator.compareTo(val3);
|
||||||
|
|
||||||
|
// then
|
||||||
|
Assert.assertEquals(1, comp1);
|
||||||
|
Assert.assertEquals(1, comp2);
|
||||||
|
Assert.assertEquals(1, comp3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLessThanValue() {
|
||||||
|
// given
|
||||||
|
byte[] val1 = Bytes.toBytes(new BigDecimal("-1000000000000000000000000000000"));
|
||||||
|
byte[] val2 = Bytes.toBytes(new BigDecimal(0));
|
||||||
|
byte[] val3 = Bytes.toBytes(new BigDecimal(1));
|
||||||
|
BigDecimal bd = new BigDecimal("-1000000000000000000000000000000.0000000000000001");
|
||||||
|
BigDecimalComparator comparator = new BigDecimalComparator(bd);
|
||||||
|
|
||||||
|
// when
|
||||||
|
int comp1 = comparator.compareTo(val1);
|
||||||
|
int comp2 = comparator.compareTo(val2);
|
||||||
|
int comp3 = comparator.compareTo(val3);
|
||||||
|
|
||||||
|
// then
|
||||||
|
Assert.assertEquals(-1, comp1);
|
||||||
|
Assert.assertEquals(-1, comp2);
|
||||||
|
Assert.assertEquals(-1, comp3);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ package org.apache.hadoop.hbase.filter;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
|
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
|
||||||
|
@ -86,4 +87,12 @@ public class TestComparatorSerialization {
|
||||||
ProtobufUtil.toComparator(ProtobufUtil.toComparator(substringComparator))));
|
ProtobufUtil.toComparator(ProtobufUtil.toComparator(substringComparator))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBigDecimalComparator() throws Exception {
|
||||||
|
BigDecimal bigDecimal = new BigDecimal(Double.MIN_VALUE);
|
||||||
|
BigDecimalComparator bigDecimalComparator = new BigDecimalComparator(bigDecimal);
|
||||||
|
assertTrue(bigDecimalComparator.areSerializedFieldsEqual(ProtobufUtil.toComparator(ProtobufUtil
|
||||||
|
.toComparator(bigDecimalComparator))));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InterruptedIOException;
|
import java.io.InterruptedIOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.security.PrivilegedExceptionAction;
|
import java.security.PrivilegedExceptionAction;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -113,6 +114,7 @@ import org.apache.hadoop.hbase.client.Scan;
|
||||||
import org.apache.hadoop.hbase.client.Table;
|
import org.apache.hadoop.hbase.client.Table;
|
||||||
import org.apache.hadoop.hbase.client.TableDescriptor;
|
import org.apache.hadoop.hbase.client.TableDescriptor;
|
||||||
import org.apache.hadoop.hbase.exceptions.FailedSanityCheckException;
|
import org.apache.hadoop.hbase.exceptions.FailedSanityCheckException;
|
||||||
|
import org.apache.hadoop.hbase.filter.BigDecimalComparator;
|
||||||
import org.apache.hadoop.hbase.filter.BinaryComparator;
|
import org.apache.hadoop.hbase.filter.BinaryComparator;
|
||||||
import org.apache.hadoop.hbase.filter.ColumnCountGetFilter;
|
import org.apache.hadoop.hbase.filter.ColumnCountGetFilter;
|
||||||
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
|
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
|
||||||
|
@ -1783,6 +1785,8 @@ public class TestHRegion {
|
||||||
byte[] qf1 = Bytes.toBytes("qualifier");
|
byte[] qf1 = Bytes.toBytes("qualifier");
|
||||||
byte[] val1 = Bytes.toBytes("value1");
|
byte[] val1 = Bytes.toBytes("value1");
|
||||||
byte[] val2 = Bytes.toBytes("value2");
|
byte[] val2 = Bytes.toBytes("value2");
|
||||||
|
BigDecimal bd1 = new BigDecimal(Double.MAX_VALUE);
|
||||||
|
BigDecimal bd2 = new BigDecimal(Double.MIN_VALUE);
|
||||||
|
|
||||||
// Setting up region
|
// Setting up region
|
||||||
this.region = initHRegion(tableName, method, CONF, fam1);
|
this.region = initHRegion(tableName, method, CONF, fam1);
|
||||||
|
@ -1803,6 +1807,25 @@ public class TestHRegion {
|
||||||
res = region.checkAndMutate(row1, fam1, qf1, CompareOperator.EQUAL, new BinaryComparator(val2),
|
res = region.checkAndMutate(row1, fam1, qf1, CompareOperator.EQUAL, new BinaryComparator(val2),
|
||||||
put, true);
|
put, true);
|
||||||
assertEquals(false, res);
|
assertEquals(false, res);
|
||||||
|
|
||||||
|
// Putting data in key
|
||||||
|
put = new Put(row1);
|
||||||
|
put.addColumn(fam1, qf1, Bytes.toBytes(bd1));
|
||||||
|
region.put(put);
|
||||||
|
|
||||||
|
// checkAndPut with wrong value
|
||||||
|
res =
|
||||||
|
region.checkAndMutate(row1, fam1, qf1, CompareOperator.EQUAL, new BigDecimalComparator(
|
||||||
|
bd2), put, true);
|
||||||
|
assertEquals(false, res);
|
||||||
|
|
||||||
|
// checkAndDelete with wrong value
|
||||||
|
delete = new Delete(row1);
|
||||||
|
delete.addFamily(fam1);
|
||||||
|
res =
|
||||||
|
region.checkAndMutate(row1, fam1, qf1, CompareOperator.EQUAL, new BigDecimalComparator(
|
||||||
|
bd2), put, true);
|
||||||
|
assertEquals(false, res);
|
||||||
} finally {
|
} finally {
|
||||||
HBaseTestingUtility.closeRegionAndWAL(this.region);
|
HBaseTestingUtility.closeRegionAndWAL(this.region);
|
||||||
this.region = null;
|
this.region = null;
|
||||||
|
@ -1815,6 +1838,7 @@ public class TestHRegion {
|
||||||
byte[] fam1 = Bytes.toBytes("fam1");
|
byte[] fam1 = Bytes.toBytes("fam1");
|
||||||
byte[] qf1 = Bytes.toBytes("qualifier");
|
byte[] qf1 = Bytes.toBytes("qualifier");
|
||||||
byte[] val1 = Bytes.toBytes("value1");
|
byte[] val1 = Bytes.toBytes("value1");
|
||||||
|
BigDecimal bd1 = new BigDecimal(Double.MIN_VALUE);
|
||||||
|
|
||||||
// Setting up region
|
// Setting up region
|
||||||
this.region = initHRegion(tableName, method, CONF, fam1);
|
this.region = initHRegion(tableName, method, CONF, fam1);
|
||||||
|
@ -1835,6 +1859,25 @@ public class TestHRegion {
|
||||||
res = region.checkAndMutate(row1, fam1, qf1, CompareOperator.EQUAL, new BinaryComparator(val1),
|
res = region.checkAndMutate(row1, fam1, qf1, CompareOperator.EQUAL, new BinaryComparator(val1),
|
||||||
delete, true);
|
delete, true);
|
||||||
assertEquals(true, res);
|
assertEquals(true, res);
|
||||||
|
|
||||||
|
// Putting data in key
|
||||||
|
put = new Put(row1);
|
||||||
|
put.addColumn(fam1, qf1, Bytes.toBytes(bd1));
|
||||||
|
region.put(put);
|
||||||
|
|
||||||
|
// checkAndPut with correct value
|
||||||
|
res =
|
||||||
|
region.checkAndMutate(row1, fam1, qf1, CompareOperator.EQUAL, new BigDecimalComparator(
|
||||||
|
bd1), put, true);
|
||||||
|
assertEquals(true, res);
|
||||||
|
|
||||||
|
// checkAndDelete with correct value
|
||||||
|
delete = new Delete(row1);
|
||||||
|
delete.addColumn(fam1, qf1);
|
||||||
|
res =
|
||||||
|
region.checkAndMutate(row1, fam1, qf1, CompareOperator.EQUAL, new BigDecimalComparator(
|
||||||
|
bd1), delete, true);
|
||||||
|
assertEquals(true, res);
|
||||||
} finally {
|
} finally {
|
||||||
HBaseTestingUtility.closeRegionAndWAL(this.region);
|
HBaseTestingUtility.closeRegionAndWAL(this.region);
|
||||||
this.region = null;
|
this.region = null;
|
||||||
|
|
Loading…
Reference in New Issue