PHOENIX-777 - Support null value for fixed length ARRAY (Dumindu Buddhika)

Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/6f890ade
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/6f890ade
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/6f890ade

Branch: refs/heads/4.x-HBase-1.1
Commit: 6f890ade0691d03469ff8fce81c2fa9edd6941af
Parents: 9c5f111
Author: ramkrishna <ramkrishna.s.vasude...@gmail.com>
Authored: Tue Jun 2 11:18:51 2015 +0530
Committer: ramkrishna <ramkrishna.s.vasude...@gmail.com>
Committed: Tue Jun 2 11:18:51 2015 +0530

----------------------------------------------------------------------
 .../phoenix/end2end/ArraysWithNullsIT.java      | 300 +++++++++++++++++++
 .../phoenix/compile/ExpressionCompiler.java     |   9 +-
 .../apache/phoenix/schema/types/PBinary.java    |   2 +-
 .../org/apache/phoenix/schema/types/PChar.java  |   5 +-
 .../org/apache/phoenix/schema/types/PDate.java  |   6 +-
 .../apache/phoenix/schema/types/PDecimal.java   |   3 +
 .../apache/phoenix/schema/types/PTimestamp.java |  17 +-
 .../phoenix/schema/types/PhoenixArray.java      |  51 ++--
 8 files changed, 358 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/6f890ade/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArraysWithNullsIT.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArraysWithNullsIT.java 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArraysWithNullsIT.java
