diff --git a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/HiveMetadata.java b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/HiveMetadata.java index b1c793d184af..0785b435afc0 100644 --- a/plugin/trino-hive/src/main/java/io/trino/plugin/hive/HiveMetadata.java +++ b/plugin/trino-hive/src/main/java/io/trino/plugin/hive/HiveMetadata.java @@ -952,9 +952,36 @@ public void createSchema(ConnectorSession session, String schemaName, Map views = listViews(session, Optional.of(schemaName)); + List tables = listTables(session, Optional.of(schemaName)).stream() + .filter(table -> !views.contains(table)) + .collect(toImmutableList()); + + for (SchemaTableName viewName : views) { + dropView(session, viewName); + } + + for (SchemaTableName tableName : tables) { + ConnectorTableHandle table = getTableHandle(session, tableName); + if (table == null) { + log.debug("Table disappeared during DROP SCHEMA CASCADE: %s", tableName); + continue; + } + dropTable(session, table); + } + + // Commit and then drop database with raw metastore because exclusive operation after dropping object is disallowed in SemiTransactionalHiveMetastore + metastore.commit(); + boolean deleteData = metastore.shouldDeleteDatabaseData(session, schemaName); + metastore.unsafeGetRawHiveMetastoreClosure().dropDatabase(schemaName, deleteData); + } + else { + metastore.dropDatabase(session, schemaName); + } } @Override diff --git a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/BaseHiveConnectorTest.java b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/BaseHiveConnectorTest.java index 778478609472..967c0f827d61 100644 --- a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/BaseHiveConnectorTest.java +++ b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/BaseHiveConnectorTest.java @@ -249,9 +249,6 @@ protected boolean hasBehavior(TestingConnectorBehavior connectorBehavior) case SUPPORTS_TOPN_PUSHDOWN: return false; - case SUPPORTS_DROP_SCHEMA_CASCADE: - return false; - case SUPPORTS_ADD_FIELD: case SUPPORTS_DROP_FIELD: case SUPPORTS_RENAME_FIELD: diff --git a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/BaseTestHiveOnDataLake.java b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/BaseTestHiveOnDataLake.java index 9c21f466b138..da982853aab9 100644 --- a/plugin/trino-hive/src/test/java/io/trino/plugin/hive/BaseTestHiveOnDataLake.java +++ b/plugin/trino-hive/src/test/java/io/trino/plugin/hive/BaseTestHiveOnDataLake.java @@ -2095,6 +2095,27 @@ public void testDropStatsPartitionedTable() assertUpdate("DROP TABLE " + getFullyQualifiedTestTableName(tableName)); } + @Test + public void testUnsupportedDropSchemaCascadeWithNonHiveTable() + { + String schemaName = "test_unsupported_drop_schema_cascade_" + randomNameSuffix(); + String icebergTableName = "test_dummy_iceberg_table" + randomNameSuffix(); + + hiveMinioDataLake.getHiveHadoop().runOnHive("CREATE DATABASE %2$s LOCATION 's3a://%1$s/%2$s'".formatted(bucketName, schemaName)); + try { + hiveMinioDataLake.getHiveHadoop().runOnHive("CREATE TABLE " + schemaName + "." + icebergTableName + " TBLPROPERTIES ('table_type'='iceberg') AS SELECT 1 a"); + + assertQueryFails("DROP SCHEMA " + schemaName + " CASCADE", "\\QCannot query Iceberg table '%s.%s'".formatted(schemaName, icebergTableName)); + + assertThat(computeActual("SHOW SCHEMAS").getOnlyColumnAsSet()).contains(schemaName); + assertThat(computeActual("SHOW TABLES FROM " + schemaName).getOnlyColumnAsSet()).contains(icebergTableName); + assertThat(hiveMinioDataLake.getMinioClient().listObjects(bucketName, schemaName).stream()).isNotEmpty(); + } + finally { + hiveMinioDataLake.getHiveHadoop().runOnHive("DROP DATABASE IF EXISTS " + schemaName + " CASCADE"); + } + } + private void renamePartitionResourcesOutsideTrino(String tableName, String partitionColumn, String regionKey) { String partitionName = format("%s=%s", partitionColumn, regionKey);