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

ppa pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new d7a6037705 IGNITE-19116 Sql. Fixed NPE when a DML statement fails on a 
non-existing table (#1917)
d7a6037705 is described below

commit d7a6037705f85a66cf086d70316d4d2855da7360
Author: Pavel Pereslegin <xxt...@gmail.com>
AuthorDate: Wed Apr 12 22:50:43 2023 +0300

    IGNITE-19116 Sql. Fixed NPE when a DML statement fails on a non-existing 
table (#1917)
---
 .../sql/engine/prepare/IgniteSqlValidator.java     | 13 ++++++++-
 .../sql/engine/planner/DmlPlannerTest.java         | 31 ++++++++++++++++++++++
 2 files changed, 43 insertions(+), 1 deletion(-)

diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlValidator.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlValidator.java
index e084e73113..311a13181f 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlValidator.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlValidator.java
@@ -169,6 +169,11 @@ public class IgniteSqlValidator extends SqlValidatorImpl {
         final SqlIdentifier targetTable = (SqlIdentifier) 
call.getTargetTable();
         final SqlValidatorTable table = 
getCatalogReader().getTable(targetTable.names);
 
+        if (table == null) {
+            // TODO IGNITE-14865 Calcite exception should be converted/wrapped 
into a public ignite exception.
+            throw newValidationError(call.getTargetTable(), 
RESOURCE.objectNotFound(targetTable.toString()));
+        }
+
         SqlIdentifier alias = call.getAlias() != null ? call.getAlias() :
                 new SqlIdentifier(deriveAlias(targetTable, 0), 
SqlParserPos.ZERO);
 
@@ -208,7 +213,13 @@ public class IgniteSqlValidator extends SqlValidatorImpl {
     @Override
     protected SqlSelect createSourceSelectForDelete(SqlDelete call) {
         final SqlNodeList selectList = new SqlNodeList(SqlParserPos.ZERO);
-        final SqlValidatorTable table = 
getCatalogReader().getTable(((SqlIdentifier) call.getTargetTable()).names);
+        final SqlIdentifier targetTable = (SqlIdentifier) 
call.getTargetTable();
+        final SqlValidatorTable table = 
getCatalogReader().getTable(targetTable.names);
+
+        if (table == null) {
+            // TODO IGNITE-14865 Calcite exception should be converted/wrapped 
into a public ignite exception.
+            throw newValidationError(targetTable, 
RESOURCE.objectNotFound(targetTable.toString()));
+        }
 
         
table.unwrap(IgniteTable.class).descriptor().deleteRowType((IgniteTypeFactory) 
typeFactory)
                 .getFieldNames().stream()
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/DmlPlannerTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/DmlPlannerTest.java
index 8613120468..6200ffa7cb 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/DmlPlannerTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/DmlPlannerTest.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.sql.engine.planner;
 import java.util.List;
 import java.util.UUID;
 import java.util.stream.Stream;
+import org.apache.calcite.sql.validate.SqlValidatorException;
 import org.apache.ignite.internal.schema.NativeTypes;
 import org.apache.ignite.internal.sql.engine.framework.TestBuilders;
 import org.apache.ignite.internal.sql.engine.rel.IgniteExchange;
@@ -30,6 +31,7 @@ import 
org.apache.ignite.internal.sql.engine.schema.IgniteSchema;
 import org.apache.ignite.internal.sql.engine.schema.IgniteTable;
 import org.apache.ignite.internal.sql.engine.trait.IgniteDistribution;
 import org.apache.ignite.internal.sql.engine.trait.IgniteDistributions;
+import org.apache.ignite.internal.testframework.IgniteTestUtils;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.MethodSource;
@@ -152,6 +154,35 @@ public class DmlPlannerTest extends AbstractPlannerTest {
         );
     }
 
+    /**
+     * Test for check basic dml operators when table doesn't exist.
+     */
+    @ParameterizedTest
+    @MethodSource("basicStatements")
+    public void testDmlQueriesOnNonExistingTable(String query) {
+        //noinspection ThrowableNotThrown
+        IgniteTestUtils.assertThrowsWithCause(
+                () -> physicalPlan(query, createSchema(newTestTable("TEST", 
IgniteDistributions.single()))),
+                SqlValidatorException.class,
+                "Object 'UNKNOWN' not found"
+        );
+    }
+
+    private static Stream<String> basicStatements() {
+        return Stream.of(
+                "SELECT * FROM unknown",
+                "INSERT INTO unknown VALUES(1)",
+                "UPDATE unknown SET ID=1",
+                "DELETE FROM unknown",
+                "MERGE INTO unknown DST USING test SRC ON DST.C1 = SRC.C1"
+                        + " WHEN MATCHED THEN UPDATE SET C2 = SRC.C2"
+                        + " WHEN NOT MATCHED THEN INSERT (C1, C2) VALUES 
(SRC.C1, SRC.C2)",
+                "MERGE INTO test DST USING unknown SRC ON DST.C1 = SRC.C1"
+                        + " WHEN MATCHED THEN UPDATE SET C2 = SRC.C2"
+                        + " WHEN NOT MATCHED THEN INSERT (C1, C2) VALUES 
(SRC.C1, SRC.C2)"
+        );
+    }
+
     // Class name is fully-qualified because AbstractPlannerTest defines a 
class with the same name.
     private static org.apache.ignite.internal.sql.engine.framework.TestTable 
newTestTable(
             String tableName, IgniteDistribution distribution) {

Reply via email to