new file mode 100644
index 0000000..b034193
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArraysWithNullsIT.java
@@ -0,0 +1,300 @@
+/*
+ * 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.end2end;
+
+import static org.junit.Assert.assertEquals;
+
+import java.sql.*;
+
+import org.apache.phoenix.schema.types.PTimestamp;
+import org.apache.phoenix.schema.types.PhoenixArray;
+import org.junit.Test;
+
+public class ArraysWithNullsIT extends BaseClientManagedTimeIT {
+
+    @Test
+    public void testArrayUpsertIntWithNulls() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.createStatement().execute("CREATE TABLE t1 ( k VARCHAR PRIMARY 
KEY, a INTEGER[])");
+
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO t1 
VALUES('a',ARRAY[null,3,null])");
+        stmt.execute();
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("Select a from t1 
where k = 'a'");
+        rs.next();
+        Array array = conn.createArrayOf("INTEGER",new Object[]{null,3,null});
+
+        assertEquals(rs.getArray(1),array);
+        conn.close();
+
+    }
+
+
+
+    @Test
+    public void testArrayUpsertVarcharWithNulls() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.createStatement().execute("CREATE TABLE t2 ( k VARCHAR PRIMARY 
KEY, a VARCHAR[])");
+
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO t2 
VALUES('a',ARRAY['10',null])");
+        stmt.execute();
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("Select a from t2 
where k = 'a'");
+        rs.next();
+        Array array = conn.createArrayOf("VARCHAR",new Object[]{"10",null});
+
+        assertEquals(rs.getArray(1),array);
+        conn.close();
+
+    }
+
+    @Test
+    public void testArrayUpsertBigIntWithNulls() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.createStatement().execute("CREATE TABLE t3 ( k VARCHAR PRIMARY 
KEY, a BIGINT[])");
+
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO t3 
VALUES('a',ARRAY[2,null,32335,4])");
+        stmt.execute();
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("Select a from t3 
where k = 'a'");
+        rs.next();
+        Array array = conn.createArrayOf("BIGINT",new 
Object[]{(long)2,null,(long)32335,(long)4});
+
+        assertEquals(rs.getArray(1),array);
+        conn.close();
+
+    }
+
+    @Test
+    public void testArrayUpsertFloatWithNulls() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.createStatement().execute("CREATE TABLE t4 ( k VARCHAR PRIMARY 
KEY, a FLOAT[])");
+
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO t4 
VALUES('a',ARRAY[1.1,2.2,null,3.4])");
+        stmt.execute();
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("Select a from t4 
where k = 'a'");
+        rs.next();
+        Array array = conn.createArrayOf("FLOAT",new 
Object[]{(float)1.1,(float)2.2,null,(float)3.4});
+
+        assertEquals(rs.getArray(1),array);
+        conn.close();
+
+    }
+
+    @Test
+    public void testArrayUpsertSmallIntWithNulls() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.createStatement().execute("CREATE TABLE t5 ( k VARCHAR PRIMARY 
KEY, a SMALLINT[])");
+
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO t5 
VALUES('a',ARRAY[123,456,null,456])");
+        stmt.execute();
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("Select a from t5 
where k = 'a'");
+        rs.next();
+        Array array = conn.createArrayOf("SMALLINT",new 
Object[]{(short)123,(short)456,null,(short)456});
+
+        assertEquals(rs.getArray(1),array);
+        conn.close();
+
+    }
+
+    @Test
+    public void testArrayUpsertTinyIntWithNulls() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.createStatement().execute("CREATE TABLE t6 ( k VARCHAR PRIMARY 
KEY, a TINYINT[])");
+
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO t6 
VALUES('a',ARRAY[123,45,null,45])");
+        stmt.execute();
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("Select a from t6 
where k = 'a'");
+        rs.next();
+        Array array = conn.createArrayOf("TINYINT",new 
Object[]{(byte)123,(byte)45,null,(byte)45});
+
+        assertEquals(rs.getArray(1),array);
+        conn.close();
+
+    }
+
+    @Test
+    public void testArrayUpsertBooleanWithNulls() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.createStatement().execute("CREATE TABLE t7 ( k VARCHAR PRIMARY 
KEY, a BOOLEAN[])");
+
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO t7 
VALUES('a',ARRAY[true,false,null,true])");
+        stmt.execute();
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("Select a from t7 
where k = 'a'");
+        rs.next();
+        Array array = conn.createArrayOf("BOOLEAN",new 
Object[]{true,false,null,true});
+
+        assertEquals(rs.getArray(1),array);
+        conn.close();
+
+    }
+
+    @Test
+    public void testArrayUpsertDoubleWithNulls() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.createStatement().execute("CREATE TABLE t8 ( k VARCHAR PRIMARY 
KEY, a DOUBLE[])");
+
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO t8 
VALUES('a',ARRAY[1.2,2.3,null,3.4])");
+        stmt.execute();
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("Select a from t8 
where k = 'a'");
+        rs.next();
+        Array array = conn.createArrayOf("DOUBLE",new 
Object[]{1.2,2.3,null,3.4});
+
+        assertEquals(rs.getArray(1),array);
+        conn.close();
+
+    }
+
+    @Test
+    public void testArrayUpsertDateWithNulls1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.createStatement().execute("CREATE TABLE t9 ( k VARCHAR PRIMARY 
KEY, a DATE[])");
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO t9 
VALUES('a',ARRAY[TO_DATE('2015-05-20 06:12:14.184'),null,TO_DATE('2015-05-20 
06:12:14.184'),null])");
+        stmt.execute();
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("Select a from t9 
where k = 'a'");
+        rs.next();
+        Array array = conn.createArrayOf("DATE",new Date[]{new 
Date(1432102334184l),new Date(0l),new Date(1432102334184l),new Date(0l)});
+
+        assertEquals(rs.getArray(1),array);
+        conn.close();
+    }
+
+    @Test
+    public void testArrayUpsertDateWithNulls2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.createStatement().execute("CREATE TABLE t10 ( k VARCHAR PRIMARY 
KEY, a DATE[])");
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO t10 
VALUES('a',ARRAY[TO_DATE('1970-01-01 00:00:00.000'), TO_DATE('2015-05-20 
06:12:14.184'),TO_DATE('2015-05-20 06:12:14.184')])");
+        stmt.execute();
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("Select a from t10 
where k = 'a'");
+        rs.next();
+        Array array = conn.createArrayOf("DATE",new Date[]{new Date(0l), new 
Date(1432102334184l), new Date(1432102334184l)});
+
+        assertEquals(rs.getArray(1),array);
+        conn.close();
+    }
+
+    @Test
+    public void testArrayUpsertTimeWithNulls1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.createStatement().execute("CREATE TABLE t11 ( k VARCHAR PRIMARY 
KEY, a TIME[])");
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO t11 
VALUES('a',ARRAY[TO_TIME('2015-05-20 06:12:14.184'),null,TO_TIME('2015-05-20 
06:12:14.184'),null])");
+        stmt.execute();
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("Select a from t11 
where k = 'a'");
+        rs.next();
+        Array array = conn.createArrayOf("TIME",new Time[]{new 
Time(1432102334184l),new Time(0l),new Time(1432102334184l),new Time(0l)});
+
+        assertEquals(rs.getArray(1),array);
+        conn.close();
+    }
+
+    @Test
+    public void testArrayUpsertTimeWithNulls2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.createStatement().execute("CREATE TABLE t12 ( k VARCHAR PRIMARY 
KEY, a TIME[])");
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO t12 
VALUES('a',ARRAY[TO_TIME('1970-01-01 00:00:00.000'), TO_TIME('2015-05-20 
06:12:14.184'),null,TO_TIME('2015-05-20 06:12:14.184'),null])");
+        stmt.execute();
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("Select a from t12 
where k = 'a'");
+        rs.next();
+        Array array = conn.createArrayOf("TIME",new Time[]{new Time(0l),new 
Time(1432102334184l),new Time(0l),new Time(1432102334184l),new Time(0l)});
+
+        assertEquals(rs.getArray(1),array);
+        conn.close();
+    }
+
+    @Test
+    public void testArrayUpsertTimeStampWithNulls1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.createStatement().execute("CREATE TABLE t13 ( k VARCHAR PRIMARY 
KEY, a TIMESTAMP[])");
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO t13 
VALUES('a',ARRAY[TO_TIMESTAMP('2015-05-20 
06:12:14.184'),null,TO_TIMESTAMP('2015-05-20 
06:12:14.184'),TO_TIMESTAMP('1970-01-01 00:00:00.000')])");
+        stmt.execute();
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("Select a from t13 
where k = 'a'");
+        rs.next();
+
+        assertEquals(rs.getArray(1),conn.createArrayOf("TIMESTAMP",new 
Timestamp[]{new Timestamp(1432102334184l),new Timestamp(0l),new 
Timestamp(1432102334184l),new Timestamp(0l)}));
+        conn.close();
+    }
+
+    @Test
+    public void testArrayUpsertTimeStampWithNulls2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.createStatement().execute("CREATE TABLE t14 ( k VARCHAR PRIMARY 
KEY, a TIMESTAMP[])");
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO t14 
VALUES('a',ARRAY[TO_TIMESTAMP('1970-01-01 
00:00:00.000'),TO_TIMESTAMP('2015-05-20 06:12:14.184'),TO_TIMESTAMP('1970-01-01 
00:00:00.000'),TO_TIMESTAMP('2015-05-20 06:12:14.184'),TO_TIMESTAMP('1970-01-01 
00:00:00.000')])");
+        stmt.execute();
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("Select a from t14 
where k = 'a'");
+        rs.next();
+
+        assertEquals(rs.getArray(1),conn.createArrayOf("TIMESTAMP",new 
Timestamp[]{new Timestamp(0l),new Timestamp(1432102334184l),new 
Timestamp(0l),new Timestamp(1432102334184l),new Timestamp(0l)}));
+        conn.close();
+    }
+
+    @Test
+    public void testArrayUpsertCharWithNulls1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.createStatement().execute("CREATE TABLE t15 ( k VARCHAR PRIMARY 
KEY, a CHAR(15)[])");
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO t15 
VALUES('a',ARRAY['foo',null,'fo','foo'])");
+        stmt.execute();
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("Select a from t15 
where k = 'a'");
+        rs.next();
+
+        assertEquals(rs.getArray(1),conn.createArrayOf("CHAR",new 
String[]{"foo","","fo","foo"}));
+        conn.close();
+    }
+
+    @Test
+    public void testArrayUpsertCharWithNulls2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        conn.createStatement().execute("CREATE TABLE t16 ( k VARCHAR PRIMARY 
KEY, a CHAR(15)[])");
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO t16 
VALUES('a',ARRAY[null,'foo',null,'fo','foo'])");
+        stmt.execute();
+        conn.commit();
+
+        ResultSet rs = conn.createStatement().executeQuery("Select a from t16 
where k = 'a'");
+        rs.next();
+
+        assertEquals(rs.getArray(1),conn.createArrayOf("CHAR",new 
String[]{"","foo","","fo","foo"}));
+        conn.close();
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/6f890ade/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java 
b/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
index 66c1b85..39baf7a 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
@@ -1271,8 +1271,13 @@ public class ExpressionCompiler extends 
UnsupportedAllParseNodeVisitor<Expressio
             for (int i = 0; i < children.size(); i++) {
                 Expression child = children.get(i);
                 child.evaluate(null, ptr);
-                Object value = arrayElemDataType.toObject(ptr, 
child.getDataType(), child.getSortOrder());
-                elements[i] = LiteralExpression.newConstant(value, 
child.getDataType(), child.getDeterminism()).getValue();
+                Object value = null;
+                if (child.getDataType() == null) {
+                    value = arrayElemDataType.toObject(ptr, 
theArrayElemDataType, child.getSortOrder());
+                } else {
+                    value = arrayElemDataType.toObject(ptr, 
child.getDataType(), child.getSortOrder());
+                }
+                elements[i] = LiteralExpression.newConstant(value, 
theArrayElemDataType, child.getDeterminism()).getValue();
             }
             Object value = 
PArrayDataType.instantiatePhoenixArray(arrayElemDataType, elements);
             return LiteralExpression.newConstant(value,

http://git-wip-us.apache.org/repos/asf/phoenix/blob/6f890ade/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinary.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinary.java 
b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinary.java
index d6d07fd..b397554 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinary.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinary.java
@@ -48,7 +48,7 @@ public class PBinary extends PDataType<byte[]> {
   public Object pad(Object object, Integer maxLength) {
     byte[] b = (byte[]) object;
     if (b == null) {
-      return null;
+      return new byte[maxLength];
     }
     if (b.length == maxLength) {
       return object;

http://git-wip-us.apache.org/repos/asf/phoenix/blob/6f890ade/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PChar.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PChar.java 
b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PChar.java
index 2effc38..c4d482c 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PChar.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PChar.java
@@ -25,6 +25,7 @@ import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.phoenix.exception.DataExceedsCapacityException;
 import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.util.ByteUtil;
 import org.apache.phoenix.util.StringUtil;
 
 import com.google.common.base.Strings;
@@ -55,7 +56,7 @@ public class PChar extends PDataType<String> {
     public Object pad(Object object, Integer maxLength) {
       String s = (String) object;
       if (s == null) {
-        return s;
+        return Strings.padEnd("", maxLength, ' ');
       }
       if (s.length() == maxLength) {
         return object;
@@ -69,7 +70,7 @@ public class PChar extends PDataType<String> {
     @Override
     public byte[] toBytes(Object object) {
       if (object == null) {
-        throw newIllegalDataException(this + " may not be null");
+        return ByteUtil.EMPTY_BYTE_ARRAY;
       }
       byte[] b = PVarchar.INSTANCE.toBytes(object);
       if (b.length != ((String) object).length()) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/6f890ade/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDate.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDate.java 
b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDate.java
index 947c30e..b10b1ac 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDate.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDate.java
@@ -39,9 +39,6 @@ public class PDate extends PDataType<Date> {
 
   @Override
   public byte[] toBytes(Object object) {
-    if (object == null) {
-      throw newIllegalDataException(this + " may not be null");
-    }
     byte[] bytes = new byte[getByteSize()];
     toBytes(object, bytes, 0);
     return bytes;
@@ -50,7 +47,8 @@ public class PDate extends PDataType<Date> {
   @Override
   public int toBytes(Object object, byte[] bytes, int offset) {
     if (object == null) {
-      throw newIllegalDataException(this + " may not be null");
+        getCodec().encodeLong(0l, bytes, offset);
+        return this.getByteSize();
     }
     getCodec().encodeLong(((java.util.Date) object).getTime(), bytes, offset);
     return this.getByteSize();

http://git-wip-us.apache.org/repos/asf/phoenix/blob/6f890ade/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 656113c..199ed28 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
@@ -393,6 +393,9 @@ public class PDecimal extends PRealNumber<BigDecimal> {
   @Override
   public String toStringLiteral(Object o, Format formatter) {
       if (formatter == null) {
+          if(o == null) {
+              return String.valueOf(o);
+          }
           return ((BigDecimal)o).toPlainString();
         }
         return super.toStringLiteral(o, formatter);

http://git-wip-us.apache.org/repos/asf/phoenix/blob/6f890ade/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTimestamp.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTimestamp.java 
b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTimestamp.java
index 9a82cc0..d396adc 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTimestamp.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PTimestamp.java
@@ -39,9 +39,6 @@ public class PTimestamp extends PDataType<Timestamp> {
 
   @Override
   public byte[] toBytes(Object object) {
-    if (object == null) {
-      throw newIllegalDataException(this + " may not be null");
-    }
     byte[] bytes = new byte[getByteSize()];
     toBytes(object, bytes, 0);
     return bytes;
@@ -50,16 +47,18 @@ public class PTimestamp extends PDataType<Timestamp> {
   @Override
   public int toBytes(Object object, byte[] bytes, int offset) {
     if (object == null) {
-      throw newIllegalDataException(this + " may not be null");
+      PDate.INSTANCE.getCodec().encodeLong(0l, bytes, offset);
+      Bytes.putInt(bytes, offset + Bytes.SIZEOF_LONG, 0);
+      return getByteSize();
     }
     java.sql.Timestamp value = (java.sql.Timestamp) object;
     PDate.INSTANCE.getCodec().encodeLong(value.getTime(), bytes, offset);
 
-            /*
-             * By not getting the stuff that got spilled over from the millis 
part,
-             * it leaves the timestamp's byte representation saner - 8 bytes 
of millis | 4 bytes of nanos.
-             * Also, it enables timestamp bytes to be directly compared with 
date/time bytes.
-             */
+    /*
+     * By not getting the stuff that got spilled over from the millis part,
+     * it leaves the timestamp's byte representation saner - 8 bytes of millis 
| 4 bytes of nanos.
+     * Also, it enables timestamp bytes to be directly compared with date/time 
bytes.
+     */
     Bytes.putInt(bytes, offset + Bytes.SIZEOF_LONG, value.getNanos() % 
1000000);
     return getByteSize();
   }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/6f890ade/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PhoenixArray.java
