From 5c65ca5ddfc372a020e4afd24f1117b483dda6b3 Mon Sep 17 00:00:00 2001 From: Eunbin Son Date: Fri, 19 Jun 2026 14:50:58 +0900 Subject: [PATCH] BigQuery: Only load table metadata when dropping with purge dropTable always called ops.current() before checking purge, which triggers a BigQuery tables.get plus a metadata file read on the first call to a fresh table ops. For a plain drop (purge=false) that remote load is wasted, since lastMetadata is only used when purging data. Load the metadata only when purge is true, matching GlueCatalog and HiveCatalog, and tolerate a NotFoundException there by continuing the drop without purge. Generated-by: Claude Code --- .../bigquery/BigQueryMetastoreCatalog.java | 13 +++++++++- .../bigquery/TestBigQueryTableOperations.java | 24 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/bigquery/src/main/java/org/apache/iceberg/gcp/bigquery/BigQueryMetastoreCatalog.java b/bigquery/src/main/java/org/apache/iceberg/gcp/bigquery/BigQueryMetastoreCatalog.java index 4c60d8783da2..c862244826e8 100644 --- a/bigquery/src/main/java/org/apache/iceberg/gcp/bigquery/BigQueryMetastoreCatalog.java +++ b/bigquery/src/main/java/org/apache/iceberg/gcp/bigquery/BigQueryMetastoreCatalog.java @@ -41,6 +41,7 @@ import org.apache.iceberg.catalog.TableIdentifier; import org.apache.iceberg.exceptions.NoSuchNamespaceException; import org.apache.iceberg.exceptions.NoSuchTableException; +import org.apache.iceberg.exceptions.NotFoundException; import org.apache.iceberg.hadoop.Configurable; import org.apache.iceberg.io.CloseableGroup; import org.apache.iceberg.io.FileIO; @@ -183,7 +184,17 @@ public List listTables(Namespace namespace) { public boolean dropTable(TableIdentifier identifier, boolean purge) { try { TableOperations ops = newTableOps(identifier); - TableMetadata lastMetadata = ops.current(); + TableMetadata lastMetadata = null; + if (purge) { + try { + lastMetadata = ops.current(); + } catch (NotFoundException e) { + LOG.warn( + "Failed to load table metadata for table: {}, continuing drop without purge", + identifier, + e); + } + } client.delete(toTableReference(identifier)); diff --git a/bigquery/src/test/java/org/apache/iceberg/gcp/bigquery/TestBigQueryTableOperations.java b/bigquery/src/test/java/org/apache/iceberg/gcp/bigquery/TestBigQueryTableOperations.java index c5095aedb000..bc69d7e8c27d 100644 --- a/bigquery/src/test/java/org/apache/iceberg/gcp/bigquery/TestBigQueryTableOperations.java +++ b/bigquery/src/test/java/org/apache/iceberg/gcp/bigquery/TestBigQueryTableOperations.java @@ -26,6 +26,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -244,6 +245,29 @@ public void createTableCommitSucceeds() throws Exception { assertThat(loadedTable.schema().asStruct()).isEqualTo(SCHEMA.asStruct()); } + @Test + public void dropTableWithoutPurgeDoesNotLoadMetadata() { + catalog.dropTable(IDENTIFIER, false); + + // A plain drop must not trigger a tables.get on BigQuery, since the metadata is only needed for + // purge. + verify(client, never()).load(TABLE_REFERENCE); + verify(client, times(1)).delete(TABLE_REFERENCE); + } + + @Test + public void dropTableWithPurgeLoadsMetadata() throws Exception { + Table createdTable = createTestTable(); + reset(client); + when(client.load(TABLE_REFERENCE)).thenReturn(createdTable); + + catalog.dropTable(IDENTIFIER, true); + + // Purge needs the current metadata to delete the table's data files, so it must load it. + verify(client, times(1)).load(TABLE_REFERENCE); + verify(client, times(1)).delete(TABLE_REFERENCE); + } + /** Creates a test table to have Iceberg metadata files in place. */ private Table createTestTable() throws Exception { when(client.load(TABLE_REFERENCE))