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/28 07:00:39 UTC

phoenix git commit: PHOENIX-2147 Implement STRING_TO_ARRAY built in function (Dumindu Buddhika)

Repository: phoenix
Updated Branches:
  refs/heads/master 28a8e9774 -> 265b6dee7


PHOENIX-2147 Implement STRING_TO_ARRAY 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/265b6dee
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/265b6dee
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/265b6dee

Branch: refs/heads/master
Commit: 265b6dee75891c1d4a35cb73d4baaf86cbae1482
Parents: 28a8e97
Author: ramkrishna <ra...@gmail.com>
Authored: Tue Jul 28 10:30:00 2015 +0530
Committer: ramkrishna <ra...@gmail.com>
Committed: Tue Jul 28 10:30:00 2015 +0530

----------------------------------------------------------------------
 .../end2end/StringToArrayFunctionIT.java        | 423 +++++++++++++++++++
 .../phoenix/expression/ExpressionType.java      |   4 +-
 .../function/StringToArrayFunction.java         |  91 ++++
 .../phoenix/schema/types/PArrayDataType.java    |  21 +
 .../expression/StringToArrayFunctionTest.java   | 275 ++++++++++++
 5 files changed, 813 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/phoenix/blob/265b6dee/phoenix-core/src/it/java/org/apache/phoenix/end2end/StringToArrayFunctionIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/StringToArrayFunctionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/StringToArrayFunctionIT.java
