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

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


The following commit(s) were added to refs/heads/master by this push:
     new db16b53b9d PHOENIX-6953 Creating indexes on a table with old indexing 
leads to inconsistent co-processors
db16b53b9d is described below

commit db16b53b9d0d7f7c142799f417fb90e1d3d8fe75
Author: Istvan Toth <st...@apache.org>
AuthorDate: Thu May 11 15:58:26 2023 +0200

    PHOENIX-6953 Creating indexes on a table with old indexing leads to 
inconsistent co-processors
---
 .../org/apache/phoenix/end2end/CreateTableIT.java  | 101 ++++++++++++++++++++-
 .../phoenix/query/ConnectionQueryServicesImpl.java |  32 ++++---
 2 files changed, 119 insertions(+), 14 deletions(-)

diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java
index 680dba1baf..8e622f40b9 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java
@@ -17,6 +17,7 @@
  */
 package org.apache.phoenix.end2end;
 
+import static org.apache.phoenix.mapreduce.index.IndexUpgradeTool.ROLLBACK_OP;
 import static org.apache.phoenix.util.TestUtil.TEST_PROPERTIES;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -37,20 +38,22 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Properties;
+import java.util.UUID;
 
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.client.Admin;
 import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;
 import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;
-import org.apache.hadoop.hbase.ipc.PhoenixRpcSchedulerFactory;
-import org.apache.hadoop.hbase.regionserver.BloomType;
 import org.apache.hadoop.hbase.client.TableDescriptor;
 import org.apache.hadoop.hbase.client.TableDescriptorBuilder;
+import org.apache.hadoop.hbase.ipc.PhoenixRpcSchedulerFactory;
+import org.apache.hadoop.hbase.regionserver.BloomType;
 import org.apache.phoenix.exception.SQLExceptionCode;
 import org.apache.phoenix.jdbc.PhoenixConnection;
 import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData;
 import org.apache.phoenix.jdbc.PhoenixStatement;
+import org.apache.phoenix.mapreduce.index.IndexUpgradeTool;
 import org.apache.phoenix.query.BaseTest;
 import org.apache.phoenix.query.KeyRange;
 import org.apache.phoenix.query.QueryConstants;
@@ -65,7 +68,6 @@ import org.apache.phoenix.schema.PTableType;
 import org.apache.phoenix.schema.SchemaNotFoundException;
 import org.apache.phoenix.schema.TableAlreadyExistsException;
 import org.apache.phoenix.schema.TableNotFoundException;
-import org.apache.phoenix.schema.export.DefaultSchemaRegistryRepository;
 import org.apache.phoenix.util.EnvironmentEdgeManager;
 import org.apache.phoenix.util.PhoenixRuntime;
 import org.apache.phoenix.util.PropertiesUtil;
@@ -1574,6 +1576,99 @@ public class CreateTableIT extends 
ParallelStatsDisabledIT {
                 .getColumnQualifierBytes()));
     }
 
