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 {
|
||||
required string substr = 1;
|
||||
}
|
||||
|
||||
message BigDecimalComparator {
|
||||
required ByteArrayComparable comparable = 1;
|
||||
}
|
||||
|
|
|
@ -72,3 +72,7 @@ message RegexStringComparator {
|
|||
message SubstringComparator {
|
||||
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.assertTrue;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
|
||||
|
@ -86,4 +87,12 @@ public class TestComparatorSerialization {
|
|||
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.InterruptedIOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.ArrayList;
|
||||
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.TableDescriptor;
|
||||
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.ColumnCountGetFilter;
|
||||
import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
|
||||
|
@ -1783,6 +1785,8 @@ public class TestHRegion {
|
|||
byte[] qf1 = Bytes.toBytes("qualifier");
|
||||
byte[] val1 = Bytes.toBytes("value1");
|
||||
byte[] val2 = Bytes.toBytes("value2");
|
||||
BigDecimal bd1 = new BigDecimal(Double.MAX_VALUE);
|
||||
BigDecimal bd2 = new BigDecimal(Double.MIN_VALUE);
|
||||
|
||||
// Setting up region
|
||||
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),
|
||||
put, true);
|
||||
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 {
|
||||
HBaseTestingUtility.closeRegionAndWAL(this.region);
|
||||
this.region = null;
|
||||
|
@ -1815,6 +1838,7 @@ public class TestHRegion {
|
|||
byte[] fam1 = Bytes.toBytes("fam1");
|
||||
byte[] qf1 = Bytes.toBytes("qualifier");
|
||||
byte[] val1 = Bytes.toBytes("value1");
|
||||
BigDecimal bd1 = new BigDecimal(Double.MIN_VALUE);
|
||||
|
||||
// Setting up region
|
||||
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),
|
||||
delete, true);
|
||||
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 {
|
||||
HBaseTestingUtility.closeRegionAndWAL(this.region);
|
||||
this.region = null;
|
||||
|
|
Loading…
Reference in New Issue