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

amashenkov 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 c70b547321 IGNITE-19262 Sql. Throw exception on explicit TX with DDL 
(#1948)
c70b547321 is described below

commit c70b54732178685a380588d61a992924f2746c21
Author: Andrew V. Mashenkov <[email protected]>
AuthorDate: Wed Apr 19 18:28:13 2023 +0300

    IGNITE-19262 Sql. Throw exception on explicit TX with DDL (#1948)
---
 .../apache/ignite/jdbc/AbstractJdbcSelfTest.java   |  2 ++
 .../apache/ignite/jdbc/ItJdbcErrorsSelfTest.java   | 21 ++++++++++++
 .../internal/sql/api/ItSqlAsynchronousApiTest.java | 34 ++++++++++++++++++
 .../sql/api/ItSqlClientSynchronousApiTest.java     |  6 ++++
 .../internal/sql/api/ItSqlSynchronousApiTest.java  | 40 ++++++++++++++++++++++
 .../internal/sql/engine/SqlQueryProcessor.java     | 15 ++++++--
 6 files changed, 116 insertions(+), 2 deletions(-)

diff --git 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/AbstractJdbcSelfTest.java
 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/AbstractJdbcSelfTest.java
index d02e5d1f7f..4cbc43fb3b 100644
--- 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/AbstractJdbcSelfTest.java
+++ 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/AbstractJdbcSelfTest.java
@@ -118,6 +118,8 @@ public class AbstractJdbcSelfTest extends 
BaseIgniteAbstractTest {
     protected void beforeTest(TestInfo testInfo) throws Exception {
         setupBase(testInfo, WORK_DIR);
 
+        conn.setAutoCommit(true);
+
         stmt = conn.createStatement();
 
         assert stmt != null;
diff --git 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcErrorsSelfTest.java
 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcErrorsSelfTest.java
index a77702acaa..2f6bad76a1 100644
--- 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcErrorsSelfTest.java
+++ 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcErrorsSelfTest.java
@@ -141,6 +141,27 @@ public class ItJdbcErrorsSelfTest extends 
ItJdbcErrorsAbstractSelfTest {
         }
     }
 
+    /**
+     * Test error code when trying to execute DDL query within a transaction.
+     *
+     * @throws SQLException if failed.
+     */
+    @Disabled("https://issues.apache.org/jira/browse/IGNITE-18985";)
+    @Test
+    public void testDdlWithDisabledAutoCommit() throws SQLException {
+        conn.setAutoCommit(false);
+
+        try (Statement stmt = conn.createStatement()) {
+            stmt.executeUpdate("CREATE TABLE test2 (id int primary key, val 
varchar)");
+
+            fail("SQLException is expected");
+        } catch (SQLException e) {
+            assertTrue(e.getMessage() != null
+                            && e.getMessage().contains("DDL doesn't support 
transactions."),
+                    "Unexpected error message: " + e.getMessage());
+        }
+    }
+
     /**
      * Check that unsupported explain of update operation causes Exception on 
the driver side with correct code and
      * message.
diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlAsynchronousApiTest.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlAsynchronousApiTest.java
index 0fdd77892a..56bcd4563b 100644
--- 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlAsynchronousApiTest.java
+++ 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlAsynchronousApiTest.java
@@ -599,6 +599,40 @@ public class ItSqlAsynchronousApiTest extends 
ClusterPerClassIntegrationTest {
         }
     }
 
+    /**
+     * DDL is non-transactional.
+     */
+    @Test
+    public void ddlInTransaction() {
+        Session ses = igniteSql().createSession();
+        sql("CREATE TABLE TEST(ID INT PRIMARY KEY, VAL0 INT)");
+
+        {
+            Transaction tx = igniteTx().begin();
+            try {
+                assertThrowsWithCause(() -> await(ses.executeAsync(tx, "CREATE 
TABLE TEST2(ID INT PRIMARY KEY, VAL0 INT)")),
+                        SqlException.class,
+                        "DDL doesn't support transactions."
+                );
+            } finally {
+                tx.rollback();
+            }
+        }
+        {
+            Transaction tx = igniteTx().begin();
+            AsyncResultSet<SqlRow> res = await(ses.executeAsync(tx, "INSERT 
INTO TEST VALUES (?, ?)", -1, -1));
+            assertEquals(1, res.affectedRows());
+
+            assertThrowsWithCause(() -> await(ses.executeAsync(tx, "CREATE 
TABLE TEST2(ID INT PRIMARY KEY, VAL0 INT)")),
+                    SqlException.class,
+                    "DDL doesn't support transactions."
+            );
+            tx.commit();
+
+            assertEquals(1, sql("SELECT ID FROM TEST WHERE ID = -1").size());
+        }
+    }
+
     @Test
     public void closeSession() {
         sql("CREATE TABLE TEST(ID INT PRIMARY KEY, VAL0 INT)");
diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlClientSynchronousApiTest.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlClientSynchronousApiTest.java
index b055b6f251..671f0d3a1d 100644
--- 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlClientSynchronousApiTest.java
+++ 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlClientSynchronousApiTest.java
@@ -22,6 +22,7 @@ import static 
org.apache.ignite.internal.runner.app.client.ItAbstractThinClientT
 import org.apache.ignite.client.IgniteClient;
 import org.apache.ignite.sql.IgniteSql;
 import org.apache.ignite.sql.Session;
+import org.apache.ignite.tx.IgniteTransactions;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
@@ -49,6 +50,11 @@ public class ItSqlClientSynchronousApiTest extends 
ItSqlSynchronousApiTest {
         return client.sql();
     }
 
+    @Override
+    protected IgniteTransactions igniteTx() {
+        return client.transactions();
+    }
+
     @Override
     @Test
     public void dml() {
diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlSynchronousApiTest.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlSynchronousApiTest.java
index 0603dccee2..2b8a4aa09a 100644
--- 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlSynchronousApiTest.java
+++ 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlSynchronousApiTest.java
@@ -56,6 +56,8 @@ import org.apache.ignite.sql.SqlBatchException;
 import org.apache.ignite.sql.SqlException;
 import org.apache.ignite.sql.SqlRow;
 import org.apache.ignite.table.Table;
+import org.apache.ignite.tx.IgniteTransactions;
+import org.apache.ignite.tx.Transaction;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.TestInfo;
@@ -92,6 +94,10 @@ public class ItSqlSynchronousApiTest extends 
ClusterPerClassIntegrationTest {
         return CLUSTER_NODES.get(0).sql();
     }
 
+    protected IgniteTransactions igniteTx() {
+        return CLUSTER_NODES.get(0).transactions();
+    }
+
     @Test
     public void ddl() throws Exception {
         IgniteSql sql = igniteSql();
@@ -279,6 +285,40 @@ public class ItSqlSynchronousApiTest extends 
ClusterPerClassIntegrationTest {
             rs.close();
             assertThrowsWithCause(() -> rs.forEachRemaining(Object::hashCode), 
CursorClosedException.class);
         }
+    }
+
+    /**
+     * DDL is non-transactional.
+     */
+    @Test
+    public void ddlInTransaction() {
+        Session ses = igniteSql().createSession();
+        sql("CREATE TABLE TEST(ID INT PRIMARY KEY, VAL0 INT)");
+
+        {
+            Transaction tx = igniteTx().begin();
+            try {
+                assertThrowsWithCause(() -> ses.execute(tx, "CREATE TABLE 
TEST2(ID INT PRIMARY KEY, VAL0 INT)"),
+                        SqlException.class,
+                        "DDL doesn't support transactions."
+                );
+            } finally {
+                tx.rollback();
+            }
+        }
+        {
+            Transaction tx = igniteTx().begin();
+            ResultSet<SqlRow> res = ses.execute(tx, "INSERT INTO TEST VALUES 
(?, ?)", -1, -1);
+            assertEquals(1, res.affectedRows());
+
+            assertThrowsWithCause(() -> ses.execute(tx, "CREATE TABLE TEST2(ID 
INT PRIMARY KEY, VAL0 INT)"),
+                    SqlException.class,
+                    "DDL doesn't support transactions."
+            );
+            tx.commit();
+
+            assertEquals(1, sql("SELECT ID FROM TEST WHERE ID = -1").size());
+        }
 
         TxManager txManagerInternal = (TxManager) 
IgniteTestUtils.getFieldValue(CLUSTER_NODES.get(0), IgniteImpl.class, 
"txManager");
 
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/SqlQueryProcessor.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/SqlQueryProcessor.java
index 4366c4f63a..7c3f29d78e 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/SqlQueryProcessor.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/SqlQueryProcessor.java
@@ -23,6 +23,7 @@ import static 
org.apache.ignite.lang.ErrorGroups.Sql.QUERY_INVALID_ERR;
 import static org.apache.ignite.lang.ErrorGroups.Sql.SCHEMA_NOT_FOUND_ERR;
 import static org.apache.ignite.lang.ErrorGroups.Sql.SESSION_EXPIRED_ERR;
 import static org.apache.ignite.lang.ErrorGroups.Sql.SESSION_NOT_FOUND_ERR;
+import static 
org.apache.ignite.lang.ErrorGroups.Sql.UNSUPPORTED_DDL_OPERATION_ERR;
 import static 
org.apache.ignite.lang.ErrorGroups.Sql.UNSUPPORTED_SQL_OPERATION_KIND_ERR;
 import static org.apache.ignite.lang.IgniteStringFormatter.format;
 
@@ -414,7 +415,7 @@ public class SqlQueryProcessor implements QueryProcessor {
                     StatementParseResult parseResult = 
IgniteSqlParser.parse(sql, StatementParseResult.MODE);
                     SqlNode sqlNode = parseResult.statement();
 
-                    validateParsedStatement(context, parseResult, sqlNode, 
params);
+                    validateParsedStatement(context, outerTx, parseResult, 
sqlNode, params);
 
                     return sqlNode;
                 })
@@ -591,7 +592,13 @@ public class SqlQueryProcessor implements QueryProcessor {
     }
 
     /** Performs additional validation of a parsed statement. **/
-    private static void validateParsedStatement(QueryContext context, 
ParseResult parseResult, SqlNode node, Object[] params) {
+    private static void validateParsedStatement(
+            QueryContext context,
+            InternalTransaction outerTx,
+            ParseResult parseResult,
+            SqlNode node,
+            Object[] params
+    ) {
         Set<SqlQueryType> allowedTypes = context.allowedQueryTypes();
         SqlQueryType queryType = Commons.getQueryType(node);
 
@@ -607,6 +614,10 @@ public class SqlQueryProcessor implements QueryProcessor {
             throw new QueryValidationException(message);
         }
 
+        if (SqlQueryType.DDL == queryType && outerTx != null) {
+            throw new SqlException(UNSUPPORTED_DDL_OPERATION_ERR, "DDL doesn't 
support transactions.");
+        }
+
         if (parseResult.dynamicParamsCount() != params.length) {
             String message = format(
                     "Unexpected number of query parameters. Provided {} but 
there is only {} dynamic parameter(s).",

Reply via email to