+    // Test for PHOENIX-6953
+    @Test
+    public void testCoprocessorsForCreateIndexOnOldImplementation() throws 
Exception {
+        String tableName = generateUniqueName();
+        String index1Name = generateUniqueName();
+        String index2Name = generateUniqueName();
+
+        String ddl =
+                "create table  " + tableName + " ( k integer PRIMARY KEY," + " 
v1 integer,"
+                        + " v2 integer)";
+        String index1Ddl = "create index  " + index1Name + " on " + tableName 
+ " (v1)";
+        String index2Ddl = "create index  " + index2Name + " on " + tableName 
+ " (v2)";
+
+        Properties props = new Properties();
+        Admin admin = driver.getConnectionQueryServices(getUrl(), 
props).getAdmin();
+
+        try (Connection conn = DriverManager.getConnection(getUrl());
+                Statement stmt = conn.createStatement();) {
+            stmt.execute(ddl);
+            stmt.execute(index1Ddl);
+
+            TableDescriptor index1DescriptorBefore =
+                    admin.getDescriptor(TableName.valueOf(index1Name));
+            assertTrue(index1DescriptorBefore
+                    
.hasCoprocessor(org.apache.phoenix.index.GlobalIndexChecker.class.getName()));
+
+            // Now roll back to the old indexing
+            IndexUpgradeTool iut =
+                    new IndexUpgradeTool(ROLLBACK_OP, tableName, null,
+                            "/tmp/index_upgrade_" + 
UUID.randomUUID().toString(), false, null,
+                            false);
+            iut.setConf(getUtility().getConfiguration());
+            iut.prepareToolSetup();
+            assertEquals(0, iut.executeTool());
+
+            TableDescriptor index1DescriptorAfter =
+                    admin.getDescriptor(TableName.valueOf(index1Name));
+            assertFalse(index1DescriptorAfter
+                    
.hasCoprocessor(org.apache.phoenix.index.GlobalIndexChecker.class.getName()));
+
+            // New index must not have GlobalIndexChecker
+            stmt.execute(index2Ddl);
+            TableDescriptor index2Descriptor = 
admin.getDescriptor(TableName.valueOf(index2Name));
+            assertFalse(index2Descriptor
+                    
.hasCoprocessor(org.apache.phoenix.index.GlobalIndexChecker.class.getName()));
+        }
+    }
+
+    // Test for PHOENIX-6953
+    @Test
+    public void 
testCoprocessorsForTransactionalCreateIndexOnOldImplementation() throws 
Exception {
+        String tableName = generateUniqueName();
+        String index1Name = generateUniqueName();
+
+        String ddl =
+                "create table  " + tableName + " ( k integer PRIMARY KEY," + " 
v1 integer,"
+                        + " v2 integer) TRANSACTIONAL=TRUE";
+        String index1Ddl = "create index  " + index1Name + " on " + tableName 
+ " (v1)";
+
+        Properties props = new Properties();
+        Admin admin = driver.getConnectionQueryServices(getUrl(), 
props).getAdmin();
+
+        try (Connection conn = DriverManager.getConnection(getUrl());
+                Statement stmt = conn.createStatement();) {
+            stmt.execute(ddl);
+            stmt.execute(index1Ddl);
+
+            // Transactional indexes don't have GlobalIndexChecker
+            TableDescriptor index1DescriptorBefore =
+                    admin.getDescriptor(TableName.valueOf(index1Name));
+            assertFalse(index1DescriptorBefore
+                    
.hasCoprocessor(org.apache.phoenix.index.GlobalIndexChecker.class.getName()));
+
+            // Now roll back to the old indexing
+            IndexUpgradeTool iut =
+                    new IndexUpgradeTool(ROLLBACK_OP, tableName, null,
+                            "/tmp/index_upgrade_" + 
UUID.randomUUID().toString(), false, null,
+                            false);
+            iut.setConf(getUtility().getConfiguration());
+            iut.prepareToolSetup();
+            assertEquals(0, iut.executeTool());
+
+            // Make sure we don't add GlobalIndexChecker
+            TableDescriptor index1DescriptorAfter =
+                    admin.getDescriptor(TableName.valueOf(index1Name));
+            assertFalse(index1DescriptorAfter
+                    
.hasCoprocessor(org.apache.phoenix.index.GlobalIndexChecker.class.getName()));
+
+            // We should also test for setting / unsetting the transactional 
status, but both are
+            // forbidden at the time of writing.
+        }
+    }
+
     public static long verifyLastDDLTimestamp(String tableFullName, long 
startTS, Connection conn) throws SQLException {
         long endTS = EnvironmentEdgeManager.currentTimeMillis();
         //Now try the PTable API
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
index cb119a8401..84c742fd13 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServicesImpl.java
@@ -939,6 +939,7 @@ public class ConnectionQueryServicesImpl extends 
DelegateQueryServices implement
         : 
TableDescriptorBuilder.newBuilder(TableName.valueOf(physicalTableName));
 
         ColumnFamilyDescriptor dataTableColDescForIndexTablePropSyncing = null;
+        boolean doNotAddGlobalIndexChecker = false;
         if (tableType == PTableType.INDEX || 
MetaDataUtil.isViewIndex(Bytes.toString(physicalTableName))) {
             byte[] defaultFamilyBytes =
                     defaultFamilyName == null ? 
QueryConstants.DEFAULT_COLUMN_FAMILY_BYTES : Bytes.toBytes(defaultFamilyName);
@@ -964,6 +965,10 @@ public class ConnectionQueryServicesImpl extends 
DelegateQueryServices implement
             if (dataTableColDescForIndexTablePropSyncing == null) {
                 dataTableColDescForIndexTablePropSyncing = 
baseTableDesc.getColumnFamilies()[0];
             }
+            if 
(baseTableDesc.hasCoprocessor(org.apache.phoenix.hbase.index.Indexer.class.getName()))
 {
+                // The base table still uses the old indexing
+                doNotAddGlobalIndexChecker = true;
+            }
         }
         // By default, do not automatically rebuild/catch up an index on a 
write failure
         // Add table-specific properties to the table descriptor
@@ -1012,7 +1017,7 @@ public class ConnectionQueryServicesImpl extends 
DelegateQueryServices implement
             }
         }
         addCoprocessors(physicalTableName, tableDescriptorBuilder,
-            tableType, tableProps, existingDesc);
+            tableType, tableProps, existingDesc, doNotAddGlobalIndexChecker);
 
         // PHOENIX-3072: Set index priority if this is a system table or index 
