Skip to content

fix: use equalsIgnoreCase in isTableRename to match HMS behaviour #138

Merged
jamespfaulkner merged 1 commit into
mainfrom
fix/gluesync-case-insensitive-rename-detection
Jun 26, 2026
Merged

fix: use equalsIgnoreCase in isTableRename to match HMS behaviour #138
jamespfaulkner merged 1 commit into
mainfrom
fix/gluesync-case-insensitive-rename-detection

Conversation

@jamespfaulkner

Copy link
Copy Markdown
Contributor

Problem

ApiaryGlueSync.isTableRename() used String.equals() to compare old and new
table names. This caused a case-only name change (e.g.
foo_bar_bazFoo_Bar_Baz) to be
treated as a genuine rename, triggering doRenameOperation and an
AlreadyExistsException from Glue on every replay of the event.

Why this happens

When a client calls alter_table on HMS with a new Table object whose
tableName differs from the stored name only in case, HMS does not treat
it as a rename. HiveAlterHandler.alterTable() lowercases the old table name
parameter (lines 135–136) and then uses equalsIgnoreCase for the rename
check (lines 138–143):

// HiveAlterHandler.java (branch-2.3, lines 135–143)                                                                                                                              
name = name.toLowerCase();                                                                                                                                                        
dbname = dbname.toLowerCase();                                                                                                                                                    
                                                                                                                                                                                  
if (!newt.getTableName().equalsIgnoreCase(name)                                                                                                                                   
    || !newt.getDbName().equalsIgnoreCase(dbname)) {                                                                                                                              
  if (msdb.getTable(newt.getDbName(), newt.getTableName()) != null) {                                                                                                             
    throw new InvalidOperationException(...)                                                                                                                                      
  }                                                                                                                                                                               
  rename = true;                                                                                                                                                                  
}                                                                                                                                                                                 
         

HMS completes the alter_table as a metadata update without renaming. The
AlterTableEvent is then fired after alterHandler.alterTable() returns,
with the original newt object unchanged — so newt.getTableName() carries
the mixed-case name as provided by the caller.

ApiaryGlueSync received this event and compared names with equals(),
disagreeing with HMS's own equalsIgnoreCase check. It entered
doRenameOperation, called GlueTableService.create() with the mixed-case
name, and got AlreadyExistsException because Glue is also case-insensitive
and the lowercase table already existed.

Fix

Change isTableRename() to use equalsIgnoreCase(), aligning it with HMS's
own rename-detection logic. A case-only difference is now treated as a regular
metadata update (falls through to updateTable) rather than a rename.

This is a defensive fix in GlueSync. The root cause — egdl-hive-agent
constructing Table objects with mixed-case names derived from Avro record
names — should be addressed separately in that repo.

Test plan

  • New test onAlterHiveTable_CaseOnlyRenameSkipsRenameOperation verifies
    that create, batchCreatePartition, and deleteTable are never called
    when old and new table names differ only by case, and that updateTable
    is called instead.
  • Existing rename tests (onAlterHiveTable_RenameTable,
    onAlterHiveTable_RenameOperationFailureIsMetered,
    onAlterIcebergTable_RenameTableSkipsRenameOperation) all continue to pass.
  • mvn -pl hive-event-listeners/apiary-gluesync-listener -am test — 110 tests, 0 failures.

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 <noreply@anthropic.com>
@jamespfaulkner jamespfaulkner marked this pull request as ready for review June 26, 2026 08:26
@jamespfaulkner jamespfaulkner requested a review from a team as a code owner June 26, 2026 08:26
@jamespfaulkner jamespfaulkner merged commit e461e3d into main Jun 26, 2026
1 check passed
@jamespfaulkner jamespfaulkner deleted the fix/gluesync-case-insensitive-rename-detection branch June 26, 2026 09:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants