This is an automated email from the ASF dual-hosted git repository.

jshao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new dc655c6f6 [#5329] improvement(core): Clarify exception when importing 
entity multiple times (#5844)
dc655c6f6 is described below

commit dc655c6f6da4be92927abb606ab424295f749c1f
Author: mchades <[email protected]>
AuthorDate: Tue Dec 17 13:58:50 2024 +0800

    [#5329] improvement(core): Clarify exception when importing entity multiple 
times (#5844)
    
    ### What changes were proposed in this pull request?
    
    - remind users not to register multiple catalogs using the same data
    source in the user doc
     - clarify exception when importing entity multiple times.
    
    ### Why are the changes needed?
    
    Fix: #5329
    
    import one source multiple times will update the existing record and
    result in unexpected behaviors
    
    ### Does this PR introduce _any_ user-facing change?
    
    yes, clarify the exception
    
    ### How was this patch tested?
    
    tests added
---
 .../integration/test/CatalogPostgreSqlIT.java      | 37 ++++++++++++++++------
 .../catalog/SchemaOperationDispatcher.java         |  6 ++++
 .../catalog/TableOperationDispatcher.java          |  6 ++++
 docs/manage-relational-metadata-using-gravitino.md |  5 +++
 4 files changed, 44 insertions(+), 10 deletions(-)

diff --git 
a/catalogs/catalog-jdbc-postgresql/src/test/java/org/apache/gravitino/catalog/postgresql/integration/test/CatalogPostgreSqlIT.java
 
b/catalogs/catalog-jdbc-postgresql/src/test/java/org/apache/gravitino/catalog/postgresql/integration/test/CatalogPostgreSqlIT.java
index 558775014..25f99c797 100644
--- 
a/catalogs/catalog-jdbc-postgresql/src/test/java/org/apache/gravitino/catalog/postgresql/integration/test/CatalogPostgreSqlIT.java
+++ 
b/catalogs/catalog-jdbc-postgresql/src/test/java/org/apache/gravitino/catalog/postgresql/integration/test/CatalogPostgreSqlIT.java
@@ -118,8 +118,8 @@ public class CatalogPostgreSqlIT extends BaseIT {
 
     postgreSqlService = new PostgreSqlService(POSTGRESQL_CONTAINER, 
TEST_DB_NAME);
     createMetalake();
-    createCatalog();
-    createSchema();
+    catalog = createCatalog(catalogName);
+    createSchema(schemaName);
   }
 
   @AfterAll
@@ -139,7 +139,7 @@ public class CatalogPostgreSqlIT extends BaseIT {
   @AfterEach
   public void resetSchema() {
     clearTableAndSchema();
-    createSchema();
+    createSchema(schemaName);
   }
 
   private void clearTableAndSchema() {
@@ -162,7 +162,7 @@ public class CatalogPostgreSqlIT extends BaseIT {
     metalake = loadMetalake;
   }
 
-  private void createCatalog() throws SQLException {
+  private Catalog createCatalog(String catalogName) throws SQLException {
     Map<String, String> catalogProperties = Maps.newHashMap();
 
     String jdbcUrl = POSTGRESQL_CONTAINER.getJdbcUrl(TEST_DB_NAME);
@@ -179,10 +179,10 @@ public class CatalogPostgreSqlIT extends BaseIT {
     Catalog loadCatalog = metalake.loadCatalog(catalogName);
     Assertions.assertEquals(createdCatalog, loadCatalog);
 
-    catalog = loadCatalog;
+    return loadCatalog;
   }
 
-  private void createSchema() {
+  private void createSchema(String schemaName) {
 
     Schema createdSchema =
         catalog.asSchemas().createSchema(schemaName, schema_comment, 
Collections.EMPTY_MAP);
@@ -654,7 +654,7 @@ public class CatalogPostgreSqlIT extends BaseIT {
   }
 
   @Test
-  void testCreateAndLoadSchema() {
+  void testCreateAndLoadSchema() throws SQLException {
     String testSchemaName = "test";
 
     Schema schema = catalog.asSchemas().createSchema(testSchemaName, 
"comment", null);
@@ -665,15 +665,32 @@ public class CatalogPostgreSqlIT extends BaseIT {
     Assertions.assertEquals("comment", schema.comment());
 
     // test null comment
-    testSchemaName = "test2";
+    String testSchemaName2 = "test2";
 
-    schema = catalog.asSchemas().createSchema(testSchemaName, null, null);
+    schema = catalog.asSchemas().createSchema(testSchemaName2, null, null);
     Assertions.assertEquals("anonymous", schema.auditInfo().creator());
     // todo: Gravitino put id to comment, makes comment is empty string not 
null.
     Assertions.assertTrue(StringUtils.isEmpty(schema.comment()));
-    schema = catalog.asSchemas().loadSchema(testSchemaName);
+    schema = catalog.asSchemas().loadSchema(testSchemaName2);
     Assertions.assertEquals("anonymous", schema.auditInfo().creator());
     Assertions.assertTrue(StringUtils.isEmpty(schema.comment()));
+
+    // test register PG service to multiple catalogs
+    String newCatalogName = GravitinoITUtils.genRandomName("new_catalog");
+    Catalog newCatalog = createCatalog(newCatalogName);
+    newCatalog.asSchemas().loadSchema(testSchemaName2);
+    Assertions.assertTrue(catalog.asSchemas().dropSchema(testSchemaName2, 
false));
+    createSchema(testSchemaName2);
+    SupportsSchemas schemaOps = newCatalog.asSchemas();
+    Assertions.assertThrows(
+        UnsupportedOperationException.class, () -> 
schemaOps.loadSchema(testSchemaName2));
+    // recovered by re-build the catalog
+    Assertions.assertTrue(metalake.dropCatalog(newCatalogName, true));
+    newCatalog = createCatalog(newCatalogName);
+    Schema loadedSchema = newCatalog.asSchemas().loadSchema(testSchemaName2);
+    Assertions.assertEquals(testSchemaName2, loadedSchema.name());
+
+    Assertions.assertTrue(metalake.dropCatalog(newCatalogName, true));
   }
 
   @Test
diff --git 
a/core/src/main/java/org/apache/gravitino/catalog/SchemaOperationDispatcher.java
 
b/core/src/main/java/org/apache/gravitino/catalog/SchemaOperationDispatcher.java
index ea423abfa..c6ec025ab 100644
--- 
a/core/src/main/java/org/apache/gravitino/catalog/SchemaOperationDispatcher.java
+++ 
b/core/src/main/java/org/apache/gravitino/catalog/SchemaOperationDispatcher.java
@@ -24,6 +24,7 @@ import static 
org.apache.gravitino.utils.NameIdentifierUtil.getCatalogIdentifier
 
 import java.time.Instant;
 import java.util.Map;
+import org.apache.gravitino.EntityAlreadyExistsException;
 import org.apache.gravitino.EntityStore;
 import org.apache.gravitino.NameIdentifier;
 import org.apache.gravitino.Namespace;
@@ -350,6 +351,11 @@ public class SchemaOperationDispatcher extends 
OperationDispatcher implements Sc
             .build();
     try {
       store.put(schemaEntity, true);
+    } catch (EntityAlreadyExistsException e) {
+      LOG.error("Failed to import schema {} with id {} to the store.", 
identifier, uid, e);
+      throw new UnsupportedOperationException(
+          "Schema managed by multiple catalogs. This may cause unexpected 
issues such as privilege conflicts. "
+              + "To resolve: Remove all catalogs managing this schema, then 
recreate one catalog to ensure single-catalog management.");
     } catch (Exception e) {
       LOG.error(FormattedErrorMessages.STORE_OP_FAILURE, "put", identifier, e);
       throw new RuntimeException("Fail to import schema entity to the store.", 
e);
diff --git 
a/core/src/main/java/org/apache/gravitino/catalog/TableOperationDispatcher.java 
b/core/src/main/java/org/apache/gravitino/catalog/TableOperationDispatcher.java
index da869d65f..de34e712a 100644
--- 
a/core/src/main/java/org/apache/gravitino/catalog/TableOperationDispatcher.java
+++ 
b/core/src/main/java/org/apache/gravitino/catalog/TableOperationDispatcher.java
@@ -35,6 +35,7 @@ import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import org.apache.commons.lang3.tuple.Pair;
+import org.apache.gravitino.EntityAlreadyExistsException;
 import org.apache.gravitino.EntityStore;
 import org.apache.gravitino.GravitinoEnv;
 import org.apache.gravitino.NameIdentifier;
@@ -394,6 +395,11 @@ public class TableOperationDispatcher extends 
OperationDispatcher implements Tab
             .build();
     try {
       store.put(tableEntity, true);
+    } catch (EntityAlreadyExistsException e) {
+      LOG.error("Failed to import table {} with id {} to the store.", 
identifier, uid, e);
+      throw new UnsupportedOperationException(
+          "Table managed by multiple catalogs. This may cause unexpected 
issues such as privilege conflicts. "
+              + "To resolve: Remove all catalogs managing this table, then 
recreate one catalog to ensure single-catalog management.");
     } catch (Exception e) {
       LOG.error(FormattedErrorMessages.STORE_OP_FAILURE, "put", identifier, e);
       throw new RuntimeException("Fail to import the table entity to the 
store.", e);
diff --git a/docs/manage-relational-metadata-using-gravitino.md 
b/docs/manage-relational-metadata-using-gravitino.md
index 280793e69..352a8de29 100644
--- a/docs/manage-relational-metadata-using-gravitino.md
+++ b/docs/manage-relational-metadata-using-gravitino.md
@@ -36,6 +36,11 @@ Assuming:
 
 ### Create a catalog
 
+:::caution
+It is not recommended to use one data source to create multiple catalogs, 
+as multiple catalogs operating on the same source may result in unpredictable 
behavior.
+:::
+
 :::tip
 The code below is an example of creating a Hive catalog. For other relational 
catalogs, the code is
 similar, but the catalog type, provider, and properties may be different. For 
more details, please refer to the related doc.

Reply via email to