----------------------------------------------------------------------
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PhoenixArray.java 
b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PhoenixArray.java
index 9ffac83..843c831 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PhoenixArray.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PhoenixArray.java
@@ -23,6 +23,7 @@ import java.sql.SQLException;
 import java.util.Arrays;
 import java.util.Map;
 
+import com.google.common.base.Strings;
 import org.apache.phoenix.util.SQLCloseable;
 
 /**
@@ -54,11 +55,15 @@ public class PhoenixArray implements Array,SQLCloseable {
        private static Object[] coerceToNewLength(PDataType baseType, Object[] 
elements, int maxLength) {
         Object[] resizedElements = new Object[elements.length];
         for (int i = 0; i < elements.length; i++) {
-            int length = baseType.getMaxLength(elements[i]);
-            if (length == maxLength) {
-                resizedElements[i] = elements[i];
+            Integer length = baseType.getMaxLength(elements[i]);
+            if (length != null) {
+                if (length == maxLength) {
+                    resizedElements[i] = elements[i];
+                } else {
+                    resizedElements[i] = baseType.pad(elements[i], maxLength);
+                }
             } else {
-                resizedElements[i] = baseType.pad(elements[i],maxLength);
+                resizedElements[i] = baseType.pad(elements[i], maxLength);
             }
         }
         return resizedElements;
@@ -67,18 +72,25 @@ public class PhoenixArray implements Array,SQLCloseable {
            if (elements == null || elements.length == 0) {
                return elements;
            }
-           Object element = elements[0];
-           int maxLength = baseType.getMaxLength(element);
-           boolean resizeElements = false;
-           for (int i = 1; i < elements.length; i++) {
-               int length = baseType.getMaxLength(elements[i]);
-               if (length > maxLength) {
-                   maxLength = length;
-                   resizeElements = true;
-               } else if (length < maxLength) {
-                   resizeElements = true;
-               }
-           }
+        int maxLength = 0;
+        boolean resizeElements = false;
+        for (int i = 0; i < elements.length; i++) {
+            Integer length = baseType.getMaxLength(elements[i]);
+            if (length != null) {
+                if (maxLength == 0){
+                    maxLength = length;
+                    continue;
+                }
+                if (length > maxLength) {
+                    maxLength = length;
+                    resizeElements = true;
+                } else if (length < maxLength) {
+                    resizeElements = true;
+                }
+            } else {
+                resizeElements = true;
+            }
+        }
            if (!resizeElements) {
                return elements;
            }
@@ -92,7 +104,12 @@ public class PhoenixArray implements Array,SQLCloseable {
                    if (baseType.getByteSize() == null) {
                    elements = coerceToEqualLength(baseType, elements);
                    if (elements != null && elements.length > 0) {
-                       this.maxLength = baseType.getMaxLength(elements[0]);
+                    for(int i = 0; i < elements.length; i++) {
+                        if(elements[i] != null) {
+                            maxLength = baseType.getMaxLength(elements[i]);
+                            break;
+                        }
+                    }
                    }
                    } else {
                        maxLength = baseType.getByteSize();

Reply via email to