new file mode 100644
index 0000000..6e6ac9f
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/StringToArrayFunctionIT.java
@@ -0,0 +1,423 @@
+/*
+ * 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.apache.phoenix.schema.types.PVarchar;
+import org.apache.phoenix.schema.types.PhoenixArray;
+import org.junit.Test;
+
+public class StringToArrayFunctionIT extends BaseHBaseManagedTimeIT {
+
+    private void initTables(Connection conn) throws Exception {
+        String ddl = "CREATE TABLE regions (region_name VARCHAR PRIMARY KEY, string1 VARCHAR, string2 CHAR(50), delimiter1 VARCHAR, delimiter2 CHAR(20), nullstring1 VARCHAR, nullstring2 CHAR(20))";
+        conn.createStatement().execute(ddl);
+        String dml = "UPSERT INTO regions(region_name, string1, string2, delimiter1, delimiter2, nullstring1, nullstring2) VALUES('SF Bay Area'," +
+                "'a,b,c,d'," +
+                "'1.2.3.4'," +
+                "','," +
+                "'.'," +
+                "'c'," +
+                "'3'" +
+                ")";
+        PreparedStatement stmt = conn.prepareStatement(dml);
+        stmt.execute();
+        conn.commit();
+    }
+
+    @Test
+    public void testStringToArrayFunction1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(string1, delimiter1) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"a", "b", "c", "d"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(string1, delimiter1, nullstring1) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"a", "b", null, "d"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction3() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(string1, delimiter1, 'a') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{null, "b", "c", "d"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction4() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(string1, delimiter1, 'd') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"a", "b", "c", null});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction5() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(string2, delimiter2) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"1", "2", "3", "4"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction6() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(string2, delimiter2, nullstring2) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"1", "2", null, "4"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction7() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(string2, delimiter2, '1') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{null, "2", "3", "4"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction8() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(string2, delimiter2, '4') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"1", "2", "3", null});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction9() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(region_name, ' ', '4') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"SF", "Bay", "Area"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction10() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY('hello,hello,hello', delimiter1) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"hello", "hello", "hello"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction11() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY('a,hello,hello,hello,b', ',', 'hello') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"a", null, null, null, "b"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunction12() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY('b.a.b', delimiter2, 'b') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{null, "a", null});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionWithNestedFunctions1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT ARRAY_LENGTH(STRING_TO_ARRAY('a, b, c', ', ')) FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        assertEquals(3, rs.getInt(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionWithNestedFunctions2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(ARRAY_TO_STRING(ARRAY['a', 'b', 'c'], delimiter2), delimiter2, 'b') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"a", null, "c"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionWithNestedFunctions3() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT STRING_TO_ARRAY(ARRAY_TO_STRING(ARRAY['a', 'b', 'c'], delimiter2), ARRAY_ELEM(ARRAY[',', '.'], 2), 'b') FROM regions WHERE region_name = 'SF Bay Area'");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"a", null, "c"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionWithUpsert1() 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', STRING_TO_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());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"hello", "world", ":-)"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionWithUpsert2() 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', STRING_TO_ARRAY('a, b, -, c', ', ', '-'))";
+        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());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"a", "b", null, "c"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionWithUpsertSelect1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+
+        String ddl = "CREATE TABLE source (region_name VARCHAR PRIMARY KEY, varchar 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, varchar) VALUES('SF Bay Area', 'a,b,c,d')";
+        conn.createStatement().execute(dml);
+
+        dml = "UPSERT INTO source(region_name, varchar) VALUES('SF Bay Area2', '1,2,3,4')";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        dml = "UPSERT INTO target(region_name, varchars) SELECT region_name, STRING_TO_ARRAY(varchar, ',') FROM source";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT varchars FROM target");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"a", "b", "c", "d"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertTrue(rs.next());
+
+        expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"1", "2", "3", "4"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionWithUpsertSelect2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+
+        String ddl = "CREATE TABLE source (region_name VARCHAR PRIMARY KEY, varchar 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, varchar) VALUES('SF Bay Area', 'a,b,-,c,d')";
+        conn.createStatement().execute(dml);
+
+        dml = "UPSERT INTO source(region_name, varchar) VALUES('SF Bay Area2', '1,2,-,3,4')";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        dml = "UPSERT INTO target(region_name, varchars) SELECT region_name, STRING_TO_ARRAY(varchar, ',', '-') FROM source";
+        conn.createStatement().execute(dml);
+        conn.commit();
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT varchars FROM target");
+        assertTrue(rs.next());
+
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"a", "b", null, "c", "d"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertTrue(rs.next());
+
+        expected = new PhoenixArray(PVarchar.INSTANCE, new Object[]{"1", "2", null, "3", "4"});
+
+        assertEquals(expected, rs.getArray(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionInWhere1() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE ARRAY['a', 'b', 'c', 'd']=STRING_TO_ARRAY(string1, delimiter1)");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionInWhere2() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE 'a'=ANY(STRING_TO_ARRAY(string1, delimiter1))");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+
+    @Test
+    public void testStringToArrayFunctionInWhere3() throws Exception {
+        Connection conn = DriverManager.getConnection(getUrl());
+        initTables(conn);
+
+        ResultSet rs;
+        rs = conn.createStatement().executeQuery("SELECT region_name FROM regions WHERE 'a'=ALL(STRING_TO_ARRAY('a,a,a,', delimiter1))");
+        assertTrue(rs.next());
+
+        assertEquals("SF Bay Area", rs.getString(1));
+        assertFalse(rs.next());
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/265b6dee/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 3c364c0..9e9cb45 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
@@ -96,6 +96,7 @@ import org.apache.phoenix.expression.function.StddevSampFunction;
 import org.apache.phoenix.expression.function.StringBasedRegexpReplaceFunction;
 import org.apache.phoenix.expression.function.StringBasedRegexpSplitFunction;
 import org.apache.phoenix.expression.function.StringBasedRegexpSubstrFunction;
+import org.apache.phoenix.expression.function.StringToArrayFunction;
 import org.apache.phoenix.expression.function.SubstrFunction;
 import org.apache.phoenix.expression.function.SumAggregateFunction;
 import org.apache.phoenix.expression.function.TimezoneOffsetFunction;
@@ -251,7 +252,8 @@ public enum ExpressionType {
     PowerFunction(PowerFunction.class),
     ArrayConcatFunction(ArrayConcatFunction.class),
     ArrayFillFunction(ArrayFillFunction.class),
-    ArrayToStringFunction(ArrayToStringFunction.class)
+    ArrayToStringFunction(ArrayToStringFunction.class),
+    StringToArrayFunction(StringToArrayFunction.class)
     ;
 
     ExpressionType(Class<? extends Expression> clazz) {

http://git-wip-us.apache.org/repos/asf/phoenix/blob/265b6dee/phoenix-core/src/main/java/org/apache/phoenix/expression/function/StringToArrayFunction.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/StringToArrayFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/StringToArrayFunction.java
new file mode 100644
index 0000000..ffbda01
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/StringToArrayFunction.java
@@ -0,0 +1,91 @@
+/*
+ * 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 = StringToArrayFunction.NAME, args = {
+        @FunctionParseNode.Argument(allowedTypes = {PVarchar.class, PChar.class}),
+        @FunctionParseNode.Argument(allowedTypes = {PVarchar.class, PChar.class}),
+        @FunctionParseNode.Argument(allowedTypes = {PVarchar.class, PChar.class}, defaultValue = "null")})
+public class StringToArrayFunction extends ScalarFunction {
+    public static final String NAME = "STRING_TO_ARRAY";
+
+    public StringToArrayFunction() {
+    }
+
+    public StringToArrayFunction(List<Expression> children) {
+        super(children);
+    }
+
+    @Override
+    public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
+        Expression delimiterExpr = children.get(1);
+        String delimiter;
+        if (!delimiterExpr.evaluate(tuple, ptr)) {
+            return false;
+        } else if (ptr.getLength() == 0) {
+            delimiter = "";
+        } else {
+            delimiter = (String) delimiterExpr.getDataType().toObject(ptr, delimiterExpr.getSortOrder(), delimiterExpr.getMaxLength(), delimiterExpr.getScale());
+        }
+
+        Expression stringExpr = children.get(0);
+        if (!stringExpr.evaluate(tuple, ptr)) {
+            return false;
+        } else if (ptr.getLength() == 0) {
+            return true;
+        }
+        String string = (String) stringExpr.getDataType().toObject(ptr, stringExpr.getSortOrder(), stringExpr.getMaxLength(), stringExpr.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.stringToArray(ptr, string, delimiter, nullString, getSortOrder());
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public Integer getMaxLength() {
+        return null;
+    }
+
+    @Override
+    public PDataType getDataType() {
+        return PVarcharArray.INSTANCE;
+    }
+
+    @Override
+    public SortOrder getSortOrder() {
+        return children.get(0).getSortOrder();
+    }
+}

http://git-wip-us.apache.org/repos/asf/phoenix/blob/265b6dee/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 28144fd..a1759a4 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
@@ -24,6 +24,7 @@ import java.sql.Types;
 import java.text.Format;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.regex.Pattern;
 
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
 import org.apache.hadoop.hbase.util.Bytes;
@@ -990,6 +991,26 @@ public abstract class PArrayDataType<T> extends PDataType<T> {
         return true;
     }
 
+    public static boolean stringToArray(ImmutableBytesWritable ptr, String string, String delimiter, String nullString, SortOrder sortOrder) {
+        Pattern pattern = Pattern.compile(Pattern.quote(delimiter));
+        String[] array;
+        if (delimiter.length() != 0) {
+            array = pattern.split(string);
+            if (nullString != null) {
+                for (int i = 0; i < array.length; i++) {
+                    if (array[i].equals(nullString)) {
+                        array[i] = null;
+                    }
+                }
+            }
+        } else {
+            array = string.split("(?!^)");
+        }
+        PhoenixArray phoenixArray = new PhoenixArray(PVarchar.INSTANCE, array);
+        ptr.set(PVarcharArray.INSTANCE.toBytes(phoenixArray, PVarchar.INSTANCE, 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/265b6dee/phoenix-core/src/test/java/org/apache/phoenix/expression/StringToArrayFunctionTest.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/expression/StringToArrayFunctionTest.java b/phoenix-core/src/test/java/org/apache/phoenix/expression/StringToArrayFunctionTest.java
new file mode 100644
index 0000000..6e8e532
--- /dev/null
+++ b/phoenix-core/src/test/java/org/apache/phoenix/expression/StringToArrayFunctionTest.java
@@ -0,0 +1,275 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.phoenix.expression;
+
+import static org.junit.Assert.assertEquals;
+
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
+import org.apache.phoenix.expression.function.StringToArrayFunction;
+import org.apache.phoenix.schema.SortOrder;
+import org.apache.phoenix.schema.types.*;
+import org.junit.Test;
+
+import com.google.common.collect.Lists;
+
+public class StringToArrayFunctionTest {
+
+    private static void testExpression(LiteralExpression array, LiteralExpression delimiter, LiteralExpression nullString, PhoenixArray expected)
+            throws SQLException {
+        List<Expression> expressions = Lists.newArrayList((Expression) array);
+        expressions.add(delimiter);
+        expressions.add(nullString);
+
+        Expression stringToArrayFunction = new StringToArrayFunction(expressions);
+        ImmutableBytesWritable ptr = new ImmutableBytesWritable();
+        stringToArrayFunction.evaluate(null, ptr);
+        PhoenixArray result = (PhoenixArray) stringToArrayFunction.getDataType().toObject(ptr, stringToArrayFunction.getSortOrder(), stringToArrayFunction.getMaxLength(), stringToArrayFunction.getScale());
+        assertEquals(expected, result);
+    }
+
+    private static void test(String string, String delimiter, String nullString, PhoenixArray expected, SortOrder stringSortOrder, SortOrder delimiterSortOrder, SortOrder nullStringSortOrder, PDataType stringType, PDataType delimiterType, PDataType nullStringType) throws SQLException {
+        LiteralExpression arrayLiteral, delimiterLiteral, nullStringLiteral;
+        arrayLiteral = LiteralExpression.newConstant(string, stringType, null, null, stringSortOrder, Determinism.ALWAYS);
+        delimiterLiteral = LiteralExpression.newConstant(delimiter, delimiterType, null, null, delimiterSortOrder, Determinism.ALWAYS);
+        nullStringLiteral = LiteralExpression.newConstant(nullString, nullStringType, null, null, nullStringSortOrder, Determinism.ALWAYS);
+        testExpression(arrayLiteral, delimiterLiteral, nullStringLiteral, expected);
+    }
+
+    @Test
+    public void testStringToArrayFunction1() throws SQLException {
+        String string = "1,2,3,4,5";
+        Object[] o1 = new Object[]{"1", "2", "3", "4", "5"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = ",";
+        String nullString = "*";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction2() throws SQLException {
+        String string = "1,2,3,4,5";
+        Object[] o1 = new Object[]{"1", "2", "3", "4", "5"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = ",";
+        String nullString = "";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction3() throws SQLException {
+        String string = "1234";
+        Object[] o1 = new Object[]{"1", "2", "3", "4"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = null;
+        String nullString = "";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction4() throws SQLException {
+        String string = "1";
+        Object[] o1 = new Object[]{"1"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = ",";
+        String nullString = "";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction5() throws SQLException {
+        String string = "hello, hello, hello";
+        Object[] o1 = new Object[]{"hello", "hello", "hello"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = ", ";
+        String nullString = "";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction6() throws SQLException {
+        String string = "1.2...2.3...5.6";
+        Object[] o1 = new Object[]{"1.2", "2.3", "5.6"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = "...";
+        String nullString = "";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction7() throws SQLException {
+        String string = "a\\b\\c\\d\\e\\f";
+        Object[] o1 = new Object[]{"a", "b", "c", "d", "e", "f"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = "\\";
+        String nullString = "";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction8() throws SQLException {
+        String string = "a-b-c-d-e-f-";
+        Object[] o1 = new Object[]{"a", "b", "c", "d", "e", "f"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = "-";
+        String nullString = "";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction9() throws SQLException {
+        String string = "a b c d e f";
+        Object[] o1 = new Object[]{"a", "b", "c", "d", "e", "f"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = " ";
+        String nullString = "";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction10() throws SQLException {
+        String string = "axbxcxdxexf";
+        Object[] o1 = new Object[]{"a", "b", "c", "d", "e", "f"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = "x";
+        String nullString = "";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction11() throws SQLException {
+        String string = "axbxcxdxexfx*";
+        Object[] o1 = new Object[]{"a", "b", "c", "d", "e", "f", null};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = "x";
+        String nullString = "*";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction12() throws SQLException {
+        String string = "* a b c d e f";
+        Object[] o1 = new Object[]{null, "a", "b", "c", "d", "e", "f"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = " ";
+        String nullString = "*";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction13() throws SQLException {
+        String string = "a * b * c d e f";
+        Object[] o1 = new Object[]{"a", null, "b", null, "c", "d", "e", "f"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = " ";
+        String nullString = "*";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction14() throws SQLException {
+        String string = "null a null";
+        Object[] o1 = new Object[]{null, "a", null};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = " ";
+        String nullString = "null";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction16() throws SQLException {
+        String string = "null a null";
+        Object[] o1 = new Object[]{null, "a", null};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = " ";
+        String nullString = "null";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction17() throws SQLException {
+        String string = "null a null";
+        Object[] o1 = new Object[]{null, "a", null};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = " ";
+        String nullString = "null";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PChar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PChar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction18() throws SQLException {
+        String string = "null,a,null";
+        Object[] o1 = new Object[]{null, "a", null};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = ",";
+        String nullString = "null";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PChar.INSTANCE, PChar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PChar.INSTANCE, PChar.INSTANCE, PVarchar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction19() throws SQLException {
+        String string = "null,a,null";
+        Object[] o1 = new Object[]{null, "a", null};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = ",";
+        String nullString = "null";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PChar.INSTANCE, PChar.INSTANCE, PChar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PChar.INSTANCE, PChar.INSTANCE, PChar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction20() throws SQLException {
+        String string = "abc";
+        Object[] o1 = new Object[]{"a", "b", "c"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = null;
+        String nullString = "null";
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PChar.INSTANCE, PChar.INSTANCE, PChar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PChar.INSTANCE, PChar.INSTANCE, PChar.INSTANCE);
+    }
+
+    @Test
+    public void testStringToArrayFunction21() throws SQLException {
+        String string = "(?!^)";
+        Object[] o1 = new Object[]{"(", "?", "!", "^", ")"};
+        PhoenixArray expected = new PhoenixArray(PVarchar.INSTANCE, o1);
+        String delimiter = null;
+        String nullString = null;
+        test(string, delimiter, nullString, expected, SortOrder.ASC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+        test(string, delimiter, nullString, expected, SortOrder.DESC, SortOrder.ASC, SortOrder.ASC, PVarchar.INSTANCE, PVarchar.INSTANCE, PVarchar.INSTANCE);
+    }
+}