From 366408c09807cfa7ce2349bc90da7145e906b99c Mon Sep 17 00:00:00 2001 From: wangd Date: Wed, 1 Jan 2025 20:02:20 +0800 Subject: [PATCH] [Iceberg]Support renaming table on hive file catalog --- .../metastore/file/FileHiveMetastore.java | 44 ++++++++++++++++--- ...tIcebergHiveCatalogDistributedQueries.java | 6 --- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/file/FileHiveMetastore.java b/presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/file/FileHiveMetastore.java index 560bf7dd8f847..d1170d3eab4a1 100644 --- a/presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/file/FileHiveMetastore.java +++ b/presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/file/FileHiveMetastore.java @@ -63,6 +63,7 @@ import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FileStatus; import org.apache.hadoop.fs.FileSystem; +import org.apache.hadoop.fs.FileUtil; import org.apache.hadoop.fs.Path; import javax.annotation.concurrent.ThreadSafe; @@ -99,7 +100,6 @@ import static com.facebook.presto.hive.metastore.MetastoreUtil.getHiveBasicStatistics; import static com.facebook.presto.hive.metastore.MetastoreUtil.getPartitionNamesWithEmptyVersion; import static com.facebook.presto.hive.metastore.MetastoreUtil.isIcebergTable; -import static com.facebook.presto.hive.metastore.MetastoreUtil.isIcebergView; import static com.facebook.presto.hive.metastore.MetastoreUtil.makePartName; import static com.facebook.presto.hive.metastore.MetastoreUtil.toPartitionValues; import static com.facebook.presto.hive.metastore.MetastoreUtil.updateStatisticsParameters; @@ -514,18 +514,50 @@ public synchronized MetastoreOperationResult renameTable(MetastoreContext metast requireNonNull(newTableName, "newTableName is null"); Table table = getRequiredTable(metastoreContext, databaseName, tableName); getRequiredDatabase(metastoreContext, newDatabaseName); - if (isIcebergTable(table) && !isIcebergView(table)) { - throw new PrestoException(NOT_SUPPORTED, "Rename not supported for Iceberg tables"); - } // verify new table does not exist verifyTableNotExists(metastoreContext, newDatabaseName, newTableName); + Optional rollbackAction = Optional.empty(); + Path metadataDirectory = getTableMetadataDirectory(databaseName, tableName); + Path newMetadataDirectory = getTableMetadataDirectory(newDatabaseName, newTableName); try { - if (!metadataFileSystem.rename(getTableMetadataDirectory(databaseName, tableName), getTableMetadataDirectory(newDatabaseName, newTableName))) { - throw new PrestoException(HIVE_METASTORE_ERROR, "Could not rename table directory"); + if (!isIcebergTable(table)) { + if (!metadataFileSystem.rename(metadataDirectory, newMetadataDirectory)) { + throw new PrestoException(HIVE_METASTORE_ERROR, "Could not rename table directory"); + } + } + else { + // If the directory `.prestoPermissions` exists, copy it to the new table metadata directory + if (metadataFileSystem.exists(new Path(metadataDirectory, PRESTO_PERMISSIONS_DIRECTORY_NAME))) { + if (!FileUtil.copy(metadataFileSystem, new Path(metadataDirectory, PRESTO_PERMISSIONS_DIRECTORY_NAME), + metadataFileSystem, new Path(newMetadataDirectory, PRESTO_PERMISSIONS_DIRECTORY_NAME), false, metadataFileSystem.getConf())) { + throw new PrestoException(HIVE_METASTORE_ERROR, "Could not rename table directory"); + } + else { + rollbackAction = Optional.of(() -> { + try { + metadataFileSystem.delete(new Path(newMetadataDirectory, PRESTO_PERMISSIONS_DIRECTORY_NAME), true); + } + catch (IOException e) { + // ignore + } + }); + } + } + + // Rename file `.prestoSchema` to change it to the new metadata path + // This will atomically execute the table renaming behavior + if (!metadataFileSystem.rename(new Path(metadataDirectory, PRESTO_SCHEMA_FILE_NAME), new Path(newMetadataDirectory, PRESTO_SCHEMA_FILE_NAME))) { + throw new PrestoException(HIVE_METASTORE_ERROR, "Could not rename table directory"); + } + + // Subsequent action, delete the redundant directory `.prestoPermissions` from the original table metadata path + metadataFileSystem.delete(new Path(metadataDirectory, PRESTO_PERMISSIONS_DIRECTORY_NAME), true); } } catch (IOException e) { + // If table renaming fails and rollback action has already been recorded, perform the rollback action to clean up junk files + rollbackAction.ifPresent(Runnable::run); throw new PrestoException(HIVE_METASTORE_ERROR, e); } diff --git a/presto-iceberg/src/test/java/com/facebook/presto/iceberg/hive/TestIcebergHiveCatalogDistributedQueries.java b/presto-iceberg/src/test/java/com/facebook/presto/iceberg/hive/TestIcebergHiveCatalogDistributedQueries.java index 3330458287b5d..800ad69043182 100644 --- a/presto-iceberg/src/test/java/com/facebook/presto/iceberg/hive/TestIcebergHiveCatalogDistributedQueries.java +++ b/presto-iceberg/src/test/java/com/facebook/presto/iceberg/hive/TestIcebergHiveCatalogDistributedQueries.java @@ -28,10 +28,4 @@ public TestIcebergHiveCatalogDistributedQueries() { super(HIVE, ImmutableMap.of("iceberg.hive-statistics-merge-strategy", Joiner.on(",").join(NUMBER_OF_DISTINCT_VALUES.name(), TOTAL_SIZE_IN_BYTES.name()))); } - - @Override - public void testRenameTable() - { - // Rename table are not supported by hive catalog - } }