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/12/01 03:48:00 UTC

[phoenix] branch master updated: PHOENIX-5960 : Creating view on non-existent table should throw TNFE

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

yanxinyi 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 3860636  PHOENIX-5960 : Creating view on non-existent table should throw TNFE
3860636 is described below

commit 3860636afc567ed955d11b3eec7748db5c675574
Author: Viraj Jasani <vj...@apache.org>
AuthorDate: Wed Nov 25 17:18:18 2020 +0530

    PHOENIX-5960 : Creating view on non-existent table should throw TNFE
    
    Signed-off-by: Xinyi Yan <ya...@apache.org>
---
 .../org/apache/phoenix/end2end/CreateTableIT.java  | 34 +++++++++++
 .../phoenix/compile/CreateTableCompiler.java       | 68 ++++++++++++++++------
 2 files changed, 83 insertions(+), 19 deletions(-)

diff --git a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java
index 2dbdf65..aa2ccf0 100644
--- a/phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java
+++ b/phoenix-core/src/it/java/org/apache/phoenix/end2end/CreateTableIT.java
@@ -60,6 +60,7 @@ import org.apache.phoenix.schema.PTableKey;
 import org.apache.phoenix.schema.PTableType;
 import org.apache.phoenix.schema.SchemaNotFoundException;
 import org.apache.phoenix.schema.TableAlreadyExistsException;
+import org.apache.phoenix.schema.TableNotFoundException;
 import org.apache.phoenix.util.EnvironmentEdgeManager;
 import org.apache.phoenix.util.PhoenixRuntime;
 import org.apache.phoenix.util.PropertiesUtil;
@@ -802,6 +803,39 @@ public class CreateTableIT extends ParallelStatsDisabledIT {
     }
 
     @Test
