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/07/16 17:51:37 UTC

phoenix git commit: PHOENIX-2101 Implement ARRAY_TO_STRING built in function (Dumindu Buddhika)

Repository: phoenix
Updated Branches:
  refs/heads/master 33d60506c -> 236ce1c87


PHOENIX-2101 Implement ARRAY_TO_STRING built in function (Dumindu
Buddhika)


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

Branch: refs/heads/master
Commit: 236ce1c87c729c9beba5985e4fe3871e300176e6
Parents: 33d6050
Author: ramkrishna <ra...@gmail.com>
Authored: Thu Jul 16 21:20:36 2015 +0530
Committer: ramkrishna <ra...@gmail.com>
Committed: Thu Jul 16 21:20:36 2015 +0530

----------------------------------------------------------------------
 .../end2end/ArrayToStringFunctionIT.java        | 654 +++++++++++++++++++
 .../phoenix/expression/ExpressionType.java      |   4 +-
 .../function/ArrayToStringFunction.java         |  84 +++
 .../phoenix/schema/types/PArrayDataType.java    |  30 +
 .../expression/ArrayToStringFunctionTest.java   | 374 +++++++++++
 5 files changed, 1145 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/236ce1c8/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayToStringFunctionIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayToStringFunctionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayToStringFunctionIT.java
