This is an automated email from the ASF dual-hosted git repository.

mchades pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new dda2c21623 [#11538] fix(catalog-glue): Support RENAME TABLE for 
Iceberg tables (#11555)
dda2c21623 is described below

commit dda2c216239e84420e68601e966588800709fbca
Author: Yuhui <[email protected]>
AuthorDate: Wed Jun 10 18:38:16 2026 +0800

    [#11538] fix(catalog-glue): Support RENAME TABLE for Iceberg tables (#11555)
    
    ### What changes were proposed in this pull request?
    
    Handle \`TableChange.RenameTable\` in
    \`GlueIcebergTableHelper.alterTable\` by
    calling \`icebergCatalog.renameTable\`. The underlying Iceberg
    \`GlueCatalog\`
    supports rename natively but was never wired up.
    
    ### Why are the changes needed?
    
    Fix: #11538
    
    \`ALTER TABLE ... RENAME TO\` on Iceberg tables in the Glue catalog
    always threw
    \`IllegalArgumentException\`.
    
    ### Does this PR introduce _any_ user-facing change?
    
    Yes — \`ALTER TABLE ... RENAME TO\` now works for Iceberg tables in the
    Glue catalog.
    
    ### How was this patch tested?
    
    - Unit:
    \`TestGlueCatalogOperationsForIceberg#testAlterTable_icebergRename\`
    - Spark AWS IT: \`SparkAwsGlueCatalogIT35#testRenameIcebergTable\` (real
    AWS Glue, end-to-end)
---
 .../catalog/glue/GlueCatalogOperations.java        | 15 ++++++++++--
 .../catalog/glue/GlueIcebergTableHelper.java       | 24 ++++++++++++++++---
 .../glue/TestGlueCatalogOperationsForIceberg.java  | 27 ++++++++++++++++++----
 .../integration/test/glue/SparkGlueCatalogIT.java  | 23 ++++++++++++++++++
 4 files changed, 79 insertions(+), 10 deletions(-)

diff --git 
a/catalogs/catalog-glue/src/main/java/org/apache/gravitino/catalog/glue/GlueCatalogOperations.java
 
b/catalogs/catalog-glue/src/main/java/org/apache/gravitino/catalog/glue/GlueCatalogOperations.java
index 66534c172e..0e8fa2dc12 100644
--- 
a/catalogs/catalog-glue/src/main/java/org/apache/gravitino/catalog/glue/GlueCatalogOperations.java
+++ 
b/catalogs/catalog-glue/src/main/java/org/apache/gravitino/catalog/glue/GlueCatalogOperations.java
@@ -67,6 +67,7 @@ import 
org.apache.gravitino.rel.expressions.transforms.Transforms;
 import org.apache.gravitino.rel.indexes.Index;
 import org.apache.gravitino.rel.types.Type;
 import org.apache.gravitino.utils.PrincipalUtils;
+import org.apache.iceberg.catalog.TableIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import software.amazon.awssdk.services.glue.GlueClient;
@@ -595,8 +596,18 @@ public class GlueCatalogOperations implements 
CatalogOperations, SupportsSchemas
     if (hasMetadataLocation && !isSdkManaged) {
       return alterRegisterModeIcebergTable(ident, dbName, rawGlueTable, 
changes);
     }
-    GlueIcebergTableHelper.alterTable(icebergGlueCatalog, dbName, 
ident.name(), changes);
-    return loadTable(ident);
+    TableIdentifier finalId =
+        GlueIcebergTableHelper.alterTable(icebergGlueCatalog, dbName, 
ident.name(), changes);
+    String newDbName = finalId.namespace().level(0);
+    NameIdentifier finalIdent;
+    if (newDbName.equals(dbName) && finalId.name().equals(ident.name())) {
+      finalIdent = ident;
+    } else {
+      String[] levels = ident.namespace().levels().clone();
+      levels[levels.length - 1] = newDbName;
+      finalIdent = NameIdentifier.of(Namespace.of(levels), finalId.name());
+    }
+    return loadTable(finalIdent);
   }
 
   private GlueTable alterRegisterModeIcebergTable(
diff --git 
a/catalogs/catalog-glue/src/main/java/org/apache/gravitino/catalog/glue/GlueIcebergTableHelper.java
 
b/catalogs/catalog-glue/src/main/java/org/apache/gravitino/catalog/glue/GlueIcebergTableHelper.java
index c69d23c992..d8bb3f6b05 100644
--- 
a/catalogs/catalog-glue/src/main/java/org/apache/gravitino/catalog/glue/GlueIcebergTableHelper.java
+++ 
b/catalogs/catalog-glue/src/main/java/org/apache/gravitino/catalog/glue/GlueIcebergTableHelper.java
@@ -380,8 +380,9 @@ final class GlueIcebergTableHelper {
   /**
    * Alters an Iceberg table via the Iceberg SDK.
    *
-   * <p>Delegates schema changes to {@link UpdateSchema} and property changes 
to {@link
-   * UpdateProperties}.
+   * <p>Supports {@link TableChange.RenameTable}, {@link 
TableChange.ColumnChange}, {@link
+   * TableChange.SetProperty}, and {@link TableChange.RemoveProperty}. A 
rename is an exclusive
+   * operation and cannot be combined with other changes.
    *
    * <p><b>Note:</b> Schema changes and property changes are committed in two 
separate transactions.
    * If the schema commit succeeds but the property commit fails, the table is 
left in a partially
@@ -391,9 +392,25 @@ final class GlueIcebergTableHelper {
    * @param dbName the Glue database name
    * @param tableName the table name
    * @param changes the table changes to apply
+   * @return the final {@link TableIdentifier} (differs from the input only 
when a rename is
+   *     applied, including cross-schema renames)
    */
-  static void alterTable(
+  static TableIdentifier alterTable(
       Catalog icebergCatalog, String dbName, String tableName, TableChange... 
changes) {
+    for (TableChange change : changes) {
+      if (change instanceof TableChange.RenameTable) {
+        Preconditions.checkArgument(
+            changes.length == 1, "RenameTable cannot be combined with other 
table changes");
+        TableChange.RenameTable rename = (TableChange.RenameTable) change;
+        String newDbName = rename.getNewSchemaName().orElse(dbName);
+        String newName = rename.getNewName();
+        TableIdentifier to = TableIdentifier.of(newDbName, newName);
+        icebergCatalog.renameTable(TableIdentifier.of(dbName, tableName), to);
+        LOG.info("Renamed Iceberg table {}.{} to {}.{}", dbName, tableName, 
newDbName, newName);
+        return to;
+      }
+    }
+
     Table table = icebergCatalog.loadTable(TableIdentifier.of(dbName, 
tableName));
 
     boolean hasSchemaChange = false;
@@ -484,6 +501,7 @@ final class GlueIcebergTableHelper {
       update.commit();
       LOG.info("Altered Iceberg table {}.{} properties via Iceberg SDK", 
dbName, tableName);
     }
+    return TableIdentifier.of(dbName, tableName);
   }
 
   // 
---------------------------------------------------------------------------
diff --git 
a/catalogs/catalog-glue/src/test/java/org/apache/gravitino/catalog/glue/TestGlueCatalogOperationsForIceberg.java
 
b/catalogs/catalog-glue/src/test/java/org/apache/gravitino/catalog/glue/TestGlueCatalogOperationsForIceberg.java
index cfb5569ccc..8970b74a4a 100644
--- 
a/catalogs/catalog-glue/src/test/java/org/apache/gravitino/catalog/glue/TestGlueCatalogOperationsForIceberg.java
+++ 
b/catalogs/catalog-glue/src/test/java/org/apache/gravitino/catalog/glue/TestGlueCatalogOperationsForIceberg.java
@@ -236,21 +236,38 @@ class TestGlueCatalogOperationsForIceberg {
   }
 
   @Test
-  void testAlterTable_icebergRenameThrows() {
+  void testAlterIcebergTableRename() {
+    String newName = "ice1_renamed";
     software.amazon.awssdk.services.glue.model.Table rawTable =
         software.amazon.awssdk.services.glue.model.Table.builder()
             .name(TABLE)
             .parameters(Map.of(TABLE_TYPE_PARAM, ICEBERG_TABLE_TYPE_VALUE))
             .storageDescriptor(StorageDescriptor.builder().build())
             .build();
+    software.amazon.awssdk.services.glue.model.Table renamedTable =
+        software.amazon.awssdk.services.glue.model.Table.builder()
+            .name(newName)
+            .parameters(Map.of(TABLE_TYPE_PARAM, ICEBERG_TABLE_TYPE_VALUE))
+            .storageDescriptor(StorageDescriptor.builder().build())
+            .build();
 
     when(mockClient.getTable(any(GetTableRequest.class)))
-        .thenReturn(GetTableResponse.builder().table(rawTable).build());
+        .thenReturn(GetTableResponse.builder().table(rawTable).build())
+        .thenReturn(GetTableResponse.builder().table(renamedTable).build());
+    when(mockIcebergCatalog.loadTable(TableIdentifier.of(DB, newName)))
+        .thenThrow(new RuntimeException("no iceberg metadata"));
+    when(mockClient.getPartitions(any(GetPartitionsRequest.class)))
+        .thenReturn(GetPartitionsResponse.builder().build());
 
     NameIdentifier ident = NameIdentifier.of("cat", "ns", DB, TABLE);
-    assertThrows(
-        IllegalArgumentException.class,
-        () -> ops.alterTable(ident, TableChange.rename("new_table_name")));
+    GlueTable result = ops.alterTable(ident, TableChange.rename(newName));
+
+    ArgumentCaptor<TableIdentifier> fromCaptor = 
ArgumentCaptor.forClass(TableIdentifier.class);
+    ArgumentCaptor<TableIdentifier> toCaptor = 
ArgumentCaptor.forClass(TableIdentifier.class);
+    verify(mockIcebergCatalog).renameTable(fromCaptor.capture(), 
toCaptor.capture());
+    assertEquals(TableIdentifier.of(DB, TABLE), fromCaptor.getValue());
+    assertEquals(TableIdentifier.of(DB, newName), toCaptor.getValue());
+    assertEquals(newName, result.name());
   }
 
   @Test
diff --git 
a/spark-connector/spark-common/src/test/java/org/apache/gravitino/spark/connector/integration/test/glue/SparkGlueCatalogIT.java
 
b/spark-connector/spark-common/src/test/java/org/apache/gravitino/spark/connector/integration/test/glue/SparkGlueCatalogIT.java
index 79b9ca4b33..db79faf217 100644
--- 
a/spark-connector/spark-common/src/test/java/org/apache/gravitino/spark/connector/integration/test/glue/SparkGlueCatalogIT.java
+++ 
b/spark-connector/spark-common/src/test/java/org/apache/gravitino/spark/connector/integration/test/glue/SparkGlueCatalogIT.java
@@ -390,6 +390,29 @@ public abstract class SparkGlueCatalogIT extends 
SparkGlueEnvIT {
     Assertions.assertEquals("1,name1,25", tableData.get(0));
   }
 
+  @Test
+  void testRenameIcebergTable() {
+    String oldName = "test_iceberg_rename_old";
+    String newName = "test_iceberg_rename_new";
+    dropTableIfExists(oldName);
+    dropTableIfExists(newName);
+
+    sql(getCreateSimpleTableString(oldName) + " USING iceberg");
+    sql(String.format("INSERT INTO %s VALUES (1, 'before_rename', 10)", 
oldName));
+
+    Assertions.assertTrue(tableExists(oldName));
+    Assertions.assertFalse(tableExists(newName));
+
+    sql(String.format("ALTER TABLE %s RENAME TO %s", oldName, newName));
+
+    Assertions.assertFalse(tableExists(oldName));
+    Assertions.assertTrue(tableExists(newName));
+
+    List<String> tableData = getTableData(newName);
+    Assertions.assertFalse(tableData.isEmpty());
+    Assertions.assertEquals("1,before_rename,10", tableData.get(0));
+  }
+
   @Test
   void testCreateTableWithComment() {
     String tableName = "test_table_with_comment";

Reply via email to