You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@phoenix.apache.org by ya...@apache.org on 2020/11/09 18:10:16 UTC
[phoenix] branch 4.x updated: PHOENIX-6203 : Add new CQS method to
return Table instance only if table exists
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 <vj...@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 <ya...@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());
}
}