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

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

commit b84ae4e343484b313a09015a981f2ed7a6ba2460
Author: Pavel Pereslegin <[email protected]>
AuthorDate: Thu Oct 9 17:19:23 2025 +0300

    IGNITE-26146 POC - compatibility test.
---
 modules/compatibility-tests/build.gradle           |  1 +
 ...ntJdbcDriverWithOldServerCompatibilityTest.java | 91 ++++++++++++++++++++++
 .../ignite/internal/jdbc/JdbcConnection.java       | 22 ++++++
 3 files changed, 114 insertions(+)

diff --git a/modules/compatibility-tests/build.gradle 
b/modules/compatibility-tests/build.gradle
index 88890796433..0dde4d408c4 100644
--- a/modules/compatibility-tests/build.gradle
+++ b/modules/compatibility-tests/build.gradle
@@ -37,6 +37,7 @@ dependencies {
     integrationTestImplementation project(':ignite-api')
     integrationTestImplementation project(':ignite-client')
     integrationTestImplementation project(':ignite-runner')
+    integrationTestImplementation project(':ignite-jdbc')
 
     testFixturesImplementation libs.gradle.tooling.api
     testFixturesImplementation libs.awaitility
diff --git 
a/modules/compatibility-tests/src/integrationTest/java/org/apache/ignite/internal/client/CurrentJdbcDriverWithOldServerCompatibilityTest.java
 
b/modules/compatibility-tests/src/integrationTest/java/org/apache/ignite/internal/client/CurrentJdbcDriverWithOldServerCompatibilityTest.java
new file mode 100644
index 00000000000..8451867e68c
--- /dev/null
+++ 
b/modules/compatibility-tests/src/integrationTest/java/org/apache/ignite/internal/client/CurrentJdbcDriverWithOldServerCompatibilityTest.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.client;
+
+import static 
org.apache.ignite.internal.testframework.IgniteTestUtils.assertThrows;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.instanceOf;
+
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.List;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.client.IgniteClient;
+import org.apache.ignite.internal.CompatibilityTestBase;
+import org.jetbrains.annotations.Nullable;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedClass;
+import org.junit.jupiter.params.provider.MethodSource;
+
+/**
+ * Tests that current Java client can work with all older server versions.
+ */
+@ParameterizedClass
+@MethodSource("serverVersions")
+public class CurrentJdbcDriverWithOldServerCompatibilityTest extends 
CompatibilityTestBase { // implements ClientCompatibilityTests
+    private @Nullable IgniteClient client;
+
+    @Override
+    protected void setupBaseVersion(Ignite baseIgnite) {
+        // No-op.
+    }
+
+    @Override
+    protected int nodesCount() {
+        return 1;
+    }
+
+    @Override
+    protected boolean restartWithCurrentEmbeddedVersion() {
+        // Keep old servers running.
+        return false;
+    }
+
+    @BeforeEach
+    public void createClient() {
+        client = cluster.createClient();
+    }
+
+    @AfterEach
+    public void closeClient() {
+        if (client != null) {
+            client.close();
+            client = null;
+        }
+    }
+
+    private static List<String> serverVersions() {
+        return List.of("3.0.0");
+    }
+
+    @Test
+    void jdbcConnectionToTheOldServerIsRejected() {
+        Throwable ex = assertThrows(SQLException.class,
+                () -> 
DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1:10800"),
+                "Failed to connect to server"
+        );
+
+        Throwable cause = ex.getCause();
+
+        assertThat(cause, instanceOf(IllegalStateException.class));
+        assertThat(cause.getMessage(), containsString("No servers supporting 
new JDBC found"));
+    }
+}
diff --git 
a/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcConnection.java
 
b/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcConnection.java
index f73ec73c812..9c780c62cf9 100644
--- 
a/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcConnection.java
+++ 
b/modules/jdbc/src/main/java/org/apache/ignite/internal/jdbc/JdbcConnection.java
@@ -58,9 +58,11 @@ import org.apache.ignite.client.BasicAuthenticator;
 import org.apache.ignite.client.IgniteClientAuthenticator;
 import org.apache.ignite.client.IgniteClientConfiguration;
 import org.apache.ignite.client.SslConfiguration;
+import org.apache.ignite.internal.client.ClientChannel;
 import org.apache.ignite.internal.client.HostAndPort;
 import org.apache.ignite.internal.client.IgniteClientConfigurationImpl;
 import org.apache.ignite.internal.client.TcpIgniteClient;
+import org.apache.ignite.internal.client.proto.ProtocolBitmaskFeature;
 import org.apache.ignite.internal.hlc.HybridTimestampTracker;
 import org.apache.ignite.internal.jdbc.proto.IgniteQueryErrorCode;
 import org.apache.ignite.internal.jdbc.proto.JdbcQueryEventHandler;
@@ -143,6 +145,26 @@ public class JdbcConnection implements Connection {
 
         try {
             client = buildClient(addrs, observableTimeTracker);
+
+            int supportedChannels = 0;
+
+            for (ClientChannel ch : client.channel().channels()) {
+                if 
(!ch.protocolContext().isFeatureSupported(ProtocolBitmaskFeature.SQL_MULTISTATEMENT_SUPPORT))
 {
+                    // TODO Check how to handle properly if some channels were 
closed
+                    // TODO heterogeneous cluster test?
+                    ch.close();
+
+                    continue;
+                }
+
+                ++supportedChannels;
+            }
+
+            if (supportedChannels == 0) {
+                client.channel().close();
+
+                throw new IllegalStateException("No servers supporting new 
JDBC found");
+            }
         } catch (Exception e) {
             throw new SQLException("Failed to connect to server", 
CLIENT_CONNECTION_FAILED, e);
         }

Reply via email to