diff --git a/paimon-presto-0.236/src/test/java/org/apache/paimon/presto/TestPrestoITCase.java b/paimon-presto-0.236/src/test/java/org/apache/paimon/presto/TestPrestoITCase.java index d57d9db..edbe701 100644 --- a/paimon-presto-0.236/src/test/java/org/apache/paimon/presto/TestPrestoITCase.java +++ b/paimon-presto-0.236/src/test/java/org/apache/paimon/presto/TestPrestoITCase.java @@ -229,6 +229,33 @@ public void testFilterWithTimeTravel() throws Exception { .isEqualTo("[[1, 1], [3, 2]]"); } + @Test + public void testFilterWithTimeTravelAndTableOptions() throws Exception { + // Time travel table t2 to first commit. + assertThat( + sql( + "SELECT a, aCa FROM paimon.default.t2 WHERE a < 7", + PrestoSessionProperties.SCAN_VERSION, + "default.t2.1")) + .isEqualTo("[[1, 1], [3, 2]]"); + + // Invalid time travel table options + assertThat( + sql( + "SELECT a, aCa FROM paimon.default.t2 WHERE a < 7", + PrestoSessionProperties.SCAN_VERSION, + "default.t1.1")) + .isEqualTo("[[1, 1], [3, 2], [5, 3]]"); + + // Time travel table t2 to first commit by table options + assertThat( + sql( + "SELECT a, aCa FROM paimon.default.t2 WHERE a < 7", + PrestoSessionProperties.SCAN_VERSION, + "default.t1.1|default.t2.1")) + .isEqualTo("[[1, 1], [3, 2]]"); + } + @Test public void testGroupByWithCast() throws Exception { assertThat( diff --git a/paimon-presto-common/src/main/java/org/apache/paimon/presto/PrestoMetadata.java b/paimon-presto-common/src/main/java/org/apache/paimon/presto/PrestoMetadata.java index b1a3aeb..14d9ca9 100644 --- a/paimon-presto-common/src/main/java/org/apache/paimon/presto/PrestoMetadata.java +++ b/paimon-presto-common/src/main/java/org/apache/paimon/presto/PrestoMetadata.java @@ -140,13 +140,19 @@ public PrestoTableHandle getTableHandle(SchemaTableName tableName, String scanVe try { Table table = catalog.getTable(tablePath); if (!StringUtils.isBlank(scanVersion)) { + String tableScanVersion = + PrestoPropertyUtils.getScanVersion(scanVersion, tablePath); table = - table.copy( - new HashMap() { - { - put(CoreOptions.SCAN_VERSION.key(), scanVersion); - } - }); + StringUtils.isBlank(tableScanVersion) + ? table + : table.copy( + new HashMap() { + { + put( + CoreOptions.SCAN_VERSION.key(), + tableScanVersion); + } + }); } serializedTable = InstantiationUtil.serializeObject(table); } catch (Catalog.TableNotExistException e) { diff --git a/paimon-presto-common/src/main/java/org/apache/paimon/presto/PrestoPropertyUtils.java b/paimon-presto-common/src/main/java/org/apache/paimon/presto/PrestoPropertyUtils.java new file mode 100644 index 0000000..8b04228 --- /dev/null +++ b/paimon-presto-common/src/main/java/org/apache/paimon/presto/PrestoPropertyUtils.java @@ -0,0 +1,66 @@ +/* + * 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.presto; + +import org.apache.paimon.catalog.Identifier; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** Utils for PrestoProperties. */ +public class PrestoPropertyUtils { + + private static final String TABLE_SCAN_OPTIONS_TEMPLATE = "(%s|\\*)\\.(%s|\\*)\\.(.+)"; + private static final String TABLE_SCAN_OPTIONS_SPLITTER = "\\|"; + + /** + * The scan version can be passed using two kind of formats: 1, global option format + * ${scanVersion}; 2, table option format + * "${dbName}.${tableName}.${scanVersion1}|${dbName}.${tableName}.${scanVersion2}", The + * dbName/tableName can be *, which means matching all the specific parts. + */ + public static String getScanVersion(String scanVersion, Identifier identifier) { + if (isGlobalScanOption(scanVersion)) { + // return scan version directly for global option format + return scanVersion.trim(); + } + + String[] tableScanOptions = scanVersion.trim().split(TABLE_SCAN_OPTIONS_SPLITTER); + String tableScanVersion = ""; + + for (String tableScanOption : tableScanOptions) { + String tableOptionsTemplate = + String.format( + TABLE_SCAN_OPTIONS_TEMPLATE, + identifier.getDatabaseName(), + identifier.getObjectName()); + Pattern tableOptionsPattern = Pattern.compile(tableOptionsTemplate); + Matcher matcher = tableOptionsPattern.matcher(tableScanOption.trim()); + if (matcher.find()) { + return matcher.group(3).trim(); + } + } + + return tableScanVersion; + } + + public static boolean isGlobalScanOption(String scanVersion) { + return !scanVersion.contains("."); + } +} diff --git a/paimon-presto-common/src/test/java/org/apache/paimon/presto/PrestoPropertyUtilsTest.java b/paimon-presto-common/src/test/java/org/apache/paimon/presto/PrestoPropertyUtilsTest.java new file mode 100644 index 0000000..ad6cc90 --- /dev/null +++ b/paimon-presto-common/src/test/java/org/apache/paimon/presto/PrestoPropertyUtilsTest.java @@ -0,0 +1,58 @@ +/* + * 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.presto; + +import org.apache.paimon.catalog.Identifier; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** Test for {@link PrestoPlugin}. */ +public class PrestoPropertyUtilsTest { + + @Test + public void testScanVersion() { + Identifier t1 = new Identifier("db", "t1"); + String scanVersion1 = "version1"; + String scanVersion2 = "*.*.version2"; + String scanVersion3 = "*.t1.version3"; + String scanVersion4 = "db.t1.version4"; + String scanVersion5 = "db.t2.version5"; + String scanVersion6 = "db.t2.version5|db.t1.version6"; + + assertThat(PrestoPropertyUtils.getScanVersion(scanVersion1, t1)).isEqualTo("version1"); + assertThat(PrestoPropertyUtils.getScanVersion(scanVersion2, t1)).isEqualTo("version2"); + assertThat(PrestoPropertyUtils.getScanVersion(scanVersion3, t1)).isEqualTo("version3"); + assertThat(PrestoPropertyUtils.getScanVersion(scanVersion4, t1)).isEqualTo("version4"); + assertThat(PrestoPropertyUtils.getScanVersion(scanVersion5, t1)).isEmpty(); + assertThat(PrestoPropertyUtils.getScanVersion(scanVersion6, t1)).isEqualTo("version6"); + } + + @Test + public void testGlobalScanOption() { + String scanVersion1 = "version1"; + String scanVersion2 = "*.*.version2"; + String scanVersion3 = "*.*.version2|db.tb.version3"; + + assertThat(PrestoPropertyUtils.isGlobalScanOption(scanVersion1)).isTrue(); + assertThat(PrestoPropertyUtils.isGlobalScanOption(scanVersion2)).isFalse(); + assertThat(PrestoPropertyUtils.isGlobalScanOption(scanVersion3)).isFalse(); + } +} diff --git a/paimon-presto-common/src/test/java/org/apache/paimon/presto/TestPrestoITCase.java b/paimon-presto-common/src/test/java/org/apache/paimon/presto/TestPrestoITCase.java index 8643fc3..e2e8fab 100644 --- a/paimon-presto-common/src/test/java/org/apache/paimon/presto/TestPrestoITCase.java +++ b/paimon-presto-common/src/test/java/org/apache/paimon/presto/TestPrestoITCase.java @@ -370,6 +370,33 @@ public void testFilterWithTimeTravel() throws Exception { .isEqualTo("[[1, 1], [3, 2]]"); } + @Test + public void testFilterWithTimeTravelAndTableOptions() throws Exception { + // Time travel table t2 to first commit. + assertThat( + sql( + "SELECT a, aCa FROM paimon.default.t2 WHERE a < 7", + PrestoSessionProperties.SCAN_VERSION, + "default.t2.1")) + .isEqualTo("[[1, 1], [3, 2]]"); + + // Invalid time travel table options + assertThat( + sql( + "SELECT a, aCa FROM paimon.default.t2 WHERE a < 7", + PrestoSessionProperties.SCAN_VERSION, + "default.t1.1")) + .isEqualTo("[[1, 1], [3, 2], [5, 3]]"); + + // Time travel table t2 to first commit by table options + assertThat( + sql( + "SELECT a, aCa FROM paimon.default.t2 WHERE a < 7", + PrestoSessionProperties.SCAN_VERSION, + "default.t1.1|default.t2.1")) + .isEqualTo("[[1, 1], [3, 2]]"); + } + @Test public void testGroupByWithCast() throws Exception { assertThat(