This is an automated email from the ASF dual-hosted git repository. vjasani 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 4ede1d6e51 PHOENIX-6864 - create view throwing NPE when referring back to itself (#1669) 4ede1d6e51 is described below commit 4ede1d6e5152fa767fe4652adba3d719cbe853a0 Author: Divneet18 <dik...@ucsd.edu> AuthorDate: Mon Sep 11 15:05:03 2023 -0700 PHOENIX-6864 - create view throwing NPE when referring back to itself (#1669) --- .../it/java/org/apache/phoenix/end2end/ViewIT.java | 66 +++++++++++++++++++++- .../phoenix/compile/CreateTableCompiler.java | 1 + .../java/org/apache/phoenix/schema/PTableImpl.java | 10 +++- 3 files changed, 74 insertions(+), 3 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 8fc9626bd5..bba3ce87d7 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 @@ -56,6 +56,10 @@ import org.apache.phoenix.query.KeyRange; 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.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; @@ -538,7 +542,6 @@ public class ViewIT extends SplitSystemCatalogIT { + "PRIMARY KEY) " + "AS SELECT * FROM " + fullTableName + " WHERE K1 = 1"; stmt.execute(ddl); - // assert PK metadata ResultSet rs = conn.getMetaData().getPrimaryKeys(null, SchemaUtil.getSchemaNameFromFullName(fullViewName), @@ -790,6 +793,67 @@ public class ViewIT extends SplitSystemCatalogIT { } } + @Test + //creating view with same name on top of a table with a non existent column + public void testCreateViewWithUndefinedSameColumnName() throws Exception { + String fullViewName = generateUniqueName(); + + try (Connection conn = DriverManager.getConnection(getUrl()); + Statement stmt = conn.createStatement()) { + String ddl = "CREATE VIEW " + fullViewName + + " AS SELECT * FROM " + fullViewName + + " WHERE " + fullViewName + " = 1"; + stmt.execute(ddl); + fail("Should have thrown an exception"); + } catch (ColumnNotFoundException columnException) { + assertEquals("Undefined column", + SQLExceptionCode.COLUMN_NOT_FOUND + .getErrorCode(), columnException.getErrorCode()); + assertEquals(fullViewName, columnException.getColumnName()); + } + } + + @Test + //creating view with same name on top of a non existent table + public void testCreateViewOnTopOfUndefinedTableWithSameName() throws Exception { + try (Connection conn = DriverManager.getConnection(getUrl()); + Statement stmt = conn.createStatement()) { + + String fullViewName = generateUniqueName(); + String ddl = "CREATE VIEW " + fullViewName + + " AS SELECT * FROM " + fullViewName; + stmt.execute(ddl); + fail("Should have thrown an exception"); + } catch (TableNotFoundException tableException) { + assertEquals("Table Undefined", + SQLExceptionCode.TABLE_UNDEFINED.getErrorCode(), + tableException.getErrorCode()); + } + } + + @Test + //creating view with same name as the parent table + public void testCreateViewOnTopOfTableWithSameName() throws Exception { + try (Connection conn = DriverManager.getConnection(getUrl()); + Statement stmt = conn.createStatement()) { + + String fullTableName = generateUniqueName(); + String ddl = "CREATE TABLE " + fullTableName + + " (k1 INTEGER NOT NULL, k2 INTEGER NOT NULL, v1 DECIMAL, " + + "CONSTRAINT pk PRIMARY KEY (k1, k2))" + tableDDLOptions; + stmt.execute(ddl); + + ddl = "CREATE VIEW " + fullTableName + "(v2 VARCHAR, k3 VARCHAR " + + "PRIMARY KEY) " + + "AS SELECT * FROM " + fullTableName + " WHERE K1 = 1"; + stmt.execute(ddl); + fail("Should have thrown an exception"); + } catch (TableAlreadyExistsException tableException) { + assertEquals("Table already exists", + SQLExceptionCode.TABLE_ALREADY_EXIST + .getErrorCode(), tableException.getErrorCode()); + } + } private void validate(String viewName, Connection tenantConn, String[] whereClauseArray, long[] expectedArray) throws SQLException { diff --git a/phoenix-core/src/main/java/org/apache/phoenix/compile/CreateTableCompiler.java b/phoenix-core/src/main/java/org/apache/phoenix/compile/CreateTableCompiler.java index c8933f30d6..f2c1671559 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/compile/CreateTableCompiler.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/compile/CreateTableCompiler.java @@ -128,6 +128,7 @@ public class CreateTableCompiler { // Used to track column references in a view ExpressionCompiler expressionCompiler = new ColumnTrackingExpressionCompiler(context, isViewColumnReferencedToBe); parentToBe = tableRef.getTable(); + // Disallow creating views on top of SYSTEM tables. See PHOENIX-5386 if (parentToBe.getType() == PTableType.SYSTEM) { throw new SQLExceptionInfo diff --git a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java index 739c577170..17a7cf56fa 100644 --- a/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java +++ b/phoenix-core/src/main/java/org/apache/phoenix/schema/PTableImpl.java @@ -1184,11 +1184,17 @@ public class PTableImpl implements PTable { @Override public PColumn getColumnForColumnName(String name) throws ColumnNotFoundException, AmbiguousColumnException { + String schemaNameStr = schemaName == null ? null : schemaName.getString(); + String tableNameStr = tableName == null ? null : tableName.getString(); + + //Throw exception if trying to create a column name that does not exist + if (columnsByName == null) { + throw new ColumnNotFoundException(schemaNameStr, tableNameStr, null, name); + } + List<PColumn> columns = columnsByName.get(name); int size = columns.size(); if (size == 0) { - String schemaNameStr = schemaName==null?null:schemaName.getString(); - String tableNameStr = tableName==null?null:tableName.getString(); throw new ColumnNotFoundException(schemaNameStr, tableNameStr, null, name); }