You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ra...@apache.org on 2015/12/09 05:19:16 UTC

[42/44] phoenix git commit: PHOENIX-1875 implement ARRAY_PREPEND built in function (Dumindu)

PHOENIX-1875 implement ARRAY_PREPEND built in function (Dumindu)


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

Branch: refs/heads/4.x-HBase-1.1
Commit: 7b448cc24c48f695836c72a2dd08c7454ae928bc
Parents: 13ddda2
Author: ramkrishna <ra...@gmail.com>
Authored: Wed May 13 10:46:19 2015 +0530
Committer: ramkrishna <ra...@gmail.com>
Committed: Wed Jul 1 09:50:26 2015 +0530

----------------------------------------------------------------------
 .../phoenix/end2end/ArrayPrependFunctionIT.java | 652 +++++++++++++++++++
 .../phoenix/expression/ExpressionType.java      |   4 +-
 .../function/ArrayAppendFunction.java           |  35 +-
 .../function/ArrayModifierFunction.java         |  75 +++
 .../function/ArrayPrependFunction.java          |  96 +++
 .../phoenix/schema/types/PArrayDataType.java    | 161 ++++-
 .../expression/ArrayPrependFunctionTest.java    | 552 ++++++++++++++++
 7 files changed, 1541 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/7b448cc2/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayPrependFunctionIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayPrependFunctionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayPrependFunctionIT.java
