PHOENIX-4712 When creating an index on a table, meta data cache of views related to the table isn't updated
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 5c0d100..279bbd7 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
@@ -33,6 +33,7 @@
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.sql.Statement;
import java.util.List;
import java.util.Properties;
@@ -894,6 +895,51 @@
}
}
+ @Test
+ public void testQueryWithSeparateConnectionForViewOnTableThatHasIndex() throws SQLException {
+ try (Connection conn = DriverManager.getConnection(getUrl());
+ Connection conn2 = DriverManager.getConnection(getUrl());
+ Statement s = conn.createStatement();
+ Statement s2 = conn2.createStatement()) {
+ String tableName = generateUniqueName();
+ String viewName = generateUniqueName();
+ String indexName = generateUniqueName();
+ helpTestQueryForViewOnTableThatHasIndex(s, s2, tableName, viewName, indexName);
+ }
+ }
+
+ @Test
+ public void testQueryForViewOnTableThatHasIndex() throws SQLException {
+ try (Connection conn = DriverManager.getConnection(getUrl());
+ Statement s = conn.createStatement()) {
+ String tableName = generateUniqueName();
+ String viewName = generateUniqueName();
+ String indexName = generateUniqueName();
+ helpTestQueryForViewOnTableThatHasIndex(s, s, tableName, viewName, indexName);
+ }
+ }
+
+ private void helpTestQueryForViewOnTableThatHasIndex(Statement s1, Statement s2, String tableName, String viewName, String indexName)
+ throws SQLException {
+ // Create a table
+ s1.execute("create table " + tableName + " (col1 varchar primary key, col2 varchar)");
+
+ // Create a view on the table
+ s1.execute("create view " + viewName + " (col3 varchar) as select * from " + tableName);
+ s1.executeQuery("select * from " + viewName);
+ // Create a index on the table
+ s1.execute("create index " + indexName + " ON " + tableName + " (col2)");
+
+ try (ResultSet rs =
+ s2.executeQuery("explain select /*+ INDEX(" + viewName + " " + indexName
+ + ") */ * from " + viewName + " where col2 = 'aaa'")) {
+ String explainPlan = QueryUtil.getExplainPlan(rs);
+
+ // check if the query uses the index
+ assertTrue(explainPlan.contains(indexName));
+ }
+ }
+
private void validate(String viewName, Connection tenantConn, String[] whereClauseArray,
long[] expectedArray) throws SQLException {
for (int i = 0; i < whereClauseArray.length; ++i) {
diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
index 69d8a56..009289b 100644
--- a/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
+++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
@@ -682,7 +682,7 @@
// In this case, we update the parent table which may in turn pull
// in indexes to add to this table.
long resolvedTime = TransactionUtil.getResolvedTime(connection, result);
- if (addIndexesFromParentTable(result, resolvedTimestamp)) {
+ if (addIndexesFromParentTable(result, resolvedTimestamp, true)) {
connection.addTable(result.getTable(), resolvedTime);
} else {
// if we aren't adding the table, we still need to update the
@@ -808,10 +808,12 @@
* TODO: combine this round trip with the one that updates the cache for the child table.
* @param result the result from updating the cache for the current table.
* @param resolvedTimestamp timestamp at which child table was resolved
+ * @param alwaysAddIndexes flag that determines whether we should recalculate
+ * all indexes that can be used in the view
* @return true if the PTable contained by result was modified and false otherwise
* @throws SQLException if the physical table cannot be found
*/
- private boolean addIndexesFromParentTable(MetaDataMutationResult result, Long resolvedTimestamp) throws SQLException {
+ private boolean addIndexesFromParentTable(MetaDataMutationResult result, Long resolvedTimestamp, boolean alwaysAddIndexes) throws SQLException {
PTable view = result.getTable();
// If not a view or if a view directly over an HBase table, there's nothing to do
if (view.getType() != PTableType.VIEW || view.getViewType() == ViewType.MAPPED) {
@@ -826,7 +828,8 @@
if (parentTable == null) {
throw new TableNotFoundException(schemaName, tableName);
}
- if (!result.wasUpdated() && !parentResult.wasUpdated()) {
+ // if alwaysAddIndexes is false we only add indexes if the parent table or view was updated from the server
+ if (!alwaysAddIndexes && !result.wasUpdated() && !parentResult.wasUpdated()) {
return false;
}
List<PTable> parentTableIndexes = parentTable.getIndexes();
@@ -3985,7 +3988,7 @@
}
private PTable addTableToCache(MetaDataMutationResult result) throws SQLException {
- addIndexesFromParentTable(result, null);
+ addIndexesFromParentTable(result, null, false);
PTable table = result.getTable();
connection.addTable(table, TransactionUtil.getResolvedTime(connection, result));
return table;