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

yanxinyi pushed a commit to branch 4.x
in repository https://gitbox.apache.org/repos/asf/phoenix.git


The following commit(s) were added to refs/heads/4.x by this push:
     new f0f2f74  PHOENIX-6203 : Add new CQS method to return Table instance 
only if table exists
f0f2f74 is described below

commit f0f2f7486911172670b415544cb654bd696590d7
Author: Viraj Jasani <vjas...@apache.org>
AuthorDate: Mon Nov 9 14:06:32 2020 +0530

    PHOENIX-6203 : Add new CQS method to return Table instance only if table 
exists
    
    Signed-off-by: Xinyi Yan <yanxi...@apache.org>
---
 .../org/apache/phoenix/end2end/AlterTableIT.java   | 74 +++++++++++++++++++++-
 .../phoenix/query/ConnectionQueryServices.java     | 17 +++++
 .../phoenix/query/ConnectionQueryServicesImpl.java | 44 +++++++++----
 .../query/ConnectionlessQueryServicesImpl.java     |  6 ++
 .../query/DelegateConnectionQueryServices.java     |  6 ++
 .../java/org/apache/phoenix/query/BaseTest.java    |  4 +-
 .../query/ConnectionQueryServicesImplTest.java     | 15 ++---
 7 files changed, 142 insertions(+), 24 deletions(-)

diff --git 
a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java 
b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java
index b60f581..3dafc59 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/AlterTableIT.java
@@ -48,12 +48,15 @@ import java.util.Properties;
 
 import org.apache.hadoop.hbase.HColumnDescriptor;
 import org.apache.hadoop.hbase.HTableDescriptor;
+import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.client.Table;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.phoenix.exception.SQLExceptionCode;
 import org.apache.phoenix.jdbc.PhoenixConnection;
 import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData;
 import org.apache.phoenix.query.BaseTest;
+import org.apache.phoenix.query.ConnectionQueryServices;
 import org.apache.phoenix.query.QueryConstants;
 import org.apache.phoenix.query.QueryServices;
 import org.apache.phoenix.schema.PTable;
@@ -1440,5 +1443,74 @@ public class AlterTableIT extends 
ParallelStatsDisabledIT {
             stmt.execute(alterDdl2);
         }
     }
+
+    @Test
+    public void testTableExists() throws Exception {
+        try (Connection conn = DriverManager.getConnection(getUrl())) {
+            ConnectionQueryServices cqs =
+                conn.unwrap(PhoenixConnection.class).getQueryServices();
+            String tableName = "randomTable";
+            // table never existed, still cqs.getTable() does not throw TNFE
+            Table randomTable = cqs.getTable(Bytes.toBytes(tableName));
+            assertNotNull(randomTable);
+            assertEquals(randomTable.getName(), TableName.valueOf(tableName));
+            try {
+                // this is correct check for existence of table
+                cqs.getTableIfExists(Bytes.toBytes(tableName));
+                fail("Should have thrown TableNotFoundException");
+            } catch (TableNotFoundException e) {
+                assertEquals(tableName, e.getTableName());
+            }
+
+            String fullTableName1 = SchemaUtil.getTableName(schemaName,
+                dataTableName);
+            String ddl = "CREATE TABLE " + fullTableName1
+                + " (col1 INTEGER PRIMARY KEY, col2 INTEGER)";
+            conn.createStatement().execute(ddl);
+            String schemaName2 = generateUniqueName();
+            String tableName2 = generateUniqueName();
+            String fullTableName2 = SchemaUtil.getTableName(schemaName2,
+                tableName2);
+            ddl = "CREATE TABLE " + fullTableName2
+                + " (col1 INTEGER PRIMARY KEY, col2 INTEGER)";
+            conn.createStatement().execute(ddl);
+
+            // table does exist and cqs.getTable() does not throw TNFE
+            Table table1 = cqs.getTable(Bytes.toBytes(fullTableName1));
+            assertNotNull(table1);
+            try {
+                cqs.getTableIfExists(Bytes.toBytes(fullTableName1));
+            } catch (TableNotFoundException e) {
+                fail("Should not throw TableNotFoundException");
+            }
+
+            disableAndDropNonSystemTables();
+            // tables have been dropped, still cqs.getTable()
+            // does not throw TNFE for tableName1 and tableName2
+            Table t1 = cqs.getTable(Bytes.toBytes(fullTableName1));
+            assertEquals(t1.getName().getNameAsString(), fullTableName1);
+            Table t2 = cqs.getTable(Bytes.toBytes(fullTableName2));
+            assertEquals(t2.getName().getNameAsString(), fullTableName2);
+
+            // this is correct check for existence of table
+            try {
+                cqs.getTableIfExists(Bytes.toBytes(fullTableName1));
+                fail("Should have thrown TableNotFoundException");
+            } catch (TableNotFoundException e) {
+                // match table and schema
+                assertEquals(dataTableName, e.getTableName());
+                assertEquals(schemaName, e.getSchemaName());
+            }
+            try {
+                cqs.getTableIfExists(Bytes.toBytes(fullTableName2));
+                fail("Should have thrown TableNotFoundException");
+            } catch (TableNotFoundException e) {
+                // match table and schema
+                assertEquals(tableName2, e.getTableName());
+                assertEquals(schemaName2, e.getSchemaName());
+            }
+
+        }
+    }
+
 }