new file mode 100644
index 0000000..3145d95
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayPrependFunctionIT.java
@@ -0,0 +1,652 @@
+/*
+ * 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.assertFalse;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.*;
+
+import org.apache.phoenix.schema.TypeMismatchException;
+import org.apache.phoenix.schema.types.PhoenixArray;
+import org.junit.Test;
+
+public class ArrayPrependFunctionIT extends BaseHBaseManagedTimeIT {
+
+    private void initTableWithVarArray(Connection conn, String type, Object[] objectArray, String value) throws SQLException {
+        conn.createStatement().execute("CREATE TABLE t ( k VARCHAR PRIMARY KEY, a " + type + "[],b " + type + ")");
+        conn.commit();
+        PreparedStatement stmt = conn.prepareStatement("UPSERT INTO t VALUES(?,?," + value + ")");
+        PhoenixArray array = (PhoenixArray) conn.createArrayOf(type, objectArray);
+        stmt.setString(1, "a");
+        stmt.setArray(2, array);
+        stmt.execute();
+        conn.commit();
+
+    }
+
+    private void initTables(Connection conn) throws Exception {
+        String ddl = "CREATE TABLE regions (region_name VARCHAR PRIMARY KEY,varchars VARCHAR[],integers INTEGER[],doubles DOUBLE[],bigints BIGINT[],chars CHAR(15)[],double1 DOUBLE,char1 CHAR(17),nullcheck INTEGER,chars2 CHAR(15)[])";
+        conn.createStatement().execute(ddl);
+        String dml = "UPSERT INTO regions(region_name,varchars,integers,doubles,bigints,chars,double1,char1,nullcheck,chars2) VALUES('SF Bay Area'," +
+                "ARRAY['2345','46345','23234']," +
+                "ARRAY[2345,46345,23234,456]," +
+                "ARRAY[23.45,46.345,23.234,45.6,5.78]," +
+                "ARRAY[12,34,56,78,910]," +
+                "ARRAY['a','bbbb','c','ddd','e']," +
+                "23.45," +
+                "'wert'," +
+                "NULL," +
+                "ARRAY['foo','a','bbbb','c','ddd','e']" +
+                ")";
+        PreparedStatement stmt = conn.prepareStatement(dml);
+        stmt.execute();
+        conn.commit();
+    }
+
+    private void initTablesDesc(Connection conn, String type, String val) throws Exception {
+        String ddl = "CREATE TABLE regions (pk " + type + " PRIMARY KEY DESC,varchars VARCHAR[],integers INTEGER[],doubles DOUBLE[],bigints BIGINT[],chars CHAR(15)[],chars2 CHAR(15)[], bools BOOLEAN[])";
+        conn.createStatement().execute(ddl);
+        String dml = "UPSERT INTO regions(pk,varchars,integers,doubles,bigints,chars,chars2,bools) VALUES(" + val + "," +
+                "ARRAY['2345','46345','23234']," +
+                "ARRAY[2345,46345,23234,456]," +
+                "ARRAY[23.45,46.345,23.234,45.6,5.78]," +
+                "ARRAY[12,34,56,78,910]," +
+                "ARRAY['a','bbbb','c','ddd','e']," +
+                "ARRAY['a','bbbb','c','ddd','e','foo']," +
+                "ARRAY[true,false]" +
+                ")";
+        PreparedStatement stmt = conn.prepareStatement(dml);
+        stmt.execute();
+        conn.commit();
+    }
+
+    @Test
+    public void testArrayPrependFunctionInteger() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(1234,integers) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        Integer[] integers = new Integer[]{1234, 2345, 46345, 23234, 456};
+
+        Array array = conn.createArrayOf("INTEGER", integers);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionVarchar() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND('34567',varchars) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String[] strings = new String[]{"34567", "2345", "46345", "23234"};
+
+        Array array = conn.createArrayOf("VARCHAR", strings);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionNulls1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        String[] s = new String[]{null, null, "1", "2"};
+        initTableWithVarArray(conn, "VARCHAR", s, null);
+        String[] s2 = new String[]{null, null, null, "1", "2"};
+        PhoenixArray array2 = (PhoenixArray) conn.createArrayOf("VARCHAR", s2);
+        conn = DriverManager.getConnection(getUrl());
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(b,a) FROM t WHERE k = 'a'");
+        assertTrue(rs.next());
+        assertEquals(array2, rs.getArray(1));
+    }
+
+    @Test
+    public void testArrayPrependFunctionNulls2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        String[] s = new String[]{"1", "2"};
+        initTableWithVarArray(conn, "VARCHAR", s, null);
+        String[] s2 = new String[]{null, "1", "2"};
+        PhoenixArray array2 = (PhoenixArray) conn.createArrayOf("VARCHAR", s2);
+        conn = DriverManager.getConnection(getUrl());
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(b,a) FROM t WHERE k = 'a'");
+        assertTrue(rs.next());
+        assertEquals(array2, rs.getArray(1));
+    }
+
+    @Test
+    public void testArrayPrependFunctionNulls3() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        String[] s = new String[]{"176", null, "212"};
+        initTableWithVarArray(conn, "VARCHAR", s, null);
+        String[] s2 = new String[]{null, "176", null, "212"};
+        PhoenixArray array2 = (PhoenixArray) conn.createArrayOf("VARCHAR", s2);
+        conn = DriverManager.getConnection(getUrl());
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(b,a) FROM t WHERE k = 'a'");
+        assertTrue(rs.next());
+        assertEquals(array2, rs.getArray(1));
+    }
+
+    @Test
+    public void testArrayPrependFunctionNulls4() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        String[] s = new String[]{"176", null, "212"};
+        initTableWithVarArray(conn, "VARCHAR", s, "'foo'");
+        String[] s2 = new String[]{"foo", "176", null, "212"};
+        PhoenixArray array2 = (PhoenixArray) conn.createArrayOf("VARCHAR", s2);
+        conn = DriverManager.getConnection(getUrl());
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(b,a) FROM t WHERE k = 'a'");
+        assertTrue(rs.next());
+        assertEquals(array2, rs.getArray(1));
+    }
+
+    @Test
+    public void testArrayPrependFunctionDouble() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(double1,doubles) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        Double[] doubles = new Double[]{23.45, 23.45, 46.345, 23.234, 45.6, 5.78};
+
+        Array array = conn.createArrayOf("DOUBLE", doubles);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionDouble2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(23,doubles) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        Double[] doubles = new Double[]{new Double(23), 23.45, 46.345, 23.234, 45.6, 5.78};
+
+        Array array = conn.createArrayOf("DOUBLE", doubles);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionBigint() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(1112,bigints) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        Long[] longs = new Long[]{1112l, 12l, 34l, 56l, 78l, 910l};
+
+        Array array = conn.createArrayOf("BIGINT", longs);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionChar() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND('fac',chars) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String[] strings = new String[]{"fac", "a", "bbbb", "c", "ddd", "e"};
+
+        Array array = conn.createArrayOf("CHAR", strings);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test(expected = TypeMismatchException.class)
+    public void testArrayPrependFunctionIntToCharArray() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(234,varchars) FROM regions WHERE region_name = 'SF Bay Area'");
+    }
+
+    @Test(expected = TypeMismatchException.class)
+    public void testArrayPrependFunctionVarcharToIntegerArray() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND('234',integers) FROM regions WHERE region_name = 'SF Bay Area'");
+
+    }
+
+    @Test(expected = SQLException.class)
+    public void testArrayPrependFunctionChar2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND('facfacfacfacfacfacfac',chars) FROM regions WHERE region_name = 'SF Bay Area'");
+        rs.next();
+        rs.getArray(1);
+    }
+
+    @Test
+    public void testArrayPrependFunctionIntegerToDoubleArray() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(45,doubles) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        Double[] doubles = new Double[]{45.0, 23.45, 46.345, 23.234, 45.6, 5.78};
+
+        Array array = conn.createArrayOf("DOUBLE", doubles);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionWithNestedFunctions1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(integers[1],ARRAY[23,45]) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        Integer[] integers = new Integer[]{2345, 23, 45};
+
+        Array array = conn.createArrayOf("INTEGER", integers);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionWithNestedFunctions2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(ARRAY_ELEM(ARRAY[2,4],1),integers) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        Integer[] integers = new Integer[]{2, 2345, 46345, 23234, 456};
+
+        Array array = conn.createArrayOf("INTEGER", integers);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionWithNestedFunctions3() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(ARRAY_ELEM(doubles,2),doubles) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        Double[] doubles = new Double[]{46.345, 23.45, 46.345, 23.234, 45.6, 5.78};
+
+        Array array = conn.createArrayOf("DOUBLE", doubles);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionWithUpsert1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+
+        String ddl = "CREATE TABLE regions (region_name VARCHAR PRIMARY KEY,varchars VARCHAR[])";
+        conn.createStatement().execute(ddl);
+
+        String dml = "UPSERT INTO regions(region_name,varchars) VALUES('SF Bay Area',ARRAY_PREPEND(':-)',ARRAY['hello','world']))";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT varchars FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String[] strings = new String[]{":-)", "hello", "world"};
+
+        Array array = conn.createArrayOf("VARCHAR", strings);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionWithUpsert2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+
+        String ddl = "CREATE TABLE regions (region_name VARCHAR PRIMARY KEY,integers INTEGER[])";
+        conn.createStatement().execute(ddl);
+
+        String dml = "UPSERT INTO regions(region_name,integers) VALUES('SF Bay Area',ARRAY_PREPEND(6,ARRAY[4,5]))";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT integers FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        Integer[] integers = new Integer[]{6, 4, 5};
+
+        Array array = conn.createArrayOf("INTEGER", integers);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionWithUpsert3() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+
+        String ddl = "CREATE TABLE regions (region_name VARCHAR PRIMARY KEY,doubles DOUBLE[])";
+        conn.createStatement().execute(ddl);
+
+        String dml = "UPSERT INTO regions(region_name,doubles) VALUES('SF Bay Area',ARRAY_PREPEND(9.0,ARRAY[5.67,7.87]))";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT doubles FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        Double[] doubles = new Double[]{new Double(9), 5.67, 7.87};
+
+        Array array = conn.createArrayOf("DOUBLE", doubles);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionWithUpsertSelect1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+
+        String ddl = "CREATE TABLE source (region_name VARCHAR PRIMARY KEY,doubles DOUBLE[])";
+        conn.createStatement().execute(ddl);
+
+        ddl = "CREATE TABLE target (region_name VARCHAR PRIMARY KEY,doubles DOUBLE[])";
+        conn.createStatement().execute(ddl);
+
+        String dml = "UPSERT INTO source(region_name,doubles) VALUES('SF Bay Area',ARRAY_PREPEND(9.0,ARRAY[5.67,7.87]))";
+        conn.createStatement().execute(dml);
+
+        dml = "UPSERT INTO source(region_name,doubles) VALUES('SF Bay Area2',ARRAY_PREPEND(9.2,ARRAY[56.7,7.87]))";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        dml = "UPSERT INTO target(region_name, doubles) SELECT region_name, ARRAY_PREPEND(5,doubles) FROM source";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT doubles FROM target");
+        assertTrue(rs.next());
+
+        Double[] doubles = new Double[]{new Double(5), new Double(9), 5.67, 7.87};
+        Array array = conn.createArrayOf("DOUBLE", doubles);
+
+        assertEquals(array, rs.getArray(1));
+        assertTrue(rs.next());
+
+        doubles = new Double[]{new Double(5), new Double(9.2), 56.7, 7.87};
+        array = conn.createArrayOf("DOUBLE", doubles);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionWithUpsertSelect2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+
+        String ddl = "CREATE TABLE source (region_name VARCHAR PRIMARY KEY,varchars VARCHAR[])";
+        conn.createStatement().execute(ddl);
+
+        ddl = "CREATE TABLE target (region_name VARCHAR PRIMARY KEY,varchars VARCHAR[])";
+        conn.createStatement().execute(ddl);
+
+        String dml = "UPSERT INTO source(region_name,varchars) VALUES('SF Bay Area',ARRAY_PREPEND('c',ARRAY['abcd','b']))";
+        conn.createStatement().execute(dml);
+
+        dml = "UPSERT INTO source(region_name,varchars) VALUES('SF Bay Area2',ARRAY_PREPEND('something',ARRAY['d','fgh']))";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        dml = "UPSERT INTO target(region_name, varchars) SELECT region_name, ARRAY_PREPEND('stu',varchars) FROM source";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT varchars FROM target");
+        assertTrue(rs.next());
+
+        String[] strings = new String[]{"stu", "c", "abcd", "b"};
+        Array array = conn.createArrayOf("VARCHAR", strings);
+
+        assertEquals(array, rs.getArray(1));
+        assertTrue(rs.next());
+
+        strings = new String[]{"stu", "something", "d", "fgh"};
+        array = conn.createArrayOf("VARCHAR", strings);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionInWhere1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE ARRAY[123,2345,46345,23234,456]=ARRAY_PREPEND(123,integers)");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionInWhere2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE varchars[1]=ANY(ARRAY_PREPEND('1234',ARRAY['2345','46345','23234']))");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionInWhere3() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE ARRAY['1234','2345','46345','23234']=ARRAY_PREPEND('1234',ARRAY['2345','46345','23234'])");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionInWhere4() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE ARRAY[123.4,23.45,4634.5,2.3234]=ARRAY_PREPEND(123.4,ARRAY[23.45,4634.5,2.3234])");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionInWhere5() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE ARRAY['foo','2345','46345','23234']=ARRAY_PREPEND('foo',varchars)");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionInWhere6() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE chars2=ARRAY_PREPEND('foo',chars)");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionInWhere7() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE ARRAY[4,2,3]=ARRAY_PREPEND(4,ARRAY[2,3])");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test(expected = SQLException.class)
+    public void testArrayPrependFunctionCharLimitCheck() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(char1,chars) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String[] strings = new String[]{"wert", "a", "bbbb", "c", "ddd", "e"};
+
+        Array array = conn.createArrayOf("CHAR", strings);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionIntegerDesc() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTablesDesc(conn, "INTEGER", "23");
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(pk,integers) FROM regions");
+        assertTrue(rs.next());
+
+        Integer[] integers = new Integer[]{23, 2345, 46345, 23234, 456};
+
+        Array array = conn.createArrayOf("INTEGER", integers);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+
+    }
+
+    @Test
+    public void testArrayPrependFunctionVarcharDesc() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTablesDesc(conn, "VARCHAR", "'e'");
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(pk,varchars) FROM regions");
+        assertTrue(rs.next());
+
+        String[] strings = new String[]{"e", "2345", "46345", "23234"};
+
+        Array array = conn.createArrayOf("VARCHAR", strings);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionBigIntDesc() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTablesDesc(conn, "BIGINT", "1112");
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(pk,bigints) FROM regions");
+        assertTrue(rs.next());
+
+        Long[] longs = new Long[]{1112l, 12l, 34l, 56l, 78l, 910l};
+
+        Array array = conn.createArrayOf("BIGINT", longs);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayPrependFunctionBooleanDesc() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTablesDesc(conn, "BOOLEAN", "false");
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(pk,bools) FROM regions");
+        assertTrue(rs.next());
+
+        Boolean[] booleans = new Boolean[]{false, true, false};
+
+        Array array = conn.createArrayOf("BOOLEAN", booleans);
+
+        assertEquals(array, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/7b448cc2/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
index 71f0521..d7142e7 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/ExpressionType.java
@@ -25,6 +25,7 @@ import org.apache.phoenix.expression.function.ArrayAppendFunction;
 import org.apache.phoenix.expression.function.ArrayElemRefExpression;
 import org.apache.phoenix.expression.function.ArrayIndexFunction;
 import org.apache.phoenix.expression.function.ArrayLengthFunction;
+import org.apache.phoenix.expression.function.ArrayPrependFunction;
 import org.apache.phoenix.expression.function.ByteBasedRegexpReplaceFunction;
 import org.apache.phoenix.expression.function.ByteBasedRegexpSplitFunction;
 import org.apache.phoenix.expression.function.ByteBasedRegexpSubstrFunction;
@@ -229,7 +230,8 @@ public enum ExpressionType {
     MinuteFunction(MinuteFunction.class),
     DayOfMonthFunction(DayOfMonthFunction.class),
     ArrayAppendFunction(ArrayAppendFunction.class),
-    UDFExpression(UDFExpression.class)
+    UDFExpression(UDFExpression.class),
+    ArrayPrependFunction(ArrayPrependFunction.class)
     ;
 
     ExpressionType(Class<? extends Expression> clazz) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/7b448cc2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAppendFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAppendFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAppendFunction.java
index db92d61..bf6c29f 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAppendFunction.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAppendFunction.java
@@ -33,7 +33,7 @@ import org.apache.phoenix.schema.tuple.Tuple;
         @FunctionParseNode.Argument(allowedTypes = {PBinaryArray.class,
                 PVarbinaryArray.class}),
         @FunctionParseNode.Argument(allowedTypes = {PVarbinary.class}, defaultValue = "null")})
-public class ArrayAppendFunction extends ScalarFunction {
+public class ArrayAppendFunction extends ArrayModifierFunction {
 
     public static final String NAME = "ARRAY_APPEND";
 
@@ -42,21 +42,6 @@ public class ArrayAppendFunction extends ScalarFunction {
 
     public ArrayAppendFunction(List<Expression> children) throws TypeMismatchException {
         super(children);
-
-        if (getDataType() != null && !(getElementExpr() instanceof LiteralExpression && getElementExpr().isNullable()) && !getElementDataType().isCoercibleTo(getBaseType())) {
-            throw TypeMismatchException.newException(getBaseType(), getElementDataType());
-        }
-
-        // If the base type of an element is fixed width, make sure the element being appended will fit
-        if (getDataType() != null && getElementExpr().getDataType().getByteSize() == null && getElementDataType() != null && getBaseType().isFixedWidth() && getElementDataType().isFixedWidth() && getArrayExpr().getMaxLength() != null &&
-                getElementExpr().getMaxLength() != null && getElementExpr().getMaxLength() > getArrayExpr().getMaxLength()) {
-            throw new DataExceedsCapacityException("");
-        }
-        // If the base type has a scale, make sure the element being appended has a scale less than or equal to it
-        if (getDataType() != null && getArrayExpr().getScale() != null && getElementExpr().getScale() != null &&
-                getElementExpr().getScale() > getArrayExpr().getScale()) {
-            throw new DataExceedsCapacityException(getBaseType(), getArrayExpr().getMaxLength(), getArrayExpr().getScale());
-        }
     }
 
     @Override
@@ -78,12 +63,8 @@ public class ArrayAppendFunction extends ScalarFunction {
             return true;
         }
 
-        if (!getBaseType().isSizeCompatible(ptr, null, getElementDataType(), getElementExpr().getMaxLength(), getElementExpr().getScale(), getArrayExpr().getMaxLength(), getArrayExpr().getScale())) {
-            throw new DataExceedsCapacityException("");
-        }
-
-        getBaseType().coerceBytes(ptr, null, getElementDataType(), getElementExpr().getMaxLength(), getElementExpr().getScale(), getElementExpr().getSortOrder(), getArrayExpr().getMaxLength(), getArrayExpr().getScale(), getArrayExpr().getSortOrder());
-
+        checkSizeCompatibility(ptr);
+        coerceBytes(ptr);
         return PArrayDataType.appendItemToArray(ptr, length, offset, arrayBytes, getBaseType(), arrayLength, getMaxLength(), getArrayExpr().getSortOrder());
     }
 
@@ -114,14 +95,4 @@ public class ArrayAppendFunction extends ScalarFunction {
     public Expression getElementExpr() {
         return getChildren().get(1);
     }
-
-    public PDataType getBaseType() {
-        return PDataType.arrayBaseType(getArrayExpr().getDataType());
-    }
-
-    public PDataType getElementDataType() {
-        return getElementExpr().getDataType();
-    }
-
-
 }

http://git-wip-us.apache.org/repos/asf/phoenix/blob/7b448cc2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayModifierFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayModifierFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayModifierFunction.java
new file mode 100644
index 0000000..afd10e5
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayModifierFunction.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.phoenix.expression.function;
+
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.exception.DataExceedsCapacityException;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.expression.LiteralExpression;
+import org.apache.phoenix.schema.TypeMismatchException;
+import org.apache.phoenix.schema.types.*;
+
+public abstract class ArrayModifierFunction extends ScalarFunction {
+
+    public ArrayModifierFunction() {
+    }
+
+    public ArrayModifierFunction(List<Expression> children) throws TypeMismatchException {
+        super(children);
+
+        if (getDataType() != null && !(getElementExpr() instanceof LiteralExpression && getElementExpr().isNullable()) && !getElementDataType().isCoercibleTo(getBaseType())) {
+            throw TypeMismatchException.newException(getBaseType(), getElementDataType());
+        }
+
+        // If the base type of an element is fixed width, make sure the element being appended will fit
+        if (getDataType() != null && getElementExpr().getDataType().getByteSize() == null && getElementDataType() != null && getBaseType().isFixedWidth() && getElementDataType().isFixedWidth() && getArrayExpr().getMaxLength() != null &&
+                getElementExpr().getMaxLength() != null && getElementExpr().getMaxLength() > getArrayExpr().getMaxLength()) {
+            throw new DataExceedsCapacityException("");
+        }
+        // If the base type has a scale, make sure the element being appended has a scale less than or equal to it
+        if (getDataType() != null && getArrayExpr().getScale() != null && getElementExpr().getScale() != null &&
+                getElementExpr().getScale() > getArrayExpr().getScale()) {
+            throw new DataExceedsCapacityException(getBaseType(), getArrayExpr().getMaxLength(), getArrayExpr().getScale());
+        }
+    }
+
+    protected void checkSizeCompatibility(ImmutableBytesWritable ptr) {
+        if (!getBaseType().isSizeCompatible(ptr, null, getElementDataType(), getElementExpr().getMaxLength(), getElementExpr().getScale(), getArrayExpr().getMaxLength(), getArrayExpr().getScale())) {
+            throw new DataExceedsCapacityException("");
+        }
+    }
+
+    protected void coerceBytes(ImmutableBytesWritable ptr) {
+        getBaseType().coerceBytes(ptr, null, getElementDataType(), getElementExpr().getMaxLength(), getElementExpr().getScale(), getElementExpr().getSortOrder(), getArrayExpr().getMaxLength(), getArrayExpr().getScale(), getArrayExpr().getSortOrder());
+    }
+
+    public abstract Expression getArrayExpr();
+
+    public abstract Expression getElementExpr();
+
+    public PDataType getBaseType() {
+        return PDataType.arrayBaseType(getArrayExpr().getDataType());
+    }
+
+    public PDataType getElementDataType() {
+        return getElementExpr().getDataType();
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/7b448cc2/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayPrependFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayPrependFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayPrependFunction.java
new file mode 100644
index 0000000..3cea4df
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayPrependFunction.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.phoenix.expression.function;
+
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.Expression;
+import org.apache.phoenix.parse.FunctionParseNode;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.TypeMismatchException;
+import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.schema.types.*;
+
+@FunctionParseNode.BuiltInFunction(name = ArrayPrependFunction.NAME, args = {
+        @FunctionParseNode.Argument(allowedTypes = {PVarbinary.class}),
+        @FunctionParseNode.Argument(allowedTypes = {PBinaryArray.class,
+                PVarbinaryArray.class})})
+public class ArrayPrependFunction  extends ArrayModifierFunction {
+
+    public static final String NAME = "ARRAY_PREPEND";
+
+    public ArrayPrependFunction() {
+    }
+
+    public ArrayPrependFunction(List<Expression> children) throws TypeMismatchException {
+        super(children);
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+
+        if (!getArrayExpr().evaluate(tuple, ptr)) {
+            return false;
+        } else if (ptr.getLength() == 0) {
+            return true;
+        }
+        int arrayLength = PArrayDataType.getArrayLength(ptr, getBaseType(), getArrayExpr().getMaxLength());
+
+        int length = ptr.getLength();
+        int offset = ptr.getOffset();
+        byte[] arrayBytes = ptr.get();
+
+        getElementExpr().evaluate(tuple, ptr);
+
+        checkSizeCompatibility(ptr);
+        coerceBytes(ptr);
+        return PArrayDataType.prependItemToArray(ptr, length, offset, arrayBytes, getBaseType(), arrayLength, getMaxLength(), getArrayExpr().getSortOrder());
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return children.get(1).getDataType();
+    }
+
+    @Override
+    public Integer getMaxLength() {
+        return this.children.get(1).getMaxLength();
+    }
+
+    @Override
+    public SortOrder getSortOrder() {
+        return getChildren().get(1).getSortOrder();
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public Expression getArrayExpr() {
+        return getChildren().get(1);
+    }
+
+    @Override
+    public Expression getElementExpr() {
+        return getChildren().get(0);
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/7b448cc2/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
index c6861f7..86f22f7 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PArrayDataType.java
@@ -21,6 +21,7 @@ import java.io.DataOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.text.Format;
+import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -512,7 +513,7 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
                 } else {
                     int off = newOffsetArrayPosition;
                     for (int arrayIndex = 0; arrayIndex < Math.abs(arrayLength) - 1; arrayIndex++) {
-                        Bytes.putInt(newArray, off, getOffset(arrayBytes, arrayIndex, true, offsetArrayPosition));
+                        Bytes.putInt(newArray, off, getOffset(arrayBytes, arrayIndex, true, offsetArrayPosition + offset));
                         off += Bytes.SIZEOF_INT;
                     }
 
@@ -543,6 +544,164 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
         Bytes.putByte(array, newOffsetArrayPosition + offsetArrayLength + byteSize + 2 * Bytes.SIZEOF_INT, header);
     }
 
+    public static boolean prependItemToArray(ImmutableBytesWritable ptr, int length, int offset, byte[] arrayBytes, PDataType baseType, int arrayLength, Integer maxLength, SortOrder sortOrder) {
+        int elementLength = maxLength == null ? ptr.getLength() : maxLength;
+        if (ptr.getLength() == 0) {
+            elementLength = 0;
+        }
+        //padding
+        if (elementLength > ptr.getLength()) {
+            baseType.pad(ptr, elementLength, sortOrder);
+        }
+        int elementOffset = ptr.getOffset();
+        byte[] elementBytes = ptr.get();
+
+        byte[] newArray;
+        if (!baseType.isFixedWidth()) {
+            int offsetArrayPosition = Bytes.toInt(arrayBytes, offset + length - Bytes.SIZEOF_INT - Bytes.SIZEOF_INT - Bytes.SIZEOF_BYTE, Bytes.SIZEOF_INT);
+            int offsetArrayLength = length - offsetArrayPosition - Bytes.SIZEOF_INT - Bytes.SIZEOF_INT - Bytes.SIZEOF_BYTE;
+            arrayLength = Math.abs(arrayLength);
+
+            //checks whether offset array consists of shorts or integers
+            boolean useInt = offsetArrayLength / arrayLength == Bytes.SIZEOF_INT;
+            boolean convertToInt = false;
+            int endElementPosition = getOffset(arrayBytes, arrayLength - 1, !useInt, offsetArrayPosition + offset) + elementLength + Bytes.SIZEOF_BYTE;
+            int newOffsetArrayPosition;
+            int lengthIncrease;
+            int firstNonNullElementPosition = 0;
+            int currentPosition = 0;
+            //handle the case where prepended element is null
+            if (elementLength == 0) {
+                int nulls = 1;
+                //counts the number of nulls which are already at the beginning of the array
+                for (int index = 0; index < arrayLength; index++) {
+                    int currOffset = getOffset(arrayBytes, index, !useInt, offsetArrayPosition + offset);
+                    if (arrayBytes[offset + currOffset] == QueryConstants.SEPARATOR_BYTE) {
+                        nulls++;
+                    } else {
+                        //gets the offset of the first element after nulls at the beginning
+                        firstNonNullElementPosition = currOffset;
+                        break;
+                    }
+                }
+
+                int nMultiplesOver255 = nulls / 255;
+                int nRemainingNulls = nulls % 255;
+
+                //Calculates the increase in length due to prepending the null
+                //There is a length increase only when nRemainingNulls == 1
+                //nRemainingNulls == 1 and nMultiplesOver255 == 0 means there were no nulls at the beginning previously.
+                //At that case we need to increase the length by two bytes, one for separator byte and one for null count.
+                //ex: initial array - 65 0 66 0 0 0 after prepending null - 0 1(inverted) 65 0 66 0 0 0
+                //nRemainingNulls == 1 and nMultiplesOver255 != 0 means there were null at the beginning previously.
+                //In this case due to prepending nMultiplesOver255 is increased by 1.
+                //We need to increase the length by one byte to store increased that.
+                //ex: initial array - 0 1 65 0 66 0 0 0 after prepending null - 0 1 1(inverted) 65 0 66 0 0 0
+                //nRemainingNulls == 0 case.
+                //ex: initial array - 0 254(inverted) 65 0 66 0 0 0 after prepending null - 0 1 65 0 66 0 0 0
+                //nRemainingNulls > 1 case.
+                //ex: initial array - 0 45(inverted) 65 0 66 0 0 0 after prepending null - 0 46(inverted) 65 0 66 0 0 0
+                lengthIncrease = nRemainingNulls == 1 ? (nMultiplesOver255 == 0 ? 2 * Bytes.SIZEOF_BYTE : Bytes.SIZEOF_BYTE) : 0;
+                endElementPosition = getOffset(arrayBytes, arrayLength - 1, !useInt, offsetArrayPosition + offset) + lengthIncrease;
+                if (!useInt) {
+                    if (PArrayDataType.useShortForOffsetArray(endElementPosition)) {
+                        newArray = new byte[length + Bytes.SIZEOF_SHORT + lengthIncrease];
+                    } else {
+                        newArray = new byte[length + arrayLength * Bytes.SIZEOF_SHORT + Bytes.SIZEOF_INT + lengthIncrease];
+                        convertToInt = true;
+                    }
+                } else {
+                    newArray = new byte[length + Bytes.SIZEOF_INT + lengthIncrease];
+                }
+                newArray[currentPosition] = QueryConstants.SEPARATOR_BYTE;
+                currentPosition++;
+
+                newOffsetArrayPosition = offsetArrayPosition + lengthIncrease;
+                while (nMultiplesOver255-- > 0) {
+                    newArray[currentPosition] = (byte) 1;
+                    currentPosition++;
+                }
+                // Write a byte for the remaining null elements
+                if (nRemainingNulls > 0) {
+                    byte nNullByte = SortOrder.invert((byte) (nRemainingNulls - 1));
+                    newArray[currentPosition] = nNullByte; // Single byte for repeating nulls
+                    currentPosition++;
+                }
+            } else {
+                if (!useInt) {
+                    if (PArrayDataType.useShortForOffsetArray(endElementPosition)) {
+                        newArray = new byte[length + elementLength + Bytes.SIZEOF_SHORT + Bytes.SIZEOF_BYTE];
+                    } else {
+                        newArray = new byte[length + elementLength + arrayLength * Bytes.SIZEOF_SHORT + Bytes.SIZEOF_INT + Bytes.SIZEOF_BYTE];
+                        convertToInt = true;
+                    }
+                } else {
+                    newArray = new byte[length + elementLength + Bytes.SIZEOF_INT + Bytes.SIZEOF_BYTE];
+                }
+                newOffsetArrayPosition = offsetArrayPosition + Bytes.SIZEOF_BYTE + elementLength;
+
+                lengthIncrease = elementLength + Bytes.SIZEOF_BYTE;
+                System.arraycopy(elementBytes, elementOffset, newArray, 0, elementLength);
+                currentPosition += elementLength + Bytes.SIZEOF_BYTE;
+            }
+
+            System.arraycopy(arrayBytes, firstNonNullElementPosition + offset, newArray, currentPosition, offsetArrayPosition);
+
+            arrayLength = arrayLength + 1;
+            //writes the new offset and changes the previous offsets
+            if (useInt || convertToInt) {
+                writeNewOffsets(arrayBytes, newArray, false, !useInt, newOffsetArrayPosition, arrayLength, offsetArrayPosition, offset, lengthIncrease, length);
+            } else {
+                writeNewOffsets(arrayBytes, newArray, true, true, newOffsetArrayPosition, arrayLength, offsetArrayPosition, offset, lengthIncrease, length);
+            }
+        } else {
+            newArray = new byte[length + elementLength];
+
+            System.arraycopy(elementBytes, elementOffset, newArray, 0, elementLength);
+            System.arraycopy(arrayBytes, offset, newArray, elementLength, length);
+        }
+
+        ptr.set(newArray);
+        return true;
+    }
+
+    private static void writeNewOffsets(byte[] arrayBytes, byte[] newArray, boolean useShortNew, boolean useShortPrevious, int newOffsetArrayPosition, int arrayLength, int offsetArrayPosition, int offset, int offsetShift, int length) {
+        int currentPosition = newOffsetArrayPosition;
+        int offsetArrayElementSize = useShortNew ? Bytes.SIZEOF_SHORT : Bytes.SIZEOF_INT;
+        if (useShortNew) {
+            Bytes.putShort(newArray, currentPosition, (short) (0 - Short.MAX_VALUE));
+        } else {
+            Bytes.putInt(newArray, currentPosition, 0);
+        }
+
+        currentPosition += offsetArrayElementSize;
+        boolean nullsAtBeginning = true;
+        for (int arrayIndex = 0; arrayIndex < arrayLength - 1; arrayIndex++) {
+            int oldOffset = getOffset(arrayBytes, arrayIndex, useShortPrevious, offsetArrayPosition + offset);
+            if (arrayBytes[offset + oldOffset] == QueryConstants.SEPARATOR_BYTE && nullsAtBeginning) {
+                if (useShortNew) {
+                    Bytes.putShort(newArray, currentPosition, (short) (oldOffset - Short.MAX_VALUE));
+                } else {
+                    Bytes.putInt(newArray, currentPosition, oldOffset);
+                }
+            } else {
+                if (useShortNew) {
+                    Bytes.putShort(newArray, currentPosition, (short) (oldOffset + offsetShift - Short.MAX_VALUE));
+                } else {
+                    Bytes.putInt(newArray, currentPosition, oldOffset + offsetShift);
+                }
+                nullsAtBeginning = false;
+            }
+            currentPosition += offsetArrayElementSize;
+        }
+
+        Bytes.putInt(newArray, currentPosition, newOffsetArrayPosition);
+        currentPosition += Bytes.SIZEOF_INT;
+        Bytes.putInt(newArray, currentPosition, useShortNew ? arrayLength : -arrayLength);
+        currentPosition += Bytes.SIZEOF_INT;
+        Bytes.putByte(newArray, currentPosition, arrayBytes[offset + length - 1]);
+    }
+
     public static int serailizeOffsetArrayIntoStream(DataOutputStream oStream, TrustedByteArrayOutputStream byteStream,
             int noOfElements, int maxOffset, int[] offsetPos) throws IOException {
         int offsetPosition = (byteStream.size());

http://git-wip-us.apache.org/repos/asf/phoenix/blob/7b448cc2/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayPrependFunctionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayPrependFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayPrependFunctionTest.java
new file mode 100644
index 0000000..4d2f960
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayPrependFunctionTest.java
@@ -0,0 +1,552 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import static org.junit.Assert.assertEquals;
+
+import java.math.BigDecimal;
+import java.sql.SQLException;
+import java.util.Calendar;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.function.ArrayPrependFunction;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.types.*;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+public class ArrayPrependFunctionTest {
+
+    private static void testExpression(LiteralExpression array, LiteralExpression element, PhoenixArray expected)
+            throws SQLException {
+        List<Expression> expressions = Lists.newArrayList((Expression) element);
+        expressions.add(array);
+
+        Expression arrayPrependFunction = new ArrayPrependFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        arrayPrependFunction.evaluate(null, ptr);
+        PhoenixArray result = (PhoenixArray) arrayPrependFunction.getDataType().toObject(ptr, expressions.get(1).getSortOrder(), array.getMaxLength(), array.getScale());
+        assertEquals(result, expected);
+    }
+
+    private static void test(PhoenixArray array, Object element, PDataType arrayDataType, Integer arrMaxLen, Integer arrScale, PDataType elementDataType, Integer elemMaxLen, Integer elemScale, PhoenixArray expected, SortOrder arraySortOrder, SortOrder elementSortOrder) throws SQLException {
+        LiteralExpression arrayLiteral, elementLiteral;
+        arrayLiteral = LiteralExpression.newConstant(array, arrayDataType, arrMaxLen, arrScale, arraySortOrder, Determinism.ALWAYS);
+        elementLiteral = LiteralExpression.newConstant(element, elementDataType, elemMaxLen, elemScale, elementSortOrder, Determinism.ALWAYS);
+        testExpression(arrayLiteral, elementLiteral, expected);
+    }
+
+    @Test
+    public void testArrayPrependFunction1() throws Exception {
+        Object[] o = new Object[]{1, 2, -3, 4};
+        Object[] o2 = new Object[]{5, 1, 2, -3, 4};
+        Object element = 5;
+        PDataType baseType = PInteger.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray.PrimitiveIntPhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray.PrimitiveIntPhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testArrayPrependFunction2() throws Exception {
+        Object[] o = new Object[]{"1", "2", "3", "4"};
+        Object[] o2 = new Object[]{"56", "1", "2", "3", "4"};
+        Object element = "56";
+        PDataType baseType = PVarchar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testArrayPrependFunction3() throws Exception {
+        //offset array short to int transition
+        Object[] o = new Object[Short.MAX_VALUE + 1];
+        for (int i = 0; i < o.length; i++) {
+            o[i] = "a";
+        }
+        Object[] o2 = new Object[Short.MAX_VALUE + 2];
+        for (int i = 1; i < o2.length; i++) {
+            o2[i] = "a";
+        }
+        Object element = "b";
+        o2[0] = element;
+        PDataType baseType = PVarchar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testArrayPrependFunction4() throws Exception {
+        //offset array int
+        Object[] o = new Object[Short.MAX_VALUE + 7];
+        for (int i = 0; i < o.length; i++) {
+            o[i] = "a";
+        }
+        Object[] o2 = new Object[Short.MAX_VALUE + 8];
+        for (int i = 1; i < o2.length; i++) {
+            o2[i] = "a";
+        }
+        Object element = "b";
+        o2[0] = element;
+        PDataType baseType = PVarchar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testArrayPrependFunctionBoolean() throws Exception {
+        Boolean[] o = new Boolean[]{true, false, false, true};
+        Boolean[] o2 = new Boolean[]{false, true, false, false, true};
+        Boolean element = false;
+        PDataType baseType = PBoolean.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray.PrimitiveBooleanPhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray.PrimitiveBooleanPhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE),
+                null, null, baseType, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testArrayPrependFunction6() throws Exception {
+        Object[] o = new Object[]{new Float(2.3), new Float(7.9), new Float(-9.6), new Float(2.3)};
+        Object[] o2 = new Object[]{new Float(8.9), new Float(2.3), new Float(7.9), new Float(-9.6), new Float(2.3)};
+        Object element = 8.9;
+        PDataType baseType = PFloat.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray.PrimitiveFloatPhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray.PrimitiveFloatPhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testArrayPrependFunction7() throws Exception {
+        Object[] o = new Object[]{4.78, 9.54, 2.34, -9.675, Double.MAX_VALUE};
+        Object[] o2 = new Object[]{12.67, 4.78, 9.54, 2.34, -9.675, Double.MAX_VALUE};
+        Object element = 12.67;
+        PDataType baseType = PDouble.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray.PrimitiveDoublePhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray.PrimitiveDoublePhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testArrayPrependFunction8() throws Exception {
+        Object[] o = new Object[]{123l, 677l, 98789l, -78989l, 66787l};
+        Object[] o2 = new Object[]{543l, 123l, 677l, 98789l, -78989l, 66787l};
+        Object element = 543l;
+        PDataType baseType = PLong.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray.PrimitiveLongPhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray.PrimitiveLongPhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testArrayPrependFunction9() throws Exception {
+        Object[] o = new Object[]{(short) 34, (short) -23, (short) -89, (short) 999, (short) 34};
+        Object[] o2 = new Object[]{(short) 7, (short) 34, (short) -23, (short) -89, (short) 999, (short) 34};
+        Object element = (short) 7;
+        PDataType baseType = PSmallint.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray.PrimitiveShortPhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray.PrimitiveShortPhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testArrayPrependFunction10() throws Exception {
+        Object[] o = new Object[]{(byte) 4, (byte) 8, (byte) 9};
+        Object[] o2 = new Object[]{(byte) 6, (byte) 4, (byte) 8, (byte) 9};
+        Object element = (byte) 6;
+        PDataType baseType = PTinyint.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray.PrimitiveBytePhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray.PrimitiveBytePhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testArrayPrependFunction11() throws Exception {
+        Object[] o = new Object[]{BigDecimal.valueOf(2345), BigDecimal.valueOf(-23.45), BigDecimal.valueOf(785)};
+        Object[] o2 = new Object[]{BigDecimal.valueOf(-19), BigDecimal.valueOf(2345), BigDecimal.valueOf(-23.45), BigDecimal.valueOf(785)};
+        Object element = BigDecimal.valueOf(-19);
+        PDataType baseType = PDecimal.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testArrayPrependFunction12() throws Exception {
+        Calendar calendar = Calendar.getInstance();
+        java.util.Date currentDate = calendar.getTime();
+        java.sql.Date date = new java.sql.Date(currentDate.getTime());
+
+        Object[] o = new Object[]{date, date, date};
+        Object[] o2 = new Object[]{date, date, date, date};
+        PDataType baseType = PDate.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, date, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testArrayPrependFunction13() throws Exception {
+        Calendar calendar = Calendar.getInstance();
+        java.util.Date currentDate = calendar.getTime();
+        java.sql.Time time = new java.sql.Time(currentDate.getTime());
+
+        Object[] o = new Object[]{time, time, time};
+        Object[] o2 = new Object[]{time, time, time, time};
+        PDataType baseType = PTime.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, time, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testArrayPrependFunction14() throws Exception {
+        Calendar calendar = Calendar.getInstance();
+        java.util.Date currentDate = calendar.getTime();
+        java.sql.Timestamp timestamp = new java.sql.Timestamp(currentDate.getTime());
+
+        Object[] o = new Object[]{timestamp, timestamp, timestamp};
+        Object[] o2 = new Object[]{timestamp, timestamp, timestamp, timestamp};
+        PDataType baseType = PTimestamp.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, timestamp, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, null, null, expected, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testArrayPrependFunction15() throws Exception {
+        Object[] o = new Object[]{1, 2, -3, 4};
+        Object[] o2 = new Object[]{5, 1, 2, -3, 4};
+        Object element = 5;
+        PDataType baseType = PInteger.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray.PrimitiveIntPhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray.PrimitiveIntPhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, null, null, expected, SortOrder.DESC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testArrayPrependFunction16() throws Exception {
+        Object[] o = new Object[]{1, 2, -3, 4};
+        Object[] o2 = new Object[]{5, 1, 2, -3, 4};
+        Object element = 5;
+        PDataType baseType = PInteger.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray.PrimitiveIntPhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray.PrimitiveIntPhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, null, null, expected, SortOrder.DESC, SortOrder.DESC);
+    }
+
+    @Test
+    public void testArrayPrependFunction17() throws Exception {
+        Object[] o = new Object[]{1, 2, -3, 4};
+        Object[] o2 = new Object[]{5, 1, 2, -3, 4};
+        Object element = 5;
+        PDataType baseType = PInteger.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray.PrimitiveIntPhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray.PrimitiveIntPhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, null, null, expected, SortOrder.ASC, SortOrder.DESC);
+    }
+
+    @Test
+    public void testArrayPrependFunction18() throws Exception {
+        Object[] o = new Object[]{"1   ", "2   ", "3   ", "4   "};
+        Object[] o2 = new Object[]{"5", "1", "2", "3", "4"};
+        Object element = "5";
+        PDataType baseType = PChar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), 4, null, baseType, 1, null, expected, SortOrder.ASC, SortOrder.DESC);
+    }
+
+    @Test
+    public void testArrayPrependFunction19() throws Exception {
+        Object[] o = new Object[]{"1   ", "2   ", "3   ", "4   "};
+        Object[] o2 = new Object[]{"5", "1", "2", "3", "4"};
+        Object element = "5";
+        PDataType baseType = PChar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), 4, null, baseType, 1, null, expected, SortOrder.DESC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testArrayPrependFunction20() throws Exception {
+        Object[] o = new Object[]{"1   ", "2   ", "3   ", "4   "};
+        Object[] o2 = new Object[]{"5", "1", "2", "3", "4"};
+        Object element = "5";
+        PDataType baseType = PChar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), 4, null, baseType, 1, null, expected, SortOrder.DESC, SortOrder.DESC);
+    }
+
+    @Test
+    public void testArrayPrependFunction21() throws Exception {
+        Object[] o = new Object[]{4.78, 9.54, 2.34, -9.675, Double.MAX_VALUE};
+        Object[] o2 = new Object[]{12.67, 4.78, 9.54, 2.34, -9.675, Double.MAX_VALUE};
+        Object element = 12.67;
+        PDataType baseType = PDouble.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray.PrimitiveDoublePhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray.PrimitiveDoublePhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, null, null, expected, SortOrder.ASC, SortOrder.DESC);
+    }
+
+    @Test
+    public void testArrayPrependFunction22() throws Exception {
+        byte[][] o = new byte[][]{new byte[]{2, 0, 3}, new byte[]{42, 3}, new byte[]{5, 3}, new byte[]{6, 3}, new byte[]{2, 5}};
+        byte[][] o2 = new byte[][]{new byte[]{5, 6}, new byte[]{2, 0, 3}, new byte[]{42, 3}, new byte[]{5, 3}, new byte[]{6, 3}, new byte[]{2, 5}};
+        byte[] element = new byte[]{5, 6};
+        PDataType baseType = PVarbinary.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, 1, null, expected, SortOrder.ASC, SortOrder.DESC);
+    }
+
+    @Test
+    public void testArrayPrependFunction23() throws Exception {
+        byte[][] o = new byte[][]{new byte[]{2, 3}, new byte[]{42, 3}, new byte[]{5, 3}, new byte[]{6, 3}, new byte[]{2, 5}};
+        byte[][] o2 = new byte[][]{new byte[]{5, 6}, new byte[]{2, 3}, new byte[]{42, 3}, new byte[]{5, 3}, new byte[]{6, 3}, new byte[]{2, 5}};
+        byte[] element = new byte[]{5, 6};
+        PDataType baseType = PBinary.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), 2, null, baseType, 1, null, expected, SortOrder.ASC, SortOrder.DESC);
+    }
+
+    @Test
+    public void testArrayPrependFunction24() throws Exception {
+        byte[][] o = new byte[][]{new byte[]{2, 0}, new byte[]{13, 3}, new byte[]{5, 3}, new byte[]{6, 3}, new byte[]{2, 5}};
+        byte[][] o2 = new byte[][]{new byte[]{5, 6}, new byte[]{2, 0}, new byte[]{13, 3}, new byte[]{5, 3}, new byte[]{6, 3}, new byte[]{2, 5}};
+        byte[] element = new byte[]{5, 6};
+        PDataType baseType = PBinary.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), 3, null, baseType, 1, null, expected, SortOrder.ASC, SortOrder.DESC);
+    }
+
+    @Test
+    public void testForNullsWithNoNullsAtBeginning() throws Exception {
+        Object[] o = new Object[]{"1   ", "2   ", "3   ", "4   "};
+        Object[] o2 = new Object[]{"1", "2", "3", "4"};
+        Object element = null;
+        PDataType baseType = PChar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), 4, null, baseType, 1, null, expected, SortOrder.ASC, SortOrder.DESC);
+    }
+
+    @Test
+    public void testForNullsAllNulls() throws Exception {
+        Object element = null;
+        PDataType baseType = PChar.INSTANCE;
+
+        PhoenixArray arr = null;
+        PhoenixArray expected = null;
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), 4, null, baseType, 1, null, expected, SortOrder.ASC, SortOrder.DESC);
+    }
+
+    @Test
+    public void testForNullsWith268NullsAtBeginning() throws Exception {
+        //268 nulls at the beginning
+        Object[] o = new Object[270];
+        for (int i = 0; i < o.length - 2; i++)
+            o[i] = null;
+
+        o[o.length - 2] = "1";
+        o[o.length - 1] = "2";
+
+        Object[] o2 = new Object[271];
+        for (int i = 0; i < o2.length - 2; i++)
+            o2[i] = null;
+
+        o2[o2.length - 2] = "1";
+        o2[o2.length - 1] = "2";
+
+        Object element = null;
+        PDataType baseType = PVarchar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, 1, null, expected, SortOrder.ASC, SortOrder.DESC);
+    }
+
+    @Test
+    public void testForNullsWith241NullsAtBeginning() throws Exception {
+        //241 nulls at the beginning
+        Object[] o = new Object[243];
+        for (int i = 0; i < o.length - 2; i++)
+            o[i] = null;
+
+        o[o.length - 2] = "1";
+        o[o.length - 1] = "2";
+
+        Object[] o2 = new Object[244];
+        for (int i = 0; i < o2.length - 2; i++)
+            o2[i] = null;
+
+        o2[o2.length - 2] = "1";
+        o2[o2.length - 1] = "2";
+
+        Object element = null;
+        PDataType baseType = PVarchar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, 1, null, expected, SortOrder.ASC, SortOrder.DESC);
+    }
+
+    @Test
+    public void testForNullsWith254NullsAtBeginning() throws Exception {
+        //254 nulls at the beginning
+        Object[] o = new Object[256];
+        for (int i = 0; i < o.length - 2; i++)
+            o[i] = null;
+
+        o[o.length - 2] = "1";
+        o[o.length - 1] = "2";
+
+        Object[] o2 = new Object[257];
+        for (int i = 0; i < o2.length - 2; i++)
+            o2[i] = null;
+
+        o2[o2.length - 2] = "1";
+        o2[o2.length - 1] = "2";
+
+        Object element = null;
+        PDataType baseType = PVarchar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, 1, null, expected, SortOrder.ASC, SortOrder.DESC);
+    }
+
+    @Test
+    public void testForNullsWith510NullsAtBeginning() throws Exception {
+        //510 nulls at the beginning
+        Object[] o = new Object[512];
+        for (int i = 0; i < o.length - 2; i++)
+            o[i] = null;
+
+        o[o.length - 2] = "1";
+        o[o.length - 1] = "2";
+
+        Object[] o2 = new Object[513];
+        for (int i = 0; i < o2.length - 2; i++)
+            o2[i] = null;
+
+        o2[o2.length - 2] = "1";
+        o2[o2.length - 1] = "2";
+
+        Object element = null;
+        PDataType baseType = PVarchar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, 1, null, expected, SortOrder.ASC, SortOrder.DESC);
+    }
+
+    @Test
+    public void testForNullsWith509NullsAtBeginning() throws Exception {
+        //509 nulls at the beginning
+        Object[] o = new Object[511];
+        for (int i = 0; i < o.length - 2; i++)
+            o[i] = null;
+
+        o[o.length - 2] = "1";
+        o[o.length - 1] = "2";
+
+        Object[] o2 = new Object[512];
+        for (int i = 0; i < o2.length - 2; i++)
+            o2[i] = null;
+
+        o2[o2.length - 2] = "1";
+        o2[o2.length - 1] = "2";
+
+        Object element = null;
+        PDataType baseType = PVarchar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, 1, null, expected, SortOrder.ASC, SortOrder.DESC);
+    }
+
+    @Test
+    public void testForNullsWith1NullAtBeginning() throws Exception {
+        Object[] o = new Object[]{"1   ", "2   ", "3   ", "4   "};
+        Object[] o2 = new Object[]{null, "1   ", "2   ", "3   ", "4   "};
+        Object element = null;
+        PDataType baseType = PVarchar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), 4, null, baseType, 1, null, expected, SortOrder.ASC, SortOrder.DESC);
+    }
+
+    @Test
+    public void testForNullsWith2NullsAtBeginning() throws Exception {
+        Object[] o = new Object[]{null, "1   ", "2   ", "3   ", "4   "};
+        Object[] o2 = new Object[]{null, null, "1   ", "2   ", "3   ", "4   "};
+        Object element = null;
+        PDataType baseType = PVarchar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), 4, null, baseType, 1, null, expected, SortOrder.ASC, SortOrder.DESC);
+    }
+
+    @Test
+    public void testForNullsWithNullsInMiddle() throws Exception {
+        Object[] o = new Object[]{"1   ", "2   ", null, "3   ", "4   "};
+        Object[] o2 = new Object[]{null, "1   ", "2   ", null, "3   ", "4   "};
+        Object element = null;
+        PDataType baseType = PVarchar.INSTANCE;
+
+        PhoenixArray arr = new PhoenixArray(baseType, o);
+        PhoenixArray expected = new PhoenixArray(baseType, o2);
+        test(arr, element, PDataType.fromTypeId(baseType.getSqlType() + PDataType.ARRAY_TYPE_BASE), null, null, baseType, 1, null, expected, SortOrder.ASC, SortOrder.DESC);
+    }
+}