danhuawang opened a new issue, #11262:
URL: https://github.com/apache/gravitino/issues/11262

   ### Version
   
   main branch
   
   ### Describe what's wrong
   
   When using the Gravitino Java client to drop a middle-layer hierarchical 
schema (e.g., `A:B`) after
   its child schema (e.g., `A:B:C`) has already been dropped, 
`catalog.asSchemas().dropSchema("A:B", false)`
   returns `false` instead of `true`, even though the schema entity still 
exists in the Gravitino store.
   
   The root cause is a mismatch between the Gravitino store state and the 
underlying Iceberg catalog state:
   
   1. User creates hierarchical schema `A:B:C` (auto-creates `A:B` and `A`).
   2. User creates a table `tbl_mid` in `A:B`.
   3. User drops the leaf schema `A:B:C` via Trino (`DROP SCHEMA 
catalog."A.B.C"`).
   4. User drops `tbl_mid` from `A:B` via Trino (`DROP TABLE 
catalog."A.B".tbl_mid`).
   5. User calls `catalog.asSchemas().dropSchema("A:B", false)` via Gravitino 
Java client.
   
   At step 5, the Iceberg namespace `["A", "B"]` no longer exists in the 
underlying Iceberg JDBC catalog
   So `IcebergCatalogOperations.dropSchema` catches `NoSuchNamespaceException` 
and returns `false`.
   
   The user expects`dropSchema` to return `true`.
   
   **Expected behavior**: `dropSchema("A:B", false)` should return `true` and 
clean up the Gravitino
   store entity when the schema no longer exists in the underlying catalog but 
still exists in the store.
   
   **Actual behavior**: Returns `false`, leaving the user confused about 
