From 85f4309e4f217ca4d9f7dedb21bb876a5150b28d Mon Sep 17 00:00:00 2001 From: David Date: Fri, 19 Dec 2014 12:58:55 -0800 Subject: [PATCH] PHOENIX-1469 4.2 patch fix binary columns for indexing --- .../end2end/index/IndexMetadataIT.java | 45 ++++++ .../org/apache/phoenix/util/IndexUtil.java | 5 + .../apache/phoenix/schema/PDataTypeTest.java | 66 +++++++- .../apache/phoenix/util/IndexUtilTest.java | 150 ++++++++++++++++++ 4 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 phoenix-core/src/test/java/org/apache/phoenix/util/IndexUtilTest.java diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMetadataIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMetadataIT.java index 26878f8ff7c..4620085cd18 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMetadataIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMetadataIT.java @@ -421,4 +421,49 @@ public void testIndexDefinitionWithSameColumnNamesInTwoFamily() throws Exception conn.close(); } } + + @Test + public void testBinaryNonnullableIndex() throws Exception { + Connection conn = DriverManager.getConnection(getUrl()); + try { + String ddl = + "CREATE TABLE test_table ( " + + "v1 BINARY(64) NOT NULL, " + + "v2 VARCHAR, " + + "v3 BINARY(64), " + + "v4 VARCHAR " + + "CONSTRAINT PK PRIMARY KEY (v1))"; + conn.createStatement().execute(ddl); + conn.commit(); + + try { + conn.createStatement().execute("CREATE INDEX idx ON test_table (v3) INCLUDE (v4)"); + fail("Should have seen SQLExceptionCode.VARBINARY_IN_ROW_KEY"); + } catch (SQLException e) { + assertEquals(SQLExceptionCode.VARBINARY_IN_ROW_KEY.getErrorCode(), e.getErrorCode()); + } + + try { + conn.createStatement().execute("CREATE INDEX idx3 ON test_table (v2, v3) INCLUDE (v4)"); + fail("Should have seen SQLExceptionCode.VARBINARY_IN_ROW_KEY"); + } catch (SQLException e) { + assertEquals(SQLExceptionCode.VARBINARY_IN_ROW_KEY.getErrorCode(), e.getErrorCode()); + } + conn.createStatement().execute("CREATE INDEX idx4 ON test_table (v4) INCLUDE (v2)"); + conn.commit(); + + conn.createStatement().execute("CREATE INDEX varbinLastInRow ON test_table (v1, v3)"); + conn.commit(); + + conn.createStatement().execute( "CREATE INDEX idx5 ON test_table (v2) INCLUDE (v4, v3, v1)"); + conn.commit(); + + conn.createStatement().executeQuery( + "select v1,v2,v3,v4 FROM test_table where v2 = 'abc' and v3 != 'a'"); + + + } finally { + conn.close(); + } + } } diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/IndexUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/IndexUtil.java index 1fbe91adcc8..011c09e487b 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/util/IndexUtil.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/util/IndexUtil.java @@ -111,6 +111,11 @@ public static PDataType getIndexColumnDataType(boolean isNullable, PDataType dat if (dataType.isCoercibleTo(PDataType.VARCHAR)) { return PDataType.VARCHAR; } + // for nullable BINARY - we want to be able to support this type but it would have to be at + // the end of an index or be the only column in the index + if (dataType == PDataType.BINARY) { + return PDataType.VARBINARY; + } throw new IllegalArgumentException("Unsupported non nullable index type " + dataType); } diff --git a/phoenix-core/src/test/java/org/apache/phoenix/schema/PDataTypeTest.java b/phoenix-core/src/test/java/org/apache/phoenix/schema/PDataTypeTest.java index 7c84928a35e..15377d58659 100644 --- a/phoenix-core/src/test/java/org/apache/phoenix/schema/PDataTypeTest.java +++ b/phoenix-core/src/test/java/org/apache/phoenix/schema/PDataTypeTest.java @@ -41,6 +41,8 @@ import org.apache.phoenix.util.TestUtil; import org.junit.Test; +import com.google.common.collect.TreeMultimap; + public class PDataTypeTest { @Test @@ -1674,5 +1676,67 @@ private long nextValueFor(long startWith, long incrementBy) { hstartWith += incrementBy; return (Long)PDataType.LONG.toObject(Bytes.toBytes(hstartWith)); } - + + @Test + public void testCoercibleGoldfile() { + TreeMultimap coercibleToMap = TreeMultimap.create(); + PDataType[] orderedTypes = PDataType.values(); + for (PDataType fromType : orderedTypes) { + for (PDataType targetType : orderedTypes) { + if (fromType.isCoercibleTo(targetType)) { + coercibleToMap.put(fromType.getSqlTypeName(), targetType.getSqlTypeName()); + } + } + } + assertEquals( + "{BIGINT=[BIGINT, BINARY, DECIMAL, DOUBLE, VARBINARY], " + + "BIGINT ARRAY=[BIGINT ARRAY, BINARY ARRAY, DECIMAL ARRAY, DOUBLE ARRAY, VARBINARY ARRAY], " + + "BINARY=[BINARY, VARBINARY], " + + "BINARY ARRAY=[BINARY ARRAY, VARBINARY ARRAY], " + + "BOOLEAN=[BINARY, BOOLEAN, VARBINARY], " + + "BOOLEAN ARRAY=[BINARY ARRAY, BOOLEAN ARRAY, VARBINARY ARRAY], " + + "CHAR=[BINARY, CHAR, VARBINARY, VARCHAR], " + + "CHAR ARRAY=[BINARY ARRAY, CHAR ARRAY, VARBINARY ARRAY, VARCHAR ARRAY], " + + "DATE=[BINARY, DATE, TIME, TIMESTAMP, VARBINARY], " + + "DATE ARRAY=[BINARY ARRAY, DATE ARRAY, TIME ARRAY, TIMESTAMP ARRAY, VARBINARY ARRAY], " + + "DECIMAL=[DECIMAL, VARBINARY], " + + "DECIMAL ARRAY=[DECIMAL ARRAY, VARBINARY ARRAY], " + + "DOUBLE=[BINARY, DECIMAL, DOUBLE, VARBINARY], " + + "DOUBLE ARRAY=[BINARY ARRAY, DECIMAL ARRAY, DOUBLE ARRAY, VARBINARY ARRAY], " + + "FLOAT=[BINARY, DECIMAL, DOUBLE, FLOAT, VARBINARY], " + + "FLOAT ARRAY=[BINARY ARRAY, DECIMAL ARRAY, DOUBLE ARRAY, FLOAT ARRAY, VARBINARY ARRAY], " + + "INTEGER=[BIGINT, BINARY, DECIMAL, DOUBLE, FLOAT, INTEGER, VARBINARY], " + + "INTEGER ARRAY=[BIGINT ARRAY, BINARY ARRAY, DECIMAL ARRAY, DOUBLE ARRAY, FLOAT ARRAY, INTEGER ARRAY, VARBINARY ARRAY], " + + "SMALLINT=[BIGINT, BINARY, DECIMAL, DOUBLE, FLOAT, INTEGER, SMALLINT, VARBINARY], " + + "SMALLINT ARRAY=[BIGINT ARRAY, BINARY ARRAY, DECIMAL ARRAY, DOUBLE ARRAY, FLOAT ARRAY, INTEGER ARRAY, SMALLINT ARRAY, VARBINARY ARRAY], " + + "TIME=[BINARY, DATE, TIME, TIMESTAMP, VARBINARY], " + + "TIME ARRAY=[BINARY ARRAY, DATE ARRAY, TIME ARRAY, TIMESTAMP ARRAY, VARBINARY ARRAY], " + + "TIMESTAMP=[BINARY, TIMESTAMP, VARBINARY], " + + "TIMESTAMP ARRAY=[BINARY ARRAY, TIMESTAMP ARRAY, VARBINARY ARRAY], " + + "TINYINT=[BIGINT, BINARY, DECIMAL, DOUBLE, FLOAT, INTEGER, SMALLINT, TINYINT, VARBINARY], " + + "TINYINT ARRAY=[BIGINT ARRAY, BINARY ARRAY, DECIMAL ARRAY, DOUBLE ARRAY, FLOAT ARRAY, INTEGER ARRAY, SMALLINT ARRAY, TINYINT ARRAY, VARBINARY ARRAY], " + + "UNSIGNED_DATE=[BINARY, DATE, TIME, TIMESTAMP, UNSIGNED_DATE, UNSIGNED_TIME, UNSIGNED_TIMESTAMP, VARBINARY], " + + "UNSIGNED_DATE ARRAY=[BINARY ARRAY, DATE ARRAY, TIME ARRAY, TIMESTAMP ARRAY, UNSIGNED_DATE ARRAY, UNSIGNED_TIME ARRAY, UNSIGNED_TIMESTAMP ARRAY, VARBINARY ARRAY], " + + "UNSIGNED_DOUBLE=[BINARY, DECIMAL, DOUBLE, UNSIGNED_DOUBLE, VARBINARY], " + + "UNSIGNED_DOUBLE ARRAY=[BINARY ARRAY, DECIMAL ARRAY, DOUBLE ARRAY, UNSIGNED_DOUBLE ARRAY, VARBINARY ARRAY], " + + "UNSIGNED_FLOAT=[BINARY, DECIMAL, DOUBLE, FLOAT, UNSIGNED_DOUBLE, UNSIGNED_FLOAT, VARBINARY], " + + "UNSIGNED_FLOAT ARRAY=[BINARY ARRAY, DECIMAL ARRAY, DOUBLE ARRAY, FLOAT ARRAY, UNSIGNED_DOUBLE ARRAY, UNSIGNED_FLOAT ARRAY, VARBINARY ARRAY], " + + "UNSIGNED_INT=[BIGINT, BINARY, DECIMAL, DOUBLE, FLOAT, INTEGER, UNSIGNED_DOUBLE, UNSIGNED_FLOAT, UNSIGNED_INT, UNSIGNED_LONG, VARBINARY], " + + "UNSIGNED_INT ARRAY=[BIGINT ARRAY, BINARY ARRAY, DECIMAL ARRAY, DOUBLE ARRAY, FLOAT ARRAY, INTEGER ARRAY, UNSIGNED_DOUBLE ARRAY, UNSIGNED_FLOAT ARRAY, UNSIGNED_INT ARRAY, UNSIGNED_LONG ARRAY, VARBINARY ARRAY], " + + "UNSIGNED_LONG=[BIGINT, BINARY, DECIMAL, DOUBLE, UNSIGNED_DOUBLE, UNSIGNED_LONG, VARBINARY], " + + "UNSIGNED_LONG ARRAY=[BIGINT ARRAY, BINARY ARRAY, DECIMAL ARRAY, DOUBLE ARRAY, UNSIGNED_DOUBLE ARRAY, UNSIGNED_LONG ARRAY, VARBINARY ARRAY], " + + "UNSIGNED_SMALLINT=[BIGINT, BINARY, DECIMAL, DOUBLE, FLOAT, INTEGER, SMALLINT, UNSIGNED_DOUBLE, UNSIGNED_FLOAT, UNSIGNED_INT, UNSIGNED_LONG, UNSIGNED_SMALLINT, VARBINARY], " + + "UNSIGNED_SMALLINT ARRAY=[BIGINT ARRAY, BINARY ARRAY, DECIMAL ARRAY, DOUBLE ARRAY, FLOAT ARRAY, INTEGER ARRAY, SMALLINT ARRAY, UNSIGNED_DOUBLE ARRAY, UNSIGNED_FLOAT ARRAY, UNSIGNED_INT ARRAY, UNSIGNED_LONG ARRAY, UNSIGNED_SMALLINT ARRAY, VARBINARY ARRAY], " + + "UNSIGNED_TIME=[BINARY, DATE, TIME, TIMESTAMP, UNSIGNED_DATE, UNSIGNED_TIME, UNSIGNED_TIMESTAMP, VARBINARY], " + + "UNSIGNED_TIME ARRAY=[BINARY ARRAY, DATE ARRAY, TIME ARRAY, TIMESTAMP ARRAY, UNSIGNED_DATE ARRAY, UNSIGNED_TIME ARRAY, UNSIGNED_TIMESTAMP ARRAY, VARBINARY ARRAY], " + + "UNSIGNED_TIMESTAMP=[BINARY, DATE, TIME, TIMESTAMP, UNSIGNED_DATE, UNSIGNED_TIME, UNSIGNED_TIMESTAMP, VARBINARY], " + + "UNSIGNED_TIMESTAMP ARRAY=[BINARY ARRAY, DATE ARRAY, TIME ARRAY, TIMESTAMP ARRAY, UNSIGNED_DATE ARRAY, UNSIGNED_TIME ARRAY, UNSIGNED_TIMESTAMP ARRAY, VARBINARY ARRAY], " + + "UNSIGNED_TINYINT=[BIGINT, BINARY, DECIMAL, DOUBLE, FLOAT, INTEGER, SMALLINT, TINYINT, UNSIGNED_DOUBLE, UNSIGNED_FLOAT, UNSIGNED_INT, UNSIGNED_LONG, UNSIGNED_SMALLINT, UNSIGNED_TINYINT, VARBINARY], " + + "UNSIGNED_TINYINT ARRAY=[BIGINT ARRAY, BINARY ARRAY, DECIMAL ARRAY, DOUBLE ARRAY, FLOAT ARRAY, INTEGER ARRAY, SMALLINT ARRAY, TINYINT ARRAY, UNSIGNED_DOUBLE ARRAY, UNSIGNED_FLOAT ARRAY, UNSIGNED_INT ARRAY, UNSIGNED_LONG ARRAY, UNSIGNED_SMALLINT ARRAY, UNSIGNED_TINYINT ARRAY, VARBINARY ARRAY], " + + "VARBINARY=[BINARY, VARBINARY], " + + "VARBINARY ARRAY=[BINARY ARRAY, VARBINARY ARRAY], " + + "VARCHAR=[BINARY, CHAR, VARBINARY, VARCHAR], " + + "VARCHAR ARRAY=[BINARY ARRAY, CHAR ARRAY, VARBINARY ARRAY, VARCHAR ARRAY]}", + coercibleToMap.toString()); + } } diff --git a/phoenix-core/src/test/java/org/apache/phoenix/util/IndexUtilTest.java b/phoenix-core/src/test/java/org/apache/phoenix/util/IndexUtilTest.java new file mode 100644 index 00000000000..1d004a606d4 --- /dev/null +++ b/phoenix-core/src/test/java/org/apache/phoenix/util/IndexUtilTest.java @@ -0,0 +1,150 @@ +/* + * 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.util; + +import static org.junit.Assert.assertEquals; + +import java.util.Map; + +import org.apache.phoenix.schema.PDataType; +import org.junit.Test; + +import com.google.common.collect.Maps; + +public class IndexUtilTest { + + @Test + public void testIndexNonNullableColumnDataType() { + verifyIndexColumnDataTypes(false, + "{BIGINT=BIGINT, " + + "BIGINT ARRAY=BIGINT ARRAY, " + + "BINARY=BINARY, " + + "BINARY ARRAY=BINARY ARRAY, " + + "BOOLEAN=BOOLEAN, " + + "BOOLEAN ARRAY=BOOLEAN ARRAY, " + + "CHAR=CHAR, " + + "CHAR ARRAY=CHAR ARRAY, " + + "DATE=DATE, " + + "DATE ARRAY=DATE ARRAY, " + + "DECIMAL=DECIMAL, " + + "DECIMAL ARRAY=DECIMAL ARRAY, " + + "DOUBLE=DOUBLE, " + + "DOUBLE ARRAY=DOUBLE ARRAY, " + + "FLOAT=FLOAT, " + + "FLOAT ARRAY=FLOAT ARRAY, " + + "INTEGER=INTEGER, " + + "INTEGER ARRAY=INTEGER ARRAY, " + + "SMALLINT=SMALLINT, " + + "SMALLINT ARRAY=SMALLINT ARRAY, " + + "TIME=TIME, " + + "TIME ARRAY=TIME ARRAY, " + + "TIMESTAMP=TIMESTAMP, " + + "TIMESTAMP ARRAY=TIMESTAMP ARRAY, " + + "TINYINT=TINYINT, " + + "TINYINT ARRAY=TINYINT ARRAY, " + + "UNSIGNED_DATE=UNSIGNED_DATE, " + + "UNSIGNED_DATE ARRAY=UNSIGNED_DATE ARRAY, " + + "UNSIGNED_DOUBLE=UNSIGNED_DOUBLE, " + + "UNSIGNED_DOUBLE ARRAY=UNSIGNED_DOUBLE ARRAY, " + + "UNSIGNED_FLOAT=UNSIGNED_FLOAT, " + + "UNSIGNED_FLOAT ARRAY=UNSIGNED_FLOAT ARRAY, " + + "UNSIGNED_INT=UNSIGNED_INT, " + + "UNSIGNED_INT ARRAY=UNSIGNED_INT ARRAY, " + + "UNSIGNED_LONG=UNSIGNED_LONG, " + + "UNSIGNED_LONG ARRAY=UNSIGNED_LONG ARRAY, " + + "UNSIGNED_SMALLINT=UNSIGNED_SMALLINT, " + + "UNSIGNED_SMALLINT ARRAY=UNSIGNED_SMALLINT ARRAY, " + + "UNSIGNED_TIME=UNSIGNED_TIME, " + + "UNSIGNED_TIME ARRAY=UNSIGNED_TIME ARRAY, " + + "UNSIGNED_TIMESTAMP=UNSIGNED_TIMESTAMP, " + + "UNSIGNED_TIMESTAMP ARRAY=UNSIGNED_TIMESTAMP ARRAY, " + + "UNSIGNED_TINYINT=UNSIGNED_TINYINT, " + + "UNSIGNED_TINYINT ARRAY=UNSIGNED_TINYINT ARRAY, " + + "VARBINARY=VARBINARY, " + + "VARBINARY ARRAY=VARBINARY ARRAY, " + + "VARCHAR=VARCHAR, " + + "VARCHAR ARRAY=VARCHAR ARRAY}"); + } + + @Test + public void testIndexNullableColumnDataType() { + verifyIndexColumnDataTypes(true, + "{BIGINT=DECIMAL, " + + "BIGINT ARRAY=BIGINT ARRAY, " + + "BINARY=VARBINARY, " + + "BINARY ARRAY=BINARY ARRAY, " + + "BOOLEAN=DECIMAL, " + + "BOOLEAN ARRAY=BOOLEAN ARRAY, " + + "CHAR=VARCHAR, " + + "CHAR ARRAY=CHAR ARRAY, " + + "DATE=DECIMAL, " + + "DATE ARRAY=DATE ARRAY, " + + "DECIMAL=DECIMAL, " + + "DECIMAL ARRAY=DECIMAL ARRAY, " + + "DOUBLE=DECIMAL, " + + "DOUBLE ARRAY=DOUBLE ARRAY, " + + "FLOAT=DECIMAL, " + + "FLOAT ARRAY=FLOAT ARRAY, " + + "INTEGER=DECIMAL, " + + "INTEGER ARRAY=INTEGER ARRAY, " + + "SMALLINT=DECIMAL, " + + "SMALLINT ARRAY=SMALLINT ARRAY, " + + "TIME=DECIMAL, " + + "TIME ARRAY=TIME ARRAY, " + + "TIMESTAMP=DECIMAL, " + + "TIMESTAMP ARRAY=TIMESTAMP ARRAY, " + + "TINYINT=DECIMAL, " + + "TINYINT ARRAY=TINYINT ARRAY, " + + "UNSIGNED_DATE=DECIMAL, " + + "UNSIGNED_DATE ARRAY=UNSIGNED_DATE ARRAY, " + + "UNSIGNED_DOUBLE=DECIMAL, " + + "UNSIGNED_DOUBLE ARRAY=UNSIGNED_DOUBLE ARRAY, " + + "UNSIGNED_FLOAT=DECIMAL, " + + "UNSIGNED_FLOAT ARRAY=UNSIGNED_FLOAT ARRAY, " + + "UNSIGNED_INT=DECIMAL, " + + "UNSIGNED_INT ARRAY=UNSIGNED_INT ARRAY, " + + "UNSIGNED_LONG=DECIMAL, " + + "UNSIGNED_LONG ARRAY=UNSIGNED_LONG ARRAY, " + + "UNSIGNED_SMALLINT=DECIMAL, " + + "UNSIGNED_SMALLINT ARRAY=UNSIGNED_SMALLINT ARRAY, " + + "UNSIGNED_TIME=DECIMAL, " + + "UNSIGNED_TIME ARRAY=UNSIGNED_TIME ARRAY, " + + "UNSIGNED_TIMESTAMP=DECIMAL, " + + "UNSIGNED_TIMESTAMP ARRAY=UNSIGNED_TIMESTAMP ARRAY, " + + "UNSIGNED_TINYINT=DECIMAL, " + + "UNSIGNED_TINYINT ARRAY=UNSIGNED_TINYINT ARRAY, " + + "VARBINARY=VARBINARY, " + + "VARBINARY ARRAY=VARBINARY ARRAY, " + + "VARCHAR=VARCHAR, " + + "VARCHAR ARRAY=VARCHAR ARRAY}"); + } + + private void verifyIndexColumnDataTypes(boolean isNullable, String expected) { + Map indexColumnDataTypes = Maps.newTreeMap(); + for (PDataType dataType : PDataType.values()) { + String indexColumnDataType = "unsupported"; + try { + indexColumnDataType = IndexUtil.getIndexColumnDataType(isNullable, dataType).getSqlTypeName(); + } catch (IllegalArgumentException e) { + } + indexColumnDataTypes.put(dataType.getSqlTypeName(), indexColumnDataType); + } + assertEquals(expected, indexColumnDataTypes.toString()); + } +} +