You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ja...@apache.org on 2015/03/16 20:41:37 UTC

phoenix git commit: PHOENIX-1715 Implement Build-in math function Sign (Shuxiong Ye)

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 <jt...@salesforce.com>
Authored: Mon Mar 16 12:41:31 2015 -0700
Committer: James Taylor <jt...@salesforce.com>
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 });
+    }
+}