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); }
