PHOENIX-3881 PHOENIX-3882 PHOENIX-3502 Support Arrays in phoenix-calcite (Ankit Singhal)
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/b2d7fe01 Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/b2d7fe01 Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/b2d7fe01 Branch: refs/heads/calcite Commit: b2d7fe01588848fc789b1f670805ccc64b6badba Parents: e37387d Author: Ankit Singhal <[email protected]> Authored: Mon Jul 3 11:06:12 2017 +0530 Committer: Ankit Singhal <[email protected]> Committed: Mon Jul 3 11:06:12 2017 +0530 ---------------------------------------------------------------------- .../phoenix/end2end/ArrayFillFunctionIT.java | 5 +- .../org/apache/phoenix/end2end/ArrayIT.java | 32 ++- .../phoenix/end2end/ArrayPrependFunctionIT.java | 19 +- .../end2end/ArrayToStringFunctionIT.java | 43 ++-- .../end2end/StringToArrayFunctionIT.java | 17 +- .../apache/phoenix/calcite/CalciteUtils.java | 140 +++++++++++-- .../phoenix/calcite/PhoenixScalarFunction.java | 23 +- .../apache/phoenix/calcite/PhoenixSchema.java | 209 +++++++++++++++---- .../expression/BindParameterExpression.java | 16 +- .../function/ArrayAppendFunction.java | 15 +- .../function/ArrayConcatFunction.java | 3 +- .../function/ArrayElemRefExpression.java | 4 + .../expression/function/ArrayFillFunction.java | 12 +- .../expression/function/ArrayIndexFunction.java | 12 +- .../function/ArrayLengthFunction.java | 10 +- .../function/ArrayPrependFunction.java | 12 +- .../function/ArrayToStringFunction.java | 11 +- .../apache/phoenix/parse/FunctionParseNode.java | 3 +- .../phoenix/schema/types/PArrayDataType.java | 5 +- .../phoenix/schema/types/PBinaryArray.java | 3 +- .../phoenix/schema/types/PBooleanArray.java | 3 +- .../apache/phoenix/schema/types/PCharArray.java | 3 +- .../apache/phoenix/schema/types/PDataType.java | 2 +- .../phoenix/schema/types/PDoubleArray.java | 3 +- .../phoenix/schema/types/PIntegerArray.java | 3 +- .../phoenix/schema/types/PVarbinaryArray.java | 3 +- .../phoenix/schema/types/PVarcharArray.java | 3 +- .../phoenix/compile/QueryCompilerTest.java | 78 +++---- .../java/org/apache/phoenix/query/BaseTest.java | 37 +++- 29 files changed, 522 insertions(+), 207 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayFillFunctionIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayFillFunctionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayFillFunctionIT.java index 5133e5d..a94444e 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayFillFunctionIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayFillFunctionIT.java @@ -18,7 +18,6 @@ package org.apache.phoenix.end2end; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -225,7 +224,7 @@ public class ArrayFillFunctionIT extends ParallelStatsDisabledIT { assertFalse(rs.next()); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = AssertionError.class) public void testArrayFillFunctionInvalidLength1() throws Exception { Connection conn = DriverManager.getConnection(getUrl()); @@ -243,7 +242,7 @@ public class ArrayFillFunctionIT extends ParallelStatsDisabledIT { assertFalse(rs.next()); } - @Test(expected = IllegalArgumentException.class) + @Test(expected = AssertionError.class) public void testArrayFillFunctionInvalidLength2() throws Exception { Connection conn = DriverManager.getConnection(getUrl()); http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java index 26fba02..32b9825 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayIT.java @@ -22,7 +22,6 @@ import static org.apache.phoenix.util.TestUtil.B_VALUE; import static org.apache.phoenix.util.TestUtil.ROW1; import static org.apache.phoenix.util.TestUtil.TABLE_WITH_ARRAY; import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -39,7 +38,6 @@ import java.sql.Types; import java.util.Properties; import org.apache.phoenix.query.BaseTest; -import org.apache.phoenix.schema.types.PhoenixArray; import org.apache.phoenix.util.PhoenixRuntime; import org.apache.phoenix.util.PropertiesUtil; import org.apache.phoenix.util.SchemaUtil; @@ -143,7 +141,7 @@ public class ArrayIT extends BaseClientManagedTimeIT { props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 2)); // Execute at timestamp 2 Connection conn = DriverManager.getConnection(getUrl(), props); - analyzeTable(conn, TABLE_WITH_ARRAY); + analyzeTable(conn, TABLE_WITH_ARRAY); try { PreparedStatement statement = conn.prepareStatement(query); statement.setString(1, tenantId); @@ -158,7 +156,7 @@ public class ArrayIT extends BaseClientManagedTimeIT { doubleArr[3] = 386.63; Array array = conn.createArrayOf("DOUBLE", doubleArr); - PhoenixArray resultArray = (PhoenixArray) rs.getArray(1); + Array resultArray = rs.getArray(1); assertEquals(resultArray, array); assertEquals("[25.343, 36.763, 37.56, 386.63]", rs.getString(1)); assertEquals(rs.getString("B_string"), B_VALUE); @@ -282,9 +280,9 @@ public class ArrayIT extends BaseClientManagedTimeIT { strArr[2] = "XYZWER"; strArr[3] = "AB"; Array array = conn.createArrayOf("VARCHAR", strArr); - PhoenixArray resultArray = (PhoenixArray) rs.getArray(1); + Array resultArray = rs.getArray(1); assertEquals(resultArray, array); - assertEquals("['ABC', 'CEDF', 'XYZWER', 'AB']", rs.getString(1)); + assertEquals("[ABC, CEDF, XYZWER, AB]", rs.getString(1)); assertFalse(rs.next()); } finally { conn.close(); @@ -692,7 +690,7 @@ public class ArrayIT extends BaseClientManagedTimeIT { Array resultArr = conn.createArrayOf("VARCHAR", strArr); assertEquals(resultArr, array); // since array is var length, last string element is messed up - String expectedPrefix = "['abc', 'defgh', 'b"; + String expectedPrefix = "[abc, defgh, b"; assertTrue("Expected to start with " + expectedPrefix, rs.getString(2).startsWith(expectedPrefix)); assertFalse(rs.next()); @@ -835,9 +833,9 @@ public class ArrayIT extends BaseClientManagedTimeIT { conn = DriverManager.getConnection(getUrl(), props); rs = conn.createStatement().executeQuery("SELECT b_string_array FROM t"); assertTrue(rs.next()); - PhoenixArray strArr = (PhoenixArray)rs.getArray(1); + Array strArr = rs.getArray(1); assertEquals(array, strArr); - assertEquals("['abc', 'def', 'ghi', 'jkll', null, null, null, 'xxx']", rs.getString(1)); + assertEquals("[abc, def, ghi, jkll, null, null, null, xxx]", rs.getString(1)); conn.close(); } @@ -1005,7 +1003,7 @@ public class ArrayIT extends BaseClientManagedTimeIT { assertArrayGetString(rs, intIndex, intArray, "5555, 6666"); assertArrayGetString(rs, longIndex, longArray, "7777777, 8888888"); assertArrayGetString(rs, shortIndex, shortArray, "333, 444"); - assertArrayGetString(rs, stringIndex, stringArray, "'a', 'b'"); + assertArrayGetString(rs, stringIndex, stringArray, "a, b"); conn.close(); } @@ -1039,11 +1037,11 @@ public class ArrayIT extends BaseClientManagedTimeIT { conn.close(); props.setProperty(PhoenixRuntime.CURRENT_SCN_ATTRIB, Long.toString(ts + 40)); conn = DriverManager.getConnection(getUrl(), props); - rs = conn.createStatement().executeQuery("SELECT CAST(a AS DOUBLE []) FROM t"); + rs = conn.createStatement().executeQuery("SELECT CAST(a AS DOUBLE array) FROM t"); assertTrue(rs.next()); Double[] d = new Double[] { 1.0, 2.0 }; array = conn.createArrayOf("DOUBLE", d); - PhoenixArray arr = (PhoenixArray)rs.getArray(1); + Array arr = rs.getArray(1); assertEquals(array, arr); assertEquals("[1.0, 2.0]", rs.getString(1)); conn.close(); @@ -1065,7 +1063,7 @@ public class ArrayIT extends BaseClientManagedTimeIT { stmt = conn.prepareStatement("UPSERT INTO t VALUES(?,?)"); stmt.setString(1, "a"); String[] s = new String[] { "1", "2" }; - PhoenixArray array = (PhoenixArray)conn.createArrayOf("VARCHAR", s); + Array array = conn.createArrayOf("VARCHAR", s); stmt.setArray(2, array); stmt.execute(); conn.commit(); @@ -1075,7 +1073,7 @@ public class ArrayIT extends BaseClientManagedTimeIT { conn = DriverManager.getConnection(getUrl(), props); rs = conn.createStatement().executeQuery("SELECT CAST(a AS CHAR ARRAY) FROM t"); assertTrue(rs.next()); - PhoenixArray arr = (PhoenixArray)rs.getArray(1); + Array arr = rs.getArray(1); String[] array2 = (String[])array.getArray(); String[] array3 = (String[])arr.getArray(); assertEquals(array2[0], array3[0]); @@ -1146,7 +1144,7 @@ public class ArrayIT extends BaseClientManagedTimeIT { doubleArr[2] = 37.56; doubleArr[3] = 386.63; Array array = conn.createArrayOf("DOUBLE", doubleArr); - PhoenixArray resultArray = (PhoenixArray) rs.getArray(1); + Array resultArray = rs.getArray(1); assertEquals(resultArray, array); assertEquals("[25.343, 36.763, 37.56, 386.63]", rs.getString(1)); assertFalse(rs.next()); @@ -1427,8 +1425,8 @@ public class ArrayIT extends BaseClientManagedTimeIT { PreparedStatement statement = conn.prepareStatement(query); ResultSet rs = statement.executeQuery(); assertTrue(rs.next()); - PhoenixArray resultArray = (PhoenixArray) rs.getArray(1); - assertNull(resultArray); + Double result = rs.getDouble(1); + assertTrue(result!=null); } finally { conn.close(); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayPrependFunctionIT.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayPrependFunctionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayPrependFunctionIT.java index 182e664..d9cf7ec 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayPrependFunctionIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayPrependFunctionIT.java @@ -18,13 +18,16 @@ package org.apache.phoenix.end2end; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import java.sql.*; +import java.sql.Array; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; import org.apache.phoenix.schema.TypeMismatchException; -import org.apache.phoenix.schema.types.PhoenixArray; import org.junit.Test; public class ArrayPrependFunctionIT extends ParallelStatsDisabledIT { @@ -33,7 +36,7 @@ public class ArrayPrependFunctionIT extends ParallelStatsDisabledIT { conn.createStatement().execute("CREATE TABLE " + tableName + " ( k VARCHAR PRIMARY KEY, a " + type + "[],b " + type + ")"); conn.commit(); PreparedStatement stmt = conn.prepareStatement("UPSERT INTO " + tableName + " VALUES(?,?," + value + ")"); - PhoenixArray array = (PhoenixArray) conn.createArrayOf(type, objectArray); + Array array = conn.createArrayOf(type, objectArray); stmt.setString(1, "a"); stmt.setArray(2, array); stmt.execute(); @@ -120,7 +123,7 @@ public class ArrayPrependFunctionIT extends ParallelStatsDisabledIT { String tableName = generateUniqueName(); initTableWithVarArray(conn, tableName, "VARCHAR", s, null); String[] s2 = new String[]{null, null, null, "1", "2"}; - PhoenixArray array2 = (PhoenixArray) conn.createArrayOf("VARCHAR", s2); + Array array2 = conn.createArrayOf("VARCHAR", s2); conn = DriverManager.getConnection(getUrl()); ResultSet rs; rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(b,a) FROM " + tableName + " WHERE k = 'a'"); @@ -135,7 +138,7 @@ public class ArrayPrependFunctionIT extends ParallelStatsDisabledIT { String tableName = generateUniqueName(); initTableWithVarArray(conn, tableName, "VARCHAR", s, null); String[] s2 = new String[]{null, "1", "2"}; - PhoenixArray array2 = (PhoenixArray) conn.createArrayOf("VARCHAR", s2); + Array array2 = conn.createArrayOf("VARCHAR", s2); conn = DriverManager.getConnection(getUrl()); ResultSet rs; rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(b,a) FROM " + tableName + " WHERE k = 'a'"); @@ -150,7 +153,7 @@ public class ArrayPrependFunctionIT extends ParallelStatsDisabledIT { String tableName = generateUniqueName(); initTableWithVarArray(conn, tableName, "VARCHAR", s, null); String[] s2 = new String[]{null, "176", null, "212"}; - PhoenixArray array2 = (PhoenixArray) conn.createArrayOf("VARCHAR", s2); + Array array2 = conn.createArrayOf("VARCHAR", s2); conn = DriverManager.getConnection(getUrl()); ResultSet rs; rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(b,a) FROM " + tableName + " WHERE k = 'a'"); @@ -165,7 +168,7 @@ public class ArrayPrependFunctionIT extends ParallelStatsDisabledIT { String tableName = generateUniqueName(); initTableWithVarArray(conn, tableName, "VARCHAR", s, "'foo'"); String[] s2 = new String[]{"foo", "176", null, "212"}; - PhoenixArray array2 = (PhoenixArray) conn.createArrayOf("VARCHAR", s2); + Array array2 = conn.createArrayOf("VARCHAR", s2); conn = DriverManager.getConnection(getUrl()); ResultSet rs; rs = conn.createStatement().executeQuery("SELECT ARRAY_PREPEND(b,a) FROM " + tableName + " WHERE k = 'a'"); http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/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 index 8a3461c..53e21ea 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayToStringFunctionIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ArrayToStringFunctionIT.java @@ -17,7 +17,6 @@ */ package org.apache.phoenix.end2end; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -258,17 +257,17 @@ public class ArrayToStringFunctionIT extends ParallelStatsDisabledIT { public void testArrayToStringFunctionWithUpsert1() throws Exception { String table = generateUniqueName(); String ddl = - "CREATE TABLE " + table + " (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)"; + "CREATE TABLE " + table + " (region_name VARCHAR PRIMARY KEY,varchars VARCHAR)"; conn.createStatement().execute(ddl); String dml = "UPSERT INTO " + table - + "(region_name,varchar) VALUES('SF Bay Area',ARRAY_TO_STRING(ARRAY['hello','world'],','))"; + + "(region_name,varchars) 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 " + table + " WHERE region_name = 'SF Bay Area'"); + "SELECT varchars FROM " + table + " WHERE region_name = 'SF Bay Area'"); assertTrue(rs.next()); String expected = "hello,world"; @@ -281,17 +280,17 @@ public class ArrayToStringFunctionIT extends ParallelStatsDisabledIT { public void testArrayToStringFunctionWithUpsert2() throws Exception { String tableName = generateUniqueName(); String ddl = - "CREATE TABLE " + tableName + " (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)"; + "CREATE TABLE " + tableName + " (region_name VARCHAR PRIMARY KEY,varchars VARCHAR)"; conn.createStatement().execute(ddl); String dml = "UPSERT INTO " + tableName - + "(region_name,varchar) VALUES('SF Bay Area',ARRAY_TO_STRING(ARRAY[3, 4, 5],', '))"; + + "(region_name,varchars) 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 " + tableName + " WHERE region_name = 'SF Bay Area'"); + "SELECT varchars FROM " + tableName + " WHERE region_name = 'SF Bay Area'"); assertTrue(rs.next()); String expected = "3, 4, 5"; @@ -304,17 +303,17 @@ public class ArrayToStringFunctionIT extends ParallelStatsDisabledIT { public void testArrayToStringFunctionWithUpsert3() throws Exception { String tableName = generateUniqueName(); String ddl = - "CREATE TABLE " + tableName + " (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)"; + "CREATE TABLE " + tableName + " (region_name VARCHAR PRIMARY KEY,varchars VARCHAR)"; conn.createStatement().execute(ddl); String dml = "UPSERT INTO " + tableName - + "(region_name,varchar) VALUES('SF Bay Area',ARRAY_TO_STRING(ARRAY[3.1, 4.2, 5.5],', '))"; + + "(region_name,varchars) 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 " + tableName + " WHERE region_name = 'SF Bay Area'"); + "SELECT varchars FROM " + tableName + " WHERE region_name = 'SF Bay Area'"); assertTrue(rs.next()); String expected = "3.1, 4.2, 5.5"; @@ -327,17 +326,17 @@ public class ArrayToStringFunctionIT extends ParallelStatsDisabledIT { public void testArrayToStringFunctionWithUpsert4() throws Exception { String tableName = generateUniqueName(); String ddl = - "CREATE TABLE " + tableName + " (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)"; + "CREATE TABLE " + tableName + " (region_name VARCHAR PRIMARY KEY,varchars VARCHAR)"; conn.createStatement().execute(ddl); String dml = "UPSERT INTO " + tableName - + "(region_name,varchar) VALUES('SF Bay Area',ARRAY_TO_STRING(ARRAY[true, false, true],', '))"; + + "(region_name,varchars) 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 " + tableName + " WHERE region_name = 'SF Bay Area'"); + "SELECT varchars FROM " + tableName + " WHERE region_name = 'SF Bay Area'"); assertTrue(rs.next()); String expected = "true, false, true"; @@ -354,7 +353,7 @@ public class ArrayToStringFunctionIT extends ParallelStatsDisabledIT { conn.createStatement().execute(ddl); String target = generateUniqueName(); - ddl = "CREATE TABLE " + target + " (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)"; + ddl = "CREATE TABLE " + target + " (region_name VARCHAR PRIMARY KEY,varchars VARCHAR)"; conn.createStatement().execute(ddl); String dml = "UPSERT INTO " + source @@ -368,13 +367,13 @@ public class ArrayToStringFunctionIT extends ParallelStatsDisabledIT { dml = "UPSERT INTO " + target - + "(region_name, varchar) SELECT region_name, ARRAY_TO_STRING(doubles, ', ') FROM " + + "(region_name, varchars) 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); + rs = conn.createStatement().executeQuery("SELECT varchars FROM " + target); assertTrue(rs.next()); String expected = "5.67, 7.87"; @@ -394,7 +393,7 @@ public class ArrayToStringFunctionIT extends ParallelStatsDisabledIT { conn.createStatement().execute(ddl); String target = generateUniqueName(); - ddl = "CREATE TABLE " + target + " (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)"; + ddl = "CREATE TABLE " + target + " (region_name VARCHAR PRIMARY KEY,varchars VARCHAR)"; conn.createStatement().execute(ddl); String dml = "UPSERT INTO " + source @@ -408,13 +407,13 @@ public class ArrayToStringFunctionIT extends ParallelStatsDisabledIT { dml = "UPSERT INTO " + target - + "(region_name, varchar) SELECT region_name, ARRAY_TO_STRING(varchars, ':') FROM " + + "(region_name, varchars) 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); + rs = conn.createStatement().executeQuery("SELECT varchars FROM " + target); assertTrue(rs.next()); String expected = "hello:-)"; @@ -434,7 +433,7 @@ public class ArrayToStringFunctionIT extends ParallelStatsDisabledIT { conn.createStatement().execute(ddl); String target = generateUniqueName(); - ddl = "CREATE TABLE " + target + " (region_name VARCHAR PRIMARY KEY,varchar VARCHAR)"; + ddl = "CREATE TABLE " + target + " (region_name VARCHAR PRIMARY KEY,varchars VARCHAR)"; conn.createStatement().execute(ddl); String dml = "UPSERT INTO " + source @@ -448,13 +447,13 @@ public class ArrayToStringFunctionIT extends ParallelStatsDisabledIT { dml = "UPSERT INTO " + target - + "(region_name, varchar) SELECT region_name, ARRAY_TO_STRING(booleans, ', ') FROM " + + "(region_name, varchars) 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); + rs = conn.createStatement().executeQuery("SELECT varchars FROM " + target); assertTrue(rs.next()); String expected = "true, true"; http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/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 index 1afe6ef..8a44c71 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/StringToArrayFunctionIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/StringToArrayFunctionIT.java @@ -17,7 +17,6 @@ */ package org.apache.phoenix.end2end; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -352,7 +351,7 @@ public class StringToArrayFunctionIT extends ParallelStatsDisabledIT { String table1 = generateUniqueName(); String ddl = - "CREATE TABLE " + table1 + " (region_name VARCHAR PRIMARY KEY, varchar VARCHAR)"; + "CREATE TABLE " + table1 + " (region_name VARCHAR PRIMARY KEY, \"varchar\" VARCHAR)"; conn.createStatement().execute(ddl); String table2 = generateUniqueName(); @@ -360,16 +359,16 @@ public class StringToArrayFunctionIT extends ParallelStatsDisabledIT { conn.createStatement().execute(ddl); String dml = - "UPSERT INTO " + table1 + "(region_name, varchar) VALUES('SF Bay Area', 'a,b,c,d')"; + "UPSERT INTO " + table1 + "(region_name, \"varchar\") VALUES('SF Bay Area', 'a,b,c,d')"; conn.createStatement().execute(dml); - dml = "UPSERT INTO " + table1 + "(region_name, varchar) VALUES('SF Bay Area2', '1,2,3,4')"; + dml = "UPSERT INTO " + table1 + "(region_name, \"varchar\") VALUES('SF Bay Area2', '1,2,3,4')"; conn.createStatement().execute(dml); conn.commit(); dml = "UPSERT INTO " + table2 - + "(region_name, varchars) SELECT region_name, STRING_TO_ARRAY(varchar, ',') FROM " + + "(region_name, varchars) SELECT region_name, STRING_TO_ARRAY(\"varchar\", ',') FROM " + table1; conn.createStatement().execute(dml); conn.commit(); @@ -396,7 +395,7 @@ public class StringToArrayFunctionIT extends ParallelStatsDisabledIT { String sourceTable = generateUniqueName(); String ddl = - "CREATE TABLE " + sourceTable + " (region_name VARCHAR PRIMARY KEY, varchar VARCHAR)"; + "CREATE TABLE " + sourceTable + " (region_name VARCHAR PRIMARY KEY, \"varchar\" VARCHAR)"; conn.createStatement().execute(ddl); String targetTable = generateUniqueName(); @@ -405,17 +404,17 @@ public class StringToArrayFunctionIT extends ParallelStatsDisabledIT { conn.createStatement().execute(ddl); String dml = "UPSERT INTO " + sourceTable - + "(region_name, varchar) VALUES('SF Bay Area', 'a,b,-,c,d')"; + + "(region_name, \"varchar\") VALUES('SF Bay Area', 'a,b,-,c,d')"; conn.createStatement().execute(dml); dml = "UPSERT INTO " + sourceTable - + "(region_name, varchar) VALUES('SF Bay Area2', '1,2,-,3,4')"; + + "(region_name, \"varchar\") VALUES('SF Bay Area2', '1,2,-,3,4')"; conn.createStatement().execute(dml); conn.commit(); dml = "UPSERT INTO " + targetTable - + "(region_name, varchars) SELECT region_name, STRING_TO_ARRAY(varchar, ',', '-') FROM " + + "(region_name, varchars) SELECT region_name, STRING_TO_ARRAY(\"varchar\", ',', '-') FROM " + sourceTable; conn.createStatement().execute(dml); conn.commit(); http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java index ecb7f0d..6995694 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/CalciteUtils.java @@ -1,13 +1,14 @@ package org.apache.phoenix.calcite; +import java.lang.reflect.InvocationTargetException; import java.sql.SQLException; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.GregorianCalendar; import java.util.List; import java.util.Map; -import java.util.Collections; import java.util.concurrent.atomic.AtomicInteger; import org.apache.calcite.avatica.util.ByteString; @@ -39,11 +40,11 @@ import org.apache.calcite.sql.SemiJoinType; import org.apache.calcite.sql.SqlAggFunction; import org.apache.calcite.sql.SqlFunction; import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlLiteral; -import org.apache.calcite.sql.SqlSelect; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlNodeList; +import org.apache.calcite.sql.SqlOperator; +import org.apache.calcite.sql.SqlSelect; import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.parser.SqlParser; import org.apache.calcite.sql.parser.SqlParserPos; @@ -62,6 +63,7 @@ import org.apache.phoenix.compile.ExpressionCompiler; import org.apache.phoenix.compile.ExpressionManager; import org.apache.phoenix.compile.StatementContext; import org.apache.phoenix.expression.AndExpression; +import org.apache.phoenix.expression.ArrayConstructorExpression; import org.apache.phoenix.expression.CaseExpression; import org.apache.phoenix.expression.CoerceExpression; import org.apache.phoenix.expression.ComparisonExpression; @@ -94,6 +96,7 @@ import org.apache.phoenix.expression.TimestampAddExpression; import org.apache.phoenix.expression.TimestampSubtractExpression; import org.apache.phoenix.expression.function.AbsFunction; import org.apache.phoenix.expression.function.AggregateFunction; +import org.apache.phoenix.expression.function.ArrayElemRefExpression; import org.apache.phoenix.expression.function.AvgAggregateFunction; import org.apache.phoenix.expression.function.CeilDateExpression; import org.apache.phoenix.expression.function.CeilDecimalExpression; @@ -130,20 +133,21 @@ import org.apache.phoenix.expression.function.SumAggregateFunction; import org.apache.phoenix.expression.function.TrimFunction; import org.apache.phoenix.expression.function.UDFExpression; import org.apache.phoenix.expression.function.UpperFunction; -import org.apache.phoenix.jdbc.PhoenixConnection; -import org.apache.phoenix.jdbc.PhoenixStatement; import org.apache.phoenix.expression.function.WeekFunction; import org.apache.phoenix.expression.function.YearFunction; +import org.apache.phoenix.jdbc.PhoenixConnection; +import org.apache.phoenix.jdbc.PhoenixStatement; import org.apache.phoenix.parse.FunctionParseNode; -import org.apache.phoenix.parse.ParseNode; -import org.apache.phoenix.parse.SQLParser; import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunctionInfo; import org.apache.phoenix.parse.JoinTableNode.JoinType; +import org.apache.phoenix.parse.ParseNode; +import org.apache.phoenix.parse.SQLParser; import org.apache.phoenix.parse.SequenceValueParseNode; import org.apache.phoenix.schema.PColumn; import org.apache.phoenix.schema.PTableType; import org.apache.phoenix.schema.SortOrder; import org.apache.phoenix.schema.TypeMismatchException; +import org.apache.phoenix.schema.types.PArrayDataType; import org.apache.phoenix.schema.types.PBinary; import org.apache.phoenix.schema.types.PBinaryArray; import org.apache.phoenix.schema.types.PChar; @@ -156,13 +160,13 @@ import org.apache.phoenix.schema.types.PLong; import org.apache.phoenix.schema.types.PTimestamp; import org.apache.phoenix.schema.types.PUnsignedTimestamp; import org.apache.phoenix.schema.types.PVarchar; +import org.apache.phoenix.schema.types.PhoenixArray; +import org.apache.phoenix.util.ExpressionUtil; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import org.apache.phoenix.util.ExpressionUtil; - /** * Utilities for interacting with Calcite. */ @@ -246,7 +250,9 @@ public class CalciteUtils { type = typeFactory.createSqlType(sqlTypeName); } if (isArrayType) { - type = typeFactory.createArrayType(type, arraySize == null ? -1 : arraySize); + type = + typeFactory.createArrayType( + typeFactory.createTypeWithNullability(type, type.isNullable()),-1); } return type; @@ -782,12 +788,12 @@ public class CalciteUtils { RexDynamicParam param = (RexDynamicParam) node; int index = param.getIndex(); PDataType type = relDataTypeToPDataType(node.getType()); - Integer maxLength = - (type == PChar.INSTANCE - || type == PCharArray.INSTANCE - || type == PBinary.INSTANCE - || type == PBinaryArray.INSTANCE) ? - node.getType().getPrecision() : null; + Integer maxLength = (type == PChar.INSTANCE + + || type == PBinary.INSTANCE) ? node.getType().getPrecision() : null; + if (type == PCharArray.INSTANCE || type == PBinaryArray.INSTANCE) { + maxLength = node.getType().getComponentType().getPrecision(); + } return implementor.newBindParameterExpression(index, type, maxLength); } }); @@ -891,7 +897,7 @@ public class CalciteUtils { @Override public Expression newExpression(RexNode node, PhoenixRelImplementor implementor) { - RexCall call = (RexCall) node; + final RexCall call = (RexCall) node; List<Expression> children = convertChildren(call, implementor); SqlOperator op = call.getOperator(); try { @@ -917,10 +923,15 @@ public class CalciteUtils { try { try { return info.getFunc().getDeclaredConstructor(List.class).newInstance(children); - } catch (Exception e) { + } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | IllegalArgumentException | SecurityException e) { return info.getFunc().getDeclaredConstructor(List.class, StatementContext.class).newInstance(children, implementor.getStatementContext()); } - } catch (Exception e) {throw new RuntimeException ("Failed to create builtin function " + info.getName(), e);} + }catch(InvocationTargetException e){ + if(e.getTargetException() instanceof SQLException){ + throw (SQLException)e.getTargetException(); + } + } + catch (NoSuchMethodException | InstantiationException | IllegalAccessException | IllegalArgumentException | SecurityException e) {throw new RuntimeException ("Failed to create builtin function " + info.getName(), e);} } return new UDFExpression(children, scalarFunc.getPFunction()); } @@ -946,7 +957,12 @@ public class CalciteUtils { return new CoalesceFunction(children); } else if (op == SqlStdOperatorTable.MOD) { return new ModulusExpression(children); - }; + } else if (op == SqlStdOperatorTable.ITEM){ + ArrayElemRefExpression arrayElemRefExpression = new ArrayElemRefExpression(children); + return arrayElemRefExpression; + } + + } catch (SQLException e) { throw new RuntimeException(e); } @@ -1085,6 +1101,66 @@ public class CalciteUtils { return implementor.newSequenceExpression(seq, SequenceValueParseNode.Op.NEXT_VALUE); } }); + EXPRESSION_MAP.put(SqlKind.ARRAY_VALUE_CONSTRUCTOR, new ExpressionFactory() { + @Override + public Expression newExpression(RexNode node, PhoenixRelImplementor implementor) { + List<Expression> children = convertChildren((RexCall) node, implementor); + boolean rowKeyOrderOptimizable = + implementor.getTableMapping().getPTable().rowKeyOrderOptimizable(); + PDataType dataType = + + relDataTypeToPDataType(node.getType().getComponentType()); + ArrayConstructorExpression arrayExpression = + new ArrayConstructorExpression(children, dataType, + rowKeyOrderOptimizable); + ImmutableBytesWritable ptr = new ImmutableBytesWritable(); + if (ExpressionUtil.isConstant(arrayExpression)) { + boolean hasNullValue=false; + for (RexNode l : ((RexCall) node).getOperands()) { + if(l instanceof RexLiteral && ((RexLiteral)l).getValue()==null){ + hasNullValue=true; + break; + } + } + PDataType arrayElemDataType = getArrayElemDataType(hasNullValue,dataType); + Object[] elements = + (Object[]) java.lang.reflect.Array + .newInstance(arrayElemDataType.getJavaClass(), children.size()); + try { + for (int i = 0; i < children.size(); i++) { + + Expression child = children.get(i); + child.evaluate(null, ptr); + Object value = null; + if (child.getDataType() == null) { + value = + arrayElemDataType.toObject(ptr, arrayElemDataType, + child.getSortOrder()); + } else { + value = + arrayElemDataType.toObject(ptr, child.getDataType(), + child.getSortOrder()); + + } + elements[i] = + LiteralExpression.newConstant(value, arrayElemDataType, + child.getDeterminism()).getValue(); + } + Object value = PArrayDataType.instantiatePhoenixArray(arrayElemDataType, + elements); + return LiteralExpression.newConstant(value, + PDataType.fromTypeId( + arrayElemDataType.getSqlType() + PDataType.ARRAY_TYPE_BASE), + null, null, arrayExpression.getSortOrder(), Determinism.ALWAYS, + rowKeyOrderOptimizable); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + return arrayExpression; + } + }); + EXPRESSION_MAP.put(SqlKind.CASE, new ExpressionFactory() { @Override public Expression newExpression(RexNode node, PhoenixRelImplementor implementor) { @@ -1428,11 +1504,19 @@ public class CalciteUtils { column.getDataType().toObject(key, column.getSortOrder(), defaultExpression.getMaxLength(), column.getScale()); + //TODO: if we can do something better here + if(column.getDataType().isArrayType()){ + try { + object=Arrays.asList(((PhoenixArray)object).getArray()); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } RelDataType pDataTypeToRelDataType = CalciteUtils.pDataTypeToRelDataType(rexBuilder.getTypeFactory(), column.getDataType(), column.getMaxLength(), column.getScale(), column.getArraySize()); - return rexBuilder.makeLiteral((Comparable)object, pDataTypeToRelDataType,true); + return rexBuilder.makeLiteral(object, pDataTypeToRelDataType,true); } private static void throwDistinctNotSupportedException(boolean isDistinct, String func) { @@ -1440,4 +1524,18 @@ public class CalciteUtils { throw new UnsupportedOperationException("DISTINCT " + func + " not supported."); } } + + private static PDataType getArrayElemDataType(boolean hasNullValue, PDataType baseType) { + // make the return type be the most general number type + if (baseType != null) { + if (baseType.isCoercibleTo(PVarchar.INSTANCE)) { + return PVarchar.INSTANCE; + } + if(hasNullValue && baseType.isCoercibleTo(PDecimal.INSTANCE)){ + return PDecimal.INSTANCE; + } + } + return baseType; + } + } http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixScalarFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixScalarFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixScalarFunction.java index 2d5978d..320d688 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixScalarFunction.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixScalarFunction.java @@ -20,8 +20,8 @@ package org.apache.phoenix.calcite; import java.util.List; import org.apache.calcite.adapter.enumerable.CallImplementor; -import org.apache.calcite.adapter.enumerable.RexToLixTranslator; import org.apache.calcite.adapter.enumerable.RexImpTable.NullAs; +import org.apache.calcite.adapter.enumerable.RexToLixTranslator; import org.apache.calcite.linq4j.tree.Expression; import org.apache.calcite.linq4j.tree.Expressions; import org.apache.calcite.rel.type.RelDataType; @@ -30,6 +30,7 @@ import org.apache.calcite.rex.RexCall; import org.apache.calcite.schema.FunctionParameter; import org.apache.calcite.schema.ImplementableFunction; import org.apache.calcite.schema.ScalarFunction; +import org.apache.calcite.sql.type.SqlTypeName; import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunctionInfo; import org.apache.phoenix.parse.PFunction; import org.apache.phoenix.parse.PFunction.FunctionArgument; @@ -63,11 +64,14 @@ public class PhoenixScalarFunction implements ScalarFunction, ImplementableFunct @SuppressWarnings("rawtypes") public RelDataType getType(RelDataTypeFactory typeFactory) { - PDataType dataType = - arg.isArrayType() ? PDataType.fromTypeId(PDataType.sqlArrayType(SchemaUtil - .normalizeIdentifier(SchemaUtil.normalizeIdentifier(arg - .getArgumentType())))) : PDataType.fromSqlTypeName(SchemaUtil - .normalizeIdentifier(arg.getArgumentType())); + PDataType dataType = + PDataType.fromSqlTypeName( + SchemaUtil.normalizeIdentifier(arg.getArgumentType())); + if (dataType.isArrayType()) { + return typeFactory.createArrayType( + typeFactory.createSqlType(SqlTypeName.valueOf(PDataType.arrayBaseType(dataType + ).getSqlTypeName())), -1); + } return typeFactory.createJavaType(dataType.getJavaClass()); } @@ -88,6 +92,13 @@ public class PhoenixScalarFunction implements ScalarFunction, ImplementableFunct @Override public RelDataType getReturnType(RelDataTypeFactory typeFactory) { + if (returnType.isArrayType()) { + return typeFactory + .createArrayType( + typeFactory.createSqlType(SqlTypeName + .valueOf(PDataType.arrayBaseType(returnType).getSqlTypeName())), + -1); + } return typeFactory.createJavaType(returnType.getJavaClass()); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixSchema.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixSchema.java b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixSchema.java index 6d9afdf..4b0ec74 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixSchema.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/calcite/PhoenixSchema.java @@ -1,71 +1,109 @@ package org.apache.phoenix.calcite; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.common.collect.Multimap; -import com.google.common.collect.ArrayListMultimap; +import java.lang.reflect.Constructor; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; import org.apache.calcite.jdbc.CalciteSchema; import org.apache.calcite.linq4j.tree.Expression; import org.apache.calcite.materialize.MaterializationService; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.rel.type.RelDataTypeFactory; -import org.apache.calcite.schema.*; +import org.apache.calcite.schema.Function; +import org.apache.calcite.schema.FunctionParameter; +import org.apache.calcite.schema.Schema; +import org.apache.calcite.schema.SchemaFactory; +import org.apache.calcite.schema.SchemaPlus; +import org.apache.calcite.schema.Table; import org.apache.calcite.schema.impl.TableFunctionImpl; import org.apache.calcite.schema.impl.ViewTable; import org.apache.calcite.sql.ListJarsTable; +import org.apache.calcite.sql.type.SqlTypeName; +import org.apache.hadoop.hbase.io.ImmutableBytesWritable; +import org.apache.hadoop.hbase.util.Pair; import org.apache.phoenix.compile.ColumnResolver; import org.apache.phoenix.compile.FromCompiler; import org.apache.phoenix.compile.SequenceManager; -import org.apache.phoenix.expression.function.FunctionExpression; -import org.apache.phoenix.expression.function.UDFExpression; +import org.apache.phoenix.expression.BaseExpression; +import org.apache.phoenix.expression.function.ByteBasedRegexpReplaceFunction; import org.apache.phoenix.expression.function.ByteBasedRegexpSplitFunction; import org.apache.phoenix.expression.function.ByteBasedRegexpSubstrFunction; -import org.apache.phoenix.expression.function.ByteBasedRegexpReplaceFunction; +import org.apache.phoenix.expression.function.FunctionExpression; +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.StringBasedRegexpReplaceFunction; +import org.apache.phoenix.expression.function.UDFExpression; +import org.apache.phoenix.expression.visitor.ExpressionVisitor; import org.apache.phoenix.jdbc.PhoenixConnection; +import org.apache.phoenix.jdbc.PhoenixStatement; import org.apache.phoenix.parse.ColumnDef; -import org.apache.phoenix.parse.NamedTableNode; -import org.apache.phoenix.parse.PFunction; -import org.apache.phoenix.parse.SequenceValueParseNode; -import org.apache.phoenix.parse.TableName; import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction; -import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunctionInfo; import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunctionArgInfo; +import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunctionInfo; import org.apache.phoenix.parse.FunctionParseNode.FunctionClassType; -import org.apache.phoenix.parse.ParseNodeFactory; +import org.apache.phoenix.parse.NamedTableNode; +import org.apache.phoenix.parse.PFunction; import org.apache.phoenix.parse.PFunction.FunctionArgument; +import org.apache.phoenix.parse.ParseNodeFactory; +import org.apache.phoenix.parse.SequenceValueParseNode; +import org.apache.phoenix.parse.TableName; import org.apache.phoenix.query.QueryServices; import org.apache.phoenix.query.QueryServicesOptions; import org.apache.phoenix.schema.MetaDataClient; import org.apache.phoenix.schema.PColumn; import org.apache.phoenix.schema.PTable; -import org.apache.phoenix.jdbc.PhoenixStatement; import org.apache.phoenix.schema.PTable.ViewType; import org.apache.phoenix.schema.PTableImpl; import org.apache.phoenix.schema.PTableType; import org.apache.phoenix.schema.Sequence; import org.apache.phoenix.schema.TableNotFoundException; import org.apache.phoenix.schema.TableRef; +import org.apache.phoenix.schema.tuple.Tuple; +import org.apache.phoenix.schema.types.PBinary; +import org.apache.phoenix.schema.types.PBinaryArray; +import org.apache.phoenix.schema.types.PBoolean; +import org.apache.phoenix.schema.types.PBooleanArray; +import org.apache.phoenix.schema.types.PChar; +import org.apache.phoenix.schema.types.PCharArray; import org.apache.phoenix.schema.types.PDataType; import org.apache.phoenix.schema.types.PDataTypeFactory; +import org.apache.phoenix.schema.types.PDate; +import org.apache.phoenix.schema.types.PDateArray; +import org.apache.phoenix.schema.types.PDouble; +import org.apache.phoenix.schema.types.PDoubleArray; +import org.apache.phoenix.schema.types.PFloat; +import org.apache.phoenix.schema.types.PFloatArray; +import org.apache.phoenix.schema.types.PInteger; +import org.apache.phoenix.schema.types.PIntegerArray; +import org.apache.phoenix.schema.types.PLong; +import org.apache.phoenix.schema.types.PLongArray; +import org.apache.phoenix.schema.types.PTime; +import org.apache.phoenix.schema.types.PTimeArray; +import org.apache.phoenix.schema.types.PTimestamp; +import org.apache.phoenix.schema.types.PTimestampArray; +import org.apache.phoenix.schema.types.PVarbinary; +import org.apache.phoenix.schema.types.PVarbinaryArray; +import org.apache.phoenix.schema.types.PVarchar; +import org.apache.phoenix.schema.types.PVarcharArray; import org.apache.phoenix.util.IndexUtil; import org.apache.phoenix.util.SchemaUtil; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Sets; /** * Implementation of Calcite's {@link Schema} SPI for Phoenix. @@ -95,6 +133,8 @@ public class PhoenixSchema implements Schema { .create(ListJarsTable.LIST_JARS_TABLE_METHOD); private final Multimap<String, Function> builtinFunctions = ArrayListMultimap.create(); private RelDataTypeFactory typeFactory; + Map<Class<? extends PDataType>, List<Class<? extends PDataType>>> overalodDataTypesForArrayFunctions = + new HashMap<Class<? extends PDataType>, List<Class<? extends PDataType>>>(); protected PhoenixSchema(String name, String schemaName, SchemaPlus parentSchema, PhoenixConnection pc) { @@ -114,9 +154,27 @@ public class PhoenixSchema implements Schema { } catch (SQLException e){ throw new RuntimeException(e); } + initializeOveralodMapForArrayFunctions(); registerBuiltinFunctions(); } + private void initializeOveralodMapForArrayFunctions() { + + this.overalodDataTypesForArrayFunctions.put(PBinaryArray.class, + new ArrayList<Class<? extends PDataType>>(Arrays.asList(PIntegerArray.class, + PFloatArray.class,PDoubleArray.class, PBooleanArray.class, PCharArray.class, PLongArray.class, + PTimeArray.class, PTimestampArray.class, PDateArray.class))); + this.overalodDataTypesForArrayFunctions.put(PVarbinaryArray.class, + new ArrayList<Class<? extends PDataType>>(Arrays.asList(PVarcharArray.class))); + this.overalodDataTypesForArrayFunctions.put(PBinary.class, + new ArrayList<Class<? extends PDataType>>( + Arrays.asList(PInteger.class, PBoolean.class, PChar.class, + PLong.class, PTime.class, PTimestamp.class, PDate.class,PFloat.class,PDouble.class))); + this.overalodDataTypesForArrayFunctions.put(PVarbinary.class, + new ArrayList<Class<? extends PDataType>>(Arrays.asList(PVarchar.class))); + + } + protected PhoenixSchema(String name, String schemaName, SchemaPlus parentSchema, PhoenixConnection pc, RelDataTypeFactory typeFactory) { this(name, schemaName, parentSchema, pc); @@ -206,8 +264,8 @@ public class PhoenixSchema implements Schema { } // Converts phoenix function information to a list of Calcite function signatures - private static List<PhoenixScalarFunction> convertBuiltinFunction(BuiltInFunctionInfo functionInfo){ - List<List<FunctionArgument>> overloadedArgs = PhoenixSchema.overloadArguments(functionInfo.getArgs()); + private List<PhoenixScalarFunction> convertBuiltinFunction(BuiltInFunctionInfo functionInfo){ + List<List<FunctionArgument>> overloadedArgs = overloadArguments(functionInfo.getArgs(),functionInfo.getClassType()==FunctionClassType.ARRAY); List<PhoenixScalarFunction> functionList = Lists.newArrayListWithExpectedSize(overloadedArgs.size()); Class<? extends FunctionExpression> clazz = functionInfo.getFunc(); @@ -230,10 +288,15 @@ public class PhoenixSchema implements Schema { @SuppressWarnings("rawtypes") public RelDataType getType(RelDataTypeFactory typeFactory) { PDataType dataType = - arg.isArrayType() ? PDataType.fromTypeId(PDataType.sqlArrayType(SchemaUtil - .normalizeIdentifier(SchemaUtil.normalizeIdentifier(arg - .getArgumentType())))) : PDataType.fromSqlTypeName(SchemaUtil + PDataType.fromSqlTypeName(SchemaUtil .normalizeIdentifier(arg.getArgumentType())); + if (dataType.isArrayType()) { + return typeFactory + .createArrayType( + typeFactory.createSqlType(SqlTypeName + .valueOf(PDataType.arrayBaseType(dataType).getSqlTypeName())), + -1); + } return typeFactory.createJavaType(dataType.getJavaClass()); } @@ -254,9 +317,44 @@ public class PhoenixSchema implements Schema { private static PDataType evaluateReturnType(Class<? extends FunctionExpression> f, List<FunctionArgument> argumentList) { BuiltInFunction d = f.getAnnotation(BuiltInFunction.class); try { - // Direct evaluation of the return type - FunctionExpression func = f.newInstance(); - return func.getDataType(); + if (argumentList.size() > 0 && d.classType() == FunctionClassType.ARRAY) { + Constructor constructor = + f.getConstructor(new Class[]{List.class}); + List<BaseExpression> list=new ArrayList<BaseExpression>(); + for(final FunctionArgument arg:argumentList){ + list.add(new BaseExpression(){ + + @Override + public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { + // TODO Auto-generated method stub + return false; + } + + @Override + public <T> T accept(ExpressionVisitor<T> visitor) { + // TODO Auto-generated method stub + return null; + } + + @Override + public List<org.apache.phoenix.expression.Expression> getChildren() { + // TODO Auto-generated method stub + return null; + } + + @Override + public PDataType getDataType() { + return PDataType.fromSqlTypeName(arg.getArgumentType()); + } + + }); + } + FunctionExpression func=(FunctionExpression)constructor.newInstance(list); + return func.getDataType(); + } else { + FunctionExpression func = f.newInstance(); + return func.getDataType(); + } } catch (Exception e) { if (d.classType() == FunctionClassType.ALIAS || d.classType() == FunctionClassType.ABSTRACT) { // should never happen @@ -269,32 +367,51 @@ public class PhoenixSchema implements Schema { } // Using Phoenix argument information, determine all possible function signatures - private static List<List<PFunction.FunctionArgument>> overloadArguments(BuiltInFunctionArgInfo[] args){ + private List<List<PFunction.FunctionArgument>> overloadArguments(BuiltInFunctionArgInfo[] args, boolean isArrayOverload){ List<List<PFunction.FunctionArgument>> overloadedArgs = Lists.newArrayList(); int solutions = 1; - for(int i = 0; i < args.length; solutions *= args[i].getAllowedTypes().length, i++); + + + List<Pair<BuiltInFunctionArgInfo, List<Class<? extends PDataType>>>> argsAllowedTypePair = + new ArrayList<Pair<BuiltInFunctionArgInfo, List<Class<? extends PDataType>>>>(); + for (int i = 0; i < args.length; i++) { + List<Class<? extends PDataType>> argList = new ArrayList<Class<? extends PDataType>>(Arrays.asList(args[i].getAllowedTypes())); + if (isArrayOverload) { + for (Class<? extends PDataType> cls : this.overalodDataTypesForArrayFunctions.keySet()) { + if (argList.contains(cls)) { + argList.addAll(this.overalodDataTypesForArrayFunctions.get(cls)); + } + } + } + argsAllowedTypePair + .add(new Pair<BuiltInFunctionArgInfo, List<Class<? extends PDataType>>>(args[i], + argList)); + } + for(int i = 0; i < argsAllowedTypePair.size(); solutions *= argsAllowedTypePair.get(i).getSecond().size(), i++); for(int i = 0; i < solutions; i++) { int j = 1; short k = 0; overloadedArgs.add(new ArrayList<PFunction.FunctionArgument>()); - for(BuiltInFunctionArgInfo arg : args) { - Class<? extends PDataType>[] temp = arg.getAllowedTypes(); - PDataType dataType = PDataTypeFactory.getInstance().instanceFromClass(temp[(i/j)%temp.length]); + for(Pair<BuiltInFunctionArgInfo, List<Class<? extends PDataType>>> arg : argsAllowedTypePair) { + List<Class<? extends PDataType>> temp = arg.getSecond(); + PDataType dataType = PDataTypeFactory.getInstance().instanceFromClass(temp.get((i/j)%temp.size())); overloadedArgs.get(i).add( new PFunction.FunctionArgument( dataType.toString(), dataType.isArrayType(), - arg.isConstant(), - arg.getDefaultValue(), - arg.getMinValue(), - arg.getMaxValue(), + arg.getFirst().isConstant(), + arg.getFirst().getDefaultValue(), + arg.getFirst().getMinValue(), + arg.getFirst().getMaxValue(), k)); k++; - j *= temp.length; + j *= temp.size(); } } + return overloadedArgs; } + @Override public Table getTable(String name) { Table table = tables.get(name); http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/main/java/org/apache/phoenix/expression/BindParameterExpression.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/BindParameterExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/BindParameterExpression.java index ce23b30..3c089d3 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/BindParameterExpression.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/BindParameterExpression.java @@ -1,11 +1,15 @@ package org.apache.phoenix.expression; +import java.sql.SQLException; + +import org.apache.calcite.avatica.util.ArrayImpl; import org.apache.hadoop.hbase.io.ImmutableBytesWritable; import org.apache.phoenix.execute.RuntimeContext; import org.apache.phoenix.expression.visitor.ExpressionVisitor; import org.apache.phoenix.schema.SortOrder; import org.apache.phoenix.schema.tuple.Tuple; import org.apache.phoenix.schema.types.PDataType; +import org.apache.phoenix.schema.types.PhoenixArray; public class BindParameterExpression extends VariableExpression { @SuppressWarnings("rawtypes") @@ -26,7 +30,17 @@ public class BindParameterExpression extends VariableExpression { if (value == null) { return false; } - + if(type.isArrayType()){ + PDataType arrayBaseType = PDataType.arrayBaseType(type); + try { + value=new PhoenixArray(arrayBaseType,(Object[])((ArrayImpl)value).getArray()); + } catch (SQLException e) { + throw new RuntimeException(e); + } + if(arrayBaseType.isFixedWidth()){ + value=new PhoenixArray((PhoenixArray)value,maxLength); + } + } ptr.set(type.toBytes(value)); type.pad(ptr, maxLength, SortOrder.ASC); return true; http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAppendFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAppendFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAppendFunction.java index 8c7fa9f..8d24461 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAppendFunction.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayAppendFunction.java @@ -22,12 +22,18 @@ 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.parse.FunctionParseNode.FunctionClassType; import org.apache.phoenix.schema.TypeMismatchException; -import org.apache.phoenix.schema.types.*; +import org.apache.phoenix.schema.types.PArrayDataType; +import org.apache.phoenix.schema.types.PBinary; +import org.apache.phoenix.schema.types.PBinaryArray; +import org.apache.phoenix.schema.types.PDataType; +import org.apache.phoenix.schema.types.PVarbinary; +import org.apache.phoenix.schema.types.PVarbinaryArray; @FunctionParseNode.BuiltInFunction(name = ArrayAppendFunction.NAME, args = { @FunctionParseNode.Argument(allowedTypes = {PBinaryArray.class, PVarbinaryArray.class}), - @FunctionParseNode.Argument(allowedTypes = {PVarbinary.class}, defaultValue = "null")}) + @FunctionParseNode.Argument(allowedTypes = {PBinary.class,PVarbinary.class}, defaultValue = "null")},classType = FunctionClassType.ARRAY) public class ArrayAppendFunction extends ArrayModifierFunction { public static final String NAME = "ARRAY_APPEND"; @@ -48,4 +54,9 @@ public class ArrayAppendFunction extends ArrayModifierFunction { public String getName() { return NAME; } + + @Override + public PDataType getDataType() { + return children.get(0).getDataType(); + } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayConcatFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayConcatFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayConcatFunction.java index 85655c6..537488e 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayConcatFunction.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayConcatFunction.java @@ -22,6 +22,7 @@ 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.parse.FunctionParseNode.FunctionClassType; import org.apache.phoenix.schema.SortOrder; import org.apache.phoenix.schema.TypeMismatchException; import org.apache.phoenix.schema.tuple.Tuple; @@ -32,7 +33,7 @@ import org.apache.phoenix.schema.types.PVarbinaryArray; @FunctionParseNode.BuiltInFunction(name = ArrayConcatFunction.NAME, args = { @FunctionParseNode.Argument(allowedTypes = {PBinaryArray.class, PVarbinaryArray.class}), - @FunctionParseNode.Argument(allowedTypes = {PBinaryArray.class, PVarbinaryArray.class})}) + @FunctionParseNode.Argument(allowedTypes = {PBinaryArray.class, PVarbinaryArray.class})},classType=FunctionClassType.ARRAY) public class ArrayConcatFunction extends ArrayModifierFunction { public static final String NAME = "ARRAY_CAT"; http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayElemRefExpression.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayElemRefExpression.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayElemRefExpression.java index 06bbced..cb44d08 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayElemRefExpression.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayElemRefExpression.java @@ -25,6 +25,7 @@ import java.util.List; import org.apache.hadoop.hbase.io.ImmutableBytesWritable; import org.apache.phoenix.expression.BaseCompoundExpression; import org.apache.phoenix.expression.Expression; +import org.apache.phoenix.expression.LiteralExpression; import org.apache.phoenix.expression.visitor.ExpressionVisitor; import org.apache.phoenix.schema.tuple.Tuple; import org.apache.phoenix.schema.types.PArrayDataTypeDecoder; @@ -48,6 +49,9 @@ public class ArrayElemRefExpression extends BaseCompoundExpression { @Override public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) { Expression arrayExpr = children.get(0); + if (children.size() > 1) { + this.index = (Integer) ((LiteralExpression) children.get(1)).getValue(); + } return PArrayDataTypeDecoder.positionAtArrayElement(tuple, ptr, index, arrayExpr, getDataType(), getMaxLength()); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayFillFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayFillFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayFillFunction.java index c8db7f9..f9a3953 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayFillFunction.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayFillFunction.java @@ -23,14 +23,20 @@ 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.parse.FunctionParseNode.FunctionClassType; import org.apache.phoenix.schema.SortOrder; import org.apache.phoenix.schema.TypeMismatchException; import org.apache.phoenix.schema.tuple.Tuple; -import org.apache.phoenix.schema.types.*; +import org.apache.phoenix.schema.types.PArrayDataType; +import org.apache.phoenix.schema.types.PBinary; +import org.apache.phoenix.schema.types.PDataType; +import org.apache.phoenix.schema.types.PInteger; +import org.apache.phoenix.schema.types.PVarbinary; +import org.apache.phoenix.schema.types.PhoenixArray; @FunctionParseNode.BuiltInFunction(name = ArrayFillFunction.NAME, args = { - @FunctionParseNode.Argument(allowedTypes = {PVarbinary.class}), - @FunctionParseNode.Argument(allowedTypes = {PInteger.class})}) + @FunctionParseNode.Argument(allowedTypes = {PBinary.class,PVarbinary.class}), + @FunctionParseNode.Argument(allowedTypes = {PInteger.class})}, classType=FunctionClassType.ARRAY) public class ArrayFillFunction extends ScalarFunction { public static final String NAME = "ARRAY_FILL"; http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayIndexFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayIndexFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayIndexFunction.java index 0f3c40c..223709e 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayIndexFunction.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayIndexFunction.java @@ -23,19 +23,19 @@ import org.apache.hadoop.hbase.io.ImmutableBytesWritable; import org.apache.phoenix.expression.Expression; import org.apache.phoenix.parse.FunctionParseNode.Argument; import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction; +import org.apache.phoenix.parse.FunctionParseNode.FunctionClassType; import org.apache.phoenix.parse.ParseException; +import org.apache.phoenix.schema.SortOrder; +import org.apache.phoenix.schema.tuple.Tuple; import org.apache.phoenix.schema.types.PArrayDataTypeDecoder; import org.apache.phoenix.schema.types.PBinaryArray; -import org.apache.phoenix.schema.types.PInteger; import org.apache.phoenix.schema.types.PDataType; +import org.apache.phoenix.schema.types.PInteger; import org.apache.phoenix.schema.types.PVarbinaryArray; -import org.apache.phoenix.schema.SortOrder; -import org.apache.phoenix.schema.tuple.Tuple; @BuiltInFunction(name = ArrayIndexFunction.NAME, args = { - @Argument(allowedTypes = { PBinaryArray.class, - PVarbinaryArray.class }), - @Argument(allowedTypes = { PInteger.class }) }) + @Argument(allowedTypes = { PBinaryArray.class, PVarbinaryArray.class}), + @Argument(allowedTypes = { PInteger.class }) },classType = FunctionClassType.ARRAY) public class ArrayIndexFunction extends ScalarFunction { public static final String NAME = "ARRAY_ELEM"; http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayLengthFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayLengthFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayLengthFunction.java index 3f7fe22..7515623 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayLengthFunction.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayLengthFunction.java @@ -23,15 +23,15 @@ import org.apache.hadoop.hbase.io.ImmutableBytesWritable; import org.apache.phoenix.expression.Expression; import org.apache.phoenix.parse.FunctionParseNode.Argument; import org.apache.phoenix.parse.FunctionParseNode.BuiltInFunction; -import org.apache.phoenix.schema.types.PBinaryArray; -import org.apache.phoenix.schema.types.PInteger; +import org.apache.phoenix.parse.FunctionParseNode.FunctionClassType; +import org.apache.phoenix.schema.tuple.Tuple; import org.apache.phoenix.schema.types.PArrayDataType; +import org.apache.phoenix.schema.types.PBinaryArray; import org.apache.phoenix.schema.types.PDataType; +import org.apache.phoenix.schema.types.PInteger; import org.apache.phoenix.schema.types.PVarbinaryArray; -import org.apache.phoenix.schema.tuple.Tuple; -@BuiltInFunction(name = ArrayLengthFunction.NAME, args = { @Argument(allowedTypes = { - PBinaryArray.class, PVarbinaryArray.class }) }) +@BuiltInFunction(name = ArrayLengthFunction.NAME, args = { @Argument(allowedTypes = {PBinaryArray.class, PVarbinaryArray.class }) },classType=FunctionClassType.ARRAY) public class ArrayLengthFunction extends ScalarFunction { public static final String NAME = "ARRAY_LENGTH"; http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayPrependFunction.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayPrependFunction.java b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayPrependFunction.java index c2311fb..20ab66c 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayPrependFunction.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/expression/function/ArrayPrependFunction.java @@ -23,12 +23,18 @@ 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.parse.FunctionParseNode.FunctionClassType; import org.apache.phoenix.schema.TypeMismatchException; -import org.apache.phoenix.schema.types.*; +import org.apache.phoenix.schema.types.PArrayDataType; +import org.apache.phoenix.schema.types.PBinary; +import org.apache.phoenix.schema.types.PBinaryArray; +import org.apache.phoenix.schema.types.PDataType; +import org.apache.phoenix.schema.types.PVarbinary; +import org.apache.phoenix.schema.types.PVarbinaryArray; @FunctionParseNode.BuiltInFunction(name = ArrayPrependFunction.NAME, args = { - @FunctionParseNode.Argument(allowedTypes = {PVarbinary.class}), - @FunctionParseNode.Argument(allowedTypes = {PBinaryArray.class, PVarbinaryArray.class})}) + @FunctionParseNode.Argument(allowedTypes = {PBinary.class,PVarbinary.class}), + @FunctionParseNode.Argument(allowedTypes = {PBinaryArray.class, PVarbinaryArray.class})}, classType=FunctionClassType.ARRAY) public class ArrayPrependFunction extends ArrayModifierFunction { public static final String NAME = "ARRAY_PREPEND"; http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/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 index 9102df4..7eda953 100644 --- 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 @@ -22,14 +22,21 @@ 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.parse.FunctionParseNode.FunctionClassType; import org.apache.phoenix.schema.SortOrder; import org.apache.phoenix.schema.tuple.Tuple; -import org.apache.phoenix.schema.types.*; +import org.apache.phoenix.schema.types.PArrayDataType; +import org.apache.phoenix.schema.types.PBinaryArray; +import org.apache.phoenix.schema.types.PChar; +import org.apache.phoenix.schema.types.PDataType; +import org.apache.phoenix.schema.types.PVarbinaryArray; +import org.apache.phoenix.schema.types.PVarchar; +import org.apache.phoenix.schema.types.PhoenixArray; @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")}) + @FunctionParseNode.Argument(allowedTypes = {PVarchar.class, PChar.class}, defaultValue = "null")},classType=FunctionClassType.ARRAY) public class ArrayToStringFunction extends ScalarFunction { public static final String NAME = "ARRAY_TO_STRING"; http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/main/java/org/apache/phoenix/parse/FunctionParseNode.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/parse/FunctionParseNode.java b/phoenix-core/src/main/java/org/apache/phoenix/parse/FunctionParseNode.java index df9ad86..957e9d4 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/parse/FunctionParseNode.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/parse/FunctionParseNode.java @@ -304,7 +304,8 @@ public class FunctionParseNode extends CompoundParseNode { ABSTRACT, DERIVED, ALIAS, - UDF + UDF, + ARRAY } /** http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/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 f31f272..2ce5252 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 @@ -84,7 +84,8 @@ public abstract class PArrayDataType<T> extends PDataType<T> { } public byte[] toBytes(Object object, PDataType baseType, SortOrder sortOrder) { - return toBytes(object, baseType, sortOrder, true); + return toBytes(object, baseType, sortOrder, true); + } public byte[] toBytes(Object object, PDataType baseType, SortOrder sortOrder, boolean rowKeyOrderOptimizable) { @@ -1051,7 +1052,7 @@ public abstract class PArrayDataType<T> extends PDataType<T> { } public static int estimateSize(int size, PDataType baseType) { - if (baseType.isFixedWidth()) { + if (baseType.isFixedWidth() && baseType.getByteSize()!=null) { return baseType.getByteSize() * size; } else { return size * ValueSchema.ESTIMATED_VARIABLE_LENGTH_SIZE; http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryArray.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryArray.java index 523f774..b61c551 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryArray.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBinaryArray.java @@ -17,6 +17,7 @@ */ package org.apache.phoenix.schema.types; +import org.apache.calcite.avatica.util.ArrayImpl; import org.apache.phoenix.schema.SortOrder; public class PBinaryArray extends PArrayDataType<byte[][]> { @@ -24,7 +25,7 @@ public class PBinaryArray extends PArrayDataType<byte[][]> { public static final PBinaryArray INSTANCE = new PBinaryArray(); private PBinaryArray() { - super("BINARY ARRAY", PDataType.ARRAY_TYPE_BASE + PBinary.INSTANCE.getSqlType(), PhoenixArray.class, null, 28); + super("BINARY ARRAY", PDataType.ARRAY_TYPE_BASE + PBinary.INSTANCE.getSqlType(), ArrayImpl.class, null, 28); } @Override http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBooleanArray.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBooleanArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBooleanArray.java index 742b0de..e5b3182 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBooleanArray.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PBooleanArray.java @@ -17,6 +17,7 @@ */ package org.apache.phoenix.schema.types; +import org.apache.calcite.avatica.util.ArrayImpl; import org.apache.phoenix.schema.SortOrder; import org.apache.phoenix.schema.types.PhoenixArray.PrimitiveBooleanPhoenixArray; @@ -25,7 +26,7 @@ public class PBooleanArray extends PArrayDataType<boolean[]> { public static final PBooleanArray INSTANCE = new PBooleanArray(); private PBooleanArray() { - super("BOOLEAN ARRAY", PDataType.ARRAY_TYPE_BASE + PBoolean.INSTANCE.getSqlType(), PhoenixArray.class, null, 25); + super("BOOLEAN ARRAY", PDataType.ARRAY_TYPE_BASE + PBoolean.INSTANCE.getSqlType(), ArrayImpl.class, null, 25); } @Override http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PCharArray.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PCharArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PCharArray.java index a740c7f..0906a20 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PCharArray.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PCharArray.java @@ -17,6 +17,7 @@ */ package org.apache.phoenix.schema.types; +import org.apache.calcite.avatica.util.ArrayImpl; import org.apache.phoenix.schema.SortOrder; public class PCharArray extends PArrayDataType<String[]> { @@ -24,7 +25,7 @@ public class PCharArray extends PArrayDataType<String[]> { public static final PCharArray INSTANCE = new PCharArray(); private PCharArray() { - super("CHAR ARRAY", PDataType.ARRAY_TYPE_BASE + PChar.INSTANCE.getSqlType(), PhoenixArray.class, + super("CHAR ARRAY", PDataType.ARRAY_TYPE_BASE + PChar.INSTANCE.getSqlType(), ArrayImpl.class, null, 29); } http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java index de1e63f..1bea92e 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDataType.java @@ -1154,7 +1154,7 @@ public abstract class PDataType<T> implements DataType<T>, Comparable<PDataType< if (type.isArrayType()) { PhoenixArray arr = (PhoenixArray)value; if ((type.getSqlType() == arr.baseType.sqlType + PDataType.ARRAY_TYPE_BASE) - && type.getJavaClass().isInstance(value)) { return type; } + ) { return type; } } else { if (type.getJavaClass().isInstance(value)) { return type; } } http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDoubleArray.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDoubleArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDoubleArray.java index d585229..b5f928c 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDoubleArray.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PDoubleArray.java @@ -17,6 +17,7 @@ */ package org.apache.phoenix.schema.types; +import org.apache.calcite.avatica.util.ArrayImpl; import org.apache.phoenix.schema.SortOrder; public class PDoubleArray extends PArrayDataType<double[]> { @@ -25,7 +26,7 @@ public class PDoubleArray extends PArrayDataType<double[]> { private PDoubleArray() { super("DOUBLE ARRAY", PDataType.ARRAY_TYPE_BASE + PDouble.INSTANCE.getSqlType(), - PhoenixArray.class, null, 34); + ArrayImpl.class, null, 34); } @Override http://git-wip-us.apache.org/repos/asf/phoenix/blob/b2d7fe01/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PIntegerArray.java ---------------------------------------------------------------------- diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PIntegerArray.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PIntegerArray.java index b317cfe..c59f93a 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PIntegerArray.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/types/PIntegerArray.java @@ -17,6 +17,7 @@ */ package org.apache.phoenix.schema.types; +import org.apache.calcite.avatica.util.ArrayImpl; import org.apache.phoenix.schema.SortOrder; public class PIntegerArray extends PArrayDataType<int[]> { @@ -25,7 +26,7 @@ public class PIntegerArray extends PArrayDataType<int[]> { private PIntegerArray() { super("INTEGER ARRAY", PDataType.ARRAY_TYPE_BASE + PInteger.INSTANCE.getSqlType(), - PhoenixArray.class, null, 24); + ArrayImpl.class, null, 24); } @Override