- 
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java
index db63d48..40bbff3 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionQueryServices.java
@@ -29,6 +29,7 @@ import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.client.HBaseAdmin;
 import org.apache.hadoop.hbase.client.HTableInterface;
 import org.apache.hadoop.hbase.client.Mutation;
+import org.apache.hadoop.hbase.client.Table;
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
 import org.apache.hadoop.hbase.security.User;
 import org.apache.hadoop.hbase.util.Pair;
@@ -72,6 +73,22 @@ public interface ConnectionQueryServices extends 
QueryServices, MetaDataMutated
      */
     public HTableInterface getTable(byte[] tableName) throws SQLException;
 
+    /**
+     * Get Table by the given name. It is the responsibility of callers
+     * to close the returned Table interface. This method uses additional Admin
+     * API to ensure if table exists before returning Table interface from
+     * Connection. If table does not exist, this method will throw
+     * {@link org.apache.phoenix.schema.TableNotFoundException}
+     *
+     * @param tableName the name of the Table
+     * @return Table interface
+     * @throws SQLException If something goes wrong while retrieving table
+     *     interface from connection managed by implementor. If table does not
+     *     exist, {@link org.apache.phoenix.schema.TableNotFoundException} will
+     *     be thrown.
+     */
+    Table getTableIfExists(byte[] tableName) throws SQLException;
+
     public HTableDescriptor getTableDescriptor(byte[] tableName) throws 
SQLException;
 
     public HRegionLocation getTableRegionLocation(byte[] tableName, byte[] 
row) throws SQLException;
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 a0512bd..55bb9fe 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
@@ -127,6 +127,7 @@ import org.apache.hadoop.hbase.NamespaceDescriptor;
 import org.apache.hadoop.hbase.NamespaceNotFoundException;
 import org.apache.hadoop.hbase.TableExistsException;
 import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.client.Admin;
 import org.apache.hadoop.hbase.client.Append;
 import org.apache.hadoop.hbase.client.Delete;
 import org.apache.hadoop.hbase.client.HBaseAdmin;
@@ -486,15 +487,28 @@ public class ConnectionQueryServicesImpl extends 
DelegateQueryServices implement
     @Override
     public HTableInterface getTable(byte[] tableName) throws SQLException {
         try {
-            return HBaseFactoryProvider.getHTableFactory().getTable(tableName, 
connection, null);
-        } catch (org.apache.hadoop.hbase.TableNotFoundException e) {
-            throw new 
TableNotFoundException(SchemaUtil.getSchemaNameFromFullName(tableName), 
SchemaUtil.getTableNameFromFullName(tableName));
+            return HBaseFactoryProvider.getHTableFactory().getTable(tableName,
+                connection, null);
         } catch (IOException e) {
             throw new SQLException(e);
         }
     }
 
     @Override
