You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ma...@apache.org on 2015/03/04 23:40:46 UTC
[11/50] [abbrv] phoenix git commit: PHOENIX-514 Support functional
indexes (Thomas D'Silva)
PHOENIX-514 Support functional indexes (Thomas D'Silva)
Project: http://git-wip-us.apache.org/repos/asf/phoenix/repo
Commit: http://git-wip-us.apache.org/repos/asf/phoenix/commit/8c340f5a
Tree: http://git-wip-us.apache.org/repos/asf/phoenix/tree/8c340f5a
Diff: http://git-wip-us.apache.org/repos/asf/phoenix/diff/8c340f5a
Branch: refs/heads/calcite
Commit: 8c340f5a6c030d009a4fa75444096a1999aea5c5
Parents: d6e7846
Author: James Taylor <ja...@apache.org>
Authored: Wed Feb 4 12:30:51 2015 -0800
Committer: James Taylor <ja...@apache.org>
Committed: Wed Feb 4 12:30:51 2015 -0800
----------------------------------------------------------------------
.../org/apache/phoenix/end2end/HashJoinIT.java | 12 +-
.../apache/phoenix/end2end/PercentileIT.java | 7 +-
.../java/org/apache/phoenix/end2end/ViewIT.java | 2 +-
.../phoenix/end2end/index/ImmutableIndexIT.java | 76 +-
.../end2end/index/IndexExpressionIT.java | 866 +++++++++++++++++++
.../phoenix/end2end/index/IndexMetadataIT.java | 20 +-
phoenix-core/src/main/antlr3/PhoenixSQL.g | 32 +-
.../IndexHalfStoreFileReaderGenerator.java | 4 +-
.../apache/phoenix/compile/DeleteCompiler.java | 4 +-
.../phoenix/compile/ExpressionCompiler.java | 9 +-
.../apache/phoenix/compile/FromCompiler.java | 6 +-
.../apache/phoenix/compile/HavingCompiler.java | 4 +-
.../compile/IndexExpressionCompiler.java | 53 ++
.../apache/phoenix/compile/JoinCompiler.java | 8 +-
.../phoenix/compile/PostIndexDDLCompiler.java | 47 +-
.../apache/phoenix/compile/UpsertCompiler.java | 2 +-
.../apache/phoenix/compile/WhereCompiler.java | 4 +-
.../coprocessor/MetaDataEndpointImpl.java | 44 +-
.../UngroupedAggregateRegionObserver.java | 3 +-
.../coprocessor/generated/PTableProtos.java | 215 ++++-
.../phoenix/exception/SQLExceptionCode.java | 6 +
.../apache/phoenix/execute/BaseQueryPlan.java | 2 +-
.../apache/phoenix/execute/MutationState.java | 4 +-
.../phoenix/expression/CoerceExpression.java | 10 +-
.../expression/RowKeyColumnExpression.java | 6 +-
.../apache/phoenix/hbase/index/ValueGetter.java | 2 +
.../index/covered/data/LazyValueGetter.java | 5 +
.../hbase/index/util/IndexManagementUtil.java | 18 -
.../apache/phoenix/index/IndexMaintainer.java | 333 ++++---
.../apache/phoenix/index/PhoenixIndexCodec.java | 2 +-
.../index/PhoenixIndexFailurePolicy.java | 21 +-
.../phoenix/jdbc/PhoenixDatabaseMetaData.java | 1 +
.../apache/phoenix/jdbc/PhoenixStatement.java | 9 +-
.../apache/phoenix/optimize/QueryOptimizer.java | 12 +-
.../apache/phoenix/parse/BetweenParseNode.java | 22 +
.../org/apache/phoenix/parse/BindParseNode.java | 22 +
.../org/apache/phoenix/parse/CastParseNode.java | 38 +
.../org/apache/phoenix/parse/ColumnDef.java | 14 +-
.../org/apache/phoenix/parse/ColumnName.java | 2 +-
.../apache/phoenix/parse/ColumnParseNode.java | 1 +
.../apache/phoenix/parse/CompoundParseNode.java | 32 +-
.../phoenix/parse/CreateIndexStatement.java | 10 +-
.../apache/phoenix/parse/ExistsParseNode.java | 22 +
.../phoenix/parse/FamilyWildcardParseNode.java | 22 +
.../apache/phoenix/parse/FunctionParseNode.java | 31 +
.../apache/phoenix/parse/InListParseNode.java | 22 +
.../org/apache/phoenix/parse/InParseNode.java | 25 +
.../parse/IndexExpressionParseNodeRewriter.java | 104 +++
.../phoenix/parse/IndexKeyConstraint.java | 12 +-
.../apache/phoenix/parse/IsNullParseNode.java | 22 +
.../org/apache/phoenix/parse/LikeParseNode.java | 26 +
.../apache/phoenix/parse/LiteralParseNode.java | 21 +
.../org/apache/phoenix/parse/NamedNode.java | 2 +-
.../apache/phoenix/parse/NamedParseNode.java | 30 +
.../apache/phoenix/parse/ParseNodeFactory.java | 34 +-
.../phoenix/parse/SequenceValueParseNode.java | 29 +
.../apache/phoenix/parse/SubqueryParseNode.java | 28 +
.../org/apache/phoenix/parse/TableName.java | 3 +-
.../phoenix/parse/TableWildcardParseNode.java | 29 +
.../apache/phoenix/parse/WildcardParseNode.java | 24 +-
.../apache/phoenix/schema/DelegateColumn.java | 6 +
.../apache/phoenix/schema/DelegateTable.java | 9 +-
.../apache/phoenix/schema/MetaDataClient.java | 173 ++--
.../java/org/apache/phoenix/schema/PColumn.java | 3 +
.../org/apache/phoenix/schema/PColumnImpl.java | 26 +-
.../apache/phoenix/schema/PMetaDataImpl.java | 2 +-
.../java/org/apache/phoenix/schema/PTable.java | 7 +-
.../org/apache/phoenix/schema/PTableImpl.java | 27 +-
.../org/apache/phoenix/schema/SaltingUtil.java | 2 +-
.../phoenix/schema/tuple/ValueGetterTuple.java | 93 ++
.../java/org/apache/phoenix/util/IndexUtil.java | 15 +-
.../expression/ColumnExpressionTest.java | 8 +-
.../phoenix/index/IndexMaintainerTest.java | 14 +-
.../iterate/AggregateResultScannerTest.java | 5 +
.../java/org/apache/phoenix/query/BaseTest.java | 26 +-
phoenix-protocol/src/main/PTable.proto | 1 +
76 files changed, 2475 insertions(+), 418 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/phoenix/blob/8c340f5a/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinIT.java
index 781bfea..76eab22 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/HashJoinIT.java
@@ -289,7 +289,7 @@ public class HashJoinIT extends BaseHBaseManagedTimeIT {
"CLIENT MERGE SORT\n" +
" PARALLEL INNER-JOIN TABLE 0\n" +
" CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_DISPLAY_NAME + "\n" +
- " SERVER FILTER BY order_id != '000000000000003'\n" +
+ " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
" PARALLEL INNER-JOIN TABLE 0\n" +
" CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_DISPLAY_NAME + "\n" +
" SERVER FILTER BY NAME != 'T3'\n" +
@@ -380,7 +380,7 @@ public class HashJoinIT extends BaseHBaseManagedTimeIT {
"CLIENT MERGE SORT\n" +
" PARALLEL INNER-JOIN TABLE 0\n" +
" CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_DISPLAY_NAME + "\n" +
- " SERVER FILTER BY order_id != '000000000000003'\n" +
+ " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
" PARALLEL INNER-JOIN TABLE 0\n" +
" CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ITEM_TABLE_DISPLAY_NAME + "\n" +
" SERVER FILTER BY NAME != 'T3'\n" +
@@ -655,7 +655,7 @@ public class HashJoinIT extends BaseHBaseManagedTimeIT {
"CLIENT MERGE SORT\n" +
" PARALLEL INNER-JOIN TABLE 0\n" +
" CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_DISPLAY_NAME + "\n" +
- " SERVER FILTER BY order_id != '000000000000003'\n" +
+ " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
" PARALLEL INNER-JOIN TABLE 0\n" +
" CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
" SERVER FILTER BY NAME != 'T3'\n" +
@@ -747,7 +747,7 @@ public class HashJoinIT extends BaseHBaseManagedTimeIT {
"CLIENT MERGE SORT\n" +
" PARALLEL INNER-JOIN TABLE 0\n" +
" CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_DISPLAY_NAME + "\n" +
- " SERVER FILTER BY order_id != '000000000000003'\n" +
+ " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
" PARALLEL INNER-JOIN TABLE 0\n" +
" CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_SCHEMA + ".idx_item\n" +
" SERVER FILTER BY NAME != 'T3'\n" +
@@ -1039,7 +1039,7 @@ public class HashJoinIT extends BaseHBaseManagedTimeIT {
"CLIENT MERGE SORT\n" +
" PARALLEL INNER-JOIN TABLE 0\n" +
" CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_DISPLAY_NAME + "\n" +
- " SERVER FILTER BY order_id != '000000000000003'\n" +
+ " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
" PARALLEL INNER-JOIN TABLE 0\n" +
" CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + MetaDataUtil.LOCAL_INDEX_TABLE_PREFIX +""+ JOIN_ITEM_TABLE_DISPLAY_NAME +" [-32768]\n" +
" SERVER FILTER BY NAME != 'T3'\n" +
@@ -1134,7 +1134,7 @@ public class HashJoinIT extends BaseHBaseManagedTimeIT {
"CLIENT MERGE SORT\n" +
" PARALLEL INNER-JOIN TABLE 0\n" +
" CLIENT PARALLEL 1-WAY FULL SCAN OVER " + JOIN_ORDER_TABLE_DISPLAY_NAME + "\n" +
- " SERVER FILTER BY order_id != '000000000000003'\n" +
+ " SERVER FILTER BY \"order_id\" != '000000000000003'\n" +
" PARALLEL INNER-JOIN TABLE 0\n" +
" CLIENT PARALLEL 1-WAY RANGE SCAN OVER " + MetaDataUtil.LOCAL_INDEX_TABLE_PREFIX +""+JOIN_ITEM_TABLE_DISPLAY_NAME + " [-32768]\n" +
" SERVER FILTER BY NAME != 'T3'\n" +
http://git-wip-us.apache.org/repos/asf/phoenix/blob/8c340f5a/phoenix-core/src/it/java/org/apache/phoenix/end2end/PercentileIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/PercentileIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/PercentileIT.java
index 685daeb..8109694 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/PercentileIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/PercentileIT.java
@@ -50,6 +50,7 @@ import java.sql.Types;
import java.util.Properties;
import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.util.DateUtil;
import org.apache.phoenix.util.PhoenixRuntime;
import org.apache.phoenix.util.PropertiesUtil;
import org.junit.Test;
@@ -516,15 +517,17 @@ public class PercentileIT extends BaseClientManagedTimeIT {
private static void populateINDEX_DATA_TABLETable() throws SQLException {
Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
Connection conn = DriverManager.getConnection(getUrl(), props);
+ Date date = DateUtil.parseDate("2015-01-01 00:00:00");
try {
String upsert = "UPSERT INTO " + INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + INDEX_DATA_TABLE
- + " VALUES(?, ?, ?, ?, ?)";
+ + " VALUES(?, ?, ?, ?, ?, ?)";
PreparedStatement stmt = conn.prepareStatement(upsert);
stmt.setString(1, "varchar1");
stmt.setString(2, "char1");
stmt.setInt(3, 1);
stmt.setLong(4, 1L);
stmt.setBigDecimal(5, new BigDecimal(1.0));
+ stmt.setDate(6, date);
stmt.executeUpdate();
stmt.setString(1, "varchar2");
@@ -532,6 +535,7 @@ public class PercentileIT extends BaseClientManagedTimeIT {
stmt.setInt(3, 2);
stmt.setLong(4, 2L);
stmt.setBigDecimal(5, new BigDecimal(2.0));
+ stmt.setDate(6, date);
stmt.executeUpdate();
stmt.setString(1, "varchar3");
@@ -539,6 +543,7 @@ public class PercentileIT extends BaseClientManagedTimeIT {
stmt.setInt(3, 3);
stmt.setLong(4, 3L);
stmt.setBigDecimal(5, new BigDecimal(3.0));
+ stmt.setDate(6, date);
stmt.executeUpdate();
conn.commit();
http://git-wip-us.apache.org/repos/asf/phoenix/blob/8c340f5a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java
index aa26f9b..9a89531 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewIT.java
@@ -424,6 +424,6 @@ public class ViewIT extends BaseViewIT {
String queryPlan = QueryUtil.getExplainPlan(rs);
assertEquals(
"CLIENT PARALLEL 1-WAY SKIP SCAN ON 4 KEYS OVER I1 [1,100] - [2,109]\n" +
- " SERVER FILTER BY (S2 = 'bas' AND S1 = 'foo')", queryPlan);
+ " SERVER FILTER BY (S2 = 'bas' AND \"S1\" = 'foo')", queryPlan);
}
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/8c340f5a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ImmutableIndexIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ImmutableIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ImmutableIndexIT.java
index 55b38a5..9eb9a57 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ImmutableIndexIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ImmutableIndexIT.java
@@ -27,6 +27,7 @@ import static org.junit.Assert.fail;
import java.math.BigDecimal;
import java.sql.Connection;
+import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -38,6 +39,7 @@ import org.apache.phoenix.exception.SQLExceptionCode;
import org.apache.phoenix.jdbc.PhoenixConnection;
import org.apache.phoenix.query.QueryConstants;
import org.apache.phoenix.schema.PTableKey;
+import org.apache.phoenix.util.DateUtil;
import org.apache.phoenix.util.PropertiesUtil;
import org.apache.phoenix.util.QueryUtil;
import org.junit.Test;
@@ -50,23 +52,27 @@ public class ImmutableIndexIT extends BaseHBaseManagedTimeIT {
Connection conn = DriverManager.getConnection(getUrl(), props);
try {
String upsert = "UPSERT INTO " + INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + INDEX_DATA_TABLE
- + " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ + " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
PreparedStatement stmt = conn.prepareStatement(upsert);
stmt.setString(1, "varchar1");
stmt.setString(2, "char1");
stmt.setInt(3, 1);
stmt.setLong(4, 1L);
stmt.setBigDecimal(5, new BigDecimal(1.0));
- stmt.setString(6, "varchar_a");
- stmt.setString(7, "chara");
- stmt.setInt(8, 2);
- stmt.setLong(9, 2L);
- stmt.setBigDecimal(10, new BigDecimal(2.0));
- stmt.setString(11, "varchar_b");
- stmt.setString(12, "charb");
- stmt.setInt(13, 3);
- stmt.setLong(14, 3L);
- stmt.setBigDecimal(15, new BigDecimal(3.0));
+ Date date = DateUtil.parseDate("2015-01-01 00:00:00");
+ stmt.setDate(6, date);
+ stmt.setString(7, "varchar_a");
+ stmt.setString(8, "chara");
+ stmt.setInt(9, 2);
+ stmt.setLong(10, 2L);
+ stmt.setBigDecimal(11, new BigDecimal(2.0));
+ stmt.setDate(12, date);
+ stmt.setString(13, "varchar_b");
+ stmt.setString(14, "charb");
+ stmt.setInt(15, 3);
+ stmt.setLong(16, 3L);
+ stmt.setBigDecimal(17, new BigDecimal(3.0));
+ stmt.setDate(18, date);
stmt.executeUpdate();
stmt.setString(1, "varchar2");
@@ -74,16 +80,20 @@ public class ImmutableIndexIT extends BaseHBaseManagedTimeIT {
stmt.setInt(3, 2);
stmt.setLong(4, 2L);
stmt.setBigDecimal(5, new BigDecimal(2.0));
- stmt.setString(6, "varchar_a");
- stmt.setString(7, "chara");
- stmt.setInt(8, 3);
- stmt.setLong(9, 3L);
- stmt.setBigDecimal(10, new BigDecimal(3.0));
- stmt.setString(11, "varchar_b");
- stmt.setString(12, "charb");
- stmt.setInt(13, 4);
- stmt.setLong(14, 4L);
- stmt.setBigDecimal(15, new BigDecimal(4.0));
+ date = DateUtil.parseDate("2015-01-02 00:00:00");
+ stmt.setDate(6, date);
+ stmt.setString(7, "varchar_a");
+ stmt.setString(8, "chara");
+ stmt.setInt(9, 3);
+ stmt.setLong(10, 3L);
+ stmt.setBigDecimal(11, new BigDecimal(3.0));
+ stmt.setDate(12, date);
+ stmt.setString(13, "varchar_b");
+ stmt.setString(14, "charb");
+ stmt.setInt(15, 4);
+ stmt.setLong(16, 4L);
+ stmt.setBigDecimal(17, new BigDecimal(4.0));
+ stmt.setDate(18, date);
stmt.executeUpdate();
stmt.setString(1, "varchar3");
@@ -91,16 +101,20 @@ public class ImmutableIndexIT extends BaseHBaseManagedTimeIT {
stmt.setInt(3, 3);
stmt.setLong(4, 3L);
stmt.setBigDecimal(5, new BigDecimal(3.0));
- stmt.setString(6, "varchar_a");
- stmt.setString(7, "chara");
- stmt.setInt(8, 4);
- stmt.setLong(9, 4L);
- stmt.setBigDecimal(10, new BigDecimal(4.0));
- stmt.setString(11, "varchar_b");
- stmt.setString(12, "charb");
- stmt.setInt(13, 5);
- stmt.setLong(14, 5L);
- stmt.setBigDecimal(15, new BigDecimal(5.0));
+ date = DateUtil.parseDate("2015-01-03 00:00:00");
+ stmt.setDate(6, date);
+ stmt.setString(7, "varchar_a");
+ stmt.setString(8, "chara");
+ stmt.setInt(9, 4);
+ stmt.setLong(10, 4L);
+ stmt.setBigDecimal(11, new BigDecimal(4.0));
+ stmt.setDate(12, date);
+ stmt.setString(13, "varchar_b");
+ stmt.setString(14, "charb");
+ stmt.setInt(15, 5);
+ stmt.setLong(16, 5L);
+ stmt.setBigDecimal(17, new BigDecimal(5.0));
+ stmt.setDate(18, date);
stmt.executeUpdate();
conn.commit();
http://git-wip-us.apache.org/repos/asf/phoenix/blob/8c340f5a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexExpressionIT.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexExpressionIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexExpressionIT.java
new file mode 100644
index 0000000..28124b6
--- /dev/null
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexExpressionIT.java
@@ -0,0 +1,866 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
+ * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
+ * applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+package org.apache.phoenix.end2end.index;
+
+import static org.apache.phoenix.util.TestUtil.INDEX_DATA_SCHEMA;
+import static org.apache.phoenix.util.TestUtil.INDEX_DATA_TABLE;
+import static org.apache.phoenix.util.TestUtil.MUTABLE_INDEX_DATA_TABLE;
+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.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.phoenix.end2end.BaseHBaseManagedTimeIT;
+import org.apache.phoenix.exception.SQLExceptionCode;
+import org.apache.phoenix.query.QueryConstants;
+import org.apache.phoenix.util.DateUtil;
+import org.apache.phoenix.util.PropertiesUtil;
+import org.apache.phoenix.util.QueryUtil;
+import org.junit.Test;
+
+public class IndexExpressionIT extends BaseHBaseManagedTimeIT {
+
+ private static final int NUM_MILLIS_IN_DAY = 86400000;
+
+ @Test
+ public void testImmutableIndexCreationAndUpdate() throws Exception {
+ helpTestCreateAndUpdate(false, false);
+ }
+
+ @Test
+ public void testImmutableLocalIndexCreationAndUpdate() throws Exception {
+ helpTestCreateAndUpdate(false, true);
+ }
+
+ @Test
+ public void testMutableIndexCreationAndUpdate() throws Exception {
+ helpTestCreateAndUpdate(true, false);
+ }
+
+ @Test
+ public void testMutableLocalIndexCreationAndUpdate() throws Exception {
+ helpTestCreateAndUpdate(true, true);
+ }
+
+ /**
+ * Adds a row to the index data table
+ *
+ * @param i
+ * row number
+ */
+ private void insertRow(PreparedStatement stmt, int i) throws SQLException {
+ // insert row
+ stmt.setString(1, "varchar" + String.valueOf(i));
+ stmt.setString(2, "char" + String.valueOf(i));
+ stmt.setInt(3, i);
+ stmt.setLong(4, i);
+ stmt.setBigDecimal(5, new BigDecimal(Double.valueOf(i)));
+ Date date = new Date(DateUtil.parseDate("2015-01-01 00:00:00").getTime() + (i - 1) * NUM_MILLIS_IN_DAY);
+ stmt.setDate(6, date);
+ stmt.setString(7, "a.varchar" + String.valueOf(i));
+ stmt.setString(8, "a.char" + String.valueOf(i));
+ stmt.setInt(9, i);
+ stmt.setLong(10, i);
+ stmt.setBigDecimal(11, new BigDecimal((double)i));
+ stmt.setDate(12, date);
+ stmt.setString(13, "b.varchar" + String.valueOf(i));
+ stmt.setString(14, "b.char" + String.valueOf(i));
+ stmt.setInt(15, i);
+ stmt.setLong(16, i);
+ stmt.setBigDecimal(17, new BigDecimal((double)i));
+ stmt.setDate(18, date);
+ stmt.executeUpdate();
+ }
+
+ private void verifyResult(ResultSet rs, int i) throws SQLException {
+ assertTrue(rs.next());
+ assertEquals("VARCHAR" + String.valueOf(i) + "_" + StringUtils.rightPad("CHAR" + String.valueOf(i), 6, ' ')
+ + "_A.VARCHAR" + String.valueOf(i) + "_" + StringUtils.rightPad("B.CHAR" + String.valueOf(i), 10, ' '),
+ rs.getString(1));
+ assertEquals(i * 4, rs.getInt(2));
+ Date date = new Date(DateUtil.parseDate("2015-01-01 00:00:00").getTime() + (i) * NUM_MILLIS_IN_DAY);
+ assertEquals(date, rs.getDate(3));
+ assertEquals(date, rs.getDate(4));
+ assertEquals(date, rs.getDate(5));
+ assertEquals("varchar" + String.valueOf(i), rs.getString(6));
+ assertEquals("char" + String.valueOf(i), rs.getString(7));
+ assertEquals(i, rs.getInt(8));
+ assertEquals(i, rs.getLong(9));
+ assertEquals(i, rs.getDouble(10), 0.000001);
+ assertEquals(i, rs.getLong(11));
+ assertEquals(i, rs.getLong(12));
+ }
+
+ protected void helpTestCreateAndUpdate(boolean mutable, boolean localIndex) throws Exception {
+ String dataTableName = mutable ? MUTABLE_INDEX_DATA_TABLE : INDEX_DATA_TABLE;
+ String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+ populateDataTable(conn, dataTableName);
+
+ // create an expression index
+ String ddl = "CREATE "
+ + (localIndex ? "LOCAL" : "")
+ + " INDEX IDX ON "
+ + fullDataTableName
+ + " ((UPPER(varchar_pk) || '_' || UPPER(char_pk) || '_' || UPPER(varchar_col1) || '_' || UPPER(char_col2)),"
+ + " (decimal_pk+int_pk+decimal_col2+int_col1)," + " date_pk+1, date1+1, date2+1 )"
+ + " INCLUDE (long_col1, long_col2)";
+ PreparedStatement stmt = conn.prepareStatement(ddl);
+ stmt.execute();
+
+ // run select query with expression in WHERE clause
+ String whereSql = "SELECT long_col1, long_col2 from "
+ + fullDataTableName
+ + " WHERE UPPER(varchar_pk) || '_' || UPPER(char_pk) || '_' || UPPER(varchar_col1) || '_' || UPPER(char_col2) = ?"
+ + " AND decimal_pk+int_pk+decimal_col2+int_col1=?"
+ // since a.date1 and b.date2 are NULLABLE and date is fixed width, these expressions are stored as
+ // DECIMAL in the index (which is not fixed width)
+ + " AND date_pk+1=? AND date1+1=? AND date2+1=?";
+ stmt = conn.prepareStatement(whereSql);
+ stmt.setString(1, "VARCHAR1_CHAR1 _A.VARCHAR1_B.CHAR1 ");
+ stmt.setInt(2, 4);
+ Date date = DateUtil.parseDate("2015-01-02 00:00:00");
+ stmt.setDate(3, date);
+ stmt.setDate(4, date);
+ stmt.setDate(5, date);
+
+ // verify that the query does a range scan on the index table
+ ResultSet rs = stmt.executeQuery("EXPLAIN " + whereSql);
+ assertEquals(
+ localIndex ? "CLIENT PARALLEL 1-WAY RANGE SCAN OVER _LOCAL_IDX_INDEX_TEST."
+ + dataTableName
+ + " [-32768,'VARCHAR1_CHAR1 _A.VARCHAR1_B.CHAR1 ',4,'2015-01-02 00:00:00.000',1,420,156,800,000,1,420,156,800,000]\nCLIENT MERGE SORT"
+ : "CLIENT PARALLEL 1-WAY RANGE SCAN OVER INDEX_TEST.IDX ['VARCHAR1_CHAR1 _A.VARCHAR1_B.CHAR1 ',4,'2015-01-02 00:00:00.000',1,420,156,800,000,1,420,156,800,000]",
+ QueryUtil.getExplainPlan(rs));
+
+ // verify that the correct results are returned
+ rs = stmt.executeQuery();
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(1));
+ assertEquals(1, rs.getInt(2));
+ assertFalse(rs.next());
+
+ // verify all rows in data table are present in index table
+ String indexSelectSql = "SELECT UPPER(varchar_pk) || '_' || UPPER(char_pk) || '_' || UPPER(varchar_col1) || '_' || UPPER(char_col2), "
+ + "decimal_pk+int_pk+decimal_col2+int_col1, "
+ + "date_pk+1, date1+1, date2+1, "
+ + "varchar_pk, char_pk, int_pk, long_pk, decimal_pk, "
+ + "long_col1, long_col2 "
+ + "from "
+ + fullDataTableName;
+ rs = conn.createStatement().executeQuery("EXPLAIN " + indexSelectSql);
+ assertEquals(localIndex ? "CLIENT PARALLEL 1-WAY RANGE SCAN OVER _LOCAL_IDX_" + fullDataTableName
+ + " [-32768]\nCLIENT MERGE SORT" : "CLIENT PARALLEL 1-WAY FULL SCAN OVER INDEX_TEST.IDX",
+ QueryUtil.getExplainPlan(rs));
+ rs = conn.createStatement().executeQuery(indexSelectSql);
+ verifyResult(rs, 1);
+ verifyResult(rs, 2);
+
+ // Insert two more rows to the index data table
+ String upsert = "UPSERT INTO " + fullDataTableName
+ + " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ stmt = conn.prepareStatement(upsert);
+ insertRow(stmt, 3);
+ insertRow(stmt, 4);
+ conn.commit();
+
+ rs = conn.createStatement().executeQuery(indexSelectSql);
+ verifyResult(rs, 1);
+ verifyResult(rs, 2);
+ // verify that two rows added after index was created were also added to
+ // the index table
+ verifyResult(rs, 3);
+ verifyResult(rs, 4);
+
+ // update the first row
+ upsert = "UPSERT INTO "
+ + fullDataTableName
+ + "(varchar_pk, char_pk, int_pk, long_pk, decimal_pk, date_pk, a.varchar_col1) VALUES(?, ?, ?, ?, ?, ?, ?)";
+
+ stmt = conn.prepareStatement(upsert);
+ stmt.setString(1, "varchar1");
+ stmt.setString(2, "char1");
+ stmt.setInt(3, 1);
+ stmt.setLong(4, 1l);
+ stmt.setBigDecimal(5, new BigDecimal(1.0));
+ stmt.setDate(6, DateUtil.parseDate("2015-01-01 00:00:00"));
+ stmt.setString(7, "a.varchar_updated");
+ stmt.executeUpdate();
+ conn.commit();
+
+ // verify only one row was updated in the data table
+ String selectSql = "UPPER(varchar_pk) || '_' || UPPER(char_pk) || '_' || UPPER(varchar_col1) || '_' || UPPER(char_col2) from "
+ + fullDataTableName;
+ rs = conn.createStatement().executeQuery("SELECT /*+ NO_INDEX */ " + selectSql);
+ assertTrue(rs.next());
+ assertEquals("VARCHAR1_CHAR1 _A.VARCHAR_UPDATED_B.CHAR1 ", rs.getString(1));
+ assertTrue(rs.next());
+ assertEquals("VARCHAR2_CHAR2 _A.VARCHAR2_B.CHAR2 ", rs.getString(1));
+ assertTrue(rs.next());
+ assertEquals("VARCHAR3_CHAR3 _A.VARCHAR3_B.CHAR3 ", rs.getString(1));
+ assertTrue(rs.next());
+ assertEquals("VARCHAR4_CHAR4 _A.VARCHAR4_B.CHAR4 ", rs.getString(1));
+ assertFalse(rs.next());
+
+ // verify that the rows in the index table are also updated
+ rs = conn.createStatement().executeQuery("SELECT " + selectSql);
+ assertTrue(rs.next());
+ // if the data table is immutable, the index table will have one more
+ // row
+ if (!mutable) {
+ assertEquals("VARCHAR1_CHAR1 _A.VARCHAR1_B.CHAR1 ", rs.getString(1));
+ assertTrue(rs.next());
+ }
+ assertEquals("VARCHAR1_CHAR1 _A.VARCHAR_UPDATED_" + (mutable ? "B.CHAR1 " : ""), rs.getString(1));
+ assertTrue(rs.next());
+ assertEquals("VARCHAR2_CHAR2 _A.VARCHAR2_B.CHAR2 ", rs.getString(1));
+ assertTrue(rs.next());
+ assertEquals("VARCHAR3_CHAR3 _A.VARCHAR3_B.CHAR3 ", rs.getString(1));
+ assertTrue(rs.next());
+ assertEquals("VARCHAR4_CHAR4 _A.VARCHAR4_B.CHAR4 ", rs.getString(1));
+ assertFalse(rs.next());
+ conn.createStatement().execute("DROP INDEX IDX ON " + fullDataTableName);
+ } finally {
+ conn.close();
+ }
+ }
+
+ private void populateDataTable(Connection conn, String dataTable) throws SQLException {
+ ensureTableCreated(getUrl(), dataTable);
+ String upsert = "UPSERT INTO " + INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTable
+ + " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ PreparedStatement stmt1 = conn.prepareStatement(upsert);
+ // insert two rows
+ insertRow(stmt1, 1);
+ insertRow(stmt1, 2);
+ conn.commit();
+ }
+
+ @Test
+ public void testDeleteIndexedExpressionImmutableIndex() throws Exception {
+ helpTestDeleteIndexedExpression(false, false);
+ }
+
+ @Test
+ public void testDeleteIndexedExpressionImmutableLocalIndex() throws Exception {
+ helpTestDeleteIndexedExpression(false, true);
+ }
+
+ @Test
+ public void testDeleteIndexedExpressionMutableIndex() throws Exception {
+ helpTestDeleteIndexedExpression(true, false);
+ }
+
+ @Test
+ public void testDeleteIndexedExpressionMutableLocalIndex() throws Exception {
+ helpTestDeleteIndexedExpression(true, true);
+ }
+
+ protected void helpTestDeleteIndexedExpression(boolean mutable, boolean localIndex) throws Exception {
+ String dataTableName = mutable ? MUTABLE_INDEX_DATA_TABLE : INDEX_DATA_TABLE;
+ String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
+ String fullIndexTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + "IDX";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+ ensureTableCreated(getUrl(), dataTableName);
+ populateDataTable(conn, dataTableName);
+ String ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX IDX ON " + fullDataTableName
+ + " (2*long_col2)";
+ PreparedStatement stmt = conn.prepareStatement(ddl);
+ stmt.execute();
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullDataTableName);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullIndexTableName);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+
+ conn.setAutoCommit(true);
+ String dml = "DELETE from " + fullDataTableName + " WHERE long_col2 = 2";
+ try {
+ conn.createStatement().execute(dml);
+ if (!mutable) {
+ fail();
+ }
+ } catch (SQLException e) {
+ if (!mutable) {
+ assertEquals(SQLExceptionCode.INVALID_FILTER_ON_IMMUTABLE_ROWS.getErrorCode(), e.getErrorCode());
+ }
+ }
+
+ if (!mutable) {
+ dml = "DELETE from " + fullDataTableName + " WHERE 2*long_col2 = 4";
+ conn.createStatement().execute(dml);
+ }
+
+ rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullDataTableName);
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(1));
+ rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullIndexTableName);
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(1));
+ conn.createStatement().execute("DROP INDEX IDX ON " + fullDataTableName);
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testDeleteCoveredColImmutableIndex() throws Exception {
+ helpTestDeleteCoveredCol(false, false);
+ }
+
+ @Test
+ public void testDeleteCoveredColImmutableLocalIndex() throws Exception {
+ helpTestDeleteCoveredCol(false, true);
+ }
+
+ @Test
+ public void testDeleteCoveredColMutableIndex() throws Exception {
+ helpTestDeleteCoveredCol(true, false);
+ }
+
+ @Test
+ public void testDeleteCoveredColMutableLocalIndex() throws Exception {
+ helpTestDeleteCoveredCol(true, true);
+ }
+
+ protected void helpTestDeleteCoveredCol(boolean mutable, boolean localIndex) throws Exception {
+ String dataTableName = mutable ? MUTABLE_INDEX_DATA_TABLE : INDEX_DATA_TABLE;
+ String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
+ String fullIndexTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + "IDX";
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+ ensureTableCreated(getUrl(), dataTableName);
+ populateDataTable(conn, dataTableName);
+ String ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX IDX ON " + fullDataTableName
+ + " (long_pk, varchar_pk, 1+long_pk, UPPER(varchar_pk) )" + " INCLUDE (long_col1, long_col2)";
+ PreparedStatement stmt = conn.prepareStatement(ddl);
+ stmt.execute();
+
+ ResultSet rs;
+ rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullDataTableName);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ rs = conn.createStatement().executeQuery("SELECT COUNT(*) FROM " + fullIndexTableName);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+
+ String dml = "DELETE from " + fullDataTableName + " WHERE long_col2 = 2";
+ assertEquals(1, conn.createStatement().executeUpdate(dml));
+ conn.commit();
+
+ String query = "SELECT /*+ NO_INDEX */ long_pk, varchar_pk, 1+long_pk, UPPER(varchar_pk) FROM "
+ + fullDataTableName;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals(1L, rs.getLong(1));
+ assertEquals("varchar1", rs.getString(2));
+ assertEquals(2L, rs.getLong(3));
+ assertEquals("VARCHAR1", rs.getString(4));
+ assertFalse(rs.next());
+
+ query = "SELECT long_pk, varchar_pk, 1+long_pk, UPPER(varchar_pk) FROM " + fullDataTableName;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals(1L, rs.getLong(1));
+ assertEquals("varchar1", rs.getString(2));
+ assertEquals(2L, rs.getLong(3));
+ assertEquals("VARCHAR1", rs.getString(4));
+ assertFalse(rs.next());
+
+ query = "SELECT * FROM " + fullIndexTableName;
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+
+ assertEquals(1L, rs.getLong(1));
+ assertEquals("varchar1", rs.getString(2));
+ assertEquals(2L, rs.getLong(3));
+ assertEquals("VARCHAR1", rs.getString(4));
+ assertFalse(rs.next());
+ conn.createStatement().execute("DROP INDEX IDX ON " + fullDataTableName);
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testGroupByCountImmutableIndex() throws Exception {
+ helpTestGroupByCount(false, false);
+ }
+
+ @Test
+ public void testGroupByCountImmutableLocalIndex() throws Exception {
+ helpTestGroupByCount(false, true);
+ }
+
+ @Test
+ public void testGroupByCountMutableIndex() throws Exception {
+ helpTestGroupByCount(true, false);
+ }
+
+ @Test
+ public void testGroupByCountMutableLocalIndex() throws Exception {
+ helpTestGroupByCount(true, true);
+ }
+
+ protected void helpTestGroupByCount(boolean mutable, boolean localIndex) throws Exception {
+ String dataTableName = mutable ? MUTABLE_INDEX_DATA_TABLE : INDEX_DATA_TABLE;
+ String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+ populateDataTable(conn, dataTableName);
+ String ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX IDX ON " + fullDataTableName
+ + " (int_col1+int_col2)";
+ PreparedStatement stmt = conn.prepareStatement(ddl);
+ stmt.execute();
+
+ String groupBySql = "SELECT (int_col1+int_col2), COUNT(*) FROM " + fullDataTableName
+ + " GROUP BY (int_col1+int_col2)";
+ ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + groupBySql);
+ String expectedPlan = "CLIENT PARALLEL 1-WAY "
+ + (localIndex ? "RANGE SCAN OVER _LOCAL_IDX_" + fullDataTableName + " [-32768]"
+ : "FULL SCAN OVER INDEX_TEST.IDX")
+ + "\n SERVER FILTER BY FIRST KEY ONLY\n SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [TO_BIGINT((A.INT_COL1 + B.INT_COL2))]\nCLIENT MERGE SORT";
+ assertEquals(expectedPlan, QueryUtil.getExplainPlan(rs));
+ rs = conn.createStatement().executeQuery(groupBySql);
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(2));
+ assertTrue(rs.next());
+ assertEquals(1, rs.getInt(2));
+ assertFalse(rs.next());
+ conn.createStatement().execute("DROP INDEX IDX ON " + fullDataTableName);
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSelectDistinctImmutableIndex() throws Exception {
+ helpTestSelectDistinct(false, false);
+ }
+
+ @Test
+ public void testSelectDistinctImmutableIndexLocal() throws Exception {
+ helpTestSelectDistinct(false, true);
+ }
+
+ @Test
+ public void testSelectDistinctMutableIndex() throws Exception {
+ helpTestSelectDistinct(true, false);
+ }
+
+ @Test
+ public void testSelectDistinctMutableLocalIndex() throws Exception {
+ helpTestSelectDistinct(true, true);
+ }
+
+ protected void helpTestSelectDistinct(boolean mutable, boolean localIndex) throws Exception {
+ String dataTableName = mutable ? MUTABLE_INDEX_DATA_TABLE : INDEX_DATA_TABLE;
+ String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+ populateDataTable(conn, dataTableName);
+ String ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX IDX ON " + fullDataTableName
+ + " (int_col1+1)";
+ PreparedStatement stmt = conn.prepareStatement(ddl);
+ stmt.execute();
+ String sql = "SELECT distinct int_col1+1 FROM " + fullDataTableName + " where int_col1+1 > 0";
+ ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + sql);
+ String expectedPlan = "CLIENT PARALLEL 1-WAY RANGE SCAN OVER "
+ + (localIndex ? "_LOCAL_IDX_" + fullDataTableName + " [-32768,0] - [-32768,*]"
+ : "INDEX_TEST.IDX [0] - [*]")
+ + "\n SERVER FILTER BY FIRST KEY ONLY\n SERVER AGGREGATE INTO ORDERED DISTINCT ROWS BY [TO_BIGINT((A.INT_COL1 + 1))]\nCLIENT MERGE SORT";
+ assertEquals(expectedPlan, QueryUtil.getExplainPlan(rs));
+ rs = conn.createStatement().executeQuery(sql);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(3, rs.getInt(1));
+ assertFalse(rs.next());
+ conn.createStatement().execute("DROP INDEX IDX ON " + fullDataTableName);
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testInClauseWithImmutableIndex() throws Exception {
+ helpTestInClauseWithIndex(false, false);
+ }
+
+ @Test
+ public void testInClauseWithImmutableLocalIndex() throws Exception {
+ helpTestInClauseWithIndex(false, true);
+ }
+
+ @Test
+ public void testInClauseWithMutableIndex() throws Exception {
+ helpTestInClauseWithIndex(true, false);
+ }
+
+ @Test
+ public void testInClauseWithMutableLocalIndex() throws Exception {
+ helpTestInClauseWithIndex(true, false);
+ }
+
+ protected void helpTestInClauseWithIndex(boolean mutable, boolean localIndex) throws Exception {
+ String dataTableName = mutable ? MUTABLE_INDEX_DATA_TABLE : INDEX_DATA_TABLE;
+ String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+ populateDataTable(conn, dataTableName);
+ String ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX IDX ON " + fullDataTableName
+ + " (int_col1+1)";
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+ PreparedStatement stmt = conn.prepareStatement(ddl);
+ stmt.execute();
+ String sql = "SELECT int_col1+1 FROM " + fullDataTableName + " where int_col1+1 IN (2)";
+ ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + sql);
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER "
+ + (localIndex ? "_LOCAL_IDX_" + fullDataTableName + " [-32768,2]\n SERVER FILTER BY FIRST KEY ONLY\nCLIENT MERGE SORT"
+ : "INDEX_TEST.IDX [2]\n SERVER FILTER BY FIRST KEY ONLY"), QueryUtil.getExplainPlan(rs));
+ rs = conn.createStatement().executeQuery(sql);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertFalse(rs.next());
+ conn.createStatement().execute("DROP INDEX IDX ON " + fullDataTableName);
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testOrderByWithImmutableIndex() throws Exception {
+ helpTestOrderByWithIndex(false, false);
+ }
+
+ @Test
+ public void testOrderByWithImmutableLocalIndex() throws Exception {
+ helpTestOrderByWithIndex(false, true);
+ }
+
+ @Test
+ public void testOrderByWithMutableIndex() throws Exception {
+ helpTestOrderByWithIndex(true, false);
+ }
+
+ @Test
+ public void testOrderByWithMutableLocalIndex() throws Exception {
+ helpTestOrderByWithIndex(true, false);
+ }
+
+ protected void helpTestOrderByWithIndex(boolean mutable, boolean localIndex) throws Exception {
+ String dataTableName = mutable ? MUTABLE_INDEX_DATA_TABLE : INDEX_DATA_TABLE;
+ String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+ populateDataTable(conn, dataTableName);
+ String ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX IDX ON " + fullDataTableName
+ + " (int_col1+1)";
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+ PreparedStatement stmt = conn.prepareStatement(ddl);
+ stmt.execute();
+ String sql = "SELECT int_col1+1 FROM " + fullDataTableName + " ORDER BY int_col1+1";
+ ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + sql);
+ assertEquals("CLIENT PARALLEL 1-WAY "
+ + (localIndex ? "RANGE SCAN OVER _LOCAL_IDX_" + fullDataTableName
+ + " [-32768]\n SERVER FILTER BY FIRST KEY ONLY\nCLIENT MERGE SORT"
+ : "FULL SCAN OVER INDEX_TEST.IDX\n SERVER FILTER BY FIRST KEY ONLY"),
+ QueryUtil.getExplainPlan(rs));
+ rs = conn.createStatement().executeQuery(sql);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertTrue(rs.next());
+ assertEquals(3, rs.getInt(1));
+ assertFalse(rs.next());
+ conn.createStatement().execute("DROP INDEX IDX ON " + fullDataTableName);
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testSelectColOnlyInDataTableImmutableIndex() throws Exception {
+ helpTestSelectColOnlyInDataTable(false, false);
+ }
+
+ @Test
+ public void testSelectColOnlyInDataTableImmutableLocalIndex() throws Exception {
+ helpTestSelectColOnlyInDataTable(false, true);
+ }
+
+ @Test
+ public void testSelectColOnlyInDataTableMutableIndex() throws Exception {
+ helpTestSelectColOnlyInDataTable(true, false);
+ }
+
+ @Test
+ public void testSelectColOnlyInDataTableMutableLocalIndex() throws Exception {
+ helpTestSelectColOnlyInDataTable(true, false);
+ }
+
+ protected void helpTestSelectColOnlyInDataTable(boolean mutable, boolean localIndex) throws Exception {
+ String dataTableName = mutable ? MUTABLE_INDEX_DATA_TABLE : INDEX_DATA_TABLE;
+ String fullDataTableName = INDEX_DATA_SCHEMA + QueryConstants.NAME_SEPARATOR + dataTableName;
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.setAutoCommit(false);
+ populateDataTable(conn, dataTableName);
+ String ddl = "CREATE " + (localIndex ? "LOCAL" : "") + " INDEX IDX ON " + fullDataTableName
+ + " (int_col1+1)";
+
+ conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+ PreparedStatement stmt = conn.prepareStatement(ddl);
+ stmt.execute();
+ String sql = "SELECT int_col1+1, int_col2 FROM " + fullDataTableName + " WHERE int_col1+1=2";
+ ResultSet rs = conn.createStatement().executeQuery("EXPLAIN " + sql);
+ assertEquals("CLIENT PARALLEL 1-WAY "
+ + (localIndex ? "RANGE SCAN OVER _LOCAL_IDX_" + fullDataTableName
+ + " [-32768,2]\n SERVER FILTER BY FIRST KEY ONLY\nCLIENT MERGE SORT" : "FULL SCAN OVER "
+ + fullDataTableName + "\n SERVER FILTER BY (A.INT_COL1 + 1) = 2"),
+ QueryUtil.getExplainPlan(rs));
+ rs = conn.createStatement().executeQuery(sql);
+ assertTrue(rs.next());
+ assertEquals(2, rs.getInt(1));
+ assertEquals(1, rs.getInt(2));
+ assertFalse(rs.next());
+ conn.createStatement().execute("DROP INDEX IDX ON " + fullDataTableName);
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testImmutableIndexWithCaseSensitiveCols() throws Exception {
+ helpTestIndexWithCaseSensitiveCols(false, false);
+ }
+
+ @Test
+ public void testImmutableLocalIndexWithCaseSensitiveCols() throws Exception {
+ helpTestIndexWithCaseSensitiveCols(true, false);
+ }
+
+ @Test
+ public void testMutableIndexWithCaseSensitiveCols() throws Exception {
+ helpTestIndexWithCaseSensitiveCols(true, false);
+ }
+
+ @Test
+ public void testMutableLocalIndexWithCaseSensitiveCols() throws Exception {
+ helpTestIndexWithCaseSensitiveCols(true, false);
+ }
+
+ protected void helpTestIndexWithCaseSensitiveCols(boolean mutable, boolean localIndex) throws Exception {
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ try {
+ conn.createStatement().execute("CREATE TABLE cs (k VARCHAR NOT NULL PRIMARY KEY, \"V1\" VARCHAR, \"v2\" VARCHAR) "+ (mutable ? "IMMUTABLE_ROWS=true" : ""));
+ String query = "SELECT * FROM cs";
+ ResultSet rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+ if (localIndex) {
+ conn.createStatement().execute("CREATE LOCAL INDEX ics ON cs (\"v2\" || '_modified') INCLUDE (\"V1\",\"v2\")");
+ } else {
+ conn.createStatement().execute("CREATE INDEX ics ON cs (\"V1\" || '_' || \"v2\") INCLUDE (\"V1\",\"v2\")");
+ }
+ query = "SELECT * FROM ics";
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ PreparedStatement stmt = conn.prepareStatement("UPSERT INTO cs VALUES(?,?,?)");
+ stmt.setString(1,"a");
+ stmt.setString(2, "x");
+ stmt.setString(3, "1");
+ stmt.execute();
+ stmt.setString(1,"b");
+ stmt.setString(2, "y");
+ stmt.setString(3, "2");
+ stmt.execute();
+ conn.commit();
+
+ //TODO FIX THIS change this to *
+ query = "SELECT (\"V1\" || '_' || \"v2\"), k, \"V1\", \"v2\" FROM cs WHERE (\"V1\" || '_' || \"v2\") = 'x_1'";
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ if(localIndex){
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER _LOCAL_IDX_CS [-32768,'x_1']\n"
+ + "CLIENT MERGE SORT", QueryUtil.getExplainPlan(rs));
+ } else {
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER ICS ['x_1']", QueryUtil.getExplainPlan(rs));
+ }
+
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("x_1",rs.getString(1));
+ assertEquals("a",rs.getString(2));
+ assertEquals("x",rs.getString(3));
+ assertEquals("1",rs.getString(4));
+ //TODO figure out why this " " is needed
+ assertEquals("x_1",rs.getString("\"('V1' || '_' || 'v2')\""));
+ assertEquals("a",rs.getString("k"));
+ assertEquals("x",rs.getString("V1"));
+ assertEquals("1",rs.getString("v2"));
+ assertFalse(rs.next());
+
+ query = "SELECT \"V1\", \"V1\" as foo1, (\"V1\" || '_' || \"v2\") as foo, (\"V1\" || '_' || \"v2\") as \"Foo1\", (\"V1\" || '_' || \"v2\") FROM cs ORDER BY foo";
+ rs = conn.createStatement().executeQuery("EXPLAIN " + query);
+ if(localIndex){
+ assertEquals("CLIENT PARALLEL 1-WAY RANGE SCAN OVER _LOCAL_IDX_CS [-32768]\nCLIENT MERGE SORT",
+ QueryUtil.getExplainPlan(rs));
+ } else {
+ assertEquals("CLIENT PARALLEL 1-WAY FULL SCAN OVER ICS", QueryUtil.getExplainPlan(rs));
+ }
+
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("x",rs.getString(1));
+ assertEquals("x",rs.getString("V1"));
+ assertEquals("x",rs.getString(2));
+ assertEquals("x",rs.getString("foo1"));
+ assertEquals("x_1",rs.getString(3));
+ assertEquals("x_1",rs.getString("Foo"));
+ assertEquals("x_1",rs.getString(4));
+ assertEquals("x_1",rs.getString("Foo1"));
+ assertEquals("x_1",rs.getString(5));
+ assertEquals("x_1",rs.getString("\"('V1' || '_' || 'v2')\""));
+ assertTrue(rs.next());
+ assertEquals("y",rs.getString(1));
+ assertEquals("y",rs.getString("V1"));
+ assertEquals("y",rs.getString(2));
+ assertEquals("y",rs.getString("foo1"));
+ assertEquals("y_2",rs.getString(3));
+ assertEquals("y_2",rs.getString("Foo"));
+ assertEquals("y_2",rs.getString(4));
+ assertEquals("y_2",rs.getString("Foo1"));
+ assertEquals("y_2",rs.getString(5));
+ assertEquals("y_2",rs.getString("\"('V1' || '_' || 'v2')\""));
+ assertFalse(rs.next());
+ conn.createStatement().execute("DROP INDEX ICS ON CS");
+ } finally {
+ conn.close();
+ }
+ }
+
+ @Test
+ public void testImmutableIndexDropIndexedColumn() throws Exception {
+ helpTestDropIndexedColumn(false, false);
+ }
+
+ @Test
+ public void testImmutableLocalIndexDropIndexedColumn() throws Exception {
+ helpTestDropIndexedColumn(false, true);
+ }
+
+ @Test
+ public void testMutableIndexDropIndexedColumn() throws Exception {
+ helpTestDropIndexedColumn(true, false);
+ }
+
+ @Test
+ public void testMutableLocalIndexDropIndexedColumn() throws Exception {
+ helpTestDropIndexedColumn(true, true);
+ }
+
+ public void helpTestDropIndexedColumn(boolean mutable, boolean local) throws Exception {
+ String query;
+ ResultSet rs;
+ PreparedStatement stmt;
+
+ Properties props = PropertiesUtil.deepCopy(TEST_PROPERTIES);
+ Connection conn = DriverManager.getConnection(getUrl(), props);
+ conn.setAutoCommit(false);
+
+ // make sure that the tables are empty, but reachable
+ conn.createStatement().execute(
+ "CREATE TABLE t (k VARCHAR NOT NULL PRIMARY KEY, v1 VARCHAR, v2 VARCHAR)");
+ query = "SELECT * FROM t" ;
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+ String indexName = "it_" + (mutable ? "m" : "im") + "_" + (local ? "l" : "h");
+ conn.createStatement().execute("CREATE " + ( local ? "LOCAL" : "") + " INDEX " + indexName + " ON t (v1 || '_' || v2)");
+
+ query = "SELECT * FROM t";
+ rs = conn.createStatement().executeQuery(query);
+ assertFalse(rs.next());
+
+ // load some data into the table
+ stmt = conn.prepareStatement("UPSERT INTO t VALUES(?,?,?)");
+ stmt.setString(1, "a");
+ stmt.setString(2, "x");
+ stmt.setString(3, "1");
+ stmt.execute();
+ conn.commit();
+
+ assertIndexExists(conn,true);
+ conn.createStatement().execute("ALTER TABLE t DROP COLUMN v1");
+ assertIndexExists(conn,false);
+
+ query = "SELECT * FROM t";
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("a",rs.getString(1));
+ assertEquals("1",rs.getString(2));
+ assertFalse(rs.next());
+
+ // load some data into the table
+ stmt = conn.prepareStatement("UPSERT INTO t VALUES(?,?)");
+ stmt.setString(1, "a");
+ stmt.setString(2, "2");
+ stmt.execute();
+ conn.commit();
+
+ query = "SELECT * FROM t";
+ rs = conn.createStatement().executeQuery(query);
+ assertTrue(rs.next());
+ assertEquals("a",rs.getString(1));
+ assertEquals("2",rs.getString(2));
+ assertFalse(rs.next());
+ }
+
+ private static void assertIndexExists(Connection conn, boolean exists) throws SQLException {
+ ResultSet rs = conn.getMetaData().getIndexInfo(null, null, "T", false, false);
+ assertEquals(exists, rs.next());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/8c340f5a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/IndexMetadataIT.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 88e7340..d6ced3c 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
@@ -100,7 +100,7 @@ public class IndexMetadataIT extends BaseHBaseManagedTimeIT {
String fullTableName = SchemaUtil.getTableName(schemaName, tableName);
conn.createStatement().executeQuery("SELECT count(*) FROM " + fullTableName).next(); // client side cache will update
PhoenixConnection pconn = conn.unwrap(PhoenixConnection.class);
- pconn.getMetaDataCache().getTable(new PTableKey(pconn.getTenantId(), fullTableName)).getIndexMaintainers(ptr);
+ pconn.getMetaDataCache().getTable(new PTableKey(pconn.getTenantId(), fullTableName)).getIndexMaintainers(ptr, pconn);
assertTrue(ptr.getLength() > 0);
}
@@ -109,7 +109,7 @@ public class IndexMetadataIT extends BaseHBaseManagedTimeIT {
String fullTableName = SchemaUtil.getTableName(schemaName, tableName);
conn.createStatement().executeQuery("SELECT count(*) FROM " + fullTableName).next(); // client side cache will update
PhoenixConnection pconn = conn.unwrap(PhoenixConnection.class);
- pconn.getMetaDataCache().getTable(new PTableKey(pconn.getTenantId(), fullTableName)).getIndexMaintainers(ptr);
+ pconn.getMetaDataCache().getTable(new PTableKey(pconn.getTenantId(), fullTableName)).getIndexMaintainers(ptr, pconn);
assertTrue(ptr.getLength() == 0);
}
@@ -135,8 +135,9 @@ public class IndexMetadataIT extends BaseHBaseManagedTimeIT {
assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX", 5, ":CHAR_PK", Order.ASC);
assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX", 6, ":LONG_PK", Order.DESC);
assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX", 7, ":DECIMAL_PK", Order.ASC);
- assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX", 8, "A:INT_COL1", null);
- assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX", 9, "B:INT_COL2", null);
+ assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX", 8, ":DATE_PK", Order.ASC);
+ assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX", 9, "A:INT_COL1", null);
+ assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX", 10, "B:INT_COL2", null);
assertFalse(rs.next());
rs = conn.getMetaData().getTables(null, StringUtil.escapeLike(INDEX_DATA_SCHEMA), StringUtil.escapeLike("IDX"), new String[] {PTableType.INDEX.getValue().getString() });
@@ -245,8 +246,9 @@ public class IndexMetadataIT extends BaseHBaseManagedTimeIT {
assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX1", 5, ":CHAR_PK", Order.ASC);
assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX1", 6, ":LONG_PK", Order.DESC);
assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX1", 7, ":DECIMAL_PK", Order.ASC);
- assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX1", 8, "A:INT_COL1", null);
- assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX1", 9, "B:INT_COL2", null);
+ assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX1", 8, ":DATE_PK", Order.ASC);
+ assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX1", 9, "A:INT_COL1", null);
+ assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX1", 10, "B:INT_COL2", null);
assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX2", 1, "A:VARCHAR_COL1", Order.ASC);
assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX2", 2, "B:VARCHAR_COL2", Order.ASC);
@@ -255,7 +257,8 @@ public class IndexMetadataIT extends BaseHBaseManagedTimeIT {
assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX2", 5, ":CHAR_PK", Order.ASC);
assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX2", 6, ":LONG_PK", Order.DESC);
assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX2", 7, ":DECIMAL_PK", Order.ASC);
- assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX2", 8, "B:INT_COL2", null);
+ assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX2", 8, ":DATE_PK", Order.ASC);
+ assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, MUTABLE_INDEX_DATA_TABLE, "IDX2", 9, "B:INT_COL2", null);
assertFalse(rs.next());
// Create another table in the same schema
@@ -307,7 +310,8 @@ public class IndexMetadataIT extends BaseHBaseManagedTimeIT {
assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, INDEX_DATA_TABLE, "IDX", 6, ":INT_PK", Order.ASC);
assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, INDEX_DATA_TABLE, "IDX", 7, ":LONG_PK", Order.DESC);
assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, INDEX_DATA_TABLE, "IDX", 8, ":DECIMAL_PK", Order.ASC);
- assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, INDEX_DATA_TABLE, "IDX", 9, "A:INT_COL1", null);
+ assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, INDEX_DATA_TABLE, "IDX", 9, ":DATE_PK", Order.ASC);
+ assertIndexInfoMetadata(rs, INDEX_DATA_SCHEMA, INDEX_DATA_TABLE, "IDX", 10, "A:INT_COL1", null);
assertFalse(rs.next());
rs = IndexTestUtil.readDataTableIndexRow(conn, INDEX_DATA_SCHEMA, INDEX_DATA_TABLE, "IDX");
http://git-wip-us.apache.org/repos/asf/phoenix/blob/8c340f5a/phoenix-core/src/main/antlr3/PhoenixSQL.g
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/antlr3/PhoenixSQL.g b/phoenix-core/src/main/antlr3/PhoenixSQL.g
index bcf26be..fad5fb3 100644
--- a/phoenix-core/src/main/antlr3/PhoenixSQL.g
+++ b/phoenix-core/src/main/antlr3/PhoenixSQL.g
@@ -393,11 +393,11 @@ create_view_node returns [CreateTableStatement ret]
// Parse a create index statement.
create_index_node returns [CreateIndexStatement ret]
: CREATE l=LOCAL? INDEX (IF NOT ex=EXISTS)? i=index_name ON t=from_table_name
- (LPAREN pk=index_pk_constraint RPAREN)
+ (LPAREN ik=ik_constraint RPAREN)
(INCLUDE (LPAREN icrefs=column_names RPAREN))?
(p=fam_properties)?
(SPLIT ON v=value_expression_list)?
- {ret = factory.createIndex(i, factory.namedTable(null,t), pk, icrefs, v, p, ex!=null, l==null ? IndexType.getDefault() : IndexType.LOCAL, getBindCount()); }
+ {ret = factory.createIndex(i, factory.namedTable(null,t), ik, icrefs, v, p, ex!=null, l==null ? IndexType.getDefault() : IndexType.LOCAL, getBindCount()); }
;
// Parse a create sequence statement.
@@ -436,17 +436,17 @@ col_name_with_sort_order returns [Pair<ColumnName, SortOrder> ret]
: f=identifier (order=ASC|order=DESC)? {$ret = Pair.newPair(factory.columnName(f), order == null ? SortOrder.getDefault() : SortOrder.fromDDLValue(order.getText()));}
;
-index_pk_constraint returns [PrimaryKeyConstraint ret]
- : cols = col_def_name_with_sort_order_list {$ret = factory.primaryKey(null, cols); }
- ;
+ik_constraint returns [IndexKeyConstraint ret]
+ : x = expression_with_sort_order_list {$ret = factory.indexKey(x); }
+;
-col_def_name_with_sort_order_list returns [List<Pair<ColumnName, SortOrder>> ret]
-@init{ret = new ArrayList<Pair<ColumnName, SortOrder>>(); }
- : p=col_def_name_with_sort_order {$ret.add(p);} (COMMA p = col_def_name_with_sort_order {$ret.add(p);} )*
+expression_with_sort_order_list returns [List<Pair<ParseNode, SortOrder>> ret]
+@init{ret = new ArrayList<Pair<ParseNode, SortOrder>>(); }
+ : p=expression_with_sort_order {$ret.add(p);} (COMMA p = expression_with_sort_order {$ret.add(p);} )*
;
-col_def_name_with_sort_order returns [Pair<ColumnName, SortOrder> ret]
- : c=column_name (order=ASC|order=DESC)? {$ret = Pair.newPair(c, order == null ? SortOrder.getDefault() : SortOrder.fromDDLValue(order.getText()));}
+expression_with_sort_order returns [Pair<ParseNode, SortOrder> ret]
+ : (x=expression) (order=ASC|order=DESC)? {$ret = Pair.newPair(x, order == null ? SortOrder.getDefault() : SortOrder.fromDDLValue(order.getText()));}
;
fam_properties returns [ListMultimap<String,Pair<String,Object>> ret]
@@ -780,7 +780,9 @@ term returns [ParseNode ret]
| field=identifier LPAREN l=zero_or_more_expressions RPAREN wg=(WITHIN GROUP LPAREN ORDER BY l2=one_or_more_expressions (a=ASC | DESC) RPAREN)?
{
FunctionParseNode f = wg==null ? factory.function(field, l) : factory.function(field,l,l2,a!=null);
- contextStack.peek().setAggregate(f.isAggregate());
+ if (!contextStack.isEmpty()) {
+ contextStack.peek().setAggregate(f.isAggregate());
+ }
$ret = f;
}
| field=identifier LPAREN t=ASTERISK RPAREN
@@ -789,13 +791,17 @@ term returns [ParseNode ret]
throwRecognitionException(t);
}
FunctionParseNode f = factory.function(field, LiteralParseNode.STAR);
- contextStack.peek().setAggregate(f.isAggregate());
+ if (!contextStack.isEmpty()) {
+ contextStack.peek().setAggregate(f.isAggregate());
+ }
$ret = f;
}
| field=identifier LPAREN t=DISTINCT l=zero_or_more_expressions RPAREN
{
FunctionParseNode f = factory.functionDistinct(field, l);
- contextStack.peek().setAggregate(f.isAggregate());
+ if (!contextStack.isEmpty()) {
+ contextStack.peek().setAggregate(f.isAggregate());
+ }
$ret = f;
}
| e=case_statement { $ret = e; }
http://git-wip-us.apache.org/repos/asf/phoenix/blob/8c340f5a/phoenix-core/src/main/java/org/apache/hadoop/hbase/regionserver/IndexHalfStoreFileReaderGenerator.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/hadoop/hbase/regionserver/IndexHalfStoreFileReaderGenerator.java b/phoenix-core/src/main/java/org/apache/hadoop/hbase/regionserver/IndexHalfStoreFileReaderGenerator.java
index f213d2d..718f820 100644
--- a/phoenix-core/src/main/java/org/apache/hadoop/hbase/regionserver/IndexHalfStoreFileReaderGenerator.java
+++ b/phoenix-core/src/main/java/org/apache/hadoop/hbase/regionserver/IndexHalfStoreFileReaderGenerator.java
@@ -57,8 +57,8 @@ import org.apache.phoenix.schema.MetaDataClient;
import org.apache.phoenix.schema.PColumn;
import org.apache.phoenix.schema.PIndexState;
import org.apache.phoenix.schema.PTable;
-import org.apache.phoenix.schema.PTableType;
import org.apache.phoenix.schema.PTable.IndexType;
+import org.apache.phoenix.schema.PTableType;
import org.apache.phoenix.util.ByteUtil;
import org.apache.phoenix.util.IndexUtil;
import org.apache.phoenix.util.MetaDataUtil;
@@ -144,7 +144,7 @@ public class IndexHalfStoreFileReaderGenerator extends BaseRegionObserver {
new HashMap<ImmutableBytesWritable, IndexMaintainer>();
for (PTable index : indexes) {
if (index.getIndexType() == IndexType.LOCAL) {
- IndexMaintainer indexMaintainer = index.getIndexMaintainer(dataTable);
+ IndexMaintainer indexMaintainer = index.getIndexMaintainer(dataTable, conn);
indexMaintainers.put(new ImmutableBytesWritable(MetaDataUtil
.getViewIndexIdDataType().toBytes(index.getViewIndexId())),
indexMaintainer);
http://git-wip-us.apache.org/repos/asf/phoenix/blob/8c340f5a/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
index 0a2ee38..322d24a 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/DeleteCompiler.java
@@ -65,7 +65,6 @@ import org.apache.phoenix.schema.MetaDataClient;
import org.apache.phoenix.schema.MetaDataEntityNotFoundException;
import org.apache.phoenix.schema.PColumn;
import org.apache.phoenix.schema.PIndexState;
-import org.apache.phoenix.schema.types.PLong;
import org.apache.phoenix.schema.PName;
import org.apache.phoenix.schema.PRow;
import org.apache.phoenix.schema.PTable;
@@ -75,6 +74,7 @@ import org.apache.phoenix.schema.ReadOnlyTableException;
import org.apache.phoenix.schema.SortOrder;
import org.apache.phoenix.schema.TableRef;
import org.apache.phoenix.schema.tuple.Tuple;
+import org.apache.phoenix.schema.types.PLong;
import org.apache.phoenix.util.MetaDataUtil;
import org.apache.phoenix.util.ScanUtil;
@@ -483,7 +483,7 @@ public class DeleteCompiler {
public MutationState execute() throws SQLException {
// TODO: share this block of code with UPSERT SELECT
ImmutableBytesWritable ptr = context.getTempPtr();
- tableRef.getTable().getIndexMaintainers(ptr);
+ tableRef.getTable().getIndexMaintainers(ptr, context.getConnection());
ServerCache cache = null;
try {
if (ptr.getLength() > 0) {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/8c340f5a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
index 95e145c..97818e6 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/ExpressionCompiler.java
@@ -135,6 +135,7 @@ public class ExpressionCompiler extends UnsupportedAllParseNodeVisitor<Expressio
protected final StatementContext context;
protected final GroupBy groupBy;
private int nodeCount;
+ private int totalNodeCount;
private final boolean resolveViewConstants;
public ExpressionCompiler(StatementContext context) {
@@ -166,6 +167,7 @@ public class ExpressionCompiler extends UnsupportedAllParseNodeVisitor<Expressio
public void reset() {
this.isAggregate = false;
this.nodeCount = 0;
+ this.totalNodeCount = 0;
}
@Override
@@ -420,6 +422,7 @@ public class ExpressionCompiler extends UnsupportedAllParseNodeVisitor<Expressio
@Override
public void addElement(List<Expression> l, Expression element) {
nodeCount--;
+ totalNodeCount++;
l.add(element);
}
@@ -553,7 +556,7 @@ public class ExpressionCompiler extends UnsupportedAllParseNodeVisitor<Expressio
expr = CastParseNode.convertToRoundExpressionIfNeeded(fromDataType, targetDataType, children);
}
}
- return CoerceExpression.create(expr, targetDataType, SortOrder.getDefault(), expr.getMaxLength());
+ return wrapGroupByExpression(CoerceExpression.create(expr, targetDataType, SortOrder.getDefault(), expr.getMaxLength()));
}
@Override
@@ -1254,4 +1257,8 @@ public class ExpressionCompiler extends UnsupportedAllParseNodeVisitor<Expressio
Object result = context.getSubqueryResult(node.getSelectNode());
return LiteralExpression.newConstant(result);
}
+
+ public int getTotalNodeCount() {
+ return totalNodeCount;
+ }
}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/8c340f5a/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
index 0163082..1a605b7 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java
@@ -184,7 +184,7 @@ public class FromCompiler {
Expression sourceExpression = projector.getColumnProjector(column.getPosition()).getExpression();
PColumnImpl projectedColumn = new PColumnImpl(column.getName(), column.getFamilyName(),
sourceExpression.getDataType(), sourceExpression.getMaxLength(), sourceExpression.getScale(), sourceExpression.isNullable(),
- column.getPosition(), sourceExpression.getSortOrder(), column.getArraySize(), column.getViewConstant(), column.isViewReferenced());
+ column.getPosition(), sourceExpression.getSortOrder(), column.getArraySize(), column.getViewConstant(), column.isViewReferenced(), column.getExpressionStr());
projectedColumns.add(projectedColumn);
sourceExpressions.add(sourceExpression);
}
@@ -391,7 +391,7 @@ public class FromCompiler {
familyName = PNameFactory.newName(family);
}
allcolumns.add(new PColumnImpl(name, familyName, dynColumn.getDataType(), dynColumn.getMaxLength(),
- dynColumn.getScale(), dynColumn.isNull(), position, dynColumn.getSortOrder(), dynColumn.getArraySize(), null, false));
+ dynColumn.getScale(), dynColumn.isNull(), position, dynColumn.getSortOrder(), dynColumn.getArraySize(), null, false, dynColumn.getExpression()));
position++;
}
theTable = PTableImpl.makePTable(theTable, allcolumns);
@@ -469,7 +469,7 @@ public class FromCompiler {
}
PColumnImpl column = new PColumnImpl(PNameFactory.newName(alias),
PNameFactory.newName(QueryConstants.DEFAULT_COLUMN_FAMILY),
- null, 0, 0, true, position++, SortOrder.ASC, null, null, false);
+ null, 0, 0, true, position++, SortOrder.ASC, null, null, false, null);
columns.add(column);
}
PTable t = PTableImpl.makePTable(null, PName.EMPTY_NAME, PName.EMPTY_NAME,
http://git-wip-us.apache.org/repos/asf/phoenix/blob/8c340f5a/phoenix-core/src/main/java/org/apache/phoenix/compile/HavingCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/HavingCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/HavingCompiler.java
index 0cd6ecf..224a9b4 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/HavingCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/HavingCompiler.java
@@ -35,8 +35,8 @@ import org.apache.phoenix.parse.ParseNode;
import org.apache.phoenix.parse.SelectStatement;
import org.apache.phoenix.parse.SelectStatementRewriter;
import org.apache.phoenix.schema.ColumnRef;
-import org.apache.phoenix.schema.types.PBoolean;
import org.apache.phoenix.schema.TypeMismatchException;
+import org.apache.phoenix.schema.types.PBoolean;
public class HavingCompiler {
@@ -171,7 +171,7 @@ public class HavingCompiler {
@Override
public Void visit(ColumnParseNode node) throws SQLException {
ColumnRef ref = context.getResolver().resolveColumn(node.getSchemaName(), node.getTableName(), node.getName());
- boolean isAggregateColumn = groupBy.getExpressions().indexOf(ref.newColumnExpression()) >= 0;
+ boolean isAggregateColumn = groupBy.getExpressions().indexOf(ref.newColumnExpression(node.isTableNameCaseSensitive(), node.isCaseSensitive())) >= 0;
if (hasOnlyAggregateColumns == null) {
hasOnlyAggregateColumns = isAggregateColumn;
} else {
http://git-wip-us.apache.org/repos/asf/phoenix/blob/8c340f5a/phoenix-core/src/main/java/org/apache/phoenix/compile/IndexExpressionCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/IndexExpressionCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/IndexExpressionCompiler.java
new file mode 100644
index 0000000..b4a4168
--- /dev/null
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/IndexExpressionCompiler.java
@@ -0,0 +1,53 @@
+/*
+ * 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.compile;
+
+import java.sql.SQLException;
+
+import org.apache.phoenix.expression.ColumnExpression;
+import org.apache.phoenix.parse.ColumnParseNode;
+import org.apache.phoenix.schema.ColumnRef;
+
+/**
+ * Used to check if the expression being compiled is a {@link ColumnExpression}
+ */
+public class IndexExpressionCompiler extends ExpressionCompiler {
+
+ //
+ private ColumnRef columnRef;
+
+ public IndexExpressionCompiler(StatementContext context) {
+ super(context);
+ this.columnRef = null;
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ this.columnRef = null;
+ }
+
+ @Override
+ protected ColumnRef resolveColumn(ColumnParseNode node) throws SQLException {
+ ColumnRef columnRef = super.resolveColumn(node);
+ if (isTopLevel()) {
+ this.columnRef = columnRef;
+ }
+ return columnRef;
+ }
+
+ /**
+ * @return if the expression being compiled is a regular column the column ref, else is null
+ */
+ public ColumnRef getColumnRef() {
+ return columnRef;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/phoenix/blob/8c340f5a/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
----------------------------------------------------------------------
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
index 445edd8..c29ea23 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/JoinCompiler.java
@@ -788,7 +788,7 @@ public class JoinCompiler {
PName name = PNameFactory.newName(aliasedName);
PColumnImpl column = new PColumnImpl(name, familyName, sourceColumn.getDataType(),
sourceColumn.getMaxLength(), sourceColumn.getScale(), sourceColumn.isNullable(),
- position, sourceColumn.getSortOrder(), sourceColumn.getArraySize(), sourceColumn.getViewConstant(), sourceColumn.isViewReferenced());
+ position, sourceColumn.getSortOrder(), sourceColumn.getArraySize(), sourceColumn.getViewConstant(), sourceColumn.isViewReferenced(), sourceColumn.getExpressionStr());
Expression sourceExpression = isLocalIndexColumnRef ?
NODE_FACTORY.column(TableName.create(schemaName, tableName), "\"" + colName + "\"", null).accept(new ExpressionCompiler(context))
: new ColumnRef(tableRef, sourceColumn.getPosition()).newColumnExpression();
@@ -807,7 +807,7 @@ public class JoinCompiler {
Expression sourceExpression = rowProjector.getColumnProjector(column.getPosition()).getExpression();
PColumnImpl projectedColumn = new PColumnImpl(PNameFactory.newName(colName), PNameFactory.newName(TupleProjector.VALUE_COLUMN_FAMILY),
sourceExpression.getDataType(), sourceExpression.getMaxLength(), sourceExpression.getScale(), sourceExpression.isNullable(),
- column.getPosition(), sourceExpression.getSortOrder(), column.getArraySize(), column.getViewConstant(), column.isViewReferenced());
+ column.getPosition(), sourceExpression.getSortOrder(), column.getArraySize(), column.getViewConstant(), column.isViewReferenced(), column.getExpressionStr());
projectedColumns.add(projectedColumn);
sourceExpressions.add(sourceExpression);
}
@@ -1367,7 +1367,7 @@ public class JoinCompiler {
} else {
PColumnImpl column = new PColumnImpl(c.getName(), c.getFamilyName(), c.getDataType(),
c.getMaxLength(), c.getScale(), true, c.getPosition(),
- c.getSortOrder(), c.getArraySize(), c.getViewConstant(), c.isViewReferenced());
+ c.getSortOrder(), c.getArraySize(), c.getViewConstant(), c.isViewReferenced(), c.getExpressionStr());
merged.add(column);
}
}
@@ -1378,7 +1378,7 @@ public class JoinCompiler {
PColumnImpl column = new PColumnImpl(c.getName(),
PNameFactory.newName(TupleProjector.VALUE_COLUMN_FAMILY), c.getDataType(),
c.getMaxLength(), c.getScale(), type == JoinType.Inner ? c.isNullable() : true, position++,
- c.getSortOrder(), c.getArraySize(), c.getViewConstant(), c.isViewReferenced());
+ c.getSortOrder(), c.getArraySize(), c.getViewConstant(), c.isViewReferenced(), c.getExpressionStr());
merged.add(column);
}
}