table
         if (tableType == PTableType.SYSTEM) {
@@ -1039,8 +1044,8 @@ public class ConnectionQueryServicesImpl extends 
DelegateQueryServices implement
 
 
     private void addCoprocessors(byte[] tableName, TableDescriptorBuilder 
builder,
-                                 PTableType tableType, Map<String,Object> 
tableProps,
-                                 TableDescriptor existingDesc) throws 
SQLException {
+            PTableType tableType, Map<String, Object> tableProps, 
TableDescriptor existingDesc,
+            boolean doNotAddGlobalIndexChecker) throws SQLException {
         // The phoenix jar must be available on HBase classpath
         int priority = props.getInt(QueryServices.COPROCESSOR_PRIORITY_ATTRIB, 
QueryServicesOptions.DEFAULT_COPROCESSOR_PRIORITY);
         try {
@@ -1071,8 +1076,11 @@ public class ConnectionQueryServicesImpl extends 
DelegateQueryServices implement
                     if 
(newDesc.hasCoprocessor(IndexRegionObserver.class.getName())) {
                         
builder.removeCoprocessor(IndexRegionObserver.class.getName());
                     }
-                    
builder.setCoprocessor(CoprocessorDescriptorBuilder.newBuilder(GlobalIndexChecker.class.getName())
-                            .setPriority(priority - 1).build());
+                    if (!doNotAddGlobalIndexChecker) {
+                        builder.setCoprocessor(CoprocessorDescriptorBuilder
+                                .newBuilder(GlobalIndexChecker.class.getName())
+                                .setPriority(priority - 1).build());
+                    }
                 }
             }
 
@@ -2609,7 +2617,9 @@ public class ConnectionQueryServicesImpl extends 
DelegateQueryServices implement
             Map<TableDescriptor, TableDescriptor> oldToNewTableDescriptors) 
