Repository: phoenix Updated Branches: refs/heads/master 241e72539 -> 828d5fb9a
PHOENIX-1715 Implement Build-in math function Sign (Shuxiong Ye) Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/828d5fb9 Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/828d5fb9 Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/828d5fb9 Branch: refs/heads/master Commit: 828d5fb9af8633500bf7d05c7f25f12c2b8d51f0 Parents: 241e725 Author: James Taylor <[email protected]> Authored: Mon Mar 16 12:41:31 2015 -0700 Committer: James Taylor <[email protected]> Committed: Mon Mar 16 12:41:31 2015 -0700 ---------------------------------------------------------------------- .../phoenix/expression/ExpressionType.java | 2 + .../expression/function/SignFunction.java | 88 +++++++++++++ .../apache/phoenix/schema/types/PDecimal.java | 18 ++- .../apache/phoenix/schema/types/PDouble.java | 11 +- .../org/apache/phoenix/schema/types/PFloat.java | 9 +- .../apache/phoenix/schema/types/PInteger.java | 9 +- .../org/apache/phoenix/schema/types/PLong.java | 13 +- .../phoenix/schema/types/PNumericType.java | 44 +++++++ .../phoenix/schema/types/PRealNumber.java | 39 ++++++ .../apache/phoenix/schema/types/PSmallint.java | 9 +- .../apache/phoenix/schema/types/PTinyint.java | 11 +- .../phoenix/schema/types/PUnsignedDouble.java | 9 +- .../phoenix/schema/types/PUnsignedFloat.java | 5 +- .../phoenix/schema/types/PUnsignedInt.java | 5 +- .../phoenix/schema/types/PUnsignedLong.java | 11 +- .../phoenix/schema/types/PUnsignedSmallint.java | 5 +- .../phoenix/schema/types/PUnsignedTinyint.java | 5 +- .../phoenix/schema/types/PWholeNumber.java | 35 ++++++ .../phoenix/expression/SignFunctionTest.java | 124 +++++++++++++++++++ 19 files changed, 406 insertions(+), 46 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java index cbbfe4a..e2db117 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java @@ -67,6 +67,7 @@ import org.apache.phoenix.expression.function.RoundTimestampExpression; import org.apache.phoenix.expression.function.SQLIndexTypeFunction; import org.apache.phoenix.expression.function.SQLTableTypeFunction; import org.apache.phoenix.expression.function.SQLViewTypeFunction; +import org.apache.phoenix.expression.function.SignFunction; import org.apache.phoenix.expression.function.SqlTypeNameFunction; import org.apache.phoenix.expression.function.StddevPopFunction; import org.apache.phoenix.expression.function.StddevSampFunction; @@ -192,6 +193,7 @@ public enum ExpressionType { RandomFunction(RandomFunction.class), ToTimeFunction(ToTimeFunction.class), ToTimestampFunction(ToTimestampFunction.class), + SignFunction(SignFunction.class), ; ExpressionType(Class<? extends Expression> clazz) { http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SignFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SignFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SignFunction.java new file mode 100644 index 0000000..0797104 --- /dev/null +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/SignFunction.java @@ -0,0 +1,88 @@ +/* + * 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.phoenix.expression.function; + +import java.sql.SQLException; +import java.util.List; + +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; +import org.apache.phoenix.expression.Expression; +import org.apache.phoenix.parse.FunctionParseNode.Argument; +import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction; +import org.apache.phoenix.schema.tuple.Tuple; +import org.apache.phoenix.schema.types.PDataType; +import org.apache.phoenix.schema.types.PDecimal; +import org.apache.phoenix.schema.types.PDouble; +import org.apache.phoenix.schema.types.PFloat; +import org.apache.phoenix.schema.types.PInteger; +import org.apache.phoenix.schema.types.PLong; +import org.apache.phoenix.schema.types.PNumericType; +import org.apache.phoenix.schema.types.PSmallint; +import org.apache.phoenix.schema.types.PTinyint; +import org.apache.phoenix.schema.types.PUnsignedDouble; +import org.apache.phoenix.schema.types.PUnsignedFloat; +import org.apache.phoenix.schema.types.PUnsignedInt; +import org.apache.phoenix.schema.types.PUnsignedLong; +import org.apache.phoenix.schema.types.PUnsignedSmallint; +import org.apache.phoenix.schema.types.PUnsignedTinyint; + +/** + * Base class for built-in SIGN function. + * @since 4.3.0 + */ +@BuiltInFunction(name = SignFunction.NAME, args = { @Argument(allowedTypes = { PFloat.class, + PDouble.class, PDecimal.class, PUnsignedFloat.class, PUnsignedDouble.class, PInteger.class, + PUnsignedInt.class, PLong.class, PUnsignedLong.class, PSmallint.class, + PUnsignedSmallint.class, PTinyint.class, PUnsignedTinyint.class }) }) +public class SignFunction extends ScalarFunction { + + public static final String NAME = "SIGN"; + + private static final byte[][] RESULT = { PInteger.INSTANCE.toBytes(Integer.valueOf(-1)), + PInteger.INSTANCE.toBytes(Integer.valueOf(0)), + PInteger.INSTANCE.toBytes(Integer.valueOf(1)), }; + + public SignFunction() { + } + + public SignFunction(List<Expression> children) throws SQLException { + super(children); + } + + @Override + public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { + Expression childExpr = children.get(0); + PDataType dataType = childExpr.getDataType(); + if (childExpr.evaluate(tuple, ptr)) { + int ret = ((PNumericType) dataType).signum(ptr, childExpr.getSortOrder()); + ptr.set(RESULT[ret + 1]); + return true; + } + return false; + } + + @Override + public PDataType getDataType() { + return PInteger.INSTANCE; + } + + @Override + public String getName() { + return NAME; + } +} http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java index e90491b..656113c 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java @@ -31,7 +31,7 @@ import org.apache.phoenix.util.NumberUtil; import com.google.common.base.Preconditions; -public class PDecimal extends PDataType<BigDecimal> { +public class PDecimal extends PRealNumber<BigDecimal> { public static final PDecimal INSTANCE = new PDecimal(); @@ -402,4 +402,20 @@ public class PDecimal extends PDataType<BigDecimal> { public Object getSampleValue(Integer maxLength, Integer arrayLength) { return new BigDecimal((Long) PLong.INSTANCE.getSampleValue(maxLength, arrayLength)); } + + // take details from org.apache.phoenix.schema.types.PDataType#toBigDecimal(byte[], int, int) + @Override + public int signum(byte[] bytes, int offset, int length, SortOrder sortOrder, Integer maxLength, + Integer scale) { + byte signByte; + if (sortOrder == SortOrder.DESC) { + signByte = SortOrder.invert(bytes[offset]); + } else { + signByte = bytes[offset]; + } + if (length == 1 && signByte == ZERO_BYTE) { + return 0; + } + return ((signByte & 0x80) == 0) ? -1 : 1; + } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDouble.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDouble.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDouble.java index d8e3c4f..e0648f2 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDouble.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDouble.java @@ -17,15 +17,16 @@ */ package org.apache.phoenix.schema.types; -import com.google.common.base.Preconditions; -import com.google.common.primitives.Doubles; +import java.math.BigDecimal; +import java.sql.Types; + import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.schema.SortOrder; -import java.math.BigDecimal; -import java.sql.Types; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Doubles; -public class PDouble extends PDataType<Double> { +public class PDouble extends PRealNumber<Double> { public static final PDouble INSTANCE = new PDouble(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloat.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloat.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloat.java index 608b270..67b7d9a 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloat.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloat.java @@ -17,14 +17,15 @@ */ package org.apache.phoenix.schema.types; -import com.google.common.base.Preconditions; +import java.math.BigDecimal; +import java.sql.Types; + import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.schema.SortOrder; -import java.math.BigDecimal; -import java.sql.Types; +import com.google.common.base.Preconditions; -public class PFloat extends PDataType<Float> { +public class PFloat extends PRealNumber<Float> { public static final PFloat INSTANCE = new PFloat(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PInteger.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PInteger.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PInteger.java index c4760b5..3c26fd5 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PInteger.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PInteger.java @@ -17,14 +17,15 @@ */ package org.apache.phoenix.schema.types; -import com.google.common.base.Preconditions; +import java.math.BigDecimal; +import java.sql.Types; + import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.schema.SortOrder; -import java.math.BigDecimal; -import java.sql.Types; +import com.google.common.base.Preconditions; -public class PInteger extends PDataType<Integer> { +public class PInteger extends PWholeNumber<Integer> { public static final PInteger INSTANCE = new PInteger(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLong.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLong.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLong.java index 1bef844..f2a0e92 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLong.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLong.java @@ -17,16 +17,17 @@ */ package org.apache.phoenix.schema.types; -import com.google.common.base.Preconditions; -import com.google.common.primitives.Doubles; -import com.google.common.primitives.Longs; +import java.math.BigDecimal; +import java.sql.Types; + import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.schema.SortOrder; -import java.math.BigDecimal; -import java.sql.Types; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Doubles; +import com.google.common.primitives.Longs; -public class PLong extends PDataType<Long> { +public class PLong extends PWholeNumber<Long> { public static final PLong INSTANCE = new PLong(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PNumericType.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PNumericType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PNumericType.java new file mode 100644 index 0000000..631ac8d --- /dev/null +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PNumericType.java @@ -0,0 +1,44 @@ +/* + * 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.phoenix.schema.types; + +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; +import org.apache.phoenix.schema.SortOrder; + +/** + * Base class for numeric PDataType, including PInteger, PFloat etc. + * @since 4.3.0 + */ +public abstract class PNumericType<T> extends PDataType<T> { + + protected PNumericType(String sqlTypeName, int sqlType, Class clazz, + org.apache.phoenix.schema.types.PDataType.PDataCodec codec, int ordinal) { + super(sqlTypeName, sqlType, clazz, codec, ordinal); + } + + public final int signum(byte[] bytes, int offset, int length, SortOrder sortOrder) { + return signum(bytes, offset, length, sortOrder, null, null); + } + + public final int signum(ImmutableBytesWritable ptr, SortOrder sortOrder) { + return signum(ptr.get(), ptr.getOffset(), ptr.getLength(), sortOrder); + } + + abstract public int signum(byte[] bytes, int offset, int length, SortOrder sortOrder, + Integer maxLength, Integer scale); +} http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PRealNumber.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PRealNumber.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PRealNumber.java new file mode 100644 index 0000000..d074511 --- /dev/null +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PRealNumber.java @@ -0,0 +1,39 @@ +/* + * 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.phoenix.schema.types; + +import org.apache.phoenix.schema.IllegalDataException; +import org.apache.phoenix.schema.SortOrder; + +public abstract class PRealNumber<T> extends PNumericType<T> { + + protected PRealNumber(String sqlTypeName, int sqlType, Class clazz, + org.apache.phoenix.schema.types.PDataType.PDataCodec codec, int ordinal) { + super(sqlTypeName, sqlType, clazz, codec, ordinal); + } + + @Override + public int signum(byte[] bytes, int offset, int length, SortOrder sortOrder, Integer maxLength, + Integer scale) { + double d = getCodec().decodeDouble(bytes, offset, sortOrder); + if (Double.isNaN(d)) { + throw new IllegalDataException(); + } + return (d > 0) ? 1 : ((d < 0) ? -1 : 0); + } +} http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PSmallint.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PSmallint.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PSmallint.java index 6ba631a..1cc0f40 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PSmallint.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PSmallint.java @@ -17,14 +17,15 @@ */ package org.apache.phoenix.schema.types; -import com.google.common.base.Preconditions; +import java.math.BigDecimal; +import java.sql.Types; + import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.schema.SortOrder; -import java.math.BigDecimal; -import java.sql.Types; +import com.google.common.base.Preconditions; -public class PSmallint extends PDataType<Short> { +public class PSmallint extends PWholeNumber<Short> { public static final PSmallint INSTANCE = new PSmallint(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTinyint.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTinyint.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTinyint.java index 681b41b..4b8f81e 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTinyint.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTinyint.java @@ -17,14 +17,15 @@ */ package org.apache.phoenix.schema.types; -import com.google.common.base.Preconditions; +import java.math.BigDecimal; +import java.sql.Types; + import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.schema.SortOrder; -import java.math.BigDecimal; -import java.sql.Types; +import com.google.common.base.Preconditions; -public class PTinyint extends PDataType<Byte> { +public class PTinyint extends PWholeNumber<Byte> { public static final PTinyint INSTANCE = new PTinyint(); @@ -126,7 +127,7 @@ public class PTinyint extends PDataType<Byte> { @Override public boolean isCoercibleTo(PDataType targetType, Object value) { if (value != null) { - if (equalsAny(targetType, this, PUnsignedDouble.INSTANCE, PUnsignedFloat.INSTANCE, + if (equalsAny(targetType, PUnsignedDouble.INSTANCE, PUnsignedFloat.INSTANCE, PUnsignedLong.INSTANCE, PUnsignedInt.INSTANCE, PUnsignedSmallint.INSTANCE, PUnsignedTinyint.INSTANCE)) { byte i = (Byte) value; http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedDouble.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedDouble.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedDouble.java index c1fd7ba..39e0d47 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedDouble.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedDouble.java @@ -17,14 +17,15 @@ */ package org.apache.phoenix.schema.types; -import com.google.common.base.Preconditions; -import com.google.common.primitives.Doubles; +import java.math.BigDecimal; + import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.schema.SortOrder; -import java.math.BigDecimal; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Doubles; -public class PUnsignedDouble extends PDataType<PDouble> { +public class PUnsignedDouble extends PRealNumber<PDouble> { public static final PUnsignedDouble INSTANCE = new PUnsignedDouble(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedFloat.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedFloat.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedFloat.java index c04b9c7..489ebd0 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedFloat.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedFloat.java @@ -17,11 +17,12 @@ */ package org.apache.phoenix.schema.types; -import com.google.common.base.Preconditions; import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.schema.SortOrder; -public class PUnsignedFloat extends PDataType<PFloat> { +import com.google.common.base.Preconditions; + +public class PUnsignedFloat extends PRealNumber<PFloat> { public static final PUnsignedFloat INSTANCE = new PUnsignedFloat(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedInt.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedInt.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedInt.java index 8bd5e6d..8d7c1a8 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedInt.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedInt.java @@ -17,11 +17,12 @@ */ package org.apache.phoenix.schema.types; -import com.google.common.base.Preconditions; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Order; import org.apache.phoenix.schema.SortOrder; +import com.google.common.base.Preconditions; + /** * Unsigned integer type that restricts values to be from 0 to {@link Integer#MAX_VALUE} * inclusive. May be used to map to existing HTable values created through @@ -30,7 +31,7 @@ import org.apache.phoenix.schema.SortOrder; * them to sort ahead of positive numbers when they're used as part of the row key when using the * HBase utility methods). */ -public class PUnsignedInt extends PDataType<Integer> { +public class PUnsignedInt extends PWholeNumber<Integer> { public static final PUnsignedInt INSTANCE = new PUnsignedInt(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedLong.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedLong.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedLong.java index a0ead11..67ae05a 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedLong.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedLong.java @@ -17,14 +17,15 @@ */ package org.apache.phoenix.schema.types; -import com.google.common.base.Preconditions; -import com.google.common.primitives.Doubles; -import com.google.common.primitives.Longs; +import java.math.BigDecimal; + import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Order; import org.apache.phoenix.schema.SortOrder; -import java.math.BigDecimal; +import com.google.common.base.Preconditions; +import com.google.common.primitives.Doubles; +import com.google.common.primitives.Longs; /** * Unsigned long type that restricts values to be from 0 to {@link Long#MAX_VALUE} @@ -34,7 +35,7 @@ import java.math.BigDecimal; * them to sort ahead of positive numbers when they're used as part of the row key when using the * HBase utility methods). */ -public class PUnsignedLong extends PDataType<Long> { +public class PUnsignedLong extends PWholeNumber<Long> { public static final PUnsignedLong INSTANCE = new PUnsignedLong(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedSmallint.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedSmallint.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedSmallint.java index 77ab263..e364dc4 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedSmallint.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedSmallint.java @@ -17,11 +17,12 @@ */ package org.apache.phoenix.schema.types; -import com.google.common.base.Preconditions; import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.schema.SortOrder; -public class PUnsignedSmallint extends PDataType<Short> { +import com.google.common.base.Preconditions; + +public class PUnsignedSmallint extends PWholeNumber<Short> { public static final PUnsignedSmallint INSTANCE = new PUnsignedSmallint(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTinyint.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTinyint.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTinyint.java index 4c70c18..901c629 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTinyint.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PUnsignedTinyint.java @@ -17,11 +17,12 @@ */ package org.apache.phoenix.schema.types; -import com.google.common.base.Preconditions; import org.apache.hadoop.hbase.util.Bytes; import org.apache.phoenix.schema.SortOrder; -public class PUnsignedTinyint extends PDataType<Byte> { +import com.google.common.base.Preconditions; + +public class PUnsignedTinyint extends PWholeNumber<Byte> { public static final PUnsignedTinyint INSTANCE = new PUnsignedTinyint(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PWholeNumber.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PWholeNumber.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PWholeNumber.java new file mode 100644 index 0000000..f1c7d13 --- /dev/null +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PWholeNumber.java @@ -0,0 +1,35 @@ +/* + * 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.phoenix.schema.types; + +import org.apache.phoenix.schema.SortOrder; + +public abstract class PWholeNumber<T> extends PNumericType<T> { + + protected PWholeNumber(String sqlTypeName, int sqlType, Class clazz, + org.apache.phoenix.schema.types.PDataType.PDataCodec codec, int ordinal) { + super(sqlTypeName, sqlType, clazz, codec, ordinal); + } + + @Override + public int signum(byte[] bytes, int offset, int length, SortOrder sortOrder, Integer maxLength, + Integer scale) { + long l = getCodec().decodeLong(bytes, offset, sortOrder); + return Long.signum(l); + } +} http://git-wip-us.apache.org/repos/asf/phoenix/blob/828d5fb9/phoenix-core/src/test/java/org/apache/phoenix/expression/SignFunctionTest.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/SignFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/SignFunctionTest.java new file mode 100644 index 0000000..37d6e1d --- /dev/null +++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/SignFunctionTest.java @@ -0,0 +1,124 @@ +/* + * 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.phoenix.expression; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.math.BigDecimal; +import java.sql.SQLException; +import java.util.List; + +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; +import org.apache.phoenix.expression.function.SignFunction; +import org.apache.phoenix.schema.SortOrder; +import org.apache.phoenix.schema.types.PDecimal; +import org.apache.phoenix.schema.types.PDouble; +import org.apache.phoenix.schema.types.PFloat; +import org.apache.phoenix.schema.types.PInteger; +import org.apache.phoenix.schema.types.PLong; +import org.apache.phoenix.schema.types.PNumericType; +import org.apache.phoenix.schema.types.PSmallint; +import org.apache.phoenix.schema.types.PTinyint; +import org.apache.phoenix.schema.types.PUnsignedDouble; +import org.apache.phoenix.schema.types.PUnsignedFloat; +import org.apache.phoenix.schema.types.PUnsignedInt; +import org.junit.Test; + +import com.google.common.collect.Lists; + +/** + * Unit tests for {@link SignFunction} + * @since 4.3.0 + */ +public class SignFunctionTest { + + private static void testExpression(LiteralExpression literal, Integer expected) + throws SQLException { + List<Expression> expressions = Lists.newArrayList((Expression) literal); + Expression signFunction = new SignFunction(expressions); + ImmutableBytesWritable ptr = new ImmutableBytesWritable(); + signFunction.evaluate(null, ptr); + Integer result = (Integer) signFunction.getDataType().toObject(ptr); + assertTrue(result.compareTo(expected) == 0); + } + + private static void test(Number value, PNumericType dataType, int expected) throws SQLException { + LiteralExpression literal; + literal = LiteralExpression.newConstant(value, dataType, SortOrder.ASC); + testExpression(literal, expected); + literal = LiteralExpression.newConstant(value, dataType, SortOrder.DESC); + testExpression(literal, expected); + } + + private static void testBatch(Number[] value, PNumericType dataType, int[] expected) + throws SQLException { + assertEquals(value.length, expected.length); + for (int i = 0; i < value.length; ++i) { + test(value[i], dataType, expected[i]); + } + } + + @Test + public void testSignFunction() throws Exception { + testBatch( + new BigDecimal[] { BigDecimal.valueOf(1.0), BigDecimal.valueOf(0.0), + BigDecimal.valueOf(-1.0), BigDecimal.valueOf(123.1234), + BigDecimal.valueOf(-123.1234) }, PDecimal.INSTANCE, + new int[] { 1, 0, -1, 1, -1 }); + + testBatch(new Float[] { 1.0f, 0.0f, -1.0f, Float.MAX_VALUE, Float.MIN_VALUE, + -Float.MAX_VALUE, -Float.MIN_VALUE, 123.1234f, -123.1234f }, PFloat.INSTANCE, + new int[] { 1, 0, -1, 1, 1, -1, -1, 1, -1 }); + + testBatch(new Float[] { 1.0f, 0.0f, Float.MAX_VALUE, Float.MIN_VALUE, 123.1234f }, + PUnsignedFloat.INSTANCE, new int[] { 1, 0, 1, 1, 1 }); + + testBatch(new Double[] { 1.0, 0.0, -1.0, Double.MAX_VALUE, Double.MIN_VALUE, + -Double.MAX_VALUE, -Double.MIN_VALUE, 123.1234, -123.1234 }, PDouble.INSTANCE, + new int[] { 1, 0, -1, 1, 1, -1, -1, 1, -1 }); + + testBatch(new Double[] { 1.0, 0.0, Double.MAX_VALUE, Double.MIN_VALUE, 123.1234 }, + PUnsignedDouble.INSTANCE, new int[] { 1, 0, 1, 1, 1 }); + + testBatch(new Long[] { (long) 1, (long) 0, (long) -1, Long.MAX_VALUE, Long.MIN_VALUE, + (long) 123, (long) -123 }, PLong.INSTANCE, new int[] { 1, 0, -1, 1, -1, 1, -1 }); + + testBatch(new Long[] { (long) 1, (long) 0, Long.MAX_VALUE, (long) 123 }, PLong.INSTANCE, + new int[] { 1, 0, 1, 1 }); + + testBatch(new Integer[] { 1, 0, -1, Integer.MAX_VALUE, Integer.MIN_VALUE, 123, -123 }, + PInteger.INSTANCE, new int[] { 1, 0, -1, 1, -1, 1, -1 }); + + testBatch(new Integer[] { 1, 0, Integer.MAX_VALUE, 123 }, PUnsignedInt.INSTANCE, new int[] { + 1, 0, 1, 1 }); + + testBatch(new Short[] { (short) 1, (short) 0, (short) -1, Short.MAX_VALUE, Short.MIN_VALUE, + (short) 123, (short) -123 }, PSmallint.INSTANCE, + new int[] { 1, 0, -1, 1, -1, 1, -1 }); + + testBatch(new Short[] { (short) 1, (short) 0, Short.MAX_VALUE, (short) 123 }, + PSmallint.INSTANCE, new int[] { 1, 0, 1, 1 }); + + testBatch(new Byte[] { (byte) 1, (byte) 0, (byte) -1, Byte.MAX_VALUE, Byte.MIN_VALUE, + (byte) 123, (byte) -123 }, PTinyint.INSTANCE, new int[] { 1, 0, -1, 1, -1, 1, -1 }); + + testBatch(new Byte[] { (byte) 1, (byte) 0, Byte.MAX_VALUE, (byte) 123 }, PTinyint.INSTANCE, + new int[] { 1, 0, 1, 1 }); + } +}
