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 {