From 576a747cca8f40cd757f2b9f5b2b2c21e5c6be77 Mon Sep 17 00:00:00 2001 From: Eunbin Son Date: Thu, 6 Aug 2026 10:05:55 +0900 Subject: [PATCH] [flink] Fix Flink version detection for key-only deletes on non-release versions Flink builds from a release branch or master publish a two-component version plus a suffix (e.g. 2.1-SNAPSHOT, 2.2-SNAPSHOT), so splitting only on '.' left "2-SNAPSHOT" as the minor part. The NumberFormatException was swallowed and key-only deletes were silently disabled on runtimes that do have the FLIP-510 API. Split on both '.' and '-', and extract the parsing into a package-private isVersionAtLeast21(String) so it can be unit tested. Strings that resolve to Flink 2.0 or below still return false, keeping the NoSuchMethodError guard intact. Generated-by: Claude Code --- .../flink/utils/ChangelogModeUtils.java | 13 +++- .../flink/utils/ChangelogModeUtilsTest.java | 62 +++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 paimon-flink/paimon-flink2-common/src/test/java/org/apache/paimon/flink/utils/ChangelogModeUtilsTest.java diff --git a/paimon-flink/paimon-flink2-common/src/main/java/org/apache/paimon/flink/utils/ChangelogModeUtils.java b/paimon-flink/paimon-flink2-common/src/main/java/org/apache/paimon/flink/utils/ChangelogModeUtils.java index 7798c5b55180..123da6de32d9 100644 --- a/paimon-flink/paimon-flink2-common/src/main/java/org/apache/paimon/flink/utils/ChangelogModeUtils.java +++ b/paimon-flink/paimon-flink2-common/src/main/java/org/apache/paimon/flink/utils/ChangelogModeUtils.java @@ -40,9 +40,18 @@ public static ChangelogMode.Builder enableKeyOnlyDeletes(ChangelogMode.Builder b } private static boolean isFlink21OrAbove() { - String version = EnvironmentInformation.getVersion(); + return isVersionAtLeast21(EnvironmentInformation.getVersion()); + } + + /** + * Flink version strings are not always {@code major.minor.patch}: builds from a release branch + * or master are published as {@code 2.2-SNAPSHOT}. Split on both {@code .} and {@code -} so + * that the major/minor prefix is read in all of those shapes. + */ + // visible for testing + static boolean isVersionAtLeast21(String version) { try { - String[] parts = version.split("\\."); + String[] parts = version.split("[.-]"); int major = Integer.parseInt(parts[0]); int minor = Integer.parseInt(parts[1]); return major > 2 || (major == 2 && minor >= 1); diff --git a/paimon-flink/paimon-flink2-common/src/test/java/org/apache/paimon/flink/utils/ChangelogModeUtilsTest.java b/paimon-flink/paimon-flink2-common/src/test/java/org/apache/paimon/flink/utils/ChangelogModeUtilsTest.java new file mode 100644 index 000000000000..40dbf077a0a8 --- /dev/null +++ b/paimon-flink/paimon-flink2-common/src/test/java/org/apache/paimon/flink/utils/ChangelogModeUtilsTest.java @@ -0,0 +1,62 @@ +/* + * 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.paimon.flink.utils; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.assertThat; + +/** Tests for {@link ChangelogModeUtils}. */ +public class ChangelogModeUtilsTest { + + @ParameterizedTest + @ValueSource( + strings = { + "2.1.0", + "2.2.0", + "3.0.0", + "2.1.0-amzn-0", + "2.1-SNAPSHOT", + "2.2-SNAPSHOT", + "2.10-SNAPSHOT" + }) + void testVersionAtLeast21(String version) { + assertThat(ChangelogModeUtils.isVersionAtLeast21(version)).isTrue(); + } + + @ParameterizedTest + @ValueSource( + strings = { + "2.0.0", + "2.0-SNAPSHOT", + "2.0-vvr-11.2-SNAPSHOT", + "2.0-rc1", + "1.20.1", + "1.20-SNAPSHOT", + "1.20-vvr-11.2-SNAPSHOT", + "", + "", + "2", + "not-a-version" + }) + void testVersionBelow21(String version) { + assertThat(ChangelogModeUtils.isVersionAtLeast21(version)).isFalse(); + } +}