This is an automated email from the ASF dual-hosted git repository. czy006 pushed a commit to branch 0.9.x in repository https://gitbox.apache.org/repos/asf/amoro.git
commit ddd03edb7007fc69657fc8fd04900f3582520f9e Author: Aakash <[email protected]> AuthorDate: Sun Sep 20 12:57:21 2026 +0530 [AMORO-4379][Iceberg] Fix OS-dependent File.separator in table URI path resolution (#4380) --- .../iceberg/maintainer/IcebergTableMaintainer.java | 9 ++++++--- .../main/java/org/apache/amoro/utils/TableFileUtil.java | 5 +++-- .../test/java/org/apache/amoro/utils/TestFileUtil.java | 15 +++++++++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/amoro-format-iceberg/src/main/java/org/apache/amoro/formats/iceberg/maintainer/IcebergTableMaintainer.java b/amoro-format-iceberg/src/main/java/org/apache/amoro/formats/iceberg/maintainer/IcebergTableMaintainer.java index 5333856ce..6ae9e3068 100644 --- a/amoro-format-iceberg/src/main/java/org/apache/amoro/formats/iceberg/maintainer/IcebergTableMaintainer.java +++ b/amoro-format-iceberg/src/main/java/org/apache/amoro/formats/iceberg/maintainer/IcebergTableMaintainer.java @@ -73,12 +73,12 @@ import org.apache.iceberg.types.Conversions; import org.apache.iceberg.types.Type; import org.apache.iceberg.types.Types; import org.apache.iceberg.util.DateTimeUtil; +import org.apache.iceberg.util.LocationUtil; import org.apache.iceberg.util.SerializableFunction; import org.apache.iceberg.util.SnapshotUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; import java.time.Instant; @@ -442,7 +442,8 @@ public class IcebergTableMaintainer implements TableMaintainer { private int clearInternalTableContentsFiles( long lastTime, Set<String> exclude, MaintainerMetrics metrics) { - String dataLocation = table.location() + File.separator + DATA_FOLDER_NAME; + String dataLocation = + String.format("%s/%s", LocationUtil.stripTrailingSlash(table.location()), DATA_FOLDER_NAME); int expected = 0, deleted = 0; AuthenticatedFileIO io = fileIO(); @@ -492,7 +493,9 @@ public class IcebergTableMaintainer implements TableMaintainer { "Exclude metadata files with name pattern {} for table {}", excludeFileNameRegex, table.name()); - String metadataLocation = table.location() + File.separator + METADATA_FOLDER_NAME; + String metadataLocation = + String.format( + "%s/%s", LocationUtil.stripTrailingSlash(table.location()), METADATA_FOLDER_NAME); LOG.info("start orphan files clean in {}", metadataLocation); AuthenticatedFileIO io = fileIO(); diff --git a/amoro-format-iceberg/src/main/java/org/apache/amoro/utils/TableFileUtil.java b/amoro-format-iceberg/src/main/java/org/apache/amoro/utils/TableFileUtil.java index 5ec207467..ae102d757 100644 --- a/amoro-format-iceberg/src/main/java/org/apache/amoro/utils/TableFileUtil.java +++ b/amoro-format-iceberg/src/main/java/org/apache/amoro/utils/TableFileUtil.java @@ -22,11 +22,11 @@ import org.apache.amoro.io.AuthenticatedFileIO; import org.apache.hadoop.fs.Path; import org.apache.iceberg.FileFormat; import org.apache.iceberg.io.BulkDeletionFailureException; +import org.apache.iceberg.util.LocationUtil; import org.apache.iceberg.util.Tasks; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; import java.net.URI; import java.util.HashSet; import java.util.Set; @@ -211,7 +211,8 @@ public class TableFileUtil { * @return new file path */ public static String getNewFilePath(String newDirectory, String filePath) { - return newDirectory + File.separator + getFileName(filePath); + return String.format( + "%s/%s", LocationUtil.stripTrailingSlash(newDirectory), getFileName(filePath)); } /** diff --git a/amoro-format-iceberg/src/test/java/org/apache/amoro/utils/TestFileUtil.java b/amoro-format-iceberg/src/test/java/org/apache/amoro/utils/TestFileUtil.java index a466e6612..73afdcb63 100644 --- a/amoro-format-iceberg/src/test/java/org/apache/amoro/utils/TestFileUtil.java +++ b/amoro-format-iceberg/src/test/java/org/apache/amoro/utils/TestFileUtil.java @@ -80,6 +80,21 @@ public class TestFileUtil { Assert.assertEquals(expected, TableFileUtil.getUriPath(path)); } + @ParameterizedTest + @CsvSource( + value = { + "s3://bucket/warehouse/db/tbl/00000-0.parquet, s3://bucket/warehouse/db/tbl, 00000-0.parquet", + "s3://bucket/warehouse/db/tbl/00000-0.parquet, s3://bucket/warehouse/db/tbl/, 00000-0.parquet", + "hdfs://nn:8020/warehouse/db/tbl/data-1.orc, hdfs://nn:8020/warehouse/db/tbl, file:/tmp/data-1.orc", + "hdfs://nn:8020/warehouse/db/tbl/data-1.orc, hdfs://nn:8020/warehouse/db/tbl/, file:/tmp/data-1.orc" + }) + public void testGetNewFilePath(String expected, String newDirectory, String filePath) { + String newFilePath = TableFileUtil.getNewFilePath(newDirectory, filePath); + Assert.assertEquals(expected, newFilePath); + Assert.assertNotNull(TableFileUtil.getUriPath(newFilePath)); + Assert.assertFalse(newFilePath.contains("\\")); + } + private static final TemporaryFolder temp = new TemporaryFolder(); static class LocalAuthenticatedFileIO
