From b4ecb87499bb8289e1bb2800011cb9fb63e2c0c4 Mon Sep 17 00:00:00 2001 From: James Faulkner Date: Thu, 25 Jun 2026 18:35:13 +0100 Subject: [PATCH] fix: use equalsIgnoreCase in isTableRename to match HMS behaviour MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HMS (HiveAlterHandler) uses equalsIgnoreCase when detecting renames, so a case-only name change (e.g. my_table → My_Table) is never treated as a rename in the metastore. GlueSync was using equals(), causing it to incorrectly enter doRenameOperation, which then failed with AlreadyExistsException because Glue is also case-insensitive and the lowercase table already existed. Co-Authored-By: Claude Sonnet 4.6 --- .../gluesync/listener/ApiaryGlueSync.java | 2 +- .../gluesync/listener/ApiaryGlueSyncTest.java | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/hive-event-listeners/apiary-gluesync-listener/src/main/java/com/expediagroup/apiary/extensions/gluesync/listener/ApiaryGlueSync.java b/hive-event-listeners/apiary-gluesync-listener/src/main/java/com/expediagroup/apiary/extensions/gluesync/listener/ApiaryGlueSync.java index 23d99a55..cd758fb2 100644 --- a/hive-event-listeners/apiary-gluesync-listener/src/main/java/com/expediagroup/apiary/extensions/gluesync/listener/ApiaryGlueSync.java +++ b/hive-event-listeners/apiary-gluesync-listener/src/main/java/com/expediagroup/apiary/extensions/gluesync/listener/ApiaryGlueSync.java @@ -302,7 +302,7 @@ private void doRenameOperation(Table oldTable, Table newTable) { } private boolean isTableRename(Table oldTable, Table newTable) { - return !oldTable.getTableName().equals(newTable.getTableName()); + return !oldTable.getTableName().equalsIgnoreCase(newTable.getTableName()); } @Override diff --git a/hive-event-listeners/apiary-gluesync-listener/src/test/java/com/expediagroup/apiary/extensions/gluesync/listener/ApiaryGlueSyncTest.java b/hive-event-listeners/apiary-gluesync-listener/src/test/java/com/expediagroup/apiary/extensions/gluesync/listener/ApiaryGlueSyncTest.java index 347ac736..7abd7b03 100644 --- a/hive-event-listeners/apiary-gluesync-listener/src/test/java/com/expediagroup/apiary/extensions/gluesync/listener/ApiaryGlueSyncTest.java +++ b/hive-event-listeners/apiary-gluesync-listener/src/test/java/com/expediagroup/apiary/extensions/gluesync/listener/ApiaryGlueSyncTest.java @@ -25,6 +25,7 @@ import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -499,6 +500,29 @@ public void onAlterHiveTable_RenameTable() throws MetaException { assertThat(toList(createTableRequest.getTableInput().getStorageDescriptor().getColumns()), is(asList(colNames))); } + @Test + public void onAlterHiveTable_CaseOnlyRenameSkipsRenameOperation() throws MetaException { + AlterTableEvent event = mock(AlterTableEvent.class); + when(event.getStatus()).thenReturn(true); + + Table oldTable = simpleHiveTable(simpleSchema(), simplePartitioning()); + oldTable.setTableName("some_table"); + when(event.getOldTable()).thenReturn(oldTable); + + Table newTable = simpleHiveTable(simpleSchema(), simplePartitioning()); + newTable.setTableName("Some_Table"); + when(event.getNewTable()).thenReturn(newTable); + + glueSync.onAlterTable(event); + + // case-only difference must not trigger the rename path (create + copy + delete) + verify(glueClient, never()).createTable(any()); + verify(glueClient, never()).deleteTable(any()); + verify(glueClient, never()).batchCreatePartition(any()); + // normal update path must be followed instead + verify(glueClient).updateTable(any()); + } + @Test public void onCreateUnpartitionedHiveTable() throws MetaException { CreateTableEvent event = mock(CreateTableEvent.class);