This is an automated email from the ASF dual-hosted git repository. vjasani 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 bb8e9daf70 PHOENIX-6864 - create view throwing NPE when referring back to itself (#1669) bb8e9daf70 is described below commit bb8e9daf703120d5976278453146d96ccbe95451 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 d45cf2af87..65173c95ef 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 @@ -59,6 +59,9 @@ import org.apache.phoenix.query.QueryServices; import org.apache.phoenix.schema.PTable; import org.apache.phoenix.schema.PTableImpl; 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.export.DefaultSchemaRegistryRepository; import org.apache.phoenix.schema.export.DefaultSchemaWriter; import org.apache.phoenix.schema.export.SchemaRegistryRepository; @@ -75,6 +78,7 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; + import org.apache.phoenix.thirdparty.com.google.common.collect.Maps; /** @@ -644,7 +648,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), @@ -896,6 +899,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 6d5512cd60..1baa2ae756 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 fb23a381c3..d332a95269 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 @@ -1287,11 +1287,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); }