This is an automated email from the ASF dual-hosted git repository. stoty pushed a commit to branch 5.1 in repository https://gitbox.apache.org/repos/asf/phoenix.git
The following commit(s) were added to refs/heads/5.1 by this push: new c009a9e1e3 PHOENIX-7034 Disallow mapped view creation when the schema does not exists c009a9e1e3 is described below commit c009a9e1e32f48956c74798fc07ec05ad48bcd49 Author: Aron Meszaros <meszaros.aron.att...@gmail.com> AuthorDate: Fri Sep 22 12:23:46 2023 +0200 PHOENIX-7034 Disallow mapped view creation when the schema does not exists --- .../it/java/org/apache/phoenix/end2end/ViewIT.java | 50 ++++++++++++++++++++- .../org/apache/phoenix/end2end/ViewMetadataIT.java | 4 ++ .../apache/phoenix/end2end/index/ViewIndexIT.java | 14 +++++- .../org/apache/phoenix/compile/FromCompiler.java | 51 ++++++++++++---------- .../java/org/apache/phoenix/util/SchemaUtil.java | 21 ++++----- 5 files changed, 103 insertions(+), 37 deletions(-) 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 bba3ce87d7..552dadd581 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 @@ -44,7 +44,14 @@ import java.util.List; import java.util.Map; import java.util.Properties; + +import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.NamespaceDescriptor; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.client.Admin; +import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; import org.apache.hadoop.hbase.client.Scan; +import org.apache.hadoop.hbase.client.TableDescriptorBuilder; import org.apache.hadoop.hbase.util.Pair; import org.apache.phoenix.compile.ExplainPlan; import org.apache.phoenix.compile.ExplainPlanAttributes; @@ -57,9 +64,9 @@ import org.apache.phoenix.query.QueryServices; import org.apache.phoenix.schema.PTable; import org.apache.phoenix.schema.ReadOnlyTableException; import org.apache.phoenix.schema.ColumnNotFoundException; +import org.apache.phoenix.schema.SchemaNotFoundException; import org.apache.phoenix.schema.TableNotFoundException; import org.apache.phoenix.schema.TableAlreadyExistsException; -import org.apache.phoenix.schema.types.PVarbinary; import org.apache.phoenix.thirdparty.com.google.common.collect.Lists; import org.apache.phoenix.transaction.PhoenixTransactionProvider.Feature; import org.apache.phoenix.transaction.TransactionFactory; @@ -273,7 +280,46 @@ public class ViewIT extends SplitSystemCatalogIT { assertEquals(4, count); } } - + + @Test + public void testCreateMappedViewWithHbaseNamespace() throws Exception { + Properties props = new Properties(); + props.setProperty(QueryServices.IS_NAMESPACE_MAPPING_ENABLED, + Boolean.TRUE.toString()); + Connection conn1 = DriverManager.getConnection(getUrl(), props); + conn1.setAutoCommit(true); + + HBaseTestingUtility testUtil = getUtility(); + Admin admin = testUtil.getAdmin(); + + String nameSpace = generateUniqueName(); + admin.createNamespace(NamespaceDescriptor.create(nameSpace).build()); + + String tableNameStr = generateUniqueName(); + TableName tableName = TableName.valueOf(nameSpace, tableNameStr); + String familyNameStr = "colFam1"; + TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(tableName); + builder.setColumnFamily(ColumnFamilyDescriptorBuilder.of( + familyNameStr)); + admin.createTable(builder.build()); + + + String viewName = SchemaUtil.getTableName(nameSpace, tableNameStr); + try { + conn1.createStatement().execute("CREATE VIEW " + viewName + + " (pk VARCHAR PRIMARY KEY, \"colFam1\".\"lastname\" VARCHAR )"); + } catch (SchemaNotFoundException e) { + assertEquals(nameSpace, e.getSchemaName()); + assertEquals("ERROR 722 (43M05): Schema does not exist schemaName=" + + nameSpace, + e.getMessage()); + } + + conn1.createStatement().execute("CREATE SCHEMA IF NOT EXISTS " + nameSpace); + conn1.createStatement().execute("CREATE VIEW " + viewName + + " (pk VARCHAR PRIMARY KEY, \"colFam1\".\"lastname\" VARCHAR )"); + } + @Test public void testViewWithCurrentDate() throws Exception { try (Connection conn = DriverManager.getConnection(getUrl()); diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewMetadataIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewMetadataIT.java index 00770fa1c3..49c795e3a7 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewMetadataIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/ViewMetadataIT.java @@ -937,6 +937,10 @@ public class ViewMetadataIT extends SplitSystemCatalogIT { if (isNamespaceMapped) { conn.createStatement().execute("CREATE SCHEMA IF NOT EXISTS " + schemaName1); + conn.createStatement().execute("CREATE SCHEMA IF NOT EXISTS " + + viewSchemaName); + conn.createStatement().execute("CREATE SCHEMA IF NOT EXISTS " + + SCHEMA3); } String ddl = "CREATE TABLE " + fullTableName1 + " (k INTEGER NOT NULL PRIMARY KEY, v1 DATE)"; diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ViewIndexIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ViewIndexIT.java index cde3a8e90d..ea9c2c6c04 100644 --- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ViewIndexIT.java +++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/index/ViewIndexIT.java @@ -177,6 +177,9 @@ public class ViewIndexIT extends SplitSystemCatalogIT { try (Connection conn1 = getConnection(); Connection conn2 = getConnection()){ createBaseTable(conn1, schemaName, tableName, false, null, null, true); + if (isNamespaceMapped) { + conn1.createStatement().execute("CREATE SCHEMA IF NOT EXISTS " + viewSchemaName); + } conn1.createStatement().execute("CREATE VIEW " + fullViewName + " AS SELECT * FROM " + fullTableName); conn1.createStatement().execute("CREATE INDEX " + indexName + " ON " + fullViewName + " (v1)"); conn2.createStatement().executeQuery("SELECT * FROM " + fullTableName).next(); @@ -202,6 +205,10 @@ public class ViewIndexIT extends SplitSystemCatalogIT { Connection conn1 = getTenantConnection("10")) { createBaseTable(conn, SCHEMA1, tableName, true, null, null, true); + if (isNamespaceMapped) { + conn.createStatement().execute("CREATE SCHEMA IF NOT EXISTS " + SCHEMA2); + } + PreparedStatement stmt = conn.prepareStatement( "UPSERT INTO " + fullTableName + " VALUES(?,?,?,?,?)"); @@ -481,11 +488,13 @@ public class ViewIndexIT extends SplitSystemCatalogIT { conn.createStatement().execute(viewDdl); conn.createStatement().execute(indexDdl); - String childViewName = String.format("S_%s.\"%s\"", generateUniqueName(), keyPrefix); + String childViewNameSchema = String.format("S_%s", generateUniqueName()); + String childViewName = String.format("%s.\"%s\"", childViewNameSchema, keyPrefix); String viewChildDDl = String.format("CREATE VIEW IF NOT EXISTS %s AS SELECT * FROM %s", childViewName, fullViewName); Connection conn2 = null; if (isNamespaceMapped) { conn2 = getTenantConnection(TENANT1); + conn2.createStatement().execute("CREATE SCHEMA IF NOT EXISTS " + childViewNameSchema); } else { conn2 = conn; } @@ -579,6 +588,8 @@ public class ViewIndexIT extends SplitSystemCatalogIT { Connection tsConn3 = DriverManager.getConnection(getUrl(), tsProps)) { if (isNamespaceMapped) { conn.createStatement().execute("CREATE SCHEMA IF NOT EXISTS " + baseSchemaName); + conn.createStatement().execute("CREATE SCHEMA IF NOT EXISTS " + viewSchemaName); + conn.createStatement().execute("CREATE SCHEMA IF NOT EXISTS " + tsViewSchemaName); } conn.createStatement().execute( "CREATE TABLE " + baseFullName + "(\n" + " ORGANIZATION_ID CHAR(15) NOT NULL,\n" @@ -696,6 +707,7 @@ public class ViewIndexIT extends SplitSystemCatalogIT { c.setAutoCommit(true); if (isNamespaceMapped) { c.createStatement().execute("CREATE SCHEMA IF NOT EXISTS " + SCHEMA1); + c.createStatement().execute("CREATE SCHEMA IF NOT EXISTS " + SCHEMA2); } s.execute("CREATE TABLE " + tableName + " (COL1 VARCHAR PRIMARY KEY, CF.COL2 VARCHAR)"); s.executeUpdate("UPSERT INTO " + tableName + " VALUES ('AAA', 'BBB')"); diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java index 64e81c352a..0ec7d523a4 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/FromCompiler.java @@ -161,16 +161,19 @@ public class FromCompiler { TableName baseTable = statement.getBaseTableName(); String schemaName; - if (baseTable == null) { - if (SchemaUtil.isSchemaCheckRequired(statement.getTableType(), connection.getQueryServices().getProps())) { - schemaName = statement.getTableName().getSchemaName(); - if (schemaName != null) { - new SchemaResolver(connection, statement.getTableName().getSchemaName(), true); - } else if (connection.getSchema() != null) { - // To ensure schema set through properties or connection string exists before creating table - new SchemaResolver(connection, connection.getSchema(), true); - } + if (SchemaUtil.isSchemaCheckRequired(statement.getTableType(), + connection.getQueryServices().getProps())) { + // To ensure schema set through properties or connection + // string exists before creating table + schemaName = statement.getTableName().getSchemaName() != null + ? statement.getTableName().getSchemaName() : connection.getSchema(); + if (schemaName != null) { + // Only create SchemaResolver object to check if constructor throws exception. + // No exception means schema exists + new SchemaResolver(connection, schemaName, true); } + } + if (baseTable == null) { return EMPTY_TABLE_RESOLVER; } NamedTableNode tableNode = NamedTableNode.create(null, baseTable, Collections.<ColumnDef>emptyList()); @@ -243,7 +246,7 @@ public class FromCompiler { */ public static TableRef refreshDerivedTableNode( ColumnResolver columnResolver, DerivedTableNode derivedTableNode) throws SQLException { - if(!(columnResolver instanceof MultiTableColumnResolver)) { + if (!(columnResolver instanceof MultiTableColumnResolver)) { throw new UnsupportedOperationException(); } return ((MultiTableColumnResolver)columnResolver).refreshDerivedTableNode(derivedTableNode); @@ -593,13 +596,13 @@ public class FromCompiler { List<PFunction> functionsFound = new ArrayList<PFunction>(functionNames.size()); if (updateCacheImmediately || connection.getAutoCommit()) { getFunctionFromCache(functionNames, functionsFound, true); - if(functionNames.isEmpty()) { + if (functionNames.isEmpty()) { return functionsFound; } MetaDataMutationResult result = client.updateCache(functionNames); timeStamp = result.getMutationTime(); functionsFound = result.getFunctions(); - if(functionNames.size() != functionsFound.size()){ + if (functionNames.size() != functionsFound.size()) { throw new FunctionNotFoundException("Some of the functions in " + functionNames.toString()+" are not found"); } @@ -610,11 +613,11 @@ public class FromCompiler { if (!functionNames.isEmpty()) { result = client.updateCache(functionNames); } - if(result!=null) { + if (result != null) { if (!result.getFunctions().isEmpty()) { functionsFound.addAll(result.getFunctions()); } - if(result.wasUpdated()) { + if (result.wasUpdated()) { timeStamp = result.getMutationTime(); } } @@ -638,7 +641,7 @@ public class FromCompiler { List<PFunction> functionsFound, boolean getOnlyTemporyFunctions) { Iterator<String> iterator = functionNames.iterator(); - while(iterator.hasNext()) { + while (iterator.hasNext()) { PFunction function = null; String functionName = iterator.next(); try { @@ -670,7 +673,7 @@ public class FromCompiler { @Override public PFunction resolveFunction(String functionName) throws SQLException { PFunction function = functionMap.get(functionName); - if(function == null) { + if (function == null) { throw new FunctionNotFoundException(functionName); } return function; @@ -977,14 +980,14 @@ public class FromCompiler { * @throws SQLException */ public TableRef refreshDerivedTableNode(DerivedTableNode derivedTableNode) throws SQLException { - String tableAlias = derivedTableNode.getAlias(); - List<TableRef> removedTableRefs = this.tableMap.removeAll(tableAlias); - if(removedTableRefs == null || removedTableRefs.isEmpty()) { - return null; - } - tables.removeAll(removedTableRefs); - this.visit(derivedTableNode); - return this.resolveTable(null, tableAlias); + String tableAlias = derivedTableNode.getAlias(); + List<TableRef> removedTableRefs = this.tableMap.removeAll(tableAlias); + if (removedTableRefs == null || removedTableRefs.isEmpty()) { + return null; + } + tables.removeAll(removedTableRefs); + this.visit(derivedTableNode); + return this.resolveTable(null, tableAlias); } private static class ColumnFamilyRef { diff --git a/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java index c97fb33218..d781e6d3ad 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/util/SchemaUtil.java @@ -247,7 +247,7 @@ public class SchemaUtil { String schemaName = SchemaUtil.getSchemaNameFromFullName(fullTableName); String tableName = SchemaUtil.getTableNameFromFullName(fullTableName); String normalizedTableName = StringUtil.EMPTY_STRING; - if(!schemaName.isEmpty()) { + if (!schemaName.isEmpty()) { normalizedTableName = normalizeIdentifier(schemaName) + QueryConstants.NAME_SEPARATOR; } return normalizedTableName + normalizeIdentifier(tableName); @@ -688,12 +688,12 @@ public class SchemaUtil { stmt.executeUpdate("ALTER TABLE SYSTEM.\"TABLE\" ADD IF NOT EXISTS " + columnDef); return metaConnection; } finally { - if(stmt != null) { + if (stmt != null) { stmt.close(); } } } finally { - if(metaConnection != null) { + if (metaConnection != null) { metaConnection.close(); } } @@ -841,7 +841,7 @@ public class SchemaUtil { } public static String getEscapedFullColumnName(String fullColumnName) { - if(fullColumnName.startsWith(ESCAPE_CHARACTER)) { + if (fullColumnName.startsWith(ESCAPE_CHARACTER)) { return fullColumnName; } int index = fullColumnName.indexOf(QueryConstants.NAME_SEPARATOR); @@ -1117,7 +1117,8 @@ public class SchemaUtil { } public static boolean isSchemaCheckRequired(PTableType tableType, ReadOnlyProps props) { - return PTableType.TABLE.equals(tableType) && isNamespaceMappingEnabled(tableType, props); + return (PTableType.TABLE.equals(tableType) || PTableType.VIEW.equals(tableType)) + && isNamespaceMappingEnabled(tableType, props); } public static boolean isNamespaceMappingEnabled(PTableType type, Configuration conf) { @@ -1251,7 +1252,7 @@ public class SchemaUtil { fullTableName = tableName; } - if(schemaName != null && schemaName.length() != 0) { + if (schemaName != null && schemaName.length() != 0) { if (schemaNameCaseSensitive) { fullTableName = "\"" + schemaName + "\"" + QueryConstants.NAME_SEPARATOR + fullTableName; } else { @@ -1303,7 +1304,7 @@ public class SchemaUtil { public static String formatIndexColumnName(String name) { String[] splitName = name.split("\\."); - if(splitName.length < 2) { + if (splitName.length < 2) { if (!name.contains("\"")) { if (quotesNeededForColumn(name)) { name = "\"" + name + "\""; @@ -1350,13 +1351,13 @@ public class SchemaUtil { boolean tableNameNeedsQuotes = isQuotesNeeded(pTableName); boolean schemaNameNeedsQuotes = isQuotesNeeded(pSchemaName); - if(schemaNameNeedsQuotes) { + if (schemaNameNeedsQuotes) { pSchemaName= "\""+pSchemaName+"\""; } - if(tableNameNeedsQuotes) { + if (tableNameNeedsQuotes) { pTableName = "\""+pTableName+"\""; } - if(tableNameNeedsQuotes || schemaNameNeedsQuotes) { + if (tableNameNeedsQuotes || schemaNameNeedsQuotes) { if (!Strings.isNullOrEmpty(pSchemaName)) { return String.format("%s.%s", pSchemaName, pTableName); } else {