diff --git a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/Versions.java b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/Versions.java index d30cca3c8cb3..fc9439eec8d2 100644 --- a/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/Versions.java +++ b/lib/trino-plugin-toolkit/src/main/java/io/trino/plugin/base/Versions.java @@ -13,9 +13,13 @@ */ package io.trino.plugin.base; +import com.google.common.annotations.VisibleForTesting; import io.trino.spi.connector.ConnectorContext; import io.trino.spi.connector.ConnectorFactory; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import static com.google.common.base.Preconditions.checkState; import static java.lang.String.format; @@ -25,6 +29,7 @@ private Versions() {} /** * Check if the SPI version of the Trino server matches exactly the SPI version the connector plugin was built for. + * We check only if the major versions matches. * Using plugins built for a different version of Trino may fail at runtime, especially if plugin author * chooses not to maintain compatibility with older SPI versions, as happens for plugins maintained together with * the Trino project. @@ -35,7 +40,25 @@ public static void checkSpiVersion(ConnectorContext context, ConnectorFactory co String compileTimeSpiVersion = SpiVersionHolder.SPI_COMPILE_TIME_VERSION; checkState( - spiVersion.equals(compileTimeSpiVersion), + checkMatch(spiVersion, compileTimeSpiVersion), format("Trino SPI version %s does not match the version %s connector %s was compiled for", spiVersion, compileTimeSpiVersion, connectorFactory.getName())); } + + @VisibleForTesting + static boolean checkMatch(String firstVersion, String secondVersion) + { + if (firstVersion.equals(secondVersion)) { + return true; + } + Pattern pattern = Pattern.compile("^(\\d+).*"); + Matcher firstMatcher = pattern.matcher(firstVersion); + if (!firstMatcher.matches()) { + return false; + } + Matcher secondMatcher = pattern.matcher(secondVersion); + if (!secondMatcher.matches()) { + return false; + } + return firstMatcher.group(1).equals(secondMatcher.group(1)); + } } diff --git a/lib/trino-plugin-toolkit/src/test/java/io/trino/plugin/base/TestVersions.java b/lib/trino-plugin-toolkit/src/test/java/io/trino/plugin/base/TestVersions.java new file mode 100644 index 000000000000..3245b56f2636 --- /dev/null +++ b/lib/trino-plugin-toolkit/src/test/java/io/trino/plugin/base/TestVersions.java @@ -0,0 +1,61 @@ +/* + * Licensed 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 io.trino.plugin.base; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +public class TestVersions +{ + @Test + public void testExactMatch() + { + assertTrue(Versions.checkMatch("420", "420")); + } + + @Test + public void testExactMatchWithSuffix() + { + assertTrue(Versions.checkMatch("420-SNAPSHOT", "420-SNAPSHOT")); + } + + @Test + public void testDifferentSuffix() + { + assertTrue(Versions.checkMatch("420-rc1", "420-SNAPSHOT")); + } + + @Test + public void testBaseVsSuffix() + { + assertTrue(Versions.checkMatch("420", "420-SNAPSHOT")); + assertTrue(Versions.checkMatch("420-SNAPSHOT", "420")); + } + + @Test + public void testFailDifferentBase() + { + assertFalse(Versions.checkMatch("420", "419")); + } + + @Test + public void testFailDifferentBaseWithSuffix() + { + assertFalse(Versions.checkMatch("420-SNAPSHOT", "421-SNAPSHOT")); + assertFalse(Versions.checkMatch("420", "421-SNAPSHOT")); + assertFalse(Versions.checkMatch("421-SNAPSHOT", "420")); + } +}