diff --git a/aws/src/main/java/org/apache/iceberg/aws/glue/GlueCatalog.java b/aws/src/main/java/org/apache/iceberg/aws/glue/GlueCatalog.java index 47807a2b9f37..c696bedf9f12 100644 --- a/aws/src/main/java/org/apache/iceberg/aws/glue/GlueCatalog.java +++ b/aws/src/main/java/org/apache/iceberg/aws/glue/GlueCatalog.java @@ -356,8 +356,13 @@ public boolean dropTable(TableIdentifier identifier, boolean purge) { .build()); LOG.info("Successfully dropped table {} from Glue", identifier); if (purge && lastMetadata != null) { - CatalogUtil.dropTableData(ops.io(), lastMetadata); - LOG.info("Glue table {} data purged", identifier); + try { + CatalogUtil.dropTableData(ops.io(), lastMetadata); + LOG.info("Glue table {} data purged", identifier); + } catch (Exception e) { + LOG.warn( + "Failed to purge data for table: {}, continuing drop without purge", identifier, e); + } } LOG.info("Dropped table: {}", identifier); return true; diff --git a/aws/src/test/java/org/apache/iceberg/aws/glue/TestGlueCatalog.java b/aws/src/test/java/org/apache/iceberg/aws/glue/TestGlueCatalog.java index 2042948eb3c9..8b78027d88fe 100644 --- a/aws/src/test/java/org/apache/iceberg/aws/glue/TestGlueCatalog.java +++ b/aws/src/test/java/org/apache/iceberg/aws/glue/TestGlueCatalog.java @@ -26,7 +26,10 @@ import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; import org.apache.iceberg.BaseMetastoreTableOperations; +import org.apache.iceberg.CatalogUtil; import org.apache.iceberg.Schema; +import org.apache.iceberg.TableMetadata; +import org.apache.iceberg.TableOperations; import org.apache.iceberg.aws.AwsProperties; import org.apache.iceberg.aws.s3.S3FileIOProperties; import org.apache.iceberg.catalog.Namespace; @@ -40,6 +43,7 @@ import org.apache.iceberg.util.LockManagers; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -312,6 +316,44 @@ public void testDropTable() { glueCatalog.dropTable(TableIdentifier.of("db1", "t1")); } + @Test + public void testDropTableWithPurgeFailure() { + Map properties = Maps.newHashMap(); + properties.put( + BaseMetastoreTableOperations.TABLE_TYPE_PROP, + BaseMetastoreTableOperations.ICEBERG_TABLE_TYPE_VALUE); + Mockito.doReturn( + GetTableResponse.builder() + .table( + Table.builder().databaseName("db1").name("t1").parameters(properties).build()) + .build()) + .when(glue) + .getTable(Mockito.any(GetTableRequest.class)); + Mockito.doReturn( + GetDatabaseResponse.builder().database(Database.builder().name("db1").build()).build()) + .when(glue) + .getDatabase(Mockito.any(GetDatabaseRequest.class)); + Mockito.doReturn(DeleteTableResponse.builder().build()) + .when(glue) + .deleteTable(Mockito.any(DeleteTableRequest.class)); + + TableMetadata mockMetadata = Mockito.mock(TableMetadata.class); + TableOperations mockOps = Mockito.mock(TableOperations.class); + Mockito.when(mockOps.current()).thenReturn(mockMetadata); + + GlueCatalog spyCatalog = Mockito.spy(glueCatalog); + Mockito.doReturn(mockOps).when(spyCatalog).newTableOps(Mockito.any(TableIdentifier.class)); + + try (MockedStatic mockedCatalogUtil = Mockito.mockStatic(CatalogUtil.class)) { + mockedCatalogUtil + .when(() -> CatalogUtil.dropTableData(Mockito.any(), Mockito.any())) + .thenThrow(new RuntimeException("Cannot delete files from S3 Table Bucket")); + + boolean result = spyCatalog.dropTable(TableIdentifier.of("db1", "t1"), true); + assertThat(result).isTrue(); + } + } + @Test public void testRenameTable() { AtomicInteger counter = new AtomicInteger(1);