throws SQLException {
         byte[] physicalTableName = table.getPhysicalName().getBytes();
         try (Admin admin = getAdmin()) {
-            setTransactional(physicalTableName, tableDescriptorBuilder, 
table.getType(), txValue, tableProps);
+            TableDescriptor baseDesc = 
admin.getDescriptor(TableName.valueOf(physicalTableName));
+            boolean hasOldIndexing = 
baseDesc.hasCoprocessor(org.apache.phoenix.hbase.index.Indexer.class.getName());
+            setTransactional(physicalTableName, tableDescriptorBuilder, 
table.getType(), txValue, tableProps, hasOldIndexing);
             Map<String, Object> indexTableProps;
             if (txValue == null) {
                 indexTableProps = Collections.emptyMap();
@@ -2655,7 +2665,7 @@ public class ConnectionQueryServicesImpl extends 
DelegateQueryServices implement
                         
indexDescriptorBuilder.setColumnFamily(indexColDescriptor.build());
                     }
                 }
-                setTransactional(index.getPhysicalName().getBytes(), 
indexDescriptorBuilder, index.getType(), txValue, indexTableProps);
+                setTransactional(index.getPhysicalName().getBytes(), 
indexDescriptorBuilder, index.getType(), txValue, indexTableProps, 
hasOldIndexing);
                 descriptorsToUpdate.add(indexDescriptorBuilder.build());
             }
             try {
@@ -2669,7 +2679,7 @@ public class ConnectionQueryServicesImpl extends 
DelegateQueryServices implement
                 }
                 TableDescriptorBuilder indexDescriptorBuilder = 
TableDescriptorBuilder.newBuilder(intermedIndexDesc);
                 setSharedIndexMaxVersion(table, 
tableDescriptorBuilder.build(), indexDescriptorBuilder);
-                
setTransactional(MetaDataUtil.getViewIndexPhysicalName(physicalTableName), 
indexDescriptorBuilder, PTableType.INDEX, txValue, indexTableProps);
+                
setTransactional(MetaDataUtil.getViewIndexPhysicalName(physicalTableName), 
indexDescriptorBuilder, PTableType.INDEX, txValue, indexTableProps, 
hasOldIndexing);
                 descriptorsToUpdate.add(indexDescriptorBuilder.build());
             } catch (org.apache.hadoop.hbase.TableNotFoundException ignore) {
                 // Ignore, as we may never have created a view index table
@@ -2685,7 +2695,7 @@ public class ConnectionQueryServicesImpl extends 
DelegateQueryServices implement
                 }
                 TableDescriptorBuilder indexDescriptorBuilder = 
TableDescriptorBuilder.newBuilder(intermedIndexDesc);
                 setSharedIndexMaxVersion(table, 
tableDescriptorBuilder.build(), indexDescriptorBuilder);
-                
setTransactional(MetaDataUtil.getViewIndexPhysicalName(physicalTableName), 
indexDescriptorBuilder, PTableType.INDEX, txValue, indexTableProps);
+                
setTransactional(MetaDataUtil.getViewIndexPhysicalName(physicalTableName), 
indexDescriptorBuilder, PTableType.INDEX, txValue, indexTableProps, 
hasOldIndexing);
                 descriptorsToUpdate.add(indexDescriptorBuilder.build());
             } catch (org.apache.hadoop.hbase.TableNotFoundException ignore) {
                 // Ignore, as we may never have created a local index
@@ -2741,13 +2751,13 @@ public class ConnectionQueryServicesImpl extends 
DelegateQueryServices implement
             }
         }
     }
-    private void setTransactional(byte[] physicalTableName, 
TableDescriptorBuilder tableDescriptorBuilder, PTableType tableType, String 
txValue, Map<String, Object> tableProps) throws SQLException {
+    private void setTransactional(byte[] physicalTableName, 
TableDescriptorBuilder tableDescriptorBuilder, PTableType tableType, String 
txValue, Map<String, Object> tableProps, boolean hasOldIndexing) throws 
SQLException {
         if (txValue == null) {
             
tableDescriptorBuilder.removeValue(Bytes.toBytes(PhoenixTransactionContext.READ_NON_TX_DATA));
         } else {
             
tableDescriptorBuilder.setValue(PhoenixTransactionContext.READ_NON_TX_DATA, 
txValue);
         }
-        this.addCoprocessors(physicalTableName, tableDescriptorBuilder, 
tableType, tableProps, null);
+        this.addCoprocessors(physicalTableName, tableDescriptorBuilder, 
tableType, tableProps, null, hasOldIndexing);
     }
 
     private Map<TableDescriptor, TableDescriptor> 
separateAndValidateProperties(PTable table,

Reply via email to