new file mode 100644
index 0000000..3b3f1d5
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayToStringFunctionIT.java
@@ -0,0 +1,654 @@
+/*
+ * 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 static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.*;
+
+import org.junit.Test;
+
+public class ArrayToStringFunctionIT extends BaseHBaseManagedTimeIT {
+    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,varchar1 VARCHAR,nullcheck INTEGER,chars2 CHAR(15)[])";
+        conn.createStatement().execute(ddl);
+        String dml = "UPSERT INTO regions(region_name,varchars,integers,doubles,bigints,chars,double1,varchar1,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," +
+                "', '," +
+                "NULL," +
+                "ARRAY['a','bbbb','c','ddd','e','foo']" +
+                ")";
+        PreparedStatement stmt = conn.prepareStatement(dml);
+        stmt.execute();
+        conn.commit();
+    }
+
+    @Test
+    public void testArrayToStringFunctionVarchar1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(varchars, ',','*') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "2345,46345,23234";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionVarchar2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(varchars, ',') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "2345,46345,23234";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionVarchar3() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY['hello', 'hello'], ',') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "hello,hello";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionInt() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(integers, ',') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "2345,46345,23234,456";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionDouble1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(doubles, ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "23.45, 46.345, 23.234, 45.6, 5.78";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionDouble2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY[2.3, 4.5], ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "2.3, 4.5";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionBigint() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(bigints, ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "12, 34, 56, 78, 910";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionChar1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(chars, ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "a   , bbbb, c   , ddd , e   ";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionChar2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(chars2, ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "a   , bbbb, c   , ddd , e   , foo ";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionChar3() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(chars2, varchar1) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "a   , bbbb, c   , ddd , e   , foo ";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithNestedFunctions1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY[integers[1],integers[1]], ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "2345, 2345";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithNestedFunctions2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY[ARRAY_ELEM(ARRAY[2,4],1),ARRAY_ELEM(ARRAY[2,4],2)], ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "2, 4";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithNestedFunctions3() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY[ARRAY_ELEM(doubles, 1), ARRAY_ELEM(doubles, 1)], ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "23.45, 23.45";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithNestedFunctions4() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_ELEM(ARRAY_APPEND(ARRAY['abc','bcd'], ARRAY_TO_STRING(ARRAY['a','b'], 'c')), 3) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "acb";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithUpsert1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+
+        String ddl = "CREATE TABLE regions (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)";
+        conn.createStatement().execute(ddl);
+
+        String dml = "UPSERT INTO regions(region_name,varchar) VALUES('SF Bay Area',ARRAY_TO_STRING(ARRAY['hello','world'],','))";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT varchar FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "hello,world";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithUpsert2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+
+        String ddl = "CREATE TABLE regions (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)";
+        conn.createStatement().execute(ddl);
+
+        String dml = "UPSERT INTO regions(region_name,varchar) VALUES('SF Bay Area',ARRAY_TO_STRING(ARRAY[3, 4, 5],', '))";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT varchar FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "3, 4, 5";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithUpsert3() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+
+        String ddl = "CREATE TABLE regions (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)";
+        conn.createStatement().execute(ddl);
+
+        String dml = "UPSERT INTO regions(region_name,varchar) VALUES('SF Bay Area',ARRAY_TO_STRING(ARRAY[3.1, 4.2, 5.5],', '))";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT varchar FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "3.1, 4.2, 5.5";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithUpsert4() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+
+        String ddl = "CREATE TABLE regions (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)";
+        conn.createStatement().execute(ddl);
+
+        String dml = "UPSERT INTO regions(region_name,varchar) VALUES('SF Bay Area',ARRAY_TO_STRING(ARRAY[true, false, true],', '))";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT varchar FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "true, false, true";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithUpsertSelect1() 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,varchar VARCHAR)";
+        conn.createStatement().execute(ddl);
+
+        String dml = "UPSERT INTO source(region_name,doubles) VALUES('SF Bay Area', ARRAY[5.67, 7.87])";
+        conn.createStatement().execute(dml);
+
+        dml = "UPSERT INTO source(region_name,doubles) VALUES('SF Bay Area2', ARRAY[9.2, 3.4])";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        dml = "UPSERT INTO target(region_name, varchar) SELECT region_name, ARRAY_TO_STRING(doubles, ', ') FROM source";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT varchar FROM target");
+        assertTrue(rs.next());
+
+        String expected = "5.67, 7.87";
+        assertEquals(expected, rs.getString(1));
+        assertTrue(rs.next());
+
+        expected = "9.2, 3.4";
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithUpsertSelect2() 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,varchar VARCHAR)";
+        conn.createStatement().execute(ddl);
+
+        String dml = "UPSERT INTO source(region_name,varchars) VALUES('SF Bay Area', ARRAY['hello', '-)'])";
+        conn.createStatement().execute(dml);
+
+        dml = "UPSERT INTO source(region_name,varchars) VALUES('SF Bay Area2', ARRAY['hello', '-('])";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        dml = "UPSERT INTO target(region_name, varchar) SELECT region_name, ARRAY_TO_STRING(varchars, ':') FROM source";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT varchar FROM target");
+        assertTrue(rs.next());
+
+        String expected = "hello:-)";
+        assertEquals(expected, rs.getString(1));
+        assertTrue(rs.next());
+
+        expected = "hello:-(";
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithUpsertSelect3() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+
+        String ddl = "CREATE TABLE source (region_name VARCHAR PRIMARY KEY,booleans BOOLEAN[])";
+        conn.createStatement().execute(ddl);
+
+        ddl = "CREATE TABLE target (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)";
+        conn.createStatement().execute(ddl);
+
+        String dml = "UPSERT INTO source(region_name, booleans) VALUES('SF Bay Area', ARRAY[true, true])";
+        conn.createStatement().execute(dml);
+
+        dml = "UPSERT INTO source(region_name, booleans) VALUES('SF Bay Area2', ARRAY[false, false])";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        dml = "UPSERT INTO target(region_name, varchar) SELECT region_name, ARRAY_TO_STRING(booleans, ', ') FROM source";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT varchar FROM target");
+        assertTrue(rs.next());
+
+        String expected = "true, true";
+        assertEquals(expected, rs.getString(1));
+        assertTrue(rs.next());
+
+        expected = "false, false";
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionInWhere1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE '2345,46345,23234,456' = ARRAY_TO_STRING(integers,',')");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionInWhere2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE 'a,b,c' = ARRAY_TO_STRING(ARRAY['a', 'b', 'c'], ',')");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionInWhere3() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE '1.1,2.2,3.3' = ARRAY_TO_STRING(ARRAY[1.1, 2.2, 3.3], ',')");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionInWhere4() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE 'true,true,true' = ARRAY_TO_STRING(ARRAY[true, true, true], ',')");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionInWhere5() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE 'a, bbbb, c, ddd, e' = ARRAY_TO_STRING(ARRAY['a', 'bbbb', 'c' , 'ddd', 'e'], ', ')");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionInWhere6() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE ARRAY_TO_STRING(ARRAY[1,2,3], varchar1) = '1, 2, 3'");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionInWhere7() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE ARRAY_TO_STRING(varchars, varchar1) = '2345, 46345, 23234'");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithNulls1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY['a', NULL, 'b'], ', ','*') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "a, *, b";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithNulls2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY['a', NULL, 'b'], ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "a, b";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithNulls3() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY[NULL, 'a', 'b'], ', ', '*') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "*, a, b";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithNulls4() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY[NULL, 'a', 'b'], ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "a, b";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithNulls5() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY['a', 'b', NULL], ', ', '*') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "a, b, *";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithNulls6() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY['a', 'b', NULL], ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "a, b";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithNulls7() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY[NULL, NULL, 'a', 'b', NULL, 'c', 'd', NULL, 'e', NULL, NULL], ', ', '*') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "*, *, a, b, *, c, d, *, e, *, *";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testArrayToStringFunctionWithNulls8() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_TO_STRING(ARRAY[NULL, NULL, 'a', 'b', NULL, 'c', 'd', NULL, 'e', NULL, NULL], ', ') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        String expected = "a, b, c, d, e";
+
+        assertEquals(expected, rs.getString(1));
+        assertFalse(rs.next());
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/236ce1c8/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 ef14e6a..3c364c0 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
@@ -29,6 +29,7 @@ import org.apache.phoenix.expression.function.ArrayFillFunction;
 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.ArrayToStringFunction;
 import org.apache.phoenix.expression.function.ByteBasedRegexpReplaceFunction;
 import org.apache.phoenix.expression.function.ByteBasedRegexpSplitFunction;
 import org.apache.phoenix.expression.function.ByteBasedRegexpSubstrFunction;
@@ -249,7 +250,8 @@ public enum ExpressionType {
     ExpFunction(ExpFunction.class),
     PowerFunction(PowerFunction.class),
     ArrayConcatFunction(ArrayConcatFunction.class),
-    ArrayFillFunction(ArrayFillFunction.class)
+    ArrayFillFunction(ArrayFillFunction.class),
+    ArrayToStringFunction(ArrayToStringFunction.class)
     ;
 
     ExpressionType(Class<? extends Expression> clazz) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/236ce1c8/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayToStringFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayToStringFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayToStringFunction.java
new file mode 100644
index 0000000..9102df4
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayToStringFunction.java
@@ -0,0 +1,84 @@
+/*
+ * 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.tuple.Tuple;
+import org.apache.phoenix.schema.types.*;
+
+@FunctionParseNode.BuiltInFunction(name = ArrayToStringFunction.NAME, args = {
+        @FunctionParseNode.Argument(allowedTypes = {PBinaryArray.class, PVarbinaryArray.class}),
+        @FunctionParseNode.Argument(allowedTypes = {PVarchar.class, PChar.class}),
+        @FunctionParseNode.Argument(allowedTypes = {PVarchar.class, PChar.class}, defaultValue = "null")})
+public class ArrayToStringFunction extends ScalarFunction {
+    public static final String NAME = "ARRAY_TO_STRING";
+
+    public ArrayToStringFunction() {
+    }
+
+    public ArrayToStringFunction(List<Expression> children) {
+        super(children);
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        Expression delimiterExpr = children.get(1);
+        if (!delimiterExpr.evaluate(tuple, ptr)) {
+            return false;
+        } else if (ptr.getLength() == 0) {
+            return true;
+        }
+        String delimiter = (String) delimiterExpr.getDataType().toObject(ptr, delimiterExpr.getSortOrder(), delimiterExpr.getMaxLength(), delimiterExpr.getScale());
+
+        Expression arrayExpr = children.get(0);
+        if (!arrayExpr.evaluate(tuple, ptr)) {
+            return false;
+        } else if (ptr.getLength() == 0) {
+            return true;
+        }
+        PhoenixArray array = (PhoenixArray) arrayExpr.getDataType().toObject(ptr, arrayExpr.getSortOrder(), arrayExpr.getMaxLength(), arrayExpr.getScale());
+
+        Expression nullExpr = children.get(2);
+        String nullString = null;
+        if (nullExpr.evaluate(tuple, ptr) && ptr.getLength() != 0) {
+            nullString = (String) nullExpr.getDataType().toObject(ptr, nullExpr.getSortOrder(), nullExpr.getMaxLength(), nullExpr.getScale());
+        }
+
+        return PArrayDataType.arrayToString(ptr, array, delimiter, nullString, getSortOrder());
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PVarchar.INSTANCE;
+    }
+
+    @Override
+    public SortOrder getSortOrder() {
+        return children.get(0).getSortOrder();
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/236ce1c8/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 9ca64c5..bad02e4 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
@@ -957,6 +957,36 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
         return true;
     }
 
+    public static boolean arrayToString(ImmutableBytesWritable ptr, PhoenixArray array, String delimiter, String nullString, SortOrder sortOrder) {
+        StringBuilder result = new StringBuilder();
+        boolean delimiterPending = false;
+        for (int i = 0; i < array.getDimensions() - 1; i++) {
+            Object element = array.getElement(i);
+            if (element == null) {
+                if (nullString != null) {
+                    result.append(nullString);
+                }
+            } else {
+                result.append(element.toString());
+                delimiterPending = true;
+            }
+            if (nullString != null || (array.getElement(i + 1) != null && delimiterPending)) {
+                result.append(delimiter);
+                delimiterPending = false;
+            }
+        }
+        Object element = array.getElement(array.getDimensions() - 1);
+        if (element == null) {
+            if (nullString != null) {
+                result.append(nullString);
+            }
+        } else {
+            result.append(element.toString());
+        }
+        ptr.set(PVarchar.INSTANCE.toBytes(result.toString(), sortOrder));
+        return true;
+    }
+
     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/236ce1c8/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayToStringFunctionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayToStringFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayToStringFunctionTest.java
new file mode 100644
index 0000000..92eb6b5
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/ArrayToStringFunctionTest.java
@@ -0,0 +1,374 @@
+/*
+ * 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.Date;
+import java.sql.SQLException;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.function.ArrayToStringFunction;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.types.*;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+public class ArrayToStringFunctionTest {
+
+    private static void testExpression(LiteralExpression array, LiteralExpression delimiter, LiteralExpression nullString, String expected)
+            throws SQLException {
+        List<Expression> expressions = Lists.newArrayList((Expression) array);
+        expressions.add(delimiter);
+        expressions.add(nullString);
+
+        Expression arrayToStringFunction = new ArrayToStringFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        arrayToStringFunction.evaluate(null, ptr);
+        String result = (String) arrayToStringFunction.getDataType().toObject(ptr, arrayToStringFunction.getSortOrder(), arrayToStringFunction.getMaxLength(), arrayToStringFunction.getScale());
+        assertEquals(expected, result);
+    }
+
+    private static void test(PhoenixArray array, PDataType arrayDataType, Integer arrMaxLen, Integer arrScale, String delimiter, String nullString, String expected, SortOrder arraySortOrder, SortOrder delimiterSortOrder, SortOrder nullStringSortOrder) throws SQLException {
+        LiteralExpression arrayLiteral, delimiterLiteral, nullStringLiteral;
+        arrayLiteral = LiteralExpression.newConstant(array, arrayDataType, arrMaxLen, arrScale, arraySortOrder, Determinism.ALWAYS);
+        delimiterLiteral = LiteralExpression.newConstant(delimiter, PVarchar.INSTANCE, null, null, delimiterSortOrder, Determinism.ALWAYS);
+        nullStringLiteral = LiteralExpression.newConstant(nullString, PVarchar.INSTANCE, null, null, nullStringSortOrder, Determinism.ALWAYS);
+        testExpression(arrayLiteral, delimiterLiteral, nullStringLiteral, expected);
+    }
+
+    @Test
+    public void testInt1() throws SQLException {
+        PDataType type = PIntegerArray.INSTANCE;
+        PDataType base = PInteger.INSTANCE;
+        Object[] o1 = new Object[]{1, 2, 3, 4, 5};
+        PhoenixArray arr = new PhoenixArray.PrimitiveIntPhoenixArray(base, o1);
+        String delimiter = ",";
+        String nullString = "*";
+        String expected = "1,2,3,4,5";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testInt2() throws SQLException {
+        PDataType type = PIntegerArray.INSTANCE;
+        PDataType base = PInteger.INSTANCE;
+        Object[] o1 = new Object[]{1, 2, 3, 4, 5};
+        PhoenixArray arr = new PhoenixArray.PrimitiveIntPhoenixArray(base, o1);
+        String delimiter = ",";
+        String nullString = "";
+        String expected = "1,2,3,4,5";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testInt3() throws SQLException {
+        PDataType type = PIntegerArray.INSTANCE;
+        PDataType base = PInteger.INSTANCE;
+        Object[] o1 = new Object[]{1, 2, 3, 4, 5};
+        PhoenixArray arr = new PhoenixArray.PrimitiveIntPhoenixArray(base, o1);
+        String delimiter = "";
+        String nullString = "";
+        String expected = null;
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testInt4() throws SQLException {
+        PDataType type = PIntegerArray.INSTANCE;
+        PDataType base = PInteger.INSTANCE;
+        Object[] o1 = new Object[]{1};
+        PhoenixArray arr = new PhoenixArray.PrimitiveIntPhoenixArray(base, o1);
+        String delimiter = ",";
+        String nullString = "";
+        String expected = "1";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testFloat1() throws SQLException {
+        PDataType type = PFloatArray.INSTANCE;
+        PDataType base = PFloat.INSTANCE;
+        Object[] o1 = new Object[]{(float) 1.1, (float) 2.2, (float) 3.3, (float) 4.4, (float) 5.5};
+        PhoenixArray arr = new PhoenixArray.PrimitiveFloatPhoenixArray(base, o1);
+        String delimiter = ",";
+        String nullString = "*";
+        String expected = "1.1,2.2,3.3,4.4,5.5";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testFloat2() throws SQLException {
+        PDataType type = PFloatArray.INSTANCE;
+        PDataType base = PFloat.INSTANCE;
+        Object[] o1 = new Object[]{(float) 1.1, (float) 2.2, (float) 3.3, (float) 4.4, (float) 5.5};
+        PhoenixArray arr = new PhoenixArray.PrimitiveFloatPhoenixArray(base, o1);
+        String delimiter = ", ";
+        String nullString = "*";
+        String expected = "1.1, 2.2, 3.3, 4.4, 5.5";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testDate() throws SQLException {
+        PDataType type = PDateArray.INSTANCE;
+        PDataType base = PDate.INSTANCE;
+        Object[] o1 = new Object[]{new Date(0l), new Date(0l), new Date(0l)};
+        PhoenixArray arr = new PhoenixArray(base, o1);
+        String delimiter = ", ";
+        String nullString = "*";
+        String expected = "1970-01-01, 1970-01-01, 1970-01-01";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testTime() throws SQLException {
+        PDataType type = PTimeArray.INSTANCE;
+        PDataType base = PTime.INSTANCE;
+        Object[] o1 = new Object[]{new Time(0l), new Time(0l), new Time(0l)};
+        PhoenixArray arr = new PhoenixArray(base, o1);
+        String delimiter = ", ";
+        String nullString = "*";
+        String expected = "";
+        for (int i = 0; i < o1.length - 1; i++) {
+            expected += o1[i].toString() + ", ";
+        }
+        expected += o1[o1.length - 1];
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testTimestamp() throws SQLException {
+        PDataType type = PTimestampArray.INSTANCE;
+        PDataType base = PTimestamp.INSTANCE;
+        Object[] o1 = new Object[]{new Timestamp(0l), new Timestamp(0l), new Timestamp(0l)};
+        PhoenixArray arr = new PhoenixArray(base, o1);
+        String delimiter = ", ";
+        String nullString = "*";
+        String expected = "";
+        for (int i = 0; i < o1.length - 1; i++) {
+            expected += o1[i].toString() + ", ";
+        }
+        expected += o1[o1.length - 1];
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testVarchar1() throws SQLException {
+        PDataType type = PVarcharArray.INSTANCE;
+        PDataType base = PVarchar.INSTANCE;
+        Object[] o1 = new Object[]{"hello", null, "hello", null};
+        PhoenixArray arr = new PhoenixArray(base, o1);
+        String delimiter = ", ";
+        String nullString = "*";
+        String expected = "hello, *, hello, *";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testVarchar2() throws SQLException {
+        PDataType type = PVarcharArray.INSTANCE;
+        PDataType base = PVarchar.INSTANCE;
+        Object[] o1 = new Object[]{"hello", null, "hello", null, null};
+        PhoenixArray arr = new PhoenixArray(base, o1);
+        String delimiter = ", ";
+        String nullString = "*";
+        String expected = "hello, *, hello, *, *";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testVarchar3() throws SQLException {
+        PDataType type = PVarcharArray.INSTANCE;
+        PDataType base = PVarchar.INSTANCE;
+        Object[] o1 = new Object[]{"hello", null, "hello", null, null};
+        PhoenixArray arr = new PhoenixArray(base, o1);
+        String delimiter = ", ";
+        String nullString = "";
+        String expected = "hello, hello";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testVarchar4() throws SQLException {
+        PDataType type = PVarcharArray.INSTANCE;
+        PDataType base = PVarchar.INSTANCE;
+        Object[] o1 = new Object[]{null, "hello", "hello", null, null};
+        PhoenixArray arr = new PhoenixArray(base, o1);
+        String delimiter = ", ";
+        String nullString = "";
+        String expected = "hello, hello";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testVarchar5() throws SQLException {
+        PDataType type = PVarcharArray.INSTANCE;
+        PDataType base = PVarchar.INSTANCE;
+        Object[] o1 = new Object[]{"hello"};
+        PhoenixArray arr = new PhoenixArray(base, o1);
+        String delimiter = ", ";
+        String nullString = "";
+        String expected = "hello";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testVarchar6() throws SQLException {
+        PDataType type = PVarcharArray.INSTANCE;
+        PDataType base = PVarchar.INSTANCE;
+        Object[] o1 = new Object[]{null, null, null, null, "hello"};
+        PhoenixArray arr = new PhoenixArray(base, o1);
+        String delimiter = ", ";
+        String nullString = "";
+        String expected = "hello";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testVarchar7() throws SQLException {
+        PDataType type = PVarcharArray.INSTANCE;
+        PDataType base = PVarchar.INSTANCE;
+        Object[] o1 = new Object[]{null, null, null, null, "hello"};
+        PhoenixArray arr = new PhoenixArray(base, o1);
+        String delimiter = ", ";
+        String nullString = "*";
+        String expected = "*, *, *, *, hello";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testDouble() throws SQLException {
+        PDataType type = PDoubleArray.INSTANCE;
+        PDataType base = PDouble.INSTANCE;
+        Object[] o1 = new Object[]{23.4, 56.8, 2.4};
+        PhoenixArray arr = new PhoenixArray.PrimitiveDoublePhoenixArray(base, o1);
+        String delimiter = ",";
+        String nullString = "*";
+        String expected = "23.4,56.8,2.4";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testTinyint() throws SQLException {
+        PDataType type = PTinyintArray.INSTANCE;
+        PDataType base = PTinyint.INSTANCE;
+        Object[] o1 = new Object[]{(byte) 2, (byte) 4, (byte) 5};
+        PhoenixArray arr = new PhoenixArray.PrimitiveBytePhoenixArray(base, o1);
+        String delimiter = ",";
+        String nullString = "*";
+        String expected = "2,4,5";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testSmallint() throws SQLException {
+        PDataType type = PSmallintArray.INSTANCE;
+        PDataType base = PSmallint.INSTANCE;
+        Object[] o1 = new Object[]{(short) 6, (short) 7, (short) 8};
+        PhoenixArray arr = new PhoenixArray.PrimitiveShortPhoenixArray(base, o1);
+        String delimiter = ",";
+        String nullString = "*";
+        String expected = "6,7,8";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testBoolean() throws SQLException {
+        PDataType type = PBooleanArray.INSTANCE;
+        PDataType base = PBoolean.INSTANCE;
+        Object[] o1 = new Object[]{true, false, true};
+        PhoenixArray arr = new PhoenixArray.PrimitiveBooleanPhoenixArray(base, o1);
+        String delimiter = ",";
+        String nullString = "*";
+        String expected = "true,false,true";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testLong() throws SQLException {
+        PDataType type = PLongArray.INSTANCE;
+        PDataType base = PLong.INSTANCE;
+        Object[] o1 = new Object[]{(long) 23, (long) 34, (long) 45};
+        PhoenixArray arr = new PhoenixArray.PrimitiveLongPhoenixArray(base, o1);
+        String delimiter = ",";
+        String nullString = "*";
+        String expected = "23,34,45";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testDecimal1() throws SQLException {
+        PDataType type = PDecimalArray.INSTANCE;
+        PDataType base = PDecimal.INSTANCE;
+        Object[] o1 = new Object[]{BigDecimal.valueOf(23.45), BigDecimal.valueOf(2.345), BigDecimal.valueOf(234.5)};
+        PhoenixArray arr = new PhoenixArray(base, o1);
+        String delimiter = ",";
+        String nullString = "*";
+        String expected = "23.45,2.345,234.5";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testDecimal2() throws SQLException {
+        PDataType type = PDecimalArray.INSTANCE;
+        PDataType base = PDecimal.INSTANCE;
+        Object[] o1 = new Object[]{BigDecimal.valueOf(23.45), BigDecimal.valueOf(2.345), BigDecimal.valueOf(234.5), null};
+        PhoenixArray arr = new PhoenixArray(base, o1);
+        String delimiter = ",";
+        String nullString = "*";
+        String expected = "23.45,2.345,234.5,*";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+
+    @Test
+    public void testDecimal3() throws SQLException {
+        PDataType type = PDecimalArray.INSTANCE;
+        PDataType base = PDecimal.INSTANCE;
+        Object[] o1 = new Object[]{BigDecimal.valueOf(23.45), BigDecimal.valueOf(2.345), null, BigDecimal.valueOf(234.5)};
+        PhoenixArray arr = new PhoenixArray(base, o1);
+        String delimiter = ",";
+        String nullString = "*";
+        String expected = "23.45,2.345,*,234.5";
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC);
+        test(arr, type, null, null, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC);
+    }
+}