whether the schema was dropped.
   
   ### Error message and/or stacktrace
   
   ```
   2026-05-27 11:50:59.388 INFO [iceberg-rest-38] 
[org.apache.gravitino.iceberg.service.CatalogWrapperForREST.injectCredentialConfig(CatalogWrapperForREST.java:325)]
 - Generate credential: s3-token for Iceberg table: 
ns_e2e_27b0ac35_tc15.parent.tbl_mid
   2026-05-27 11:50:59.388 INFO [iceberg-rest-38] 
[org.apache.gravitino.audit.FileAuditWriter.doWrite(FileAuditWriter.java:71)] - 
[2026-05-27 11:50:59] service-account-postman-client  UNKNOWN_OPERATION       
test.catalog_iceberg_s3.ns_e2e_27b0ac35_tc15.parent.tbl_mid     SUCCESS
   2026-05-27 11:50:59.397 INFO [iceberg-rest-31] 
[org.apache.gravitino.iceberg.service.rest.IcebergTableOperations.dropTable(IcebergTableOperations.java:260)]
 - Drop Iceberg table, catalog: catalog_iceberg_s3, namespace: 
ns_e2e_27b0ac35_tc15.parent, table: tbl_mid, purgeRequested: true
   2026-05-27 11:50:59.398 INFO [iceberg-rest-31] 
[org.apache.iceberg.BaseMetastoreTableOperations.refreshFromMetadataLocation(BaseMetastoreTableOperations.java:190)]
 - Refreshing table metadata from new version: 
s3://irc-e2e-env1-metalake-b-warehouse/gravitino-e2e-env2-oauth2-auth/test/catalog_iceberg_s3/ns_e2e_27b0ac35_tc15/parent/tbl_mid-8b8c08933c3643fd9abdce29c5d02e0d/metadata/00001-da28e5c2-9279-4840-b432-3cf60858e257.metadata.json
   2026-05-27 11:51:00.779 INFO [iceberg-rest-31] 
[org.apache.iceberg.CatalogUtil.dropTableData(CatalogUtil.java:115)] - 
Manifests to delete: GenericManifestFile{content=DATA, 
path=s3://irc-e2e-env1-metalake-b-warehouse/gravitino-e2e-env2-oauth2-auth/test/catalog_iceberg_s3/ns_e2e_27b0ac35_tc15/parent/tbl_mid-8b8c08933c3643fd9abdce29c5d02e0d/metadata/4d894834-6634-4e95-83a7-6501f728561d-m0.avro,
 length=7130, partition_spec_id=0, added_snapshot_id=6056422233030878467, 
added_data_files_count=1, added_rows_count=1, existing_data_files_count=0, 
existing_rows_count=0, deleted_data_files_count=0, deleted_rows_count=0, 
partitions=[], key_metadata=null, sequence_number=2, min_sequence_number=2, 
first_row_id=null}
   2026-05-27 11:51:08.375 INFO [iceberg-rest-31] 
[org.apache.iceberg.jdbc.JdbcCatalog.dropTable(JdbcCatalog.java:319)] - Dropped 
table: ns_e2e_27b0ac35_tc15.parent.tbl_mid
   2026-05-27 11:51:08.376 INFO [iceberg-rest-31] 
[org.apache.gravitino.audit.FileAuditWriter.doWrite(FileAuditWriter.java:71)] - 
[2026-05-27 11:51:08] service-account-postman-client  UNKNOWN_OPERATION       
test.catalog_iceberg_s3.ns_e2e_27b0ac35_tc15.parent.tbl_mid     SUCCESS
   2026-05-27 11:51:08.427 INFO [Gravitino-webserver-52] 
[org.apache.gravitino.server.web.rest.SchemaOperations.dropSchema(SchemaOperations.java:245)]
 - Received drop schema request: 
test.catalog_iceberg_s3.ns_e2e_27b0ac35_tc15:parent
   2026-05-27 11:51:08.429 INFO [Gravitino-webserver-52] 
[org.apache.gravitino.audit.FileAuditWriter.doWrite(FileAuditWriter.java:71)] - 
[2026-05-27 11:51:08]  service-account-postman-client  LOAD_CATALOG    
test.catalog_iceberg_s3 SUCCESS
   2026-05-27 11:51:08.430 INFO [Gravitino-webserver-52] 
[org.apache.gravitino.audit.FileAuditWriter.doWrite(FileAuditWriter.java:71)] - 
[2026-05-27 11:51:08]  service-account-postman-client  LOAD_SCHEMA     
test.catalog_iceberg_s3.ns_e2e_27b0ac35_tc15:parent     FAILURE
   2026-05-27 11:51:08.430 WARN [Gravitino-webserver-52] 
[org.apache.gravitino.authorization.AuthorizationUtils.getMetadataObjectLocation(AuthorizationUtils.java:631)]
 - Failed to get location paths for metadata object 
test.catalog_iceberg_s3.ns_e2e_27b0ac35_tc15:parent type SCHEMA
   org.apache.gravitino.exceptions.NoSuchSchemaException: Iceberg schema 
(database) does not exist: ns_e2e_27b0ac35_tc15:parent in Gravitino store
        at 
org.apache.gravitino.catalog.lakehouse.iceberg.IcebergCatalogOperations.loadSchema(IcebergCatalogOperations.java:274)
        at 
org.apache.gravitino.catalog.lakehouse.iceberg.IcebergCatalogOperations.loadSchema(IcebergCatalogOperations.java:93)
        at 
org.apache.gravitino.catalog.SchemaOperationDispatcher.lambda$internalLoadSchema$20(SchemaOperationDispatcher.java:456)
        at 
org.apache.gravitino.catalog.CatalogManager$CatalogWrapper.lambda$doWithSchemaOps$0(CatalogManager.java:144)
        at 
org.apache.gravitino.utils.IsolatedClassLoader.withClassLoader(IsolatedClassLoader.java:86)
        at 
org.apache.gravitino.catalog.CatalogManager$CatalogWrapper.doWithSchemaOps(CatalogManager.java:139)
        at 
org.apache.gravitino.catalog.SchemaOperationDispatcher.lambda$internalLoadSchema$21(SchemaOperationDispatcher.java:456)
        at 
org.apache.gravitino.catalog.OperationDispatcher.doWithCatalog(OperationDispatcher.java:98)
        at 
org.apache.gravitino.catalog.SchemaOperationDispatcher.internalLoadSchema(SchemaOperationDispatcher.java:454)
        at 
org.apache.gravitino.catalog.SchemaOperationDispatcher.lambda$loadSchema$8(SchemaOperationDispatcher.java:192)
        at 
org.apache.gravitino.lock.TreeLockUtils.doWithTreeLock(TreeLockUtils.java:49)
        at 
org.apache.gravitino.catalog.SchemaOperationDispatcher.loadSchema(SchemaOperationDispatcher.java:192)
        at 
org.apache.gravitino.catalog.SchemaNormalizeDispatcher.loadSchema(SchemaNormalizeDispatcher.java:71)
        at 
org.apache.gravitino.listener.SchemaEventDispatcher.loadSchema(SchemaEventDispatcher.java:116)
        at 
org.apache.gravitino.hook.SchemaHookDispatcher.loadSchema(SchemaHookDispatcher.java:160)
        at 
org.apache.gravitino.authorization.AuthorizationUtils.getMetadataObjectLocation(AuthorizationUtils.java:553)
        at 
org.apache.gravitino.hook.SchemaHookDispatcher.dropSchema(SchemaHookDispatcher.java:174)
        at 
org.apache.gravitino.server.web.rest.SchemaOperations.lambda$dropSchema$5(SchemaOperations.java:251)
        at 
java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
        at java.base/javax.security.auth.Subject.doAs(Subject.java:439)
        at 
org.apache.gravitino.utils.PrincipalUtils.doAs(PrincipalUtils.java:53)
        at org.apache.gravitino.server.web.Utils.doAs(Utils.java:209)
        at 
org.apache.gravitino.server.web.rest.SchemaOperations.dropSchema(SchemaOperations.java:247)
        at 
org.apache.gravitino.server.web.rest.SchemaOperations_$$_jvst915_3._d4dropSchema(SchemaOperations_$$_jvst915_3.java)
        at 
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at 
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at 
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:569)
        at 
org.glassfish.hk2.utilities.reflection.ReflectionHelper.invoke(ReflectionHelper.java:1268)
        at 
org.jvnet.hk2.internal.MethodInterceptorHandler$MethodInvocationImpl.proceed(MethodInterceptorHandler.java:164)
        at 
org.apache.gravitino.server.web.filter.GravitinoInterceptionService$MetadataAuthorizationMethodInterceptor.invoke(GravitinoInterceptionService.java:212)
        at 
org.jvnet.hk2.internal.MethodInterceptorHandler.invoke(MethodInterceptorHandler.java:97)
        at 
org.apache.gravitino.server.web.rest.SchemaOperations_$$_jvst915_3.dropSchema(SchemaOperations_$$_jvst915_3.java)
        at 
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at 
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at 
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:569)
        at 
org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:52)
        at 
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:146)
        at 
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:189)
        at 
org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:176)
        at 
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:93)
        at 
org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:478)
        at 
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:400)
        at 
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:81)
        at 
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:256)
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
        at org.glassfish.jersey.internal.Errors.process(Errors.java:244)
        at 
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265)
        at 
org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:235)
        at 
org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:684)
        at 
org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:394)
        at 
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346)
        at 
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:358)
        at 
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:311)
        at 
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205)
        at 
org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:799)
        at 
org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1656)
        at 
org.apache.gravitino.server.authentication.AuthenticationFilter.lambda$doFilter$0(AuthenticationFilter.java:96)
        at 
java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
        at java.base/javax.security.auth.Subject.doAs(Subject.java:439)
        at 
org.apache.gravitino.utils.PrincipalUtils.doAs(PrincipalUtils.java:53)
        at 
org.apache.gravitino.server.authentication.AuthenticationFilter.doFilter(AuthenticationFilter.java:93)
        at 
org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
        at 
org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
        at 
org.apache.gravitino.server.web.VersioningFilter.doFilter(VersioningFilter.java:111)
        at 
org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
        at 
org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
        at 
org.apache.gravitino.server.web.RequestContextFilter.doFilter(RequestContextFilter.java:59)
        at 
org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:193)
        at 
org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1626)
        at 
org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:552)
        at 
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
        at 
org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:600)
        at 
org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
        at 
org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
        at 
org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1624)
        at 
org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
        at 
org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1440)
        at 
org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
        at 
org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:505)
        at 
org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1594)
        at 
org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
        at 
org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1355)
        at 
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
        at 
org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:146)
        at 
org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
        at org.eclipse.jetty.server.Server.handle(Server.java:516)
        at 
org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:487)
        at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:732)
        at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:479)
        at 
org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:277)
        at 
org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
        at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
        at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
        at 
org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:338)
        at 
org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:315)
        at 
org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:173)
        at 
org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
        at 
org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:409)
        at 
org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883)
        at 
org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034)
        at java.base/java.lang.Thread.run(Thread.java:840)
   Caused by: org.apache.iceberg.exceptions.NoSuchNamespaceException: Namespace 
does not exist: ns_e2e_27b0ac35_tc15.parent
        at 
org.apache.iceberg.jdbc.JdbcCatalog.loadNamespaceMetadata(JdbcCatalog.java:508)
        at 
org.apache.iceberg.rest.CatalogHandlers.loadNamespace(CatalogHandlers.java:175)
        at 
org.apache.gravitino.iceberg.common.ops.IcebergCatalogWrapper.loadNamespace(IcebergCatalogWrapper.java:182)
        at 
org.apache.gravitino.catalog.lakehouse.iceberg.IcebergCatalogOperations.loadSchema(IcebergCatalogOperations.java:257)
        ... 105 more
   2026-05-27 11:51:08.432 WARN [Gravitino-webserver-52] 
[org.apache.gravitino.catalog.lakehouse.iceberg.IcebergCatalogOperations.dropSchema(IcebergCatalogOperations.java:362)]
 - Iceberg schema (database) ns_e2e_27b0ac35_tc15:parent does not exist
   2026-05-27 11:51:08.530 INFO [Gravitino-webserver-52] 
[org.apache.gravitino.audit.FileAuditWriter.doWrite(FileAuditWriter.java:71)] - 
[2026-05-27 11:51:08]  service-account-postman-client  DROP_SCHEMA     
test.catalog_iceberg_s3.ns_e2e_27b0ac35_tc15:parent     SUCCESS
   2026-05-27 11:51:08.530 WARN [Gravitino-webserver-52] 
[org.apache.gravitino.server.web.rest.SchemaOperations.lambda$dropSchema$5(SchemaOperations.java:256)]
 - Fail to drop schema ns_e2e_27b0ac35_tc15:parent under namespace 
test.catalog_iceberg_s3
   
   ```
   
   ### How to reproduce
   
   1. Use Gravitino main branch with Iceberg catalog (JDBC backend).
   2. Create a 3-level hierarchical schema:
      ```java
      catalog.asSchemas().createSchema("A:B:C", "test", Collections.emptyMap());
      ```
   3. Create a table in the middle level via Trino:
      ```sql
      CREATE TABLE catalog."A.B".tbl_mid (id bigint);
      INSERT INTO catalog."A.B".tbl_mid VALUES (1);
      ```
   4. Drop the leaf schema via Trino:
      ```sql
      DROP TABLE catalog."A.B.C".some_table;  -- if any
      DROP SCHEMA catalog."A.B.C";
      ```
   5. Drop the table in the middle level via Trino:
      ```sql
      DROP TABLE catalog."A.B".tbl_mid;
      ```
   6. Attempt to drop the middle schema via Gravitino client:
      ```java
      boolean result = catalog.asSchemas().dropSchema("A:B", false);
      // Expected: true
      // Actual: false
      ```
   
   ### Additional context
   
   _No response_


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to