This is an automated email from the ASF dual-hosted git repository.

vjasani pushed a commit to branch 5.2
in repository https://gitbox.apache.org/repos/asf/phoenix.git


The following commit(s) were added to refs/heads/5.2 by this push:
     new 848b926b59 PHOENIX-7386 Override UPDATE_CACHE_FREQUENCY if table has 
disabled indexes (#1955) (#1959)
848b926b59 is described below

commit 848b926b598eaf41bbf23ba3f815cfe9a456bd9e
Author: Viraj Jasani <[email protected]>
AuthorDate: Fri Aug 23 19:54:54 2024 -0700

    PHOENIX-7386 Override UPDATE_CACHE_FREQUENCY if table has disabled indexes 
(#1955) (#1959)
---
 .../org/apache/phoenix/index/IndexMaintainer.java  |  10 +-
 .../org/apache/phoenix/schema/MetaDataClient.java  |  31 +-
 .../phoenix/end2end/UCFWithDisabledIndexIT.java    | 417 +++++++++++++++++++++
 3 files changed, 455 insertions(+), 3 deletions(-)

diff --git 
a/phoenix-core-client/src/main/java/org/apache/phoenix/index/IndexMaintainer.java
 
b/phoenix-core-client/src/main/java/org/apache/phoenix/index/IndexMaintainer.java
index 6c27be2ecb..5dcc18ecdb 100644
--- 
a/phoenix-core-client/src/main/java/org/apache/phoenix/index/IndexMaintainer.java
+++ 
b/phoenix-core-client/src/main/java/org/apache/phoenix/index/IndexMaintainer.java
@@ -150,8 +150,14 @@ public class IndexMaintainer implements Writable, 
Iterable<ColumnReference> {
         IndexMaintainer maintainer = new IndexMaintainer(dataTable, index, 
connection);
         return maintainer;
     }
-    
-    private static boolean sendIndexMaintainer(PTable index) {
+
+    /**
+     * Determines whether the client should send IndexMaintainer for the given 
Index table.
+     *
+     * @param index PTable for the index table.
+     * @return True if the client needs to send IndexMaintainer for the given 
Index.
+     */
+    public static boolean sendIndexMaintainer(PTable index) {
         PIndexState indexState = index.getIndexState();
         return ! ( indexState.isDisabled() || PIndexState.PENDING_ACTIVE == 
indexState );
     }
diff --git 
a/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
 
b/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
index e1336ec0e0..6ecfd8c022 100644
--- 
a/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
+++ 
b/phoenix-core-client/src/main/java/org/apache/phoenix/schema/MetaDataClient.java
@@ -769,10 +769,39 @@ public class MetaDataClient {
             final long effectiveUpdateCacheFreq;
             final String ucfInfoForLogging; // Only used for logging purposes
 
+            boolean overrideUcfToDefault = false;
+            if (table.getType() == INDEX) {
+                overrideUcfToDefault =
+                        
PIndexState.PENDING_DISABLE.equals(table.getIndexState()) ||
+                                !IndexMaintainer.sendIndexMaintainer(table);
+            }
+            if (!overrideUcfToDefault && !table.getIndexes().isEmpty()) {
+                List<PTable> indexes = table.getIndexes();
+                List<PTable> maintainedIndexes =
+                        
Lists.newArrayList(IndexMaintainer.maintainedIndexes(indexes.iterator()));
+                // The maintainedIndexes contain only the indexes that are 
used by clients
+                // while generating the mutations. If all the indexes are 
usable by clients,
+                // we don't need to override UPDATE_CACHE_FREQUENCY. However, 
if any index is
+                // not in usable state by the client mutations, we should 
override
+                // UPDATE_CACHE_FREQUENCY to default value so that we make 
getTable() RPC calls
+                // until all index states change to ACTIVE, BUILDING or other 
usable states.
+                overrideUcfToDefault = indexes.size() != 
maintainedIndexes.size();
+            }
+
             // What if the table is created with UPDATE_CACHE_FREQUENCY 
explicitly set to ALWAYS?
             // i.e. explicitly set to 0. We should ideally be checking for 
something like
             // hasUpdateCacheFrequency().
-            if (table.getUpdateCacheFrequency() != 0L) {
+
+            //always fetch an Index in PENDING_DISABLE state to retrieve 
server timestamp
+            //QueryOptimizer needs that to decide whether the index can be used
+            if (overrideUcfToDefault) {
+                effectiveUpdateCacheFreq =
+                    (Long) ConnectionProperty.UPDATE_CACHE_FREQUENCY.getValue(
+                        connection.getQueryServices().getProps()
+                            
.get(QueryServices.DEFAULT_UPDATE_CACHE_FREQUENCY_ATRRIB));
+                ucfInfoForLogging = "connection-level-default";
+            } else if (table.getUpdateCacheFrequency()
+                    != QueryServicesOptions.DEFAULT_UPDATE_CACHE_FREQUENCY) {
                 effectiveUpdateCacheFreq = table.getUpdateCacheFrequency();
                 ucfInfoForLogging = "table-level";
             } else {
diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/UCFWithDisabledIndexIT.java
 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UCFWithDisabledIndexIT.java
new file mode 100644
index 0000000000..cd72ff8435
--- /dev/null
+++ 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/UCFWithDisabledIndexIT.java
@@ -0,0 +1,417 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.phoenix.end2end;
+
+import com.google.protobuf.RpcCallback;
+import com.google.protobuf.RpcController;
+import org.apache.hadoop.hbase.DoNotRetryIOException;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.apache.phoenix.compile.ExplainPlan;
+import org.apache.phoenix.compile.ExplainPlanAttributes;
+import org.apache.phoenix.coprocessor.MetaDataEndpointImpl;
+import org.apache.phoenix.coprocessor.generated.MetaDataProtos;
+import org.apache.phoenix.coprocessorclient.BaseScannerRegionObserverConstants;
+import org.apache.phoenix.exception.PhoenixIOException;
+import org.apache.phoenix.jdbc.PhoenixConnection;
+import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData;
+import org.apache.phoenix.jdbc.PhoenixPreparedStatement;
+import org.apache.phoenix.protobuf.ProtobufUtil;
+import org.apache.phoenix.query.BaseTest;
+import org.apache.phoenix.query.QueryServices;
+import org.apache.phoenix.schema.PIndexState;
+import org.apache.phoenix.schema.PTable;
+import org.apache.phoenix.thirdparty.com.google.common.collect.Maps;
+import org.apache.phoenix.util.ClientUtil;
+import org.apache.phoenix.util.ReadOnlyProps;
+import org.apache.phoenix.util.SchemaUtil;
+import org.apache.phoenix.util.TestUtil;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Map;
+import java.util.Properties;
+
+import static 
org.apache.phoenix.query.QueryServices.DISABLE_VIEW_SUBTREE_VALIDATION;
+
+/**
+ * Tests that use UPDATE_CACHE_FREQUENCY with some of the disabled index 
states that require
+ * clients to override UPDATE_CACHE_FREQUENCY and perform metadata calls to 
retrieve PTable.
+ */
+@Category(NeedsOwnMiniClusterTest.class)
+public class UCFWithDisabledIndexIT extends BaseTest {
+
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(UCFWithDisabledIndexIT.class);
+
+    private static void initCluster() throws Exception {
+        Map<String, String> props = Maps.newConcurrentMap();
+        
props.put(BaseScannerRegionObserverConstants.PHOENIX_MAX_LOOKBACK_AGE_CONF_KEY,
+                Integer.toString(60 * 60 * 1000));
+        props.put(QueryServices.DEFAULT_UPDATE_CACHE_FREQUENCY_ATRRIB, 
"ALWAYS");
+        props.put(QueryServices.TASK_HANDLING_INITIAL_DELAY_MS_ATTRIB,
+                Long.toString(Long.MAX_VALUE));
+        props.put(DISABLE_VIEW_SUBTREE_VALIDATION, "true");
+        setUpTestDriver(new ReadOnlyProps(props.entrySet().iterator()));
+    }
+
+    @BeforeClass
+    public static synchronized void doSetup() throws Exception {
+        initCluster();
+    }
+
+    public static class TestMetaDataEndpointImpl extends MetaDataEndpointImpl {
+
+        @Override
+        public void getTable(RpcController controller, 
MetaDataProtos.GetTableRequest request,
+                             RpcCallback<MetaDataProtos.MetaDataResponse> 
done) {
+            LOGGER.error("Not expected to get getTable() for {}",
+                    Bytes.toString(request.getTableName().toByteArray()));
+            ProtobufUtil.setControllerException(controller,
+                    ClientUtil.createIOException(
+                            SchemaUtil.getPhysicalTableName(
+                                            
PhoenixDatabaseMetaData.SYSTEM_CATALOG_NAME_BYTES,
+                                            false).toString(),
+                            new DoNotRetryIOException("Not allowed")));
+
+        }
+
+    }
+
+    @Test
+    public void testUcfWithNoGetTableCalls() throws Throwable {
+        final String tableName = generateUniqueName();
+        final String indexName = "IDX_" + tableName;
+        final String view01 = "v01_" + tableName;
+        final String view02 = "v02_" + tableName;
+        final String index_view01 = "idx_v01_" + tableName;
+        final String index_view02 = "idx_v02_" + tableName;
+        final String index_view03 = "idx_v03_" + tableName;
+        final String index_view04 = "idx_v04_" + tableName;
+
+        try (Connection conn = DriverManager.getConnection(getUrl())) {
+            final Statement stmt = conn.createStatement();
+
+            stmt.execute("CREATE TABLE " + tableName
+                    + " (COL1 CHAR(10) NOT NULL, COL2 CHAR(5) NOT NULL, COL3 
VARCHAR,"
+                    + " COL4 VARCHAR CONSTRAINT pk PRIMARY KEY(COL1, COL2))"
+                    + " UPDATE_CACHE_FREQUENCY=20000");
+            stmt.execute("CREATE INDEX " + indexName
+                    + " ON " + tableName + " (COL3) INCLUDE (COL4)");
+            stmt.execute("CREATE VIEW " + view01
+                    + " (VCOL1 CHAR(8), COL5 VARCHAR) AS SELECT * FROM " + 
tableName
+                    + " WHERE COL1 = 'col1'");
+            stmt.execute("CREATE VIEW " + view02 + " (VCOL2 CHAR(10), COL6 
VARCHAR)"
+                    + " AS SELECT * FROM " + view01 + " WHERE VCOL1 = 
'vcol1'");
+
+            stmt.execute("CREATE INDEX " + index_view01 + " ON " + view01 + " 
(COL5) INCLUDE "
+                    + "(COL1, COL2, COL3)");
+            stmt.execute("CREATE INDEX " + index_view02 + " ON " + view02 + " 
(COL6) INCLUDE "
+                    + "(COL1, COL2, COL3)");
+            stmt.execute("CREATE INDEX " + index_view03 + " ON " + view01 + " 
(COL5) INCLUDE "
+                    + "(COL2, COL1)");
+            stmt.execute("CREATE INDEX " + index_view04 + " ON " + view02 + " 
(COL6) INCLUDE "
+                    + "(COL2, COL1)");
+
+            stmt.execute("UPSERT INTO " + view02
+                    + " (col2, vcol2, col5, col6) values ('0001', 'vcol2_01', 
'col5_01', " +
+                    "'col6_01')");
+            conn.commit();
+
+            TestUtil.removeCoprocessor(conn, "SYSTEM.CATALOG", 
MetaDataEndpointImpl.class);
+            TestUtil.addCoprocessor(conn, "SYSTEM.CATALOG", 
TestMetaDataEndpointImpl.class);
+
+            stmt.execute("UPSERT INTO " + view02
+                    +
+                    " (col2, vcol2, col5, col6) values ('0002', 'vcol2_02', 
'col5_02', 'col6_02')");
+            stmt.execute("UPSERT INTO " + view02
+                    +
+                    " (col2, vcol2, col5, col6) values ('0003', 'vcol2_03', 
'col5_03', 'col6_03')");
+            stmt.execute("UPSERT INTO " + view01 + " (col2, vcol1, col3, col4, 
col5) values "
+                    + "('0004', 'vcol2', 'col3_04', 'col4_04', 'col5_04')");
+            stmt.execute("UPSERT INTO " + view01 + " (col2, vcol1, col3, col4, 
col5) values "
+                    + "('0005', 'vcol-2', 'col3_05', 'col4_05', 'col5_05')");
+            stmt.execute("UPSERT INTO " + view01 + " (col2, vcol1, col3, col4, 
col5) values "
+                    + "('0006', 'vcol-1', 'col3_06', 'col4_06', 'col5_06')");
+            stmt.execute("UPSERT INTO " + view01 + " (col2, vcol1, col3, col4, 
col5) values "
+                    + "('0007', 'vcol1', 'col3_07', 'col4_07', 'col5_07')");
+            stmt.execute("UPSERT INTO " + view02
+                    +
+                    " (col2, vcol2, col5, col6) values ('0008', 'vcol2_08', 
'col5_08', 'col6_02')");
+            conn.commit();
+
+            final Statement statement = conn.createStatement();
+            ResultSet rs =
+                    statement.executeQuery(
+                            "SELECT COL2, VCOL1, VCOL2, COL5, COL6 FROM " + 
view02);
+            Assert.assertTrue(rs.next());
+            Assert.assertTrue(rs.next());
+            Assert.assertTrue(rs.next());
+            Assert.assertTrue(rs.next());
+            Assert.assertTrue(rs.next());
+            Assert.assertFalse(rs.next());
+
+            String query = "SELECT COL1, COL2, COL3, COL4 FROM " + tableName + 
" WHERE COL3 = " +
+                    "'col3_04'";
+            rs = statement.executeQuery(query);
+            Assert.assertTrue(rs.next());
+            Assert.assertFalse(rs.next());
+
+            ExplainPlan explainPlan = conn.prepareStatement(query)
+                    .unwrap(PhoenixPreparedStatement.class).optimizeQuery()
+                    .getExplainPlan();
+            ExplainPlanAttributes explainPlanAttributes =
+                    explainPlan.getPlanStepsAsAttributes();
+            Assert.assertEquals(indexName, 
explainPlanAttributes.getTableName());
+
+            TestUtil.removeCoprocessor(conn, "SYSTEM.CATALOG", 
TestMetaDataEndpointImpl.class);
+            TestUtil.addCoprocessor(conn, "SYSTEM.CATALOG", 
MetaDataEndpointImpl.class);
+        }
+    }
+
+    @Test
+    public void testUcfWithDisabledIndex1() throws Throwable {
+        final String tableName = generateUniqueName();
+        final String indexName = "IDX_" + tableName;
+
+        Connection conn = DriverManager.getConnection(getUrl());
+        try {
+            final Statement stmt = createIndexAndUpdateCoproc(conn, tableName, 
indexName, true);
+
+            stmt.execute("UPSERT INTO " + tableName
+                    + " (col1, col2, col3, col4) values ('c011', "
+                    + "'c012', 'c013', 'c014')");
+            conn.commit();
+            throw new RuntimeException("Should not reach here");
+        } catch (PhoenixIOException e) {
+            LOGGER.error("Error thrown. ", e);
+            Assert.assertTrue(e.getCause() instanceof DoNotRetryIOException);
+            Assert.assertTrue(e.getCause().getMessage().contains("Not 
allowed"));
+        } finally {
+            updateIndexToRebuild(conn, tableName, indexName);
+            TestUtil.removeCoprocessor(conn, "SYSTEM.CATALOG", 
TestMetaDataEndpointImpl.class);
+            TestUtil.addCoprocessor(conn, "SYSTEM.CATALOG", 
MetaDataEndpointImpl.class);
+            verifyTableAndIndexRows(conn, tableName, indexName, false);
+            conn.close();
+        }
+    }
+
+    private static void verifyTableAndIndexRows(Connection conn,
+                                                String tableName,
+                                                String indexName,
+                                                boolean isCreateDisableCase)
+            throws SQLException {
+        ResultSet rs1 = conn.createStatement().executeQuery("SELECT * FROM " + 
tableName);
+        ResultSet rs2 = conn.createStatement().executeQuery("SELECT * FROM " + 
indexName);
+        if (!isCreateDisableCase) {
+            Assert.assertTrue(rs1.next());
+            Assert.assertEquals("c000", rs1.getString(1));
+            Assert.assertEquals("c002", rs1.getString(2));
+            Assert.assertEquals("c003", rs1.getString(3));
+            Assert.assertEquals("c004", rs1.getString(4));
+            Assert.assertTrue(rs1.next());
+            Assert.assertEquals("c001", rs1.getString(1));
+            Assert.assertEquals("c002", rs1.getString(2));
+            Assert.assertEquals("c003", rs1.getString(3));
+            Assert.assertEquals("c004", rs1.getString(4));
+        }
+        Assert.assertTrue(rs1.next());
+        Assert.assertEquals("c011", rs1.getString(1));
+        Assert.assertEquals("c012", rs1.getString(2));
+        Assert.assertEquals("c013", rs1.getString(3));
+        Assert.assertEquals("c014", rs1.getString(4));
+        Assert.assertTrue(rs1.next());
+        Assert.assertEquals("c0112", rs1.getString(1));
+        Assert.assertEquals("c012", rs1.getString(2));
+        Assert.assertEquals("c013", rs1.getString(3));
+        Assert.assertEquals("c014", rs1.getString(4));
+        Assert.assertFalse(rs1.next());
+
+        if (!isCreateDisableCase) {
+            Assert.assertTrue(rs2.next());
+            Assert.assertEquals("c003", rs2.getString(1));
+            Assert.assertEquals("c000", rs2.getString(2));
+            Assert.assertEquals("c002", rs2.getString(3));
+            Assert.assertEquals("c004", rs2.getString(4));
+            Assert.assertTrue(rs2.next());
+            Assert.assertEquals("c003", rs2.getString(1));
+            Assert.assertEquals("c001", rs2.getString(2));
+            Assert.assertEquals("c002", rs2.getString(3));
+            Assert.assertEquals("c004", rs2.getString(4));
+        }
+        Assert.assertTrue(rs2.next());
+        Assert.assertEquals("c013", rs2.getString(1));
+        Assert.assertEquals("c011", rs2.getString(2));
+        Assert.assertEquals("c012", rs2.getString(3));
+        Assert.assertEquals("c014", rs2.getString(4));
+        Assert.assertTrue(rs2.next());
+        Assert.assertEquals("c013", rs2.getString(1));
+        Assert.assertEquals("c0112", rs2.getString(2));
+        Assert.assertEquals("c012", rs2.getString(3));
+        Assert.assertEquals("c014", rs2.getString(4));
+        Assert.assertFalse(rs2.next());
+    }
+
+    private static void updateIndexToRebuild(Connection conn, String 
tableName, String indexName)
+            throws Exception {
+        // re-attach original coproc
+        TestUtil.removeCoprocessor(conn, "SYSTEM.CATALOG", 
TestMetaDataEndpointImpl.class);
+        TestUtil.addCoprocessor(conn, "SYSTEM.CATALOG", 
MetaDataEndpointImpl.class);
+
+        final Statement stmt = conn.createStatement();
+        stmt.execute("UPSERT INTO " + tableName
+                + " (col1, col2, col3, col4) values ('c011', "
+                + "'c012', 'c013', 'c014')");
+        // expected to call getTable
+        conn.commit();
+
+        stmt.execute("ALTER INDEX " + indexName + " ON " + tableName + " 
REBUILD");
+
+        PTable indexTable = 
conn.unwrap(PhoenixConnection.class).getTableNoCache(indexName);
+        Assert.assertEquals(PIndexState.ACTIVE, indexTable.getIndexState());
+
+        // attach coproc that does not allow getTable RPC call
+        TestUtil.removeCoprocessor(conn, "SYSTEM.CATALOG", 
MetaDataEndpointImpl.class);
+        TestUtil.addCoprocessor(conn, "SYSTEM.CATALOG", 
TestMetaDataEndpointImpl.class);
+
+        stmt.execute("UPSERT INTO " + tableName
+                + " (col1, col2, col3, col4) values ('c0112', "
+                + "'c012', 'c013', 'c014')");
+        // not expected to call getTable
+        conn.commit();
+    }
+
+    private static Statement createIndexAndUpdateCoproc(Connection conn,
+                                                        String tableName,
+                                                        String indexName,
+                                                        boolean 
alterIndexState)
+            throws Exception {
+        final Statement stmt = conn.createStatement();
+
+        stmt.execute("CREATE TABLE " + tableName
+                + " (COL1 CHAR(10) NOT NULL, COL2 CHAR(5) NOT NULL, COL3 
VARCHAR,"
+                + " COL4 VARCHAR CONSTRAINT pk PRIMARY KEY(COL1, COL2))"
+                + " UPDATE_CACHE_FREQUENCY=10000");
+        stmt.execute("CREATE INDEX " + indexName
+                + " ON " + tableName + " (COL3) INCLUDE (COL4)");
+
+        if (alterIndexState) {
+            stmt.execute("ALTER INDEX " + indexName + " ON " + tableName + " 
DISABLE");
+        }
+
+        // expected to call getTable
+        ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName);
+        Assert.assertFalse(rs.next());
+
+        // attach coproc that does not allow getTable RPC call
+        TestUtil.removeCoprocessor(conn, "SYSTEM.CATALOG", 
MetaDataEndpointImpl.class);
+        TestUtil.addCoprocessor(conn, "SYSTEM.CATALOG", 
TestMetaDataEndpointImpl.class);
+
+        stmt.execute("UPSERT INTO " + tableName
+                + " (col1, col2, col3, col4) values ('c000', "
+                + "'c002', 'c003', 'c004')");
+        // not expected to call getTable unless index is created in 
CREATE_DISABLE state
+        conn.commit();
+
+        // re-attach original coproc
+        TestUtil.removeCoprocessor(conn, "SYSTEM.CATALOG", 
TestMetaDataEndpointImpl.class);
+        TestUtil.addCoprocessor(conn, "SYSTEM.CATALOG", 
MetaDataEndpointImpl.class);
+
+        Thread.sleep(11000);
+        stmt.execute("UPSERT INTO " + tableName
+                + " (col1, col2, col3, col4) values ('c001', "
+                + "'c002', 'c003', 'c004')");
+        // expected to call getTable
+        conn.commit();
+
+        PTable indexTable = 
conn.unwrap(PhoenixConnection.class).getTableNoCache(indexName);
+        if (alterIndexState) {
+            Assert.assertEquals(PIndexState.DISABLE, 
indexTable.getIndexState());
+        } else {
+            Assert.assertEquals(PIndexState.CREATE_DISABLE, 
indexTable.getIndexState());
+        }
+
+        // attach coproc that does not allow getTable RPC call
+        TestUtil.removeCoprocessor(conn, "SYSTEM.CATALOG", 
MetaDataEndpointImpl.class);
+        TestUtil.addCoprocessor(conn, "SYSTEM.CATALOG", 
TestMetaDataEndpointImpl.class);
+        return stmt;
+    }
+
+    @Test
+    public void testUcfWithDisabledIndex2() throws Throwable {
+        final String tableName = generateUniqueName();
+        final String indexName = "IDX_" + tableName;
+
+        Connection conn = DriverManager.getConnection(getUrl());
+        try {
+            final Statement stmt = createIndexAndUpdateCoproc(conn, tableName, 
indexName, true);
+
+            stmt.execute("SELECT * FROM " + indexName);
+            throw new RuntimeException("Should not reach here");
+        } catch (PhoenixIOException e) {
+            LOGGER.error("Error thrown. ", e);
+            Assert.assertTrue(e.getCause() instanceof DoNotRetryIOException);
+            Assert.assertTrue(e.getCause().getMessage().contains("Not 
allowed"));
+        } finally {
+            updateIndexToRebuild(conn, tableName, indexName);
+            TestUtil.removeCoprocessor(conn, "SYSTEM.CATALOG", 
TestMetaDataEndpointImpl.class);
+            TestUtil.addCoprocessor(conn, "SYSTEM.CATALOG", 
MetaDataEndpointImpl.class);
+            verifyTableAndIndexRows(conn, tableName, indexName, false);
+            conn.close();
+        }
+    }
+
+    @Test
+    public void testUcfWithDisabledIndex3() throws Throwable {
+        final String tableName = generateUniqueName();
+        final String indexName = "IDX_" + tableName;
+
+        Properties props = new Properties();
+        props.setProperty(QueryServices.INDEX_CREATE_DEFAULT_STATE,
+                PIndexState.CREATE_DISABLE.toString());
+        Connection conn = DriverManager.getConnection(getUrl(), props);
+        try {
+            final Statement stmt = createIndexAndUpdateCoproc(conn, tableName,
+                    indexName, false);
+
+            stmt.execute("UPSERT INTO " + tableName
+                    + " (col1, col2, col3, col4) values ('c011', "
+                    + "'c012', 'c013', 'c014')");
+            conn.commit();
+            throw new RuntimeException("Should not reach here");
+        } catch (PhoenixIOException e) {
+            LOGGER.error("Error thrown. ", e);
+            Assert.assertTrue(e.getCause() instanceof DoNotRetryIOException);
+            Assert.assertTrue(e.getCause().getMessage().contains("Not 
allowed"));
+        } finally {
+            updateIndexToRebuild(conn, tableName, indexName);
+            TestUtil.removeCoprocessor(conn, "SYSTEM.CATALOG", 
TestMetaDataEndpointImpl.class);
+            TestUtil.addCoprocessor(conn, "SYSTEM.CATALOG", 
MetaDataEndpointImpl.class);
+            verifyTableAndIndexRows(conn, tableName, indexName, true);
+            conn.close();
+        }
+    }
+
+}

Reply via email to