phoenix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ndimi...@apache.org
Subject [12/22] phoenix git commit: PHOENIX-1514 Break up PDataType Enum
Date Thu, 18 Dec 2014 00:11:50 GMT
http://git-wip-us.apache.org/repos/asf/phoenix/blob/04ef859b/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
new file mode 100644
index 0000000..6b2dc84
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimal.java
@@ -0,0 +1,396 @@
+/*
+ * 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 com.google.common.base.Preconditions;
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.util.ByteUtil;
+import org.apache.phoenix.util.NumberUtil;
+
+import java.math.BigDecimal;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.text.Format;
+
+public class PDecimal extends PDataType<BigDecimal> {
+
+  public static final PDecimal INSTANCE = new PDecimal();
+
+  private static final BigDecimal MIN_DOUBLE_AS_BIG_DECIMAL =
+      BigDecimal.valueOf(-Double.MAX_VALUE);
+  private static final BigDecimal MAX_DOUBLE_AS_BIG_DECIMAL =
+      BigDecimal.valueOf(Double.MAX_VALUE);
+  private static final BigDecimal MIN_FLOAT_AS_BIG_DECIMAL =
+      BigDecimal.valueOf(-Float.MAX_VALUE);
+  private static final BigDecimal MAX_FLOAT_AS_BIG_DECIMAL =
+      BigDecimal.valueOf(Float.MAX_VALUE);
+
+  private PDecimal() {
+    super("DECIMAL", Types.DECIMAL, BigDecimal.class, null, 8);
+  }
+
+  @Override
+  public byte[] toBytes(Object object) {
+    if (object == null) {
+      return ByteUtil.EMPTY_BYTE_ARRAY;
+    }
+    BigDecimal v = (BigDecimal) object;
+    v = NumberUtil.normalize(v);
+    int len = getLength(v);
+    byte[] result = new byte[Math.min(len, MAX_BIG_DECIMAL_BYTES)];
+    PDataType.toBytes(v, result, 0, len);
+    return result;
+  }
+
+  @Override
+  public int toBytes(Object object, byte[] bytes, int offset) {
+    if (object == null) {
+      return 0;
+    }
+    BigDecimal v = (BigDecimal) object;
+    v = NumberUtil.normalize(v);
+    int len = getLength(v);
+    return PDataType.toBytes(v, bytes, offset, len);
+  }
+
+  private int getLength(BigDecimal v) {
+    int signum = v.signum();
+    if (signum == 0) { // Special case for zero
+      return 1;
+    }
+            /*
+             * Size of DECIMAL includes:
+             * 1) one byte for exponent
+             * 2) one byte for terminal byte if negative
+             * 3) one byte for every two digits with the following caveats:
+             *    a) add one to round up in the case when there is an odd number of digits
+             *    b) add one in the case that the scale is odd to account for 10x of lowest significant digit
+             *       (basically done to increase the range of exponents that can be represented)
+             */
+    return (signum < 0 ? 2 : 1) + (v.precision() + 1 + (v.scale() % 2 == 0 ? 0 : 1)) / 2;
+  }
+
+  @Override
+  public int estimateByteSize(Object o) {
+    if (o == null) {
+      return 1;
+    }
+    BigDecimal v = (BigDecimal) o;
+    // TODO: should we strip zeros and round here too?
+    return Math.min(getLength(v), MAX_BIG_DECIMAL_BYTES);
+  }
+
+  @Override
+  public Integer getMaxLength(Object o) {
+    if (o == null) {
+      return MAX_PRECISION;
+    }
+    BigDecimal v = (BigDecimal) o;
+    return v.precision();
+  }
+
+  @Override
+  public Integer getScale(Object o) {
+    return null;
+  }
+
+  @Override
+  public Object toObject(byte[] b, int o, int l, PDataType actualType, SortOrder sortOrder,
+      Integer maxLength, Integer scale) {
+    Preconditions.checkNotNull(sortOrder);
+    if (l == 0) {
+      return null;
+    }
+    if (actualType == PDecimal.INSTANCE) {
+      if (sortOrder == SortOrder.DESC) {
+        b = SortOrder.invert(b, o, new byte[l], 0, l);
+        o = 0;
+      }
+      return toBigDecimal(b, o, l);
+    } else if (equalsAny(actualType, PDate.INSTANCE, PTime.INSTANCE, PUnsignedDate.INSTANCE,
+        PUnsignedTime.INSTANCE, PLong.INSTANCE, PUnsignedLong.INSTANCE, PInteger.INSTANCE,
+        PUnsignedInt.INSTANCE, PSmallint.INSTANCE, PUnsignedSmallint.INSTANCE, PTinyint.INSTANCE,
+        PUnsignedTinyint.INSTANCE)) {
+      return BigDecimal.valueOf(actualType.getCodec().decodeLong(b, o, sortOrder));
+    } else if (equalsAny(actualType, PFloat.INSTANCE, PUnsignedFloat.INSTANCE)) {
+      return BigDecimal.valueOf(actualType.getCodec().decodeFloat(b, o, sortOrder));
+    } else if (equalsAny(actualType, PDouble.INSTANCE, PUnsignedDouble.INSTANCE)) {
+      return BigDecimal.valueOf(actualType.getCodec().decodeDouble(b, o, sortOrder));
+    } else if (equalsAny(actualType, PTimestamp.INSTANCE,
+        PUnsignedTimestamp.INSTANCE)) {
+      long millisPart = actualType.getCodec().decodeLong(b, o, sortOrder);
+      int nanoPart = PUnsignedInt.INSTANCE.getCodec().decodeInt(b, o + Bytes.SIZEOF_LONG, sortOrder);
+      BigDecimal nanosPart = BigDecimal.valueOf(
+          (nanoPart % QueryConstants.MILLIS_TO_NANOS_CONVERTOR)
+              / QueryConstants.MILLIS_TO_NANOS_CONVERTOR);
+      return BigDecimal.valueOf(millisPart).add(nanosPart);
+    } else if (actualType == PBoolean.INSTANCE) {
+      return (Boolean) PBoolean.INSTANCE.toObject(b, o, l, actualType, sortOrder) ?
+          BigDecimal.ONE :
+          BigDecimal.ZERO;
+    }
+    return throwConstraintViolationException(actualType, this);
+  }
+
+  @Override
+  public Object toObject(Object object, PDataType actualType) {
+    if (object == null) {
+      return null;
+    }
+    if (equalsAny(actualType, PInteger.INSTANCE, PUnsignedInt.INSTANCE)) {
+      return BigDecimal.valueOf((Integer) object);
+    } else if (equalsAny(actualType, PLong.INSTANCE, PUnsignedLong.INSTANCE)) {
+      return BigDecimal.valueOf((Long) object);
+    } else if (equalsAny(actualType, PSmallint.INSTANCE, PUnsignedSmallint.INSTANCE)) {
+      return BigDecimal.valueOf((Short) object);
+    } else if (equalsAny(actualType, PTinyint.INSTANCE, PUnsignedTinyint.INSTANCE)) {
+      return BigDecimal.valueOf((Byte) object);
+    } else if (equalsAny(actualType, PFloat.INSTANCE, PUnsignedFloat.INSTANCE)) {
+      return BigDecimal.valueOf((Float) object);
+    } else if (equalsAny(actualType, PDouble.INSTANCE, PUnsignedDouble.INSTANCE)) {
+      return BigDecimal.valueOf((Double) object);
+    } else if (actualType == PDecimal.INSTANCE) {
+      return object;
+    } else if (equalsAny(actualType, PDate.INSTANCE, PUnsignedDate.INSTANCE, PTime.INSTANCE,
+        PUnsignedTime.INSTANCE)) {
+      java.util.Date d = (java.util.Date) object;
+      return BigDecimal.valueOf(d.getTime());
+    } else if (equalsAny(actualType, PTimestamp.INSTANCE,
+        PUnsignedTimestamp.INSTANCE)) {
+      Timestamp ts = (Timestamp) object;
+      long millisPart = ts.getTime();
+      BigDecimal nanosPart = BigDecimal.valueOf(
+          (ts.getNanos() % QueryConstants.MILLIS_TO_NANOS_CONVERTOR)
+              / QueryConstants.MILLIS_TO_NANOS_CONVERTOR);
+      BigDecimal value = BigDecimal.valueOf(millisPart).add(nanosPart);
+      return value;
+    } else if (actualType == PBoolean.INSTANCE) {
+      return ((Boolean) object) ? BigDecimal.ONE : BigDecimal.ZERO;
+    }
+    return throwConstraintViolationException(actualType, this);
+  }
+
+  @Override
+  public boolean isFixedWidth() {
+    return false;
+  }
+
+  @Override
+  public Integer getByteSize() {
+    return MAX_BIG_DECIMAL_BYTES;
+  }
+
+  @Override
+  public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+    if (rhsType == PDecimal.INSTANCE) {
+      return ((BigDecimal) lhs).compareTo((BigDecimal) rhs);
+    }
+    return -rhsType.compareTo(rhs, lhs, this);
+  }
+
+  @Override
+  public boolean isCastableTo(PDataType targetType) {
+    return super.isCastableTo(targetType) || targetType.isCoercibleTo(
+        PTimestamp.INSTANCE) || targetType.equals(PBoolean.INSTANCE);
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType, Object value) {
+    if (value != null) {
+      BigDecimal bd;
+      if (equalsAny(targetType, PUnsignedLong.INSTANCE, PUnsignedInt.INSTANCE,
+          PUnsignedSmallint.INSTANCE, PUnsignedTinyint.INSTANCE)) {
+        bd = (BigDecimal) value;
+        if (bd.signum() == -1) {
+          return false;
+        }
+      } else if (targetType.equals(PLong.INSTANCE)) {
+        bd = (BigDecimal) value;
+        try {
+          bd.longValueExact();
+          return true;
+        } catch (ArithmeticException e) {
+          return false;
+        }
+      } else if (targetType.equals(PInteger.INSTANCE)) {
+        bd = (BigDecimal) value;
+        try {
+          bd.intValueExact();
+          return true;
+        } catch (ArithmeticException e) {
+          return false;
+        }
+      } else if (targetType.equals(PSmallint.INSTANCE)) {
+        bd = (BigDecimal) value;
+        try {
+          bd.shortValueExact();
+          return true;
+        } catch (ArithmeticException e) {
+          return false;
+        }
+      } else if (targetType.equals(PTinyint.INSTANCE)) {
+        bd = (BigDecimal) value;
+        try {
+          bd.byteValueExact();
+          return true;
+        } catch (ArithmeticException e) {
+          return false;
+        }
+      } else if (targetType.equals(PUnsignedFloat.INSTANCE)) {
+        bd = (BigDecimal) value;
+        try {
+          BigDecimal maxFloat = MAX_FLOAT_AS_BIG_DECIMAL;
+          boolean isNegtive = (bd.signum() == -1);
+          return bd.compareTo(maxFloat) <= 0 && !isNegtive;
+        } catch (Exception e) {
+          return false;
+        }
+      } else if (targetType.equals(PFloat.INSTANCE)) {
+        bd = (BigDecimal) value;
+        try {
+          BigDecimal maxFloat = MAX_FLOAT_AS_BIG_DECIMAL;
+          // Float.MIN_VALUE should not be used here, as this is the
+          // smallest in terms of closest to zero.
+          BigDecimal minFloat = MIN_FLOAT_AS_BIG_DECIMAL;
+          return bd.compareTo(maxFloat) <= 0 && bd.compareTo(minFloat) >= 0;
+        } catch (Exception e) {
+          return false;
+        }
+      } else if (targetType.equals(PUnsignedDouble.INSTANCE)) {
+        bd = (BigDecimal) value;
+        try {
+          BigDecimal maxDouble = MAX_DOUBLE_AS_BIG_DECIMAL;
+          boolean isNegtive = (bd.signum() == -1);
+          return bd.compareTo(maxDouble) <= 0 && !isNegtive;
+        } catch (Exception e) {
+          return false;
+        }
+      } else if (targetType.equals(PDouble.INSTANCE)) {
+        bd = (BigDecimal) value;
+        try {
+          BigDecimal maxDouble = MAX_DOUBLE_AS_BIG_DECIMAL;
+          BigDecimal minDouble = MIN_DOUBLE_AS_BIG_DECIMAL;
+          return bd.compareTo(maxDouble) <= 0 && bd.compareTo(minDouble) >= 0;
+        } catch (Exception e) {
+          return false;
+        }
+      }
+    }
+    return super.isCoercibleTo(targetType, value);
+  }
+
+  @Override
+  public boolean isSizeCompatible(ImmutableBytesWritable ptr, Object value, PDataType srcType,
+      Integer maxLength, Integer scale, Integer desiredMaxLength, Integer desiredScale) {
+    if (ptr.getLength() == 0) {
+      return true;
+    }
+    // Use the scale from the value if provided, as it prevents a deserialization.
+    // The maxLength and scale for the underlying expression are ignored, because they
+    // are not relevant in this case: for example a DECIMAL(10,2) may be assigned to a
+    // DECIMAL(5,0) as long as the value fits.
+    if (value != null) {
+      BigDecimal v = (BigDecimal) value;
+      maxLength = v.precision();
+      scale = v.scale();
+    } else {
+      int[] v = getDecimalPrecisionAndScale(ptr.get(), ptr.getOffset(), ptr.getLength());
+      maxLength = v[0];
+      scale = v[1];
+    }
+    if (desiredMaxLength != null && desiredScale != null && maxLength != null && scale != null &&
+        ((desiredScale == null && desiredMaxLength < maxLength) ||
+            (desiredMaxLength - desiredScale) < (maxLength - scale))) {
+      return false;
+    }
+    return true;
+  }
+
+  @Override
+  public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
+      Integer maxLength, Integer scale, SortOrder actualModifier, Integer desiredMaxLength, Integer desiredScale,
+      SortOrder expectedModifier) {
+    if (desiredScale == null) {
+      // deiredScale not available, or we do not have scale requirement, delegate to parents.
+      super.coerceBytes(ptr, object, actualType, maxLength, scale, actualModifier, desiredMaxLength,
+          desiredScale, expectedModifier);
+      return;
+    }
+    if (ptr.getLength() == 0) {
+      return;
+    }
+    if (scale == null) {
+      if (object != null) {
+        BigDecimal v = (BigDecimal) object;
+        scale = v.scale();
+      } else {
+        int[] v = getDecimalPrecisionAndScale(ptr.get(), ptr.getOffset(), ptr.getLength());
+        scale = v[1];
+      }
+    }
+    if (this == actualType && scale <= desiredScale) {
+      // No coerce and rescale necessary
+      return;
+    } else {
+      BigDecimal decimal;
+      // Rescale is necessary.
+      if (object != null) { // value object is passed in.
+        decimal = (BigDecimal) toObject(object, actualType);
+      } else { // only value bytes is passed in, need to convert to object first.
+        decimal = (BigDecimal) toObject(ptr);
+      }
+      decimal = decimal.setScale(desiredScale, BigDecimal.ROUND_DOWN);
+      ptr.set(toBytes(decimal));
+    }
+  }
+
+  @Override
+  public Object toObject(String value) {
+    if (value == null || value.length() == 0) {
+      return null;
+    }
+    try {
+      return new BigDecimal(value);
+    } catch (NumberFormatException e) {
+      throw newIllegalDataException(e);
+    }
+  }
+
+  @Override
+  public Integer estimateByteSizeFromLength(Integer length) {
+    // No association of runtime byte size from decimal precision.
+    return null;
+  }
+
+  @Override
+  public String toStringLiteral(byte[] b, int offset, int length, Format formatter) {
+    if (formatter == null) {
+      BigDecimal o = (BigDecimal) toObject(b, offset, length);
+      return o.toPlainString();
+    }
+    return super.toStringLiteral(b, offset, length, formatter);
+  }
+
+  @Override
+  public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+    return new BigDecimal((Long) PLong.INSTANCE.getSampleValue(maxLength, arrayLength));
+  }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/04ef859b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimalArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimalArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimalArray.java
new file mode 100644
index 0000000..6874ac3
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDecimalArray.java
@@ -0,0 +1,110 @@
+/*
+ * 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;
+
+import java.math.BigDecimal;
+import java.sql.Types;
+
+public class PDecimalArray extends PArrayDataType<BigDecimal[]> {
+
+  public static final PDecimalArray INSTANCE = new PDecimalArray();
+
+  private PDecimalArray() {
+    super("DECIMAL ARRAY", PDataType.ARRAY_TYPE_BASE + PDecimal.INSTANCE.getSqlType(),
+        PhoenixArray.class, null, 35);
+  }
+
+  @Override
+  public boolean isArrayType() {
+    return true;
+  }
+
+  @Override
+  public boolean isFixedWidth() {
+    return false;
+  }
+
+  @Override
+  public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+    return compareTo(lhs, rhs);
+  }
+
+  @Override
+  public Integer getByteSize() {
+    return null;
+  }
+
+  @Override
+  public byte[] toBytes(Object object) {
+    return toBytes(object, SortOrder.ASC);
+  }
+
+  @Override
+  public byte[] toBytes(Object object, SortOrder sortOrder) {
+    return toBytes(object, PDecimal.INSTANCE, sortOrder);
+  }
+
+  @Override
+  public Object toObject(byte[] bytes, int offset, int length,
+      PDataType actualType, SortOrder sortOrder, Integer maxLength,
+      Integer scale) {
+    return toObject(bytes, offset, length, PDecimal.INSTANCE, sortOrder, maxLength, scale,
+        PDecimal.INSTANCE);
+  }
+
+  @Override
+  public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
+      Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
+      Integer desiredScale, SortOrder desiredModifier) {
+    coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
+        this, actualModifer, desiredModifier);
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType) {
+    return isCoercibleTo(targetType, this);
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType, Object value) {
+    if (value == null) {
+      return true;
+    }
+    PhoenixArray pArr = (PhoenixArray) value;
+    Object[] decimalArr = (Object[]) pArr.array;
+    for (Object i : decimalArr) {
+      if (!super.isCoercibleTo(PDecimal.INSTANCE, i)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @Override
+  public int getResultSetSqlType() {
+    return Types.ARRAY;
+  }
+
+  @Override
+  public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+    return getSampleValue(PDecimal.INSTANCE, arrayLength, maxLength);
+  }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/04ef859b/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
new file mode 100644
index 0000000..d8e3c4f
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDouble.java
@@ -0,0 +1,311 @@
+/*
+ * 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 com.google.common.base.Preconditions;
+import com.google.common.primitives.Doubles;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.schema.SortOrder;
+
+import java.math.BigDecimal;
+import java.sql.Types;
+
+public class PDouble extends PDataType<Double> {
+
+  public static final PDouble INSTANCE = new PDouble();
+
+  private PDouble() {
+    super("DOUBLE", Types.DOUBLE, Double.class, new DoubleCodec(), 7);
+  }
+
+  @Override
+  public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+    if (rhsType == PDecimal.INSTANCE) {
+      return -((BigDecimal) rhs).compareTo(BigDecimal.valueOf(((Number) lhs).doubleValue()));
+    }
+    return Doubles.compare(((Number) lhs).doubleValue(), ((Number) rhs).doubleValue());
+  }
+
+  @Override
+  public boolean isFixedWidth() {
+    return true;
+  }
+
+  @Override
+  public Integer getByteSize() {
+    return Bytes.SIZEOF_DOUBLE;
+  }
+
+  @Override
+  public Integer getScale(Object o) {
+    if (o == null) {
+      return null;
+    }
+    Double v = (Double) o;
+    BigDecimal bd = BigDecimal.valueOf(v);
+    return bd.scale() == 0 ? null : bd.scale();
+  }
+
+  @Override
+  public Integer getMaxLength(Object o) {
+    if (o == null) {
+      return null;
+    }
+    Double v = (Double) o;
+    BigDecimal db = BigDecimal.valueOf(v);
+    return db.precision();
+  }
+
+  @Override
+  public byte[] toBytes(Object object) {
+    byte[] b = new byte[Bytes.SIZEOF_DOUBLE];
+    toBytes(object, b, 0);
+    return b;
+  }
+
+  @Override
+  public int toBytes(Object object, byte[] bytes, int offset) {
+    if (object == null) {
+      throw newIllegalDataException(this + " may not be null");
+    }
+    return this.getCodec().encodeDouble(((Number) object).doubleValue(),
+        bytes, offset);
+  }
+
+  @Override
+  public Object toObject(String value) {
+    if (value == null || value.length() == 0) {
+      return null;
+    }
+    try {
+      return Double.parseDouble(value);
+    } catch (NumberFormatException e) {
+      throw newIllegalDataException(e);
+    }
+  }
+
+  @Override
+  public Object toObject(Object object, PDataType actualType) {
+    if (object == null) {
+      return null;
+    }
+    double de;
+    if (equalsAny(actualType, PDouble.INSTANCE, PUnsignedDouble.INSTANCE)) {
+      return object;
+    } else if (equalsAny(actualType, PFloat.INSTANCE, PUnsignedFloat.INSTANCE)) {
+      de = (Float) object;
+      return de;
+    } else if (equalsAny(actualType, PLong.INSTANCE, PUnsignedLong.INSTANCE)) {
+      de = (Long) object;
+      return de;
+    } else if (equalsAny(actualType, PInteger.INSTANCE, PUnsignedInt.INSTANCE)) {
+      de = (Integer) object;
+      return de;
+    } else if (equalsAny(actualType, PTinyint.INSTANCE, PUnsignedTinyint.INSTANCE)) {
+      de = (Byte) object;
+      return de;
+    } else if (equalsAny(actualType, PSmallint.INSTANCE, PUnsignedSmallint.INSTANCE)) {
+      de = (Short) object;
+      return de;
+    } else if (actualType == PDecimal.INSTANCE) {
+      BigDecimal d = (BigDecimal) object;
+      return d.doubleValue();
+    }
+    return throwConstraintViolationException(actualType, this);
+  }
+
+  @Override
+  public Double toObject(byte[] b, int o, int l, PDataType actualType,
+      SortOrder sortOrder, Integer maxLength, Integer scale) {
+    if (l <= 0) {
+      return null;
+    }
+    if (equalsAny(actualType, PDouble.INSTANCE, PUnsignedDouble.INSTANCE, PFloat.INSTANCE,
+        PUnsignedFloat.INSTANCE, PLong.INSTANCE, PUnsignedLong.INSTANCE, PInteger.INSTANCE,
+        PUnsignedInt.INSTANCE, PSmallint.INSTANCE, PUnsignedSmallint.INSTANCE, PTinyint.INSTANCE,
+        PUnsignedTinyint.INSTANCE)) {
+      return actualType.getCodec().decodeDouble(b, o, sortOrder);
+    } else if (actualType == PDecimal.INSTANCE) {
+      BigDecimal bd = (BigDecimal) actualType.toObject(b, o, l, actualType, sortOrder);
+      return bd.doubleValue();
+    }
+    throwConstraintViolationException(actualType, this);
+    return null;
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType, Object value) {
+    if (value != null) {
+      double d = (Double) value;
+      if (targetType.equals(PUnsignedDouble.INSTANCE)) {
+        return d >= 0;
+      } else if (targetType.equals(PFloat.INSTANCE)) {
+        return Double.isNaN(d)
+            || d == Double.POSITIVE_INFINITY
+            || d == Double.NEGATIVE_INFINITY
+            || (d >= -Float.MAX_VALUE && d <= Float.MAX_VALUE);
+      } else if (targetType.equals(PUnsignedFloat.INSTANCE)) {
+        return Double.isNaN(d) || d == Double.POSITIVE_INFINITY
+            || (d >= 0 && d <= Float.MAX_VALUE);
+      } else if (targetType.equals(PUnsignedLong.INSTANCE)) {
+        return (d >= 0 && d <= Long.MAX_VALUE);
+      } else if (targetType.equals(PLong.INSTANCE)) {
+        return (d >= Long.MIN_VALUE && d <= Long.MAX_VALUE);
+      } else if (targetType.equals(PUnsignedInt.INSTANCE)) {
+        return (d >= 0 && d <= Integer.MAX_VALUE);
+      } else if (targetType.equals(PInteger.INSTANCE)) {
+        return (d >= Integer.MIN_VALUE && d <= Integer.MAX_VALUE);
+      } else if (targetType.equals(PUnsignedSmallint.INSTANCE)) {
+        return (d >= 0 && d <= Short.MAX_VALUE);
+      } else if (targetType.equals(PSmallint.INSTANCE)) {
+        return (d >= Short.MIN_VALUE && d <= Short.MAX_VALUE);
+      } else if (targetType.equals(PTinyint.INSTANCE)) {
+        return (d >= Byte.MIN_VALUE && d < Byte.MAX_VALUE);
+      } else if (targetType.equals(PUnsignedTinyint.INSTANCE)) {
+        return (d >= 0 && d < Byte.MAX_VALUE);
+      }
+    }
+    return super.isCoercibleTo(targetType, value);
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType) {
+    return equalsAny(targetType, this, PDecimal.INSTANCE, PVarbinary.INSTANCE, PBinary.INSTANCE);
+  }
+
+  @Override
+  public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+    return RANDOM.get().nextDouble();
+  }
+
+  static class DoubleCodec extends BaseCodec {
+
+    @Override
+    public long decodeLong(byte[] b, int o, SortOrder sortOrder) {
+      double v = decodeDouble(b, o, sortOrder);
+      if (v < Long.MIN_VALUE || v > Long.MAX_VALUE) {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be cast to Long without changing its value");
+      }
+      return (long) v;
+    }
+
+    @Override
+    public int decodeInt(byte[] b, int o, SortOrder sortOrder) {
+      double v = decodeDouble(b, o, sortOrder);
+      if (v < Integer.MIN_VALUE || v > Integer.MAX_VALUE) {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be cast to Integer without changing its value");
+      }
+      return (int) v;
+    }
+
+    @Override
+    public byte decodeByte(byte[] b, int o, SortOrder sortOrder) {
+      double v = decodeDouble(b, o, sortOrder);
+      if (v < Byte.MIN_VALUE || v > Byte.MAX_VALUE) {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be cast to Byte without changing its value");
+      }
+      return (byte) v;
+    }
+
+    @Override
+    public short decodeShort(byte[] b, int o, SortOrder sortOrder) {
+      double v = decodeDouble(b, o, sortOrder);
+      if (v < Short.MIN_VALUE || v > Short.MAX_VALUE) {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be cast to Short without changing its value");
+      }
+      return (short) v;
+    }
+
+    @Override
+    public double decodeDouble(byte[] b, int o, SortOrder sortOrder) {
+      Preconditions.checkNotNull(sortOrder);
+      checkForSufficientLength(b, o, Bytes.SIZEOF_LONG);
+      if (sortOrder == SortOrder.DESC) {
+        for (int i = o; i < Bytes.SIZEOF_LONG; i++) {
+          b[i] = (byte) (b[i] ^ 0xff);
+        }
+      }
+      long l = Bytes.toLong(b, o);
+      l--;
+      l ^= (~l >> Long.SIZE - 1) | Long.MIN_VALUE;
+      return Double.longBitsToDouble(l);
+    }
+
+    @Override
+    public float decodeFloat(byte[] b, int o, SortOrder sortOrder) {
+      double v = decodeDouble(b, o, sortOrder);
+      if (Double.isNaN(v) || v == Double.NEGATIVE_INFINITY
+          || v == Double.POSITIVE_INFINITY
+          || (v >= -Float.MAX_VALUE && v <= Float.MAX_VALUE)) {
+        return (float) v;
+      } else {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be cast to Float without changing its value");
+      }
+
+    }
+
+    @Override
+    public int encodeShort(short v, byte[] b, int o) {
+      return encodeDouble(v, b, o);
+    }
+
+    @Override
+    public int encodeLong(long v, byte[] b, int o) {
+      return encodeDouble(v, b, o);
+    }
+
+    @Override
+    public int encodeInt(int v, byte[] b, int o) {
+      return encodeDouble(v, b, o);
+    }
+
+    @Override
+    public int encodeByte(byte v, byte[] b, int o) {
+      return encodeDouble(v, b, o);
+    }
+
+    @Override
+    public int encodeDouble(double v, byte[] b, int o) {
+      checkForSufficientLength(b, o, Bytes.SIZEOF_LONG);
+      long l = Double.doubleToLongBits(v);
+      l = (l ^ ((l >> Long.SIZE - 1) | Long.MIN_VALUE)) + 1;
+      Bytes.putLong(b, o, l);
+      return Bytes.SIZEOF_LONG;
+    }
+
+    @Override
+    public int encodeFloat(float v, byte[] b, int o) {
+      return encodeDouble(v, b, o);
+    }
+
+    @Override
+    public PhoenixArrayFactory getPhoenixArrayFactory() {
+      return new PhoenixArrayFactory() {
+        @Override
+        public PhoenixArray newArray(PDataType type, Object[] elements) {
+          return new PhoenixArray.PrimitiveDoublePhoenixArray(type, elements);
+        }
+      };
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/04ef859b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDoubleArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDoubleArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDoubleArray.java
new file mode 100644
index 0000000..7ecec61
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDoubleArray.java
@@ -0,0 +1,108 @@
+/*
+ * 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;
+
+import java.sql.Types;
+
+public class PDoubleArray extends PArrayDataType<double[]> {
+
+  public static final PDoubleArray INSTANCE = new PDoubleArray();
+
+  private PDoubleArray() {
+    super("DOUBLE ARRAY", PDataType.ARRAY_TYPE_BASE + PDouble.INSTANCE.getSqlType(),
+        PhoenixArray.class, null, 34);
+  }
+
+  @Override
+  public boolean isArrayType() {
+    return true;
+  }
+
+  @Override
+  public boolean isFixedWidth() {
+    return false;
+  }
+
+  @Override
+  public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+    return compareTo(lhs, rhs);
+  }
+
+  @Override
+  public Integer getByteSize() {
+    return null;
+  }
+
+  @Override
+  public byte[] toBytes(Object object) {
+    return toBytes(object, SortOrder.ASC);
+  }
+
+  @Override
+  public byte[] toBytes(Object object, SortOrder sortOrder) {
+    return toBytes(object, PDouble.INSTANCE, sortOrder);
+  }
+
+  @Override
+  public Object toObject(byte[] bytes, int offset, int length,
+      PDataType actualType, SortOrder sortOrder, Integer maxLength, Integer scale) {
+    return toObject(bytes, offset, length, PDouble.INSTANCE, sortOrder, maxLength, scale,
+        PDouble.INSTANCE);
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType) {
+    return isCoercibleTo(targetType, this);
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType, Object value) {
+    if (value == null) {
+      return true;
+    }
+    PhoenixArray.PrimitiveDoublePhoenixArray pArr = (PhoenixArray.PrimitiveDoublePhoenixArray) value;
+    double[] doubleArr = (double[]) pArr.array;
+    for (double i : doubleArr) {
+      if (!super.isCoercibleTo(PDouble.INSTANCE, i)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @Override
+  public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
+      Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
+      Integer desiredScale, SortOrder desiredModifier) {
+    coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
+        this, actualModifer, desiredModifier);
+  }
+
+  @Override
+  public int getResultSetSqlType() {
+    return Types.ARRAY;
+  }
+
+  @Override
+  public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+    return getSampleValue(PDouble.INSTANCE, arrayLength, maxLength);
+  }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/04ef859b/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
new file mode 100644
index 0000000..608b270
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloat.java
@@ -0,0 +1,308 @@
+/*
+ * 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 com.google.common.base.Preconditions;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.schema.SortOrder;
+
+import java.math.BigDecimal;
+import java.sql.Types;
+
+public class PFloat extends PDataType<Float> {
+
+  public static final PFloat INSTANCE = new PFloat();
+
+  private PFloat() {
+    super("FLOAT", Types.FLOAT, Float.class, new FloatCodec(), 6);
+  }
+
+  @Override
+  public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+    return PDouble.INSTANCE.compareTo(lhs, rhs, rhsType);
+  }
+
+  @Override
+  public boolean isFixedWidth() {
+    return true;
+  }
+
+  @Override
+  public Integer getByteSize() {
+    return Bytes.SIZEOF_FLOAT;
+  }
+
+  @Override
+  public Integer getScale(Object o) {
+    if (o == null) {
+      return null;
+    }
+    Float v = (Float) o;
+    BigDecimal bd = BigDecimal.valueOf(v);
+    return bd.scale() == 0 ? null : bd.scale();
+  }
+
+  @Override
+  public Integer getMaxLength(Object o) {
+    if (o == null) {
+      return null;
+    }
+    Float v = (Float) o;
+    BigDecimal bd = BigDecimal.valueOf(v);
+    return bd.precision();
+  }
+
+  @Override
+  public byte[] toBytes(Object object) {
+    byte[] b = new byte[Bytes.SIZEOF_FLOAT];
+    toBytes(object, b, 0);
+    return b;
+  }
+
+  @Override
+  public int toBytes(Object object, byte[] bytes, int offset) {
+    if (object == null) {
+      throw newIllegalDataException(this + " may not be null");
+    }
+    return this.getCodec().encodeFloat(((Number) object).floatValue(),
+        bytes, offset);
+  }
+
+  @Override
+  public Object toObject(String value) {
+    if (value == null || value.length() == 0) {
+      return null;
+    }
+    try {
+      return Float.parseFloat(value);
+    } catch (NumberFormatException e) {
+      throw newIllegalDataException(e);
+    }
+  }
+
+  @Override
+  public Object toObject(Object object, PDataType actualType) {
+    if (object == null) {
+      return null;
+    }
+    float f;
+    if (equalsAny(actualType, PFloat.INSTANCE, PUnsignedFloat.INSTANCE)) {
+      return object;
+    } else if (equalsAny(actualType, PDouble.INSTANCE, PUnsignedDouble.INSTANCE)) {
+      double d = (Double) object;
+      if (Double.isNaN(d)
+          || d == Double.POSITIVE_INFINITY
+          || d == Double.NEGATIVE_INFINITY
+          || (d >= -Float.MAX_VALUE && d <= Float.MAX_VALUE)) {
+        return (float) d;
+      } else {
+        throw newIllegalDataException(
+            actualType + " value " + d + " cannot be cast to Float without changing its value");
+      }
+    } else if (equalsAny(actualType, PLong.INSTANCE, PUnsignedLong.INSTANCE)) {
+      f = (Long) object;
+      return f;
+    } else if (equalsAny(actualType, PInteger.INSTANCE, PUnsignedInt.INSTANCE)) {
+      f = (Integer) object;
+      return f;
+    } else if (equalsAny(actualType, PTinyint.INSTANCE, PUnsignedTinyint.INSTANCE)) {
+      f = (Byte) object;
+      return f;
+    } else if (equalsAny(actualType, PSmallint.INSTANCE, PUnsignedSmallint.INSTANCE)) {
+      f = (Short) object;
+      return f;
+    } else if (actualType == PDecimal.INSTANCE) {
+      BigDecimal dl = (BigDecimal) object;
+      return dl.floatValue();
+    }
+    return throwConstraintViolationException(actualType, this);
+  }
+
+  @Override
+  public Float toObject(byte[] b, int o, int l, PDataType actualType, SortOrder sortOrder,
+      Integer maxLength, Integer scale) {
+    if (l <= 0) {
+      return null;
+    }
+    if (equalsAny(actualType, PFloat.INSTANCE, PUnsignedFloat.INSTANCE, PDouble.INSTANCE,
+        PUnsignedDouble.INSTANCE, PLong.INSTANCE, PUnsignedLong.INSTANCE, PInteger.INSTANCE,
+        PUnsignedInt.INSTANCE, PSmallint.INSTANCE, PUnsignedSmallint.INSTANCE, PTinyint.INSTANCE,
+        PUnsignedTinyint.INSTANCE)) {
+      return actualType.getCodec().decodeFloat(b, o, sortOrder);
+    } else if (actualType == PDecimal.INSTANCE) {
+      BigDecimal bd = (BigDecimal) actualType.toObject(b, o, l, actualType, sortOrder);
+      return bd.floatValue();
+    }
+
+    throwConstraintViolationException(actualType, this);
+    return null;
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType, Object value) {
+    if (value != null) {
+      float f = (Float) value;
+      if (targetType.equals(PUnsignedFloat.INSTANCE)) {
+        return f >= 0;
+      } else if (targetType.equals(PUnsignedLong.INSTANCE)) {
+        return (f >= 0 && f <= Long.MAX_VALUE);
+      } else if (targetType.equals(PLong.INSTANCE)) {
+        return (f >= Long.MIN_VALUE && f <= Long.MAX_VALUE);
+      } else if (targetType.equals(PUnsignedInt.INSTANCE)) {
+        return (f >= 0 && f <= Integer.MAX_VALUE);
+      } else if (targetType.equals(PInteger.INSTANCE)) {
+        return (f >= Integer.MIN_VALUE && f <= Integer.MAX_VALUE);
+      } else if (targetType.equals(PUnsignedSmallint.INSTANCE)) {
+        return (f >= 0 && f <= Short.MAX_VALUE);
+      } else if (targetType.equals(PSmallint.INSTANCE)) {
+        return (f >= Short.MIN_VALUE && f <= Short.MAX_VALUE);
+      } else if (targetType.equals(PTinyint.INSTANCE)) {
+        return (f >= Byte.MIN_VALUE && f < Byte.MAX_VALUE);
+      } else if (targetType.equals(PUnsignedTinyint.INSTANCE)) {
+        return (f >= 0 && f < Byte.MAX_VALUE);
+      }
+    }
+    return super.isCoercibleTo(targetType, value);
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType) {
+    return this.equals(targetType) || PDouble.INSTANCE.isCoercibleTo(targetType);
+  }
+
+  @Override
+  public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+    return RANDOM.get().nextFloat();
+  }
+
+  static class FloatCodec extends BaseCodec {
+
+    @Override
+    public long decodeLong(byte[] b, int o, SortOrder sortOrder) {
+      float v = decodeFloat(b, o, sortOrder);
+      if (v < Long.MIN_VALUE || v > Long.MAX_VALUE) {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be cast to Long without changing its value");
+      }
+      return (long) v;
+    }
+
+    @Override
+    public int decodeInt(byte[] b, int o, SortOrder sortOrder) {
+      float v = decodeFloat(b, o, sortOrder);
+      if (v < Integer.MIN_VALUE || v > Integer.MAX_VALUE) {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be cast to Integer without changing its value");
+      }
+      return (int) v;
+    }
+
+    @Override
+    public byte decodeByte(byte[] b, int o, SortOrder sortOrder) {
+      float v = decodeFloat(b, o, sortOrder);
+      if (v < Byte.MIN_VALUE || v > Byte.MAX_VALUE) {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be cast to Byte without changing its value");
+      }
+      return (byte) v;
+    }
+
+    @Override
+    public short decodeShort(byte[] b, int o, SortOrder sortOrder) {
+      float v = decodeFloat(b, o, sortOrder);
+      if (v < Short.MIN_VALUE || v > Short.MAX_VALUE) {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be cast to Short without changing its value");
+      }
+      return (short) v;
+    }
+
+    @Override
+    public double decodeDouble(byte[] b, int o,
+        SortOrder sortOrder) {
+      return decodeFloat(b, o, sortOrder);
+    }
+
+    @Override
+    public float decodeFloat(byte[] b, int o, SortOrder sortOrder) {
+      Preconditions.checkNotNull(sortOrder);
+      checkForSufficientLength(b, o, Bytes.SIZEOF_INT);
+      if (sortOrder == SortOrder.DESC) {
+        for (int i = o; i < Bytes.SIZEOF_INT; i++) {
+          b[i] = (byte) (b[i] ^ 0xff);
+        }
+      }
+      int i = Bytes.toInt(b, o);
+      i--;
+      i ^= (~i >> Integer.SIZE - 1) | Integer.MIN_VALUE;
+      return Float.intBitsToFloat(i);
+    }
+
+    @Override
+    public int encodeShort(short v, byte[] b, int o) {
+      return encodeFloat(v, b, o);
+    }
+
+    @Override
+    public int encodeLong(long v, byte[] b, int o) {
+      return encodeFloat(v, b, o);
+    }
+
+    @Override
+    public int encodeInt(int v, byte[] b, int o) {
+      return encodeFloat(v, b, o);
+    }
+
+    @Override
+    public int encodeByte(byte v, byte[] b, int o) {
+      return encodeFloat(v, b, o);
+    }
+
+    @Override
+    public int encodeDouble(double v, byte[] b, int o) {
+      if (Double.isNaN(v) || v == Double.POSITIVE_INFINITY
+          || v == Double.NEGATIVE_INFINITY
+          || (v >= -Float.MAX_VALUE && v <= Float.MAX_VALUE)) {
+        return encodeFloat((float) v, b, o);
+      } else {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be encoded as an Float without changing its value");
+      }
+
+    }
+
+    @Override
+    public int encodeFloat(float v, byte[] b, int o) {
+      checkForSufficientLength(b, o, Bytes.SIZEOF_FLOAT);
+      int i = Float.floatToIntBits(v);
+      i = (i ^ ((i >> Integer.SIZE - 1) | Integer.MIN_VALUE)) + 1;
+      Bytes.putInt(b, o, i);
+      return Bytes.SIZEOF_FLOAT;
+    }
+
+    @Override
+    public PhoenixArrayFactory getPhoenixArrayFactory() {
+      return new PhoenixArrayFactory() {
+        @Override
+        public PhoenixArray newArray(PDataType type, Object[] elements) {
+          return new PhoenixArray.PrimitiveFloatPhoenixArray(type, elements);
+        }
+      };
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/04ef859b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloatArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloatArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloatArray.java
new file mode 100644
index 0000000..5e8ddb3
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PFloatArray.java
@@ -0,0 +1,109 @@
+/*
+ * 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;
+
+import java.sql.Types;
+
+public class PFloatArray extends PArrayDataType<float[]> {
+
+  public static final PFloatArray INSTANCE = new PFloatArray();
+
+  private PFloatArray() {
+    super("FLOAT ARRAY", PDataType.ARRAY_TYPE_BASE + PFloat.INSTANCE.getSqlType(),
+        PhoenixArray.class, null, 33);
+  }
+
+  @Override
+  public boolean isArrayType() {
+    return true;
+  }
+
+  @Override
+  public boolean isFixedWidth() {
+    return false;
+  }
+
+  @Override
+  public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+    return compareTo(lhs, rhs);
+  }
+
+  @Override
+  public Integer getByteSize() {
+    return null;
+  }
+
+  @Override
+  public byte[] toBytes(Object object) {
+    return toBytes(object, SortOrder.ASC);
+  }
+
+  @Override
+  public byte[] toBytes(Object object, SortOrder sortOrder) {
+    return toBytes(object, PFloat.INSTANCE, sortOrder);
+  }
+
+  @Override
+  public Object toObject(byte[] bytes, int offset, int length,
+      PDataType actualType, SortOrder sortOrder, Integer maxLength,
+      Integer scale) {
+    return toObject(bytes, offset, length, PFloat.INSTANCE, sortOrder, maxLength, scale,
+        PFloat.INSTANCE);
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType) {
+    return isCoercibleTo(targetType, this);
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType, Object value) {
+    if (value == null) {
+      return true;
+    }
+    PhoenixArray.PrimitiveFloatPhoenixArray pArr = (PhoenixArray.PrimitiveFloatPhoenixArray) value;
+    float[] floatArr = (float[]) pArr.array;
+    for (float i : floatArr) {
+      if (!super.isCoercibleTo(PFloat.INSTANCE, i)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @Override
+  public int getResultSetSqlType() {
+    return Types.ARRAY;
+  }
+
+  @Override
+  public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
+      Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
+      Integer desiredScale, SortOrder desiredModifier) {
+    coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
+        this, actualModifer, desiredModifier);
+  }
+
+  @Override
+  public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+    return getSampleValue(PFloat.INSTANCE, arrayLength, maxLength);
+  }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/04ef859b/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
new file mode 100644
index 0000000..c4760b5
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PInteger.java
@@ -0,0 +1,275 @@
+/*
+ * 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 com.google.common.base.Preconditions;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.schema.SortOrder;
+
+import java.math.BigDecimal;
+import java.sql.Types;
+
+public class PInteger extends PDataType<Integer> {
+
+  public static final PInteger INSTANCE = new PInteger();
+
+  private PInteger() {
+    super("INTEGER", Types.INTEGER, Integer.class, new IntCodec(), 3);
+  }
+
+  @Override
+  public Integer getScale(Object o) {
+    return ZERO;
+  }
+
+  @Override
+  public byte[] toBytes(Object object) {
+    byte[] b = new byte[Bytes.SIZEOF_INT];
+    toBytes(object, b, 0);
+    return b;
+  }
+
+  @Override
+  public int toBytes(Object object, byte[] b, int o) {
+    if (object == null) {
+      throw newIllegalDataException(this + " may not be null");
+    }
+    return this.getCodec().encodeInt(((Number) object).intValue(), b, o);
+  }
+
+  @Override
+  public Object toObject(Object object, PDataType actualType) {
+    Object o = PLong.INSTANCE.toObject(object, actualType);
+    if (!(o instanceof Long) || o == null) {
+      return o;
+    }
+    long l = (Long) o;
+    if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) {
+      throw newIllegalDataException(
+          actualType + " value " + l + " cannot be cast to Integer without changing its value");
+    }
+    int v = (int) l;
+    return v;
+  }
+
+  @Override
+  public Integer toObject(byte[] b, int o, int l, PDataType actualType,
+      SortOrder sortOrder, Integer maxLength, Integer scale) {
+    if (l == 0) {
+      return null;
+    }
+    if (equalsAny(actualType, PLong.INSTANCE, PUnsignedLong.INSTANCE, PInteger.INSTANCE,
+        PUnsignedInt.INSTANCE, PSmallint.INSTANCE, PUnsignedSmallint.INSTANCE, PTinyint.INSTANCE,
+        PUnsignedTinyint.INSTANCE, PFloat.INSTANCE, PUnsignedFloat.INSTANCE, PDouble.INSTANCE,
+        PUnsignedDouble.INSTANCE)) {
+      return actualType.getCodec().decodeInt(b, o, sortOrder);
+    } else if (actualType == PDecimal.INSTANCE) {
+      BigDecimal bd = (BigDecimal) actualType.toObject(b, o, l, actualType, sortOrder);
+      return bd.intValueExact();
+    }
+    throwConstraintViolationException(actualType, this);
+    return null;
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType, Object value) {
+    if (value != null) {
+      int i;
+      if (equalsAny(targetType, PUnsignedDouble.INSTANCE, PUnsignedFloat.INSTANCE,
+          PUnsignedLong.INSTANCE, PUnsignedInt.INSTANCE)) {
+        i = (Integer) value;
+        return i >= 0;
+      } else if (targetType.equals(PUnsignedSmallint.INSTANCE)) {
+        i = (Integer) value;
+        return (i >= 0 && i <= Short.MAX_VALUE);
+      } else if (targetType.equals(PSmallint.INSTANCE)) {
+        i = (Integer) value;
+        return (i >= Short.MIN_VALUE && i <= Short.MAX_VALUE);
+      } else if (targetType.equals(PTinyint.INSTANCE)) {
+        i = (Integer) value;
+        return (i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE);
+      } else if (targetType.equals(PUnsignedTinyint.INSTANCE)) {
+        i = (Integer) value;
+        return (i >= 0 && i < Byte.MAX_VALUE);
+      }
+    }
+    return super.isCoercibleTo(targetType, value);
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType) {
+    return equalsAny(targetType, this, PFloat.INSTANCE) || PLong.INSTANCE.isCoercibleTo(targetType);
+  }
+
+  @Override
+  public boolean isFixedWidth() {
+    return true;
+  }
+
+  @Override
+  public Integer getByteSize() {
+    return Bytes.SIZEOF_INT;
+  }
+
+  @Override
+  public Integer getMaxLength(Object o) {
+    return INT_PRECISION;
+  }
+
+  @Override
+  public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+    return PLong.INSTANCE.compareTo(lhs, rhs, rhsType);
+  }
+
+  @Override
+  public boolean isComparableTo(PDataType targetType) {
+    return PDecimal.INSTANCE.isComparableTo(targetType);
+  }
+
+  @Override
+  public Object toObject(String value) {
+    if (value == null || value.length() == 0) {
+      return null;
+    }
+    try {
+      return Integer.parseInt(value);
+    } catch (NumberFormatException e) {
+      throw newIllegalDataException(e);
+    }
+  }
+
+  @Override
+  public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+    return RANDOM.get().nextInt();
+  }
+
+  static class IntCodec extends BaseCodec {
+
+    @Override
+    public long decodeLong(byte[] b, int o, SortOrder sortOrder) {
+      return decodeInt(b, o, sortOrder);
+    }
+
+    @Override
+    public float decodeFloat(byte[] b, int o, SortOrder sortOrder) {
+      return decodeInt(b, o, sortOrder);
+    }
+
+    @Override
+    public double decodeDouble(byte[] b, int o,
+        SortOrder sortOrder) {
+      return decodeInt(b, o, sortOrder);
+    }
+
+    @Override
+    public int decodeInt(byte[] bytes, int o, SortOrder sortOrder) {
+      Preconditions.checkNotNull(sortOrder);
+      checkForSufficientLength(bytes, o, Bytes.SIZEOF_INT);
+      int v;
+      if (sortOrder == SortOrder.ASC) {
+        v = bytes[o] ^ 0x80; // Flip sign bit back
+        for (int i = 1; i < Bytes.SIZEOF_INT; i++) {
+          v = (v << 8) + (bytes[o + i] & 0xff);
+        }
+      } else {
+        v = bytes[o] ^ 0xff ^ 0x80; // Flip sign bit back
+        for (int i = 1; i < Bytes.SIZEOF_INT; i++) {
+          v = (v << 8) + ((bytes[o + i] ^ 0xff) & 0xff);
+        }
+      }
+      return v;
+    }
+
+    @Override
+    public int encodeInt(int v, byte[] b, int o) {
+      checkForSufficientLength(b, o, Bytes.SIZEOF_INT);
+      b[o + 0] = (byte) ((v >> 24) ^ 0x80); // Flip sign bit so that INTEGER is binary comparable
+      b[o + 1] = (byte) (v >> 16);
+      b[o + 2] = (byte) (v >> 8);
+      b[o + 3] = (byte) v;
+      return Bytes.SIZEOF_INT;
+    }
+
+    @Override
+    public int encodeFloat(float v, byte[] b, int o) {
+      if (v < Integer.MIN_VALUE || v > Integer.MAX_VALUE) {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be encoded as an Integer without changing its value");
+      }
+      return encodeInt((int) v, b, o);
+    }
+
+    @Override
+    public int encodeDouble(double v, byte[] b, int o) {
+      if (v < Integer.MIN_VALUE || v > Integer.MAX_VALUE) {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be encoded as an Integer without changing its value");
+      }
+      return encodeInt((int) v, b, o);
+    }
+
+    @Override
+    public int encodeLong(long v, byte[] b, int o) {
+      if (v < Integer.MIN_VALUE || v > Integer.MAX_VALUE) {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be encoded as an Integer without changing its value");
+      }
+      return encodeInt((int) v, b, o);
+    }
+
+    @Override
+    public byte decodeByte(byte[] b, int o, SortOrder sortOrder) {
+      int v = decodeInt(b, o, sortOrder);
+      if (v < Byte.MIN_VALUE || v > Byte.MAX_VALUE) {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be cast to Byte without changing its value");
+      }
+      return (byte) v;
+    }
+
+    @Override
+    public short decodeShort(byte[] b, int o, SortOrder sortOrder) {
+      int v = decodeInt(b, o, sortOrder);
+      if (v < Short.MIN_VALUE || v > Short.MAX_VALUE) {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be cast to Short without changing its value");
+      }
+      return (short) v;
+    }
+
+    @Override
+    public int encodeByte(byte v, byte[] b, int o) {
+      return encodeInt(v, b, o);
+    }
+
+    @Override
+    public int encodeShort(short v, byte[] b, int o) {
+      return encodeInt(v, b, o);
+    }
+
+    @Override
+    public PhoenixArrayFactory getPhoenixArrayFactory() {
+      return new PhoenixArrayFactory() {
+        @Override
+        public PhoenixArray newArray(PDataType type, Object[] elements) {
+          return new PhoenixArray.PrimitiveIntPhoenixArray(type, elements);
+        }
+      };
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/04ef859b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PIntegerArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PIntegerArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PIntegerArray.java
new file mode 100644
index 0000000..28a5c4c
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PIntegerArray.java
@@ -0,0 +1,109 @@
+/*
+ * 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;
+
+import java.sql.Types;
+
+public class PIntegerArray extends PArrayDataType<int[]> {
+
+  public static final PIntegerArray INSTANCE = new PIntegerArray();
+
+  private PIntegerArray() {
+    super("INTEGER ARRAY", PDataType.ARRAY_TYPE_BASE + PInteger.INSTANCE.getSqlType(),
+        PhoenixArray.class, null, 24);
+  }
+
+  @Override
+  public boolean isArrayType() {
+    return true;
+  }
+
+  @Override
+  public boolean isFixedWidth() {
+    return false;
+  }
+
+  @Override
+  public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+    return compareTo(lhs, rhs);
+  }
+
+  @Override
+  public Integer getByteSize() {
+    return null;
+  }
+
+  @Override
+  public byte[] toBytes(Object object) {
+    return toBytes(object, SortOrder.ASC);
+  }
+
+  @Override
+  public byte[] toBytes(Object object, SortOrder sortOrder) {
+    return toBytes(object, PInteger.INSTANCE, sortOrder);
+  }
+
+  @Override
+  public Object toObject(byte[] bytes, int offset, int length,
+      PDataType actualType, SortOrder sortOrder, Integer maxLength,
+      Integer scale) {
+    return toObject(bytes, offset, length, PInteger.INSTANCE, sortOrder, maxLength, scale,
+        PInteger.INSTANCE);
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType) {
+    return isCoercibleTo(targetType, this);
+  }
+
+  @Override
+  public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
+      Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
+      Integer desiredScale, SortOrder desiredModifier) {
+    coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
+        this, actualModifer, desiredModifier);
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType, Object value) {
+    if (value == null) {
+      return true;
+    }
+    PhoenixArray.PrimitiveIntPhoenixArray pArr = (PhoenixArray.PrimitiveIntPhoenixArray) value;
+    int[] intArr = (int[]) pArr.array;
+    for (int i : intArr) {
+      if (!super.isCoercibleTo(PInteger.INSTANCE, i)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @Override
+  public int getResultSetSqlType() {
+    return Types.ARRAY;
+  }
+
+  @Override
+  public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+    return getSampleValue(PInteger.INSTANCE, arrayLength, maxLength);
+  }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/04ef859b/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
new file mode 100644
index 0000000..1bef844
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLong.java
@@ -0,0 +1,331 @@
+/*
+ * 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 com.google.common.base.Preconditions;
+import com.google.common.primitives.Doubles;
+import com.google.common.primitives.Longs;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.schema.SortOrder;
+
+import java.math.BigDecimal;
+import java.sql.Types;
+
+public class PLong extends PDataType<Long> {
+
+  public static final PLong INSTANCE = new PLong();
+
+  private PLong() {
+    super("BIGINT", Types.BIGINT, Long.class, new LongCodec(), 2);
+  }
+
+  @Override
+  public Integer getScale(Object o) {
+    return ZERO;
+  }
+
+  @Override
+  public byte[] toBytes(Object object) {
+    byte[] b = new byte[Bytes.SIZEOF_LONG];
+    toBytes(object, b, 0);
+    return b;
+  }
+
+  @Override
+  public int toBytes(Object object, byte[] b, int o) {
+    if (object == null) {
+      throw newIllegalDataException(this + " may not be null");
+    }
+    return this.getCodec().encodeLong(((Number) object).longValue(), b, o);
+  }
+
+  @Override
+  public Object toObject(Object object, PDataType actualType) {
+    if (object == null) {
+      return null;
+    }
+    long s;
+    if (equalsAny(actualType, PLong.INSTANCE, PUnsignedLong.INSTANCE)) {
+      return object;
+    } else if (equalsAny(actualType, PUnsignedInt.INSTANCE,
+        PInteger.INSTANCE)) {
+      s = (Integer) object;
+      return s;
+    } else if (equalsAny(actualType, PTinyint.INSTANCE, PUnsignedTinyint.INSTANCE)) {
+      s = (Byte) object;
+      return s;
+    } else if (equalsAny(actualType, PSmallint.INSTANCE, PUnsignedSmallint.INSTANCE)) {
+      s = (Short) object;
+      return s;
+    } else if (equalsAny(actualType, PFloat.INSTANCE, PUnsignedFloat.INSTANCE)) {
+      Float f = (Float) object;
+      if (f > Long.MAX_VALUE || f < Long.MIN_VALUE) {
+        throw newIllegalDataException(
+            actualType + " value " + f + " cannot be cast to Long without changing its value");
+      }
+      s = f.longValue();
+      return s;
+    } else if (equalsAny(actualType, PDouble.INSTANCE, PUnsignedDouble.INSTANCE)) {
+      Double de = (Double) object;
+      if (de > Long.MAX_VALUE || de < Long.MIN_VALUE) {
+        throw newIllegalDataException(
+            actualType + " value " + de + " cannot be cast to Long without changing its value");
+      }
+      s = de.longValue();
+      return s;
+    } else if (actualType == PDecimal.INSTANCE) {
+      BigDecimal d = (BigDecimal) object;
+      return d.longValueExact();
+    } else if (equalsAny(actualType, PDate.INSTANCE, PUnsignedDate.INSTANCE, PTime.INSTANCE,
+        PUnsignedTime.INSTANCE)) {
+      java.util.Date date = (java.util.Date) object;
+      return date.getTime();
+    }
+    return throwConstraintViolationException(actualType, this);
+  }
+
+  @Override
+  public Long toObject(byte[] b, int o, int l, PDataType actualType, SortOrder sortOrder,
+      Integer maxLength, Integer scale) {
+    if (l == 0) {
+      return null;
+    }
+    if (equalsAny(actualType, PLong.INSTANCE, PUnsignedLong.INSTANCE,
+        PInteger.INSTANCE, PUnsignedInt.INSTANCE, PSmallint.INSTANCE,
+        PUnsignedSmallint.INSTANCE, PTinyint.INSTANCE, PUnsignedTinyint.INSTANCE, PFloat.INSTANCE,
+        PUnsignedFloat.INSTANCE, PDouble.INSTANCE, PUnsignedDouble.INSTANCE, PDate.INSTANCE,
+        PUnsignedDate.INSTANCE, PTime.INSTANCE, PUnsignedTime.INSTANCE)) {
+      return actualType.getCodec().decodeLong(b, o, sortOrder);
+    } else if (actualType == PDecimal.INSTANCE) {
+      BigDecimal bd = (BigDecimal) actualType.toObject(b, o, l, actualType, sortOrder);
+      return bd.longValueExact();
+    }
+    throwConstraintViolationException(actualType, this);
+    return null;
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType) {
+    // In general, don't allow conversion of LONG to INTEGER. There are times when
+    // we check isComparableTo for a more relaxed check and then throw a runtime
+    // exception if we overflow
+    return equalsAny(targetType, this, PDecimal.INSTANCE, PVarbinary.INSTANCE, PBinary.INSTANCE, PDouble.INSTANCE);
+  }
+
+  @Override
+  public boolean isComparableTo(PDataType targetType) {
+    return PDecimal.INSTANCE.isComparableTo(targetType);
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType, Object value) {
+    if (value != null) {
+      long l;
+      if (equalsAny(targetType, PUnsignedDouble.INSTANCE, PUnsignedFloat.INSTANCE,
+          PUnsignedLong.INSTANCE)) {
+        l = (Long) value;
+        return l >= 0;
+      } else if (targetType.equals(PUnsignedInt.INSTANCE)) {
+        l = (Long) value;
+        return (l >= 0 && l <= Integer.MAX_VALUE);
+      } else if (targetType.equals(PInteger.INSTANCE)) {
+        l = (Long) value;
+        return (l >= Integer.MIN_VALUE && l <= Integer.MAX_VALUE);
+      } else if (targetType.equals(PUnsignedSmallint.INSTANCE)) {
+        l = (Long) value;
+        return (l >= 0 && l <= Short.MAX_VALUE);
+      } else if (targetType.equals(PSmallint.INSTANCE)) {
+        l = (Long) value;
+        return (l >= Short.MIN_VALUE && l <= Short.MAX_VALUE);
+      } else if (targetType.equals(PTinyint.INSTANCE)) {
+        l = (Long) value;
+        return (l >= Byte.MIN_VALUE && l < Byte.MAX_VALUE);
+      } else if (targetType.equals(PUnsignedTinyint.INSTANCE)) {
+        l = (Long) value;
+        return (l >= 0 && l < Byte.MAX_VALUE);
+      }
+    }
+    return super.isCoercibleTo(targetType, value);
+  }
+
+  @Override
+  public boolean isCastableTo(PDataType targetType) {
+    return super.isCastableTo(targetType) || targetType.isCoercibleTo(PTimestamp.INSTANCE);
+  }
+
+  @Override
+  public boolean isFixedWidth() {
+    return true;
+  }
+
+  @Override
+  public Integer getByteSize() {
+    return Bytes.SIZEOF_LONG;
+  }
+
+  @Override
+  public Integer getMaxLength(Object o) {
+    return LONG_PRECISION;
+  }
+
+  @Override
+  public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+    if (rhsType == PDecimal.INSTANCE) {
+      return -((BigDecimal) rhs).compareTo(BigDecimal.valueOf(((Number) lhs).longValue()));
+    } else if (equalsAny(rhsType, PDouble.INSTANCE, PFloat.INSTANCE, PUnsignedDouble.INSTANCE, PUnsignedFloat.INSTANCE)) {
+      return Doubles.compare(((Number) lhs).doubleValue(), ((Number) rhs).doubleValue());
+    }
+    return Longs.compare(((Number) lhs).longValue(), ((Number) rhs).longValue());
+  }
+
+  @Override
+  public Object toObject(String value) {
+    if (value == null || value.length() == 0) {
+      return null;
+    }
+    try {
+      return Long.parseLong(value);
+    } catch (NumberFormatException e) {
+      throw newIllegalDataException(e);
+    }
+  }
+
+  @Override
+  public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+    return RANDOM.get().nextLong();
+  }
+
+  static class LongCodec extends BaseCodec {
+
+    @Override
+    public float decodeFloat(byte[] b, int o, SortOrder sortOrder) {
+      return decodeLong(b, o, sortOrder);
+    }
+
+    @Override
+    public double decodeDouble(byte[] b, int o, SortOrder sortOrder) {
+      return decodeLong(b, o, sortOrder);
+    }
+
+    @Override
+    public long decodeLong(byte[] bytes, int o, SortOrder sortOrder) {
+      Preconditions.checkNotNull(sortOrder);
+      checkForSufficientLength(bytes, o, Bytes.SIZEOF_LONG);
+      long v;
+      byte b = bytes[o];
+      if (sortOrder == SortOrder.ASC) {
+        v = b ^ 0x80; // Flip sign bit back
+        for (int i = 1; i < Bytes.SIZEOF_LONG; i++) {
+          b = bytes[o + i];
+          v = (v << 8) + (b & 0xff);
+        }
+      } else {
+        b = (byte) (b ^ 0xff);
+        v = b ^ 0x80; // Flip sign bit back
+        for (int i = 1; i < Bytes.SIZEOF_LONG; i++) {
+          b = bytes[o + i];
+          b ^= 0xff;
+          v = (v << 8) + (b & 0xff);
+        }
+      }
+      return v;
+    }
+
+    @Override
+    public int decodeInt(byte[] b, int o, SortOrder sortOrder) {
+      long v = decodeLong(b, o, sortOrder);
+      if (v < Integer.MIN_VALUE || v > Integer.MAX_VALUE) {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be cast to Integer without changing its value");
+      }
+      return (int) v;
+    }
+
+    @Override
+    public int encodeFloat(float v, byte[] b, int o) {
+      if (v < Long.MIN_VALUE || v > Long.MAX_VALUE) {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be encoded as an Long without changing its value");
+      }
+      return encodeLong((long) v, b, o);
+    }
+
+    @Override
+    public int encodeDouble(double v, byte[] b, int o) {
+      if (v < Long.MIN_VALUE || v > Long.MAX_VALUE) {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be encoded as an Long without changing its value");
+      }
+      return encodeLong((long) v, b, o);
+    }
+
+    @Override
+    public int encodeLong(long v, byte[] b, int o) {
+      checkForSufficientLength(b, o, Bytes.SIZEOF_LONG);
+      b[o + 0] = (byte) ((v >> 56) ^ 0x80); // Flip sign bit so that INTEGER is binary comparable
+      b[o + 1] = (byte) (v >> 48);
+      b[o + 2] = (byte) (v >> 40);
+      b[o + 3] = (byte) (v >> 32);
+      b[o + 4] = (byte) (v >> 24);
+      b[o + 5] = (byte) (v >> 16);
+      b[o + 6] = (byte) (v >> 8);
+      b[o + 7] = (byte) v;
+      return Bytes.SIZEOF_LONG;
+    }
+
+    @Override
+    public byte decodeByte(byte[] b, int o, SortOrder sortOrder) {
+      long v = decodeLong(b, o, sortOrder);
+      if (v < Byte.MIN_VALUE || v > Byte.MAX_VALUE) {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be cast to Byte without changing its value");
+      }
+      return (byte) v;
+    }
+
+    @Override
+    public short decodeShort(byte[] b, int o, SortOrder sortOrder) {
+      long v = decodeLong(b, o, sortOrder);
+      if (v < Short.MIN_VALUE || v > Short.MAX_VALUE) {
+        throw newIllegalDataException(
+            "Value " + v + " cannot be cast to Short without changing its value");
+      }
+      return (short) v;
+    }
+
+    @Override
+    public int encodeByte(byte v, byte[] b, int o) {
+      return encodeLong(v, b, o);
+    }
+
+    @Override
+    public int encodeShort(short v, byte[] b, int o) {
+      return encodeLong(v, b, o);
+    }
+
+    @Override
+    public PhoenixArrayFactory getPhoenixArrayFactory() {
+      return new PhoenixArrayFactory() {
+        @Override
+        public PhoenixArray newArray(PDataType type, Object[] elements) {
+          return new PhoenixArray.PrimitiveLongPhoenixArray(type, elements);
+        }
+      };
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/04ef859b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLongArray.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLongArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLongArray.java
new file mode 100644
index 0000000..0670792
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PLongArray.java
@@ -0,0 +1,109 @@
+/*
+ * 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;
+
+import java.sql.Types;
+
+public class PLongArray extends PArrayDataType<long[]> {
+
+  public static final PLongArray INSTANCE = new PLongArray();
+
+  private PLongArray() {
+    super("BIGINT ARRAY", PDataType.ARRAY_TYPE_BASE + PLong.INSTANCE.getSqlType(),
+        PhoenixArray.class, null, 30);
+  }
+
+  @Override
+  public boolean isArrayType() {
+    return true;
+  }
+
+  @Override
+  public boolean isFixedWidth() {
+    return false;
+  }
+
+  @Override
+  public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+    return compareTo(lhs, rhs);
+  }
+
+  @Override
+  public Integer getByteSize() {
+    return null;
+  }
+
+  @Override
+  public byte[] toBytes(Object object) {
+    return toBytes(object, SortOrder.ASC);
+  }
+
+  @Override
+  public byte[] toBytes(Object object, SortOrder sortOrder) {
+    return toBytes(object, PLong.INSTANCE, sortOrder);
+  }
+
+  @Override
+  public Object toObject(byte[] bytes, int offset, int length,
+      PDataType actualType, SortOrder sortOrder, Integer maxLength,
+      Integer scale) {
+    return toObject(bytes, offset, length, PLong.INSTANCE, sortOrder, maxLength, scale,
+        PLong.INSTANCE);
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType) {
+    return isCoercibleTo(targetType, this);
+  }
+
+  @Override
+  public boolean isCoercibleTo(PDataType targetType, Object value) {
+    if (value == null) {
+      return true;
+    }
+    PhoenixArray.PrimitiveLongPhoenixArray pArr = (PhoenixArray.PrimitiveLongPhoenixArray) value;
+    long[] longArr = (long[]) pArr.array;
+    for (long i : longArr) {
+      if (!super.isCoercibleTo(PLong.INSTANCE, i)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @Override
+  public int getResultSetSqlType() {
+    return Types.ARRAY;
+  }
+
+  @Override
+  public void coerceBytes(ImmutableBytesWritable ptr, Object object, PDataType actualType,
+      Integer maxLength, Integer scale, SortOrder actualModifer, Integer desiredMaxLength,
+      Integer desiredScale, SortOrder desiredModifier) {
+    coerceBytes(ptr, object, actualType, maxLength, scale, desiredMaxLength, desiredScale,
+        this, actualModifer, desiredModifier);
+  }
+
+  @Override
+  public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+    return getSampleValue(PLong.INSTANCE, arrayLength, maxLength);
+  }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/04ef859b/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
new file mode 100644
index 0000000..6ba631a
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PSmallint.java
@@ -0,0 +1,259 @@
+/*
+ * 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 com.google.common.base.Preconditions;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.schema.SortOrder;
+
+import java.math.BigDecimal;
+import java.sql.Types;
+
+public class PSmallint extends PDataType<Short> {
+
+  public static final PSmallint INSTANCE = new PSmallint();
+
+  private PSmallint() {
+    super("SMALLINT", Types.SMALLINT, Short.class, new ShortCodec(), 4);
+  }
+
+  @Override
+    public Integer getScale(Object o) {
+      return ZERO;
+    }
+
+    @Override
+    public int compareTo(Object lhs, Object rhs, PDataType rhsType) {
+      return PLong.INSTANCE.compareTo(lhs, rhs, rhsType);
+    }
+
+    @Override
+    public boolean isComparableTo(PDataType targetType) {
+      return PDecimal.INSTANCE.isComparableTo(targetType);
+    }
+
+    @Override
+    public boolean isFixedWidth() {
+      return true;
+    }
+
+    @Override
+    public Integer getByteSize() {
+      return Bytes.SIZEOF_SHORT;
+    }
+
+    @Override
+    public Integer getMaxLength(Object o) {
+      return SHORT_PRECISION;
+    }
+
+    @Override
+    public byte[] toBytes(Object object) {
+      byte[] b = new byte[Bytes.SIZEOF_SHORT];
+      toBytes(object, b, 0);
+      return b;
+    }
+
+    @Override
+    public int toBytes(Object object, byte[] bytes, int offset) {
+      if (object == null) {
+        throw newIllegalDataException(this + " may not be null");
+      }
+      return this.getCodec().encodeShort(((Number)object).shortValue(), bytes, offset);
+    }
+
+    @Override
+    public Object toObject(Object object, PDataType actualType) {
+      Object o = PLong.INSTANCE.toObject(object, actualType);
+      if (!(o instanceof Long) || o == null) {
+        return o;
+      }
+      long l = (Long)o;
+      if (l < Short.MIN_VALUE || l > Short.MAX_VALUE) {
+        throw newIllegalDataException(actualType + " value " + l + " cannot be cast to Short without changing its value");
+      }
+      short s = (short)l;
+      return s;
+    }
+
+    @Override
+    public Short toObject(byte[] b, int o, int l, PDataType actualType, SortOrder sortOrder, Integer maxLength, Integer scale) {
+      if (l == 0) {
+        return null;
+      }
+      if (equalsAny(actualType, PSmallint.INSTANCE, PUnsignedSmallint.INSTANCE, PTinyint.INSTANCE,
+          PUnsignedTinyint.INSTANCE, PLong.INSTANCE, PUnsignedLong.INSTANCE, PInteger.INSTANCE,
+          PUnsignedInt.INSTANCE, PFloat.INSTANCE, PUnsignedFloat.INSTANCE, PDouble.INSTANCE,
+          PUnsignedDouble.INSTANCE)) {
+        return actualType.getCodec().decodeShort(b, o, sortOrder);
+      } else if (actualType == PDecimal.INSTANCE) {
+        BigDecimal bd = (BigDecimal)actualType.toObject(b, o, l, actualType, sortOrder);
+        return bd.shortValueExact();
+      }
+      throwConstraintViolationException(actualType,this);
+      return null;
+    }
+
+    @Override
+    public Object toObject(String value) {
+      if (value == null || value.length() == 0) {
+        return null;
+      }
+      try {
+        return Short.parseShort(value);
+      } catch (NumberFormatException e) {
+        throw newIllegalDataException(e);
+      }
+    }
+
+    @Override
+    public boolean isCoercibleTo(PDataType targetType, Object value) {
+      if (value != null) {
+        short i;
+        if (equalsAny(targetType, PUnsignedDouble.INSTANCE, PUnsignedFloat.INSTANCE,
+            PUnsignedLong.INSTANCE, PUnsignedInt.INSTANCE, PUnsignedSmallint.INSTANCE)) {
+          i = (Short) value;
+          return i >= 0;
+        } else if (targetType == PUnsignedTinyint.INSTANCE) {
+          i = (Short) value;
+          return (i >= 0 && i <= Byte.MAX_VALUE);
+        } else if (targetType == PTinyint.INSTANCE) {
+          i = (Short) value;
+          return (i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE);
+        }
+      }
+      return super.isCoercibleTo(targetType, value);
+    }
+
+    @Override
+    public boolean isCoercibleTo(PDataType targetType) {
+      return this.equals(targetType) || PInteger.INSTANCE.isCoercibleTo(targetType);
+    }
+
+    @Override
+    public Object getSampleValue(Integer maxLength, Integer arrayLength) {
+      return ((Integer) PInteger.INSTANCE.getSampleValue(maxLength, arrayLength)).shortValue();
+    }
+
+  static class ShortCodec extends BaseCodec {
+
+      @Override
+      public long decodeLong(byte[] b, int o, SortOrder sortOrder) {
+        return decodeShort(b, o, sortOrder);
+      }
+
+      @Override
+      public int decodeInt(byte[] b, int o, SortOrder sortOrder) {
+        return decodeShort(b, o, sortOrder);
+      }
+
+      @Override
+      public byte decodeByte(byte[] b, int o, SortOrder sortOrder) {
+        short v = decodeShort(b, o, sortOrder);
+        if (v < Byte.MIN_VALUE || v > Byte.MAX_VALUE) {
+            throw newIllegalDataException("Value " + v + " cannot be cast to Byte without changing its value");
+        }
+        return (byte)v;
+      }
+
+      @Override
+      public short decodeShort(byte[] b, int o, SortOrder sortOrder) {
+    	Preconditions.checkNotNull(sortOrder);
+        checkForSufficientLength(b, o, Bytes.SIZEOF_SHORT);
+        int v;
+        if (sortOrder == SortOrder.ASC) {
+            v = b[o] ^ 0x80; // Flip sign bit back
+            for (int i = 1; i < Bytes.SIZEOF_SHORT; i++) {
+                v = (v << 8) + (b[o + i] & 0xff);
+            }
+        } else {
+            v = b[o] ^ 0xff ^ 0x80; // Flip sign bit back
+            for (int i = 1; i < Bytes.SIZEOF_SHORT; i++) {
+                v = (v << 8) + ((b[o + i] ^ 0xff) & 0xff);
+            }
+        }
+        return (short)v;
+      }
+
+      @Override
+      public int encodeShort(short v, byte[] b, int o) {
+          checkForSufficientLength(b, o, Bytes.SIZEOF_SHORT);
+          b[o + 0] = (byte) ((v >> 8) ^ 0x80); // Flip sign bit so that Short is binary comparable
+          b[o + 1] = (byte) v;
+          return Bytes.SIZEOF_SHORT;
+      }
+
+      @Override
+      public int encodeLong(long v, byte[] b, int o) {
+          if (v < Short.MIN_VALUE || v > Short.MAX_VALUE) {
+              throw newIllegalDataException("Value " + v + " cannot be encoded as an Short without changing its value");
+          }
+          return encodeShort((short)v,b,o);
+      }
+
+      @Override
+      public int encodeInt(int v, byte[] b, int o) {
+        if (v < Short.MIN_VALUE || v > Short.MAX_VALUE) {
+          throw newIllegalDataException("Value " + v + " cannot be encoded as an Short without changing its value");
+        }
+        return encodeShort((short)v,b,o);
+      }
+
+      @Override
+      public int encodeByte(byte v, byte[] b, int o) {
+        return encodeShort(v,b,o);
+      }
+
+      @Override
+      public float decodeFloat(byte[] b, int o, SortOrder sortOrder) {
+          return decodeShort(b, o, sortOrder);
+      }
+
+      @Override
+      public double decodeDouble(byte[] b, int o,
+              SortOrder sortOrder) {
+          return decodeShort(b, o, sortOrder);
+      }
+
+      @Override
+      public int encodeDouble(double v, byte[] b, int o) {
+          if (v < Short.MIN_VALUE || v > Short.MAX_VALUE) {
+              throw newIllegalDataException("Value " + v + " cannot be encoded as an Short without changing its value");
+          }
+          return encodeShort((short)v,b,o);
+      }
+
+      @Override
+      public int encodeFloat(float v, byte[] b, int o) {
+          if (v < Short.MIN_VALUE || v > Short.MAX_VALUE) {
+              throw newIllegalDataException("Value " + v + " cannot be encoded as an Short without changing its value");
+          }
+          return encodeShort((short)v,b,o);
+      }
+
+      @Override
+      public PhoenixArrayFactory getPhoenixArrayFactory() {
+          return new PhoenixArrayFactory() {
+              @Override
+              public PhoenixArray newArray(PDataType type, Object[] elements) {
+                  return new PhoenixArray.PrimitiveShortPhoenixArray(type, elements);
+              }
+          };
+      }
+    }
+}


Mime
View raw message