HonahX commented on code in PR #2223:
URL: https://github.com/apache/polaris/pull/2223#discussion_r2370850774


##########
runtime/service/src/main/java/org/apache/polaris/service/admin/PolarisAdminService.java:
##########
@@ -1686,14 +1691,33 @@ public boolean grantPrivilegeOnNamespaceToRole(
         PolarisAuthorizableOperation.ADD_NAMESPACE_GRANT_TO_CATALOG_ROLE;
     authorizeGrantOnNamespaceOperationOrThrow(op, catalogName, namespace, 
catalogRoleName);
 
+    CatalogEntity catalogEntity =
+        findCatalogByName(catalogName)
+            .orElseThrow(() -> new NotFoundException("Parent catalog %s not 
found", catalogName));
     PolarisEntity catalogRoleEntity =
         findCatalogRoleByName(catalogName, catalogRoleName)
             .orElseThrow(() -> new NotFoundException("CatalogRole %s not 
found", catalogRoleName));
 
     PolarisResolvedPathWrapper resolvedPathWrapper = 
resolutionManifest.getResolvedPath(namespace);
     if (resolvedPathWrapper == null
         || !resolvedPathWrapper.isFullyResolvedNamespace(catalogName, 
namespace)) {
-      throw new NotFoundException("Namespace %s not found", namespace);
+      boolean rbacForFederatedCatalogsEnabled =
+          getCurrentPolarisContext()
+              .getRealmConfig()
+              
.getConfig(FeatureConfiguration.ENABLE_SUB_CATALOG_RBAC_FOR_FEDERATED_CATALOGS);
+      if (resolutionManifest.getIsPassthroughFacade() && 
rbacForFederatedCatalogsEnabled) {
+        resolvedPathWrapper =
+            createSyntheticNamespaceEntities(catalogEntity, namespace, 
resolvedPathWrapper);
+        if (resolvedPathWrapper == null
+            || !resolvedPathWrapper.isFullyResolvedNamespace(catalogName, 
namespace)) {
+          throw new RuntimeException(
+              String.format(
+                  "Failed to create synthetic namespace entities for namespace 
%s in catalog %s",

Review Comment:
   Since currently we just create synthetic entities without performing a 
passthrough, the expectation for `createSyntheticNamespaceEntities` is to 
create all synthetic entities or make sure they all exist. If something like 
`CommitStateUnknown` 
(https://github.com/apache/polaris/pull/2223/files#r2366658329) happens, it 
should be thrown inside the `createSyntheticNamespaceEntities`. 
   
   At this point, I think it make sense to mark this as IllegalStateException 
or others that mapped to 500. WDYT?



##########
runtime/service/src/main/java/org/apache/polaris/service/admin/PolarisAdminService.java:
##########
@@ -1737,6 +1761,80 @@ public boolean revokePrivilegeOnNamespaceFromRole(
         .isSuccess();
   }
 
+  /**
+   * Creates and persists the missing synthetic namespace entities for 
external catalogs.
+   *
+   * @param catalogEntity the external passthrough facade catalog entity.
+   * @param namespace the expected fully resolved namespace to be created.
+   * @param existingPath the partially resolved path currently stored in the 
metastore.
+   * @return the fully resolved path wrapper.
+   */
+  private PolarisResolvedPathWrapper createSyntheticNamespaceEntities(
+      CatalogEntity catalogEntity, Namespace namespace, 
PolarisResolvedPathWrapper existingPath) {
+
+    if (existingPath == null) {
+      throw new IllegalStateException(
+          String.format("Catalog entity %s does not exist.", 
catalogEntity.getName()));
+    }
+
+    List<PolarisEntity> completePath = new 
ArrayList<>(existingPath.getRawFullPath());
+    PolarisEntity currentParent = existingPath.getRawLeafEntity();
+
+    String[] allNamespaceLevels = namespace.levels();
+    int numMatchingLevels = 0;
+    // Find parts of the complete path that match the namespace levels.
+    // We skip index 0 because it is the CatalogEntity.
+    for (PolarisEntity entity : completePath.subList(1, completePath.size())) {
+      if (!entity.getName().equals(allNamespaceLevels[numMatchingLevels])) {
+        break;
+      }
+      numMatchingLevels++;
+    }
+
+    for (int i = numMatchingLevels; i < allNamespaceLevels.length; i++) {
+      String[] namespacePart = Arrays.copyOfRange(allNamespaceLevels, 0, i + 
1);
+      String leafNamespace = namespacePart[namespacePart.length - 1];
+      Namespace currentNamespace = Namespace.of(namespacePart);
+
+      // TODO: Instead of creating synthetic entitties, rely on external 
catalog mediated backfill.
+      PolarisEntity syntheticNamespace =
+          new NamespaceEntity.Builder(currentNamespace)
+              
.setId(metaStoreManager.generateNewEntityId(getCurrentPolarisContext()).getId())
+              .setCatalogId(catalogEntity.getId())
+              .setParentId(currentParent.getId())
+              .setCreateTimestamp(System.currentTimeMillis())
+              .build();
+
+      EntityResult result =
+          metaStoreManager.createEntityIfNotExists(
+              getCurrentPolarisContext(),
+              PolarisEntity.toCoreList(completePath),
+              syntheticNamespace);
+
+      if (result.isSuccess()) {
+        syntheticNamespace = PolarisEntity.of(result.getEntity());
+      } else {
+        Namespace partialNamespace = 
Namespace.of(Arrays.copyOf(allNamespaceLevels, i + 1));
+        PolarisResolvedPathWrapper partialPath =
+            resolutionManifest.getResolvedPath(partialNamespace);
+        PolarisEntity partialLeafEntity = partialPath.getRawLeafEntity();
+        if (partialLeafEntity == null
+            || !(partialLeafEntity.getName().equals(leafNamespace)
+                && partialLeafEntity.getType() == 
PolarisEntityType.NAMESPACE)) {
+          throw new RuntimeException(
+              String.format(
+                  "Failed to create or find namespace entity '%s' in federated 
catalog '%s'",
+                  leafNamespace, catalogEntity.getName()));
+        }

Review Comment:
   Hi @poojanilangekar, for `backfill` I mean creating JIT dummy entities like 
what the current PR do. But yes, the remaining persistence layer changes are 
not yet supported in Polaris and also does not need to be in this PR.
   
   For this one, using `getPassthroughResolvedPath` to get the fresh entity 
should be enough : )



-- 
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