+    public Table getTableIfExists(byte[] tableName) throws SQLException {
+        try (Admin admin = getAdmin()) {
+            if (!admin.tableExists(TableName.valueOf(tableName))) {
+                throw new TableNotFoundException(
+                    SchemaUtil.getSchemaNameFromFullName(tableName),
+                    SchemaUtil.getTableNameFromFullName(tableName));
+            }
+        } catch (IOException e) {
+            throw new SQLException(e);
+        }
+        return getTable(tableName);
+    }
+
+    @Override
     public HTableDescriptor getTableDescriptor(byte[] tableName) throws 
SQLException {
         HTableInterface htable = getTable(tableName);
         try {
@@ -4498,17 +4512,21 @@ public class ConnectionQueryServicesImpl extends 
DelegateQueryServices implement
     }
 
     @VisibleForTesting
-    public Table getSysMutexTable() throws SQLException, IOException {
-        String table = SYSTEM_MUTEX_NAME;
-        TableName tableName = TableName.valueOf(table);
-        try (HBaseAdmin admin = getAdmin()) {
-            if (!admin.tableExists(tableName)) {
-                table = table.replace(QueryConstants.NAME_SEPARATOR,
-                  QueryConstants.NAMESPACE_SEPARATOR);
-                tableName = TableName.valueOf(table);
-            }
-            return connection.getTable(tableName);
+    public Table getSysMutexTable() throws SQLException {
+        String tableNameAsString = SYSTEM_MUTEX_NAME;
+        Table table;
+        try {
+            table = getTableIfExists(Bytes.toBytes(tableNameAsString));
+        } catch (TableNotFoundException e) {
+            tableNameAsString = tableNameAsString.replace(
+                QueryConstants.NAME_SEPARATOR,
+                QueryConstants.NAMESPACE_SEPARATOR);
+            // if SYSTEM.MUTEX does not exist, we don't need to check
+            // for the existence of SYSTEM:MUTEX as it must exist, hence
+            // we can call getTable() here instead of getTableIfExists()
+            table = getTable(Bytes.toBytes(tableNameAsString));
         }
+        return table;
     }
 
     private String addColumn(String columnsToAddSoFar, String columns) {
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java
index bc636ab..9679734 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/query/ConnectionlessQueryServicesImpl.java
@@ -41,6 +41,7 @@ import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.client.HBaseAdmin;
 import org.apache.hadoop.hbase.client.HTableInterface;
 import org.apache.hadoop.hbase.client.Mutation;
+import org.apache.hadoop.hbase.client.Table;
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
 import org.apache.hadoop.hbase.security.User;
 import org.apache.hadoop.hbase.util.Addressing;
@@ -212,6 +213,11 @@ public class ConnectionlessQueryServicesImpl extends 
DelegateQueryServices imple
     }
 
     @Override
+    public Table getTableIfExists(byte[] tableName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public List<HRegionLocation> getAllTableRegions(byte[] tableName) throws 
SQLException {
         List<HRegionLocation> regions = 
tableSplits.get(Bytes.toString(tableName));
         if (regions != null) {
diff --git 
a/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java
 
b/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java
index 8f3273e..d271547 100644
--- 
a/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java
+++ 
b/phoenix-core/src/main/java/org/apache/phoenix/query/DelegateConnectionQueryServices.java
@@ -29,6 +29,7 @@ import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.client.HBaseAdmin;
 import org.apache.hadoop.hbase.client.HTableInterface;
 import org.apache.hadoop.hbase.client.Mutation;
+import org.apache.hadoop.hbase.client.Table;
 import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
 import org.apache.hadoop.hbase.security.User;
 import org.apache.hadoop.hbase.util.Pair;
@@ -75,6 +76,11 @@ public class DelegateConnectionQueryServices extends 
DelegateQueryServices imple
     }
 
     @Override
+    public Table getTableIfExists(byte[] tableName) throws SQLException {
+        return getDelegate().getTableIfExists(tableName);
+    }
+
+    @Override
     public List<HRegionLocation> getAllTableRegions(byte[] tableName) throws 
SQLException {
         return getDelegate().getAllTableRegions(tableName);
     }
diff --git a/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java 
b/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
index a1e794a..fc9df19 100644
--- a/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
+++ b/phoenix-core/src/test/java/org/apache/phoenix/query/BaseTest.java
@@ -1555,9 +1555,9 @@ public abstract class BaseTest {
     }
     
     /**
-     * Disable and drop all the tables except SYSTEM.CATALOG and 
SYSTEM.SEQUENCE
+     * Disable and drop all non system tables
      */
-    private static void disableAndDropNonSystemTables() throws Exception {
+    protected static void disableAndDropNonSystemTables() throws Exception {
         if (driver == null) return;
         HBaseAdmin admin = driver.getConnectionQueryServices(null, 
null).getAdmin();
         try {
diff --git 
a/phoenix-core/src/test/java/org/apache/phoenix/query/ConnectionQueryServicesImplTest.java
 
b/phoenix-core/src/test/java/org/apache/phoenix/query/ConnectionQueryServicesImplTest.java
index da16dfe..6cf0140 100644
--- 
a/phoenix-core/src/test/java/org/apache/phoenix/query/ConnectionQueryServicesImplTest.java
+++ 
b/phoenix-core/src/test/java/org/apache/phoenix/query/ConnectionQueryServicesImplTest.java
@@ -58,6 +58,7 @@ import org.apache.phoenix.jdbc.PhoenixDatabaseMetaData;
 import org.apache.phoenix.util.ReadOnlyProps;
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Matchers;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
@@ -112,6 +113,8 @@ public class ConnectionQueryServicesImplTest {
         when(mockCqs.updateAndConfirmSplitPolicyForTask(SYS_TASK_TDB_SP))
             .thenCallRealMethod();
         when(mockCqs.getSysMutexTable()).thenCallRealMethod();
+        when(mockCqs.getTable(Matchers.<byte[]>any())).thenCallRealMethod();
+        
when(mockCqs.getTableIfExists(Matchers.<byte[]>any())).thenCallRealMethod();
     }
 
     @SuppressWarnings("unchecked")
@@ -210,26 +213,22 @@ public class ConnectionQueryServicesImplTest {
     @Test
     public void testGetSysMutexTableWithName() throws Exception {
         when(mockAdmin.tableExists(any(TableName.class))).thenReturn(true);
-        when(mockConn.getTable(TableName.valueOf("SYSTEM.MUTEX")))
-            .thenReturn(mockTable);
         when(mockCqs.getAdmin()).thenReturn(mockAdmin);
+        
when(mockCqs.getTable(Bytes.toBytes("SYSTEM.MUTEX"))).thenReturn(mockTable);
         assertSame(mockCqs.getSysMutexTable(), mockTable);
         verify(mockAdmin, Mockito.times(1)).tableExists(any(TableName.class));
-        verify(mockConn, Mockito.times(1))
-            .getTable(TableName.valueOf("SYSTEM.MUTEX"));
         verify(mockCqs, Mockito.times(1)).getAdmin();
+        verify(mockCqs, Mockito.times(2)).getTable(Matchers.<byte[]>any());
     }
 
     @Test
     public void testGetSysMutexTableWithNamespace() throws Exception {
         when(mockAdmin.tableExists(any(TableName.class))).thenReturn(false);
-        when(mockConn.getTable(TableName.valueOf("SYSTEM:MUTEX")))
-          .thenReturn(mockTable);
         when(mockCqs.getAdmin()).thenReturn(mockAdmin);
+        
when(mockCqs.getTable(Bytes.toBytes("SYSTEM:MUTEX"))).thenReturn(mockTable);
         assertSame(mockCqs.getSysMutexTable(), mockTable);
         verify(mockAdmin, Mockito.times(1)).tableExists(any(TableName.class));
-        verify(mockConn, Mockito.times(1))
-          .getTable(TableName.valueOf("SYSTEM:MUTEX"));
         verify(mockCqs, Mockito.times(1)).getAdmin();
+        verify(mockCqs, Mockito.times(2)).getTable(Matchers.<byte[]>any());
     }
 }

Reply via email to