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

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


The following commit(s) were added to refs/heads/jdbc_over_thin_sql by this 
push:
     new cd6d4867a31 IGNITE-26143 Sql. Jdbc. Statement.executeBatch using thin 
client SQL API (#6824)
cd6d4867a31 is described below

commit cd6d4867a312282fc2bbd43d9ed224212a2ea836
Author: Pavel Pereslegin <[email protected]>
AuthorDate: Thu Oct 23 11:43:19 2025 +0300

    IGNITE-26143 Sql. Jdbc. Statement.executeBatch using thin client SQL API 
(#6824)
---
 .../cli/commands/sql/ItSqlReplCommandTest.java     |  1 -
 .../internal/jdbc/proto/IgniteQueryErrorCode.java  |  1 +
 .../internal/client/sql/ClientAsyncResultSet.java  | 62 ----------------
 .../apache/ignite/jdbc/ItJdbcBatchSelfTest.java    | 48 ++++++------
 .../apache/ignite/jdbc/ItJdbcErrorsSelfTest.java   |  2 -
 .../ignite/jdbc/ItJdbcMultiStatementSelfTest.java  | 14 ----
 .../org/apache/ignite/jdbc/ItJdbcSchemaTest.java   |  2 -
 .../ignite/jdbc/ItJdbcStatementCancelSelfTest.java |  2 -
 .../ignite/jdbc/ItJdbcStatementSelfTest.java       |  2 -
 .../apache/ignite/jdbc/ItJdbcTransactionTest.java  |  2 -
 .../ignite/internal/jdbc2/JdbcStatement2.java      | 85 +++++++++++++++++++---
 11 files changed, 98 insertions(+), 123 deletions(-)

diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/sql/ItSqlReplCommandTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/sql/ItSqlReplCommandTest.java
index 4791dbea68a..7c672122bc9 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/sql/ItSqlReplCommandTest.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/sql/ItSqlReplCommandTest.java
@@ -67,7 +67,6 @@ class ItSqlReplCommandTest extends CliIntegrationTest {
         execute("CREATE TABLE MULTILINE_TABLE(K INT PRIMARY KEY); \n INSERT 
INTO MULTILINE_TABLE VALUES(1);", "--jdbc-url", JDBC_URL);
 
         assertAll(
-                // TODO https://issues.apache.org/jira/browse/IGNITE-26790
                 // The output from CREATE TABLE is: Updated 0 rows.
                 () -> assertOutputContains("Updated 0 rows."),
                 this::assertErrOutputIsEmpty
diff --git 
a/modules/client-common/src/main/java/org/apache/ignite/internal/jdbc/proto/IgniteQueryErrorCode.java
 
b/modules/client-common/src/main/java/org/apache/ignite/internal/jdbc/proto/IgniteQueryErrorCode.java
index 351ed264e4f..7ea0c741729 100644
--- 
a/modules/client-common/src/main/java/org/apache/ignite/internal/jdbc/proto/IgniteQueryErrorCode.java
+++ 
b/modules/client-common/src/main/java/org/apache/ignite/internal/jdbc/proto/IgniteQueryErrorCode.java
@@ -65,6 +65,7 @@ public final class IgniteQueryErrorCode {
      * @see <a 
href="http://en.wikibooks.org/wiki/Structured_Query_Language/SQLSTATE";>Wikipedia:
 SQLSTATE spec.</a>
      * @see IgniteQueryErrorCode
      */
+    // TODO https://issues.apache.org/jira/browse/IGNITE-15247 Map Ignite 
error codes to specific JDBC SQL state codes
     public static String codeToSqlState(int statusCode) {
         switch (statusCode) {
             case UNSUPPORTED_OPERATION:
diff --git 
a/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientAsyncResultSet.java
 
b/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientAsyncResultSet.java
index 97d1cfd09fe..64ed9dcc61e 100644
--- 
a/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientAsyncResultSet.java
+++ 
b/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientAsyncResultSet.java
@@ -316,68 +316,6 @@ public class ClientAsyncResultSet<T> implements 
AsyncResultSet<T> {
         rows = Collections.unmodifiableList(res);
     }
 
-    private static Object readValue(BinaryTupleReader in, int idx, 
ColumnMetadata col) {
-        if (in.hasNullValue(idx)) {
-            return null;
-        }
-
-        switch (col.type()) {
-            case BOOLEAN:
-                return in.byteValue(idx) != 0;
-
-            case INT8:
-                return in.byteValue(idx);
-
-            case INT16:
-                return in.shortValue(idx);
-
-            case INT32:
-                return in.intValue(idx);
-
-            case INT64:
-                return in.longValue(idx);
-
-            case FLOAT:
-                return in.floatValue(idx);
-
-            case DOUBLE:
-                return in.doubleValue(idx);
-
-            case DECIMAL:
-                return in.decimalValue(idx, col.scale());
-
-            case DATE:
-                return in.dateValue(idx);
-
-            case TIME:
-                return in.timeValue(idx);
-
-            case DATETIME:
-                return in.dateTimeValue(idx);
-
-            case TIMESTAMP:
-                return in.timestampValue(idx);
-
-            case UUID:
-                return in.uuidValue(idx);
-
-            case STRING:
-                return in.stringValue(idx);
-
-            case BYTE_ARRAY:
-                return in.bytesValue(idx);
-
-            case PERIOD:
-                return in.periodValue(idx);
-
-            case DURATION:
-                return in.durationValue(idx);
-
-            default:
-                throw new UnsupportedOperationException("Unsupported column 
type: " + col.type());
-        }
-    }
-
     private static <T> Marshaller marshaller(ResultSetMetadata metadata, 
MarshallersProvider marshallers, Mapper<T> mapper) {
         var schemaColumns = new ClientColumn[metadata.columns().size()];
         List<ColumnMetadata> columns = metadata.columns();
diff --git 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcBatchSelfTest.java
 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcBatchSelfTest.java
index a0f517a4197..96264a38981 100644
--- 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcBatchSelfTest.java
+++ 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcBatchSelfTest.java
@@ -47,10 +47,10 @@ import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 import org.apache.ignite.internal.TestWrappers;
 import org.apache.ignite.internal.app.IgniteImpl;
-import org.apache.ignite.internal.jdbc.JdbcStatement;
 import org.apache.ignite.internal.jdbc.proto.IgniteQueryErrorCode;
 import org.apache.ignite.internal.jdbc.proto.SqlStateCode;
 import org.apache.ignite.internal.jdbc2.JdbcPreparedStatement2;
+import org.apache.ignite.internal.jdbc2.JdbcStatement2;
 import org.apache.ignite.internal.sql.engine.QueryCancelledException;
 import org.apache.ignite.internal.sql.engine.SqlQueryProcessor;
 import org.apache.ignite.internal.sql.engine.exec.fsm.QueryInfo;
@@ -61,7 +61,6 @@ import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
@@ -138,11 +137,11 @@ public class ItJdbcBatchSelfTest extends 
AbstractJdbcSelfTest {
 
         Awaitility.await().timeout(5, TimeUnit.SECONDS).untilAsserted(() -> {
             assertThat(openResources(CLUSTER) - resourcesBefore, is(0));
+            assertThat(openCursors(CLUSTER), is(0));
         });
     }
 
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
     public void testBatch() throws SQLException {
         final int batchSize = 10;
 
@@ -161,7 +160,6 @@ public class ItJdbcBatchSelfTest extends 
AbstractJdbcSelfTest {
     }
 
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
     public void testBatchWithDdl() throws SQLException {
         stmt.addBatch("CREATE TABLE t1(ID INT PRIMARY KEY)");
         stmt.addBatch("CREATE TABLE t2(ID INT PRIMARY KEY)");
@@ -178,7 +176,6 @@ public class ItJdbcBatchSelfTest extends 
AbstractJdbcSelfTest {
     }
 
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
     public void testBatchWithKill() throws SQLException {
         try (Statement targetQueryStatement = conn.createStatement()) {
             try (ResultSet rs = targetQueryStatement.executeQuery("SELECT x 
FROM system_range(0, 100000);")) {
@@ -208,22 +205,17 @@ public class ItJdbcBatchSelfTest extends 
AbstractJdbcSelfTest {
     }
 
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
-    public void testMultipleStatementForBatchIsNotAllowed() throws 
SQLException {
+    public void testMultipleStatementInBatchAreAllowed() throws SQLException {
         String insertStmt = "insert into Person (id, firstName, lastName, age) 
values";
         String ins1 = insertStmt + valuesRow(1);
         String ins2 = insertStmt + valuesRow(2);
 
         stmt.addBatch(ins1 + ";" + ins2);
 
-        assertThrowsSqlException(
-                BatchUpdateException.class,
-                "Multiple statements are not allowed.",
-                () -> stmt.executeBatch());
+        assertArrayEquals(stmt.executeBatch(), new int[]{1, 1});
     }
 
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
     public void testBatchOnClosedStatement() throws SQLException {
         Statement stmt2 = conn.createStatement();
         PreparedStatement pstmt2 = conn.prepareStatement("");
@@ -293,7 +285,6 @@ public class ItJdbcBatchSelfTest extends 
AbstractJdbcSelfTest {
 
     @ParameterizedTest(name = "{0}")
     @MethodSource("forbiddenStatements")
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
     public void testForbiddenQueryTypes(String sql, String expectedError) 
throws SQLException {
         stmt.addBatch(sql);
 
@@ -305,7 +296,6 @@ public class ItJdbcBatchSelfTest extends 
AbstractJdbcSelfTest {
     }
 
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
     public void testBatchException() throws Exception {
         final int successUpdates = 5;
 
@@ -337,7 +327,6 @@ public class ItJdbcBatchSelfTest extends 
AbstractJdbcSelfTest {
     }
 
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
     public void testBatchParseException() throws Exception {
         final int successUpdates = 5;
 
@@ -370,7 +359,6 @@ public class ItJdbcBatchSelfTest extends 
AbstractJdbcSelfTest {
     }
 
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
     public void testBatchMerge() throws SQLException {
         final int batchSize = 5;
 
@@ -414,7 +402,6 @@ public class ItJdbcBatchSelfTest extends 
AbstractJdbcSelfTest {
     }
 
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
     public void testBatchKeyDuplicatesException() throws Exception {
         final int successUpdates = 5;
 
@@ -451,7 +438,6 @@ public class ItJdbcBatchSelfTest extends 
AbstractJdbcSelfTest {
     }
 
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
     public void testHeterogeneousBatch() throws SQLException {
         stmt.addBatch("insert into Person (id, firstName, lastName, age) 
values (0, 'Name0', 'Lastname0', 10)");
         stmt.addBatch("insert into Person (id, firstName, lastName, age) "
@@ -466,7 +452,6 @@ public class ItJdbcBatchSelfTest extends 
AbstractJdbcSelfTest {
     }
 
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
     public void testHeterogeneousBatchException() throws Exception {
         stmt.addBatch("insert into Person (id, firstName, lastName, age) 
values (0, 'Name0', 'Lastname0', 10)");
         stmt.addBatch("insert into Person (id, firstName, lastName, age) "
@@ -487,7 +472,6 @@ public class ItJdbcBatchSelfTest extends 
AbstractJdbcSelfTest {
     }
 
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
     public void testBatchClear() throws SQLException {
         final int batchSize = 7;
 
@@ -812,8 +796,7 @@ public class ItJdbcBatchSelfTest extends 
AbstractJdbcSelfTest {
         // Each statement in a batch is executed separately, and timeout is 
applied to each statement.
         // Retry until timeout exception is thrown.
         Awaitility.await().untilAsserted(() -> {
-            int timeoutMillis = 1;
-            igniteStmt.timeout(timeoutMillis);
+            igniteStmt.timeout(1);
 
             for (int i = 0; i < 3; i++) {
                 pstmt.setInt(1, 42);
@@ -841,9 +824,8 @@ public class ItJdbcBatchSelfTest extends 
AbstractJdbcSelfTest {
     }
 
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
     public void testBatchTimeout() throws SQLException {
-        JdbcStatement igniteStmt = stmt.unwrap(JdbcStatement.class);
+        JdbcStatement2 igniteStmt = stmt.unwrap(JdbcStatement2.class);
 
         {
             // Disable timeout
@@ -883,6 +865,18 @@ public class ItJdbcBatchSelfTest extends 
AbstractJdbcSelfTest {
         }
     }
 
+    @Test
+    public void testMoreResults() throws Exception {
+        stmt.addBatch("INSERT INTO person (id, firstName, lastName, age) 
VALUES (0, 'Name0', 'Lastname0', 10)");
+        stmt.addBatch("INSERT INTO person (id, firstName, lastName, age) 
VALUES (1, 'Name1', 'Lastname1', 20)");
+        int[] arr = stmt.executeBatch();
+
+        assertEquals(2, arr.length);
+        assertArrayEquals(new int[]{1, 1}, arr);
+        assertEquals(-1, stmt.getUpdateCount());
+        assertFalse(stmt.getMoreResults());
+    }
+
     /**
      * Generate values for insert query.
      *
@@ -953,13 +947,13 @@ public class ItJdbcBatchSelfTest extends 
AbstractJdbcSelfTest {
                         "Invalid SQL statement type."),
 
                 Arguments.of("START TRANSACTION",
-                        "Transaction control statement can not be executed as 
an independent statement."),
+                        "Invalid SQL statement type. Expected [DML, DDL, KILL] 
but got TX_CONTROL."),
 
                 Arguments.of("COMMIT",
-                        "Transaction control statement can not be executed as 
an independent statement."),
+                        "Invalid SQL statement type. Expected [DML, DDL, KILL] 
but got TX_CONTROL."),
 
                 Arguments.of("START TRANSACTION; COMMIT",
-                        "Multiple statements are not allowed.")
+                        "Invalid SQL statement type. Expected [DML, DDL, KILL] 
but got TX_CONTROL.")
         );
     }
 }
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 53d83aaa0f9..0869ab72255 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
@@ -112,9 +112,7 @@ public class ItJdbcErrorsSelfTest extends 
ItJdbcErrorsAbstractSelfTest {
      * @throws SQLException if failed.
      */
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
     public void testBatchUpdateException() throws SQLException {
-
         stmt.executeUpdate("CREATE TABLE test2 (id int primary key, val 
varchar)");
 
         stmt.addBatch("insert into test2 (id, val) values (1, 'val1')");
diff --git 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcMultiStatementSelfTest.java
 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcMultiStatementSelfTest.java
index 86db5d79615..5a005bad391 100644
--- 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcMultiStatementSelfTest.java
+++ 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcMultiStatementSelfTest.java
@@ -22,7 +22,6 @@ import static 
org.apache.ignite.internal.testframework.IgniteTestUtils.waitForCo
 import static 
org.apache.ignite.jdbc.util.JdbcTestUtils.assertThrowsSqlException;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.containsString;
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -597,19 +596,6 @@ public class ItJdbcMultiStatementSelfTest extends 
AbstractJdbcSelfTest {
         assertEquals(-1, stmt.getUpdateCount());
     }
 
-    @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
-    public void testResultsFromExecuteBatch() throws Exception {
-        stmt.addBatch("INSERT INTO TEST_TX VALUES (7, 25, 'Michel');");
-        stmt.addBatch("INSERT INTO TEST_TX VALUES (8, 25, 'Michel');");
-        int[] arr = stmt.executeBatch();
-
-        assertEquals(2, arr.length);
-        assertArrayEquals(new int[]{1, 1}, arr);
-        assertEquals(-1, stmt.getUpdateCount());
-        assertFalse(stmt.getMoreResults());
-    }
-
     /**
      * Sanity test for scripts, containing empty statements are handled 
correctly.
      */
diff --git 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcSchemaTest.java
 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcSchemaTest.java
index 970932e4d3d..71ea66e1bb4 100644
--- 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcSchemaTest.java
+++ 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcSchemaTest.java
@@ -26,7 +26,6 @@ import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.sql.Statement;
 import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
 /**
@@ -148,7 +147,6 @@ public class ItJdbcSchemaTest extends AbstractJdbcSelfTest {
     }
 
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
     public void useSchemaWithBatch() throws SQLException {
         try (Statement stmt = conn.createStatement()) {
             stmt.executeUpdate("CREATE SCHEMA schema1");
diff --git 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcStatementCancelSelfTest.java
 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcStatementCancelSelfTest.java
index a49b0e07a29..72c502548ea 100644
--- 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcStatementCancelSelfTest.java
+++ 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcStatementCancelSelfTest.java
@@ -32,7 +32,6 @@ import java.sql.Statement;
 import java.util.concurrent.CompletableFuture;
 import org.apache.ignite.internal.sql.engine.QueryCancelledException;
 import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
 /**
@@ -188,7 +187,6 @@ public class ItJdbcStatementCancelSelfTest extends 
AbstractJdbcSelfTest {
     }
 
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
     void cancellationOfBatch() throws Exception {
         stmt.executeUpdate("CREATE TABLE dummy (id INT PRIMARY KEY, val INT)");
         stmt.addBatch("INSERT INTO dummy SELECT x, x FROM system_range(1, 1)");
diff --git 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcStatementSelfTest.java
 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcStatementSelfTest.java
index 100c87c7098..b90fa9991f3 100644
--- 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcStatementSelfTest.java
+++ 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcStatementSelfTest.java
@@ -43,7 +43,6 @@ import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
 /**
@@ -725,7 +724,6 @@ public class ItJdbcStatementSelfTest extends 
ItJdbcAbstractStatementSelfTest {
     }
 
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
     public void testBatchEmpty() throws Exception {
         assertTrue(conn.getMetaData().supportsBatchUpdates());
 
diff --git 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcTransactionTest.java
 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcTransactionTest.java
index f055b8ec040..ed4fa64a9da 100644
--- 
a/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcTransactionTest.java
+++ 
b/modules/jdbc/src/integrationTest/java/org/apache/ignite/jdbc/ItJdbcTransactionTest.java
@@ -36,7 +36,6 @@ import 
org.apache.ignite.internal.testframework.IgniteTestUtils;
 import org.apache.ignite.internal.tx.TxManager;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.CsvSource;
@@ -189,7 +188,6 @@ public class ItJdbcTransactionTest extends 
AbstractJdbcSelfTest {
      * @throws Exception If failed.
      */
     @Test
-    @Disabled("https://issues.apache.org/jira/browse/IGNITE-26143";)
     public void testBatch() throws Exception {
         checkRollbackAndCommit((conn, start, cnt) -> {
             try (Statement stmt = conn.createStatement()) {
diff --git 
a/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement2.java
 
b/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement2.java
index fa1251189cc..79efecb640d 100644
--- 
a/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement2.java
+++ 
b/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement2.java
@@ -20,7 +20,9 @@ package org.apache.ignite.internal.jdbc2;
 import static java.sql.ResultSet.CONCUR_READ_ONLY;
 import static java.sql.ResultSet.FETCH_FORWARD;
 import static java.sql.ResultSet.TYPE_FORWARD_ONLY;
+import static org.apache.ignite.internal.util.ArrayUtils.INT_EMPTY_ARRAY;
 
+import java.sql.BatchUpdateException;
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
@@ -28,13 +30,16 @@ import java.sql.SQLFeatureNotSupportedException;
 import java.sql.SQLWarning;
 import java.sql.Statement;
 import java.time.ZoneId;
+import java.util.ArrayList;
 import java.util.EnumSet;
+import java.util.List;
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import org.apache.ignite.internal.client.sql.ClientAsyncResultSet;
 import org.apache.ignite.internal.client.sql.ClientSql;
 import org.apache.ignite.internal.client.sql.QueryModifier;
+import org.apache.ignite.internal.jdbc.proto.IgniteQueryErrorCode;
 import org.apache.ignite.internal.jdbc.proto.SqlStateCode;
 import org.apache.ignite.internal.util.ArrayUtils;
 import org.apache.ignite.lang.CancelHandle;
@@ -104,6 +109,8 @@ public class JdbcStatement2 implements Statement {
 
     volatile @Nullable CancelHandle cancelHandle;
 
+    private @Nullable List<String> batch;
+
     JdbcStatement2(
             Connection connection,
             IgniteSql igniteSql,
@@ -546,8 +553,15 @@ public class JdbcStatement2 implements Statement {
 
         Objects.requireNonNull(sql);
 
-        // TODO https://issues.apache.org/jira/browse/IGNITE-26143 batch 
operations
-        throw new UnsupportedOperationException("Batch operation");
+        if (sql.isBlank()) {
+            return;
+        }
+
+        if (batch == null) {
+            batch = new ArrayList<>(2);
+        }
+
+        batch.add(sql);
     }
 
     /** {@inheritDoc} */
@@ -555,8 +569,7 @@ public class JdbcStatement2 implements Statement {
     public void clearBatch() throws SQLException {
         ensureNotClosed();
 
-        // TODO https://issues.apache.org/jira/browse/IGNITE-26143 batch 
operations
-        throw new UnsupportedOperationException("Batch operation");
+        batch = null;
     }
 
     /** {@inheritDoc} */
@@ -566,8 +579,62 @@ public class JdbcStatement2 implements Statement {
 
         closeResults();
 
-        // TODO https://issues.apache.org/jira/browse/IGNITE-26143 batch 
operations
-        throw new UnsupportedOperationException("Batch operation");
+        if (batch == null) {
+            return INT_EMPTY_ARRAY;
+        }
+
+        assert !batch.isEmpty();
+
+        String script = String.join(";", batch);
+
+        org.apache.ignite.sql.Statement igniteStmt = 
createIgniteStatement(script);
+
+        JdbcConnection2 conn = connection.unwrap(JdbcConnection2.class);
+        Transaction tx = conn.startTransactionIfNoAutoCommit();
+
+        ClientSql clientSql = (ClientSql) igniteSql;
+
+        // Cancel handle is not reusable, we should create a new one for each 
execution.
+        CancelHandle handle = CancelHandle.create();
+        cancelHandle = handle;
+
+        List<Integer> results = new ArrayList<>(batch.size());
+
+        try {
+            ClientAsyncResultSet<SqlRow> asyncRs = 
(ClientAsyncResultSet<SqlRow>) clientSql.executeAsyncInternal(tx,
+                    (Mapper<SqlRow>) null,
+                    handle.token(),
+                    EnumSet.of(QueryModifier.ALLOW_MULTISTATEMENT, 
QueryModifier.ALLOW_APPLIED_RESULT,
+                            QueryModifier.ALLOW_AFFECTED_ROWS_RESULT),
+                    igniteStmt
+            ).get();
+
+            while (true) {
+                int affRows = asyncRs.affectedRows() == -1L ? SUCCESS_NO_INFO 
: (int) asyncRs.affectedRows();
+
+                results.add(affRows);
+
+                // DML/DDL-like cursors are immediately closed on the server 
side after the batch statement
+                // is executed and are not stored in client resources, so 
calling close should do nothing.
+                asyncRs.closeAsync();
+
+                if (!asyncRs.hasNextResultSet()) {
+                    break;
+                }
+
+                asyncRs = asyncRs.nextResultSet().get();
+            }
+
+            return results.stream().mapToInt(Integer::intValue).toArray();
+        } catch (Exception e) {
+            // TODO https://issues.apache.org/jira/browse/IGNITE-15247 Map 
Ignite errors to specific JDBC SQL state codes
+            throw new BatchUpdateException(e.getMessage(),
+                    SqlStateCode.INTERNAL_ERROR,
+                    IgniteQueryErrorCode.UNKNOWN,
+                    results.stream().mapToInt(Integer::intValue).toArray());
+        } finally {
+            batch = null;
+        }
     }
 
     /** {@inheritDoc} */
@@ -655,10 +722,10 @@ public class JdbcStatement2 implements Statement {
         return iface != null && iface.isAssignableFrom(JdbcStatement2.class);
     }
 
-    /** Sets timeout in milliseconds. */
+    /** Sets query timeout in milliseconds. */
     @TestOnly
-    public void timeout(long timeoutMillis) {
-        this.queryTimeoutMillis = timeoutMillis;
+    public void timeout(long queryTimeoutMillis) {
+        this.queryTimeoutMillis = queryTimeoutMillis;
     }
 
     org.apache.ignite.sql.Statement createIgniteStatement(String sql) throws 
SQLException {

Reply via email to