+    public void testCreateViewFromNonExistentTable() throws Exception {
+        try (Connection conn = DriverManager.getConnection(getUrl())) {
+            conn.createStatement().execute(
+                "CREATE TABLE IF NOT EXISTS S.T1 (A INTEGER PRIMARY KEY, B INTEGER)");
+            // 1. create view from non-existent table (without schema)
+            try {
+                conn.createStatement().execute(
+                    "CREATE VIEW IF NOT EXISTS V1(C INTEGER) AS SELECT * FROM T2");
+                fail("Creating view on non-existent table should have failed");
+            } catch (TableNotFoundException e) {
+                assertEquals("T2", e.getTableName());
+                assertEquals("", e.getSchemaName());
+                assertEquals("ERROR 1012 (42M03): Table undefined. tableName=T2",
+                    e.getMessage());
+            }
+            // 2. create view from existing table - successful
+            conn.createStatement().execute(
+                "CREATE VIEW IF NOT EXISTS V1(C INTEGER) AS SELECT * FROM S.T1");
+            // 3. create view from non-existent table (with schema)
+            try {
+                conn.createStatement().execute(
+                    "CREATE VIEW IF NOT EXISTS V2(C INTEGER) AS SELECT * FROM S.T2");
+                fail("Creating view on non-existent table should have failed");
+            } catch (TableNotFoundException e) {
+                assertEquals("T2", e.getTableName());
+                assertEquals("S", e.getSchemaName());
+                assertEquals("ERROR 1012 (42M03): Table undefined. tableName=S.T2",
+                    e.getMessage());
+            }
+        }
+    }
+
+    @Test
     public void testSettingGuidePostWidth() throws Exception {
         try (Connection conn = DriverManager.getConnection(getUrl())) {
             String dataTable = generateUniqueName();
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 8e4e575..111fcc2 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
@@ -56,6 +56,7 @@ import org.apache.phoenix.query.QueryConstants;
 import org.apache.phoenix.schema.ColumnRef;
 import org.apache.phoenix.schema.MetaDataClient;
 import org.apache.phoenix.schema.PDatum;
+import org.apache.phoenix.schema.PName;
 import org.apache.phoenix.schema.PTable;
 import org.apache.phoenix.schema.PTable.ViewType;
 import org.apache.phoenix.schema.PTableType;
@@ -63,11 +64,11 @@ import org.apache.phoenix.schema.SortOrder;
 import org.apache.phoenix.schema.TableRef;
 import org.apache.phoenix.schema.types.PDataType;
 import org.apache.phoenix.schema.types.PVarbinary;
+import org.apache.phoenix.thirdparty.com.google.common.collect.Iterators;
 import org.apache.phoenix.util.ByteUtil;
 import org.apache.phoenix.util.MetaDataUtil;
 import org.apache.phoenix.util.QueryUtil;
-
-import org.apache.phoenix.thirdparty.com.google.common.collect.Iterators;
+import org.apache.phoenix.util.SchemaUtil;
 
 
 public class CreateTableCompiler {
@@ -164,22 +165,10 @@ public class CreateTableCompiler {
                     }
                 }
             }
-            if (viewTypeToBe == ViewType.MAPPED && parentToBe.getPKColumns().size() == 0) {
-                boolean isPKMissed = true;
-                if (pkConstraint.getColumnNames().size() > 0) {
-                    isPKMissed = false;
-                } else {
-                    for (ColumnDef columnDef: columnDefs) {
-                        if (columnDef.isPK()){
-                            isPKMissed = false;
-                            break;
-                        }
-                    }
-                }
-                if (isPKMissed) {
-                    throw new SQLExceptionInfo.Builder(SQLExceptionCode.PRIMARY_KEY_MISSING)
-                            .build().buildException();
-                }
+            if (viewTypeToBe == ViewType.MAPPED
+                    && parentToBe.getPKColumns().isEmpty()) {
+                validateCreateViewCompilation(connection, parentToBe,
+                    columnDefs, pkConstraint);
             }
         }
         final ViewType viewType = viewTypeToBe;
@@ -211,7 +200,48 @@ public class CreateTableCompiler {
         return new CreateTableMutationPlan(context, client, finalCreate, splits, parent,
             viewStatement, viewType, viewColumnConstants, isViewColumnReferenced, connection);
     }
-    
+
+    /**
+     * Validate View creation compilation.
+     * 1. If view creation syntax does not specify primary key, the method
+     * throws SQLException with PRIMARY_KEY_MISSING code.
+     * 2. If parent table does not exist, the method throws TNFE.
+     *
+     * @param connection The client connection
+     * @param parentToBe To be parent for given view
+     * @param columnDefs List of column defs
+     * @param pkConstraint PrimaryKey constraint retrieved from CreateTable
+     *     statement
+     * @throws SQLException If view creation validation fails
+     */
+    private void validateCreateViewCompilation(
+            final PhoenixConnection connection, final PTable parentToBe,
+            final List<ColumnDef> columnDefs,
+            final PrimaryKeyConstraint pkConstraint) throws SQLException {
+        boolean isPKMissed = true;
+        if (pkConstraint.getColumnNames().size() > 0) {
+            isPKMissed = false;
+        } else {
+            for (ColumnDef columnDef : columnDefs) {
+                if (columnDef.isPK()) {
+                    isPKMissed = false;
+                    break;
+                }
+            }
+        }
+        PName fullTableName = SchemaUtil.getPhysicalHBaseTableName(
+            parentToBe.getSchemaName(), parentToBe.getTableName(),
+            parentToBe.isNamespaceMapped());
+        // getTableIfExists will throw TNFE if table does not exist
+        connection.getQueryServices().getTableIfExists(
+            fullTableName.getBytes());
+        if (isPKMissed) {
+            throw new SQLExceptionInfo
+                .Builder(SQLExceptionCode.PRIMARY_KEY_MISSING)
+                .build().buildException();
+        }
+    }
+
     public static class ColumnTrackingExpressionCompiler extends ExpressionCompiler {
         private final BitSet isColumnReferenced;