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

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


The following commit(s) were added to refs/heads/main by this push:
     new 2ae08b846 core: rename Resolvable.CATALOG_ROLES to 
Resolvable.CALLER_CATALOG_ROLES (#3916)
2ae08b846 is described below

commit 2ae08b8469c512aa3d07a83f46b322b5301836c5
Author: Sung Yun <[email protected]>
AuthorDate: Mon Mar 2 18:35:30 2026 -0500

    core: rename Resolvable.CATALOG_ROLES to Resolvable.CALLER_CATALOG_ROLES 
(#3916)
    
    * rename Resolvable.CALLER_CATALOG_ROLES and add special handling for 
requested CATALOG_ROLES
    
    * adopt feedback
---
 .../resolver/PolarisResolutionManifest.java        |  8 ++-
 .../core/persistence/resolver/Resolvable.java      | 13 ++--
 .../core/persistence/resolver/Resolver.java        | 72 ++++++++++++++--------
 .../polaris/core/persistence/ResolverTest.java     | 24 +++++++-
 4 files changed, 82 insertions(+), 35 deletions(-)

diff --git 
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/PolarisResolutionManifest.java
 
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/PolarisResolutionManifest.java
index a3965bd4f..4954cdd48 100644
--- 
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/PolarisResolutionManifest.java
+++ 
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/PolarisResolutionManifest.java
@@ -96,7 +96,13 @@ public class PolarisResolutionManifest implements 
PolarisResolutionManifestCatal
     addTopLevelName(PolarisEntityConstants.getRootContainerName(), 
PolarisEntityType.ROOT, true);
   }
 
-  /** Adds a name of a top-level entity (Catalog, Principal, PrincipalRole) to 
be resolved. */
+  /**
+   * Adds a named entity to be resolved via the resolver's name-based 
registration surface.
+   *
+   * <p>This includes top-level entities (Catalog, Principal, PrincipalRole), 
and also {@code
+   * CATALOG_ROLE}. For {@code CATALOG_ROLE}, a reference catalog must be 
present on the
+   * manifest/resolver context.
+   */
   public void addTopLevelName(String entityName, PolarisEntityType entityType, 
boolean isOptional) {
     addedTopLevelNames.put(entityName, entityType);
     if (isOptional) {
diff --git 
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolvable.java
 
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolvable.java
index 28f3f09b9..e1393bfaa 100644
--- 
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolvable.java
+++ 
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolvable.java
@@ -29,16 +29,19 @@ public enum Resolvable {
   CALLER_PRINCIPAL,
   /** Resolve the caller's activated principal-role entities. */
   CALLER_PRINCIPAL_ROLES,
-  /** Resolve catalog-role entities (e.g., roles attached in the reference 
catalog). */
-  CATALOG_ROLES,
+  /** Resolve caller-activated catalog-role entities in the reference catalog. 
*/
+  CALLER_CATALOG_ROLES,
   /** Resolve the reference catalog entity. */
   REFERENCE_CATALOG,
   /** Resolve explicitly registered paths (via addPath/addPassthroughPath). */
   REQUESTED_PATHS,
   /**
-   * Resolve any additional top-level entities explicitly registered via 
addTopLevelName, such as
-   * catalog/principal/principal-role names used for authorization beyond the 
caller and reference
-   * catalog.
+   * Resolve any additional top-level entities explicitly registered via {@link
+   * PolarisResolutionManifest#addTopLevelName}, such as 
catalog/principal/principal-role names used
+   * for authorization beyond the caller and reference catalog.
+   *
+   * <p>All entity types resolved here share the same {@link
+   * PolarisResolutionManifest#addTopLevelName} registration surface.
    */
   REQUESTED_TOP_LEVEL_ENTITIES
 }
diff --git 
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolver.java
 
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolver.java
index 532e9aa69..c6f1a7e88 100644
--- 
a/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolver.java
+++ 
b/polaris-core/src/main/java/org/apache/polaris/core/persistence/resolver/Resolver.java
@@ -251,7 +251,8 @@ public class Resolver {
   public ResolverStatus resolveSelections(@Nonnull Set<Resolvable> selections) 
{
     diagnostics.checkNotNull(selections, "resolver_selections_is_null");
     diagnostics.check(!selections.isEmpty(), "resolver_selections_is_empty");
-    return resolveWithPlan(ResolvePlan.fromSelections(selections, 
referenceCatalogName));
+    return resolveWithPlan(
+        ResolvePlan.fromSelections(selections, referenceCatalogName, 
hasRequestedCatalogRoles()));
   }
 
   private ResolverStatus resolveWithPlan(ResolvePlan plan) {
@@ -429,7 +430,8 @@ public class Resolver {
     // first resolve the principal and determine the set of activated 
principal roles
     ResolverStatus status =
         plan.resolveCallerPrincipal()
-            ? this.resolveCallerPrincipalAndPrincipalRoles(toValidate, 
plan.resolvePrincipalRoles())
+            ? this.resolveCallerPrincipalAndPrincipalRoles(
+                toValidate, plan.resolveCallerPrincipalRoles())
             : new ResolverStatus(ResolverStatus.StatusEnum.SUCCESS);
 
     // if success, continue resolving
@@ -439,18 +441,19 @@ public class Resolver {
         this.diagnostics.checkNotNull(this.referenceCatalogName, 
"reference_catalog_expected");
         status =
             this.resolveReferenceCatalog(
-                toValidate, this.referenceCatalogName, 
plan.resolveCatalogRoles());
+                toValidate, this.referenceCatalogName, 
plan.resolveCallerCatalogRoles());
       }
 
       // if success, continue resolving
       if (status.getStatus() == ResolverStatus.StatusEnum.SUCCESS) {
         // then resolve all the additional entities we were asked to resolve
-        if (plan.resolveTopLevelEntities()) {
+        if (plan.resolveRequestedTopLevelEntities()) {
           status = this.resolveEntities(toValidate, this.entitiesToResolve);
         }
 
         // if success, continue resolving
-        if (status.getStatus() == ResolverStatus.StatusEnum.SUCCESS && 
plan.resolvePaths()) {
+        if (status.getStatus() == ResolverStatus.StatusEnum.SUCCESS
+            && plan.resolveRequestedPaths()) {
           // finally, resolve all paths we need to resolve
           status = this.resolvePaths(toValidate, this.pathsToResolve);
         }
@@ -472,6 +475,15 @@ public class Resolver {
     return validationSuccess ? status : null;
   }
 
+  private boolean hasRequestedCatalogRoles() {
+    for (ResolverEntityName entityName : this.entitiesToResolve) {
+      if (entityName.entityType() == PolarisEntityType.CATALOG_ROLE) {
+        return true;
+      }
+    }
+    return false;
+  }
+
   /**
    * Update all entities which have been resolved since after validation, some 
might have changed
    */
@@ -828,20 +840,21 @@ public class Resolver {
   }
 
   /**
-   * Resolve the reference catalog and determine all activated role. The 
principal and principal
-   * roles should have already been resolved
+   * Resolve the reference catalog and optionally determine all 
caller-activated catalog roles. The
+   * principal and principal roles should have already been resolved.
    *
    * @param toValidate all entities we have resolved incrementally, possibly 
with some entries
    *     coming from cache, hence we will have to verify that these entities 
have not changed in the
    *     backend
-   * @param referenceCatalogName name of the reference catalog to resolve, 
along with all catalog
-   *     roles which are activated
+   * @param referenceCatalogName name of the reference catalog to resolve
+   * @param resolveCallerCatalogRoles whether to resolve caller-activated 
catalog roles for the
+   *     reference catalog
    * @return the status of resolution
    */
   private ResolverStatus resolveReferenceCatalog(
       @Nonnull List<ResolvedPolarisEntity> toValidate,
       @Nonnull String referenceCatalogName,
-      boolean resolveCatalogRoles) {
+      boolean resolveCallerCatalogRoles) {
     // resolve the catalog
     this.resolvedReferenceCatalog =
         this.resolveByName(toValidate, PolarisEntityType.CATALOG, 
referenceCatalogName);
@@ -852,7 +865,7 @@ public class Resolver {
       return new ResolverStatus(PolarisEntityType.CATALOG, 
this.referenceCatalogName);
     }
 
-    if (resolveCatalogRoles) {
+    if (resolveCallerCatalogRoles) {
       // determine the set of catalog roles which have been activated
       long catalogId = this.resolvedReferenceCatalog.getEntity().getId();
       for (ResolvedPolarisEntity principalRole : resolvedCallerPrincipalRoles) 
{
@@ -890,11 +903,11 @@ public class Resolver {
 
   private static record ResolvePlan(
       boolean resolveCallerPrincipal,
-      boolean resolvePrincipalRoles,
+      boolean resolveCallerPrincipalRoles,
       boolean resolveReferenceCatalog,
-      boolean resolveCatalogRoles,
-      boolean resolveTopLevelEntities,
-      boolean resolvePaths) {
+      boolean resolveCallerCatalogRoles,
+      boolean resolveRequestedTopLevelEntities,
+      boolean resolveRequestedPaths) {
 
     private static ResolvePlan all(@Nullable String referenceCatalogName) {
       boolean hasReferenceCatalog = referenceCatalogName != null;
@@ -903,20 +916,25 @@ public class Resolver {
     }
 
     private static ResolvePlan fromSelections(
-        Set<Resolvable> selections, @Nullable String referenceCatalogName) {
-      boolean resolvePaths = selections.contains(Resolvable.REQUESTED_PATHS);
-      boolean resolveTopLevelEntities =
+        Set<Resolvable> selections,
+        @Nullable String referenceCatalogName,
+        boolean hasRequestedCatalogRoles) {
+      boolean resolveRequestedPaths = 
selections.contains(Resolvable.REQUESTED_PATHS);
+      boolean resolveRequestedTopLevelEntities =
           selections.contains(Resolvable.REQUESTED_TOP_LEVEL_ENTITIES);
-      boolean resolveCatalogRoles = 
selections.contains(Resolvable.CATALOG_ROLES);
+      boolean resolveCallerCatalogRoles = 
selections.contains(Resolvable.CALLER_CATALOG_ROLES);
       // Principal roles depend on resolving the caller principal, and catalog 
roles depend on
       // principal roles. Only those selections require caller principal 
resolution.
-      boolean resolvePrincipalRoles =
-          selections.contains(Resolvable.CALLER_PRINCIPAL_ROLES) || 
resolveCatalogRoles;
+      boolean resolveCallerPrincipalRoles =
+          selections.contains(Resolvable.CALLER_PRINCIPAL_ROLES) || 
resolveCallerCatalogRoles;
       // Reference catalog is required for path resolution and catalog role 
expansion.
       boolean resolveReferenceCatalog =
-          selections.contains(Resolvable.REFERENCE_CATALOG) || resolvePaths || 
resolveCatalogRoles;
+          selections.contains(Resolvable.REFERENCE_CATALOG)
+              || resolveRequestedPaths
+              || resolveCallerCatalogRoles
+              || (resolveRequestedTopLevelEntities && 
hasRequestedCatalogRoles);
       boolean resolveCallerPrincipal =
-          selections.contains(Resolvable.CALLER_PRINCIPAL) || 
resolvePrincipalRoles;
+          selections.contains(Resolvable.CALLER_PRINCIPAL) || 
resolveCallerPrincipalRoles;
 
       boolean hasReferenceCatalog = referenceCatalogName != null;
       if (!hasReferenceCatalog && resolveReferenceCatalog) {
@@ -927,11 +945,11 @@ public class Resolver {
 
       return new ResolvePlan(
           resolveCallerPrincipal,
-          resolvePrincipalRoles,
+          resolveCallerPrincipalRoles,
           resolveReferenceCatalog,
-          resolveCatalogRoles,
-          resolveTopLevelEntities,
-          resolvePaths);
+          resolveCallerCatalogRoles,
+          resolveRequestedTopLevelEntities,
+          resolveRequestedPaths);
     }
   }
 
diff --git 
a/polaris-core/src/test/java/org/apache/polaris/core/persistence/ResolverTest.java
 
b/polaris-core/src/test/java/org/apache/polaris/core/persistence/ResolverTest.java
index 3af68107a..edf5de2de 100644
--- 
a/polaris-core/src/test/java/org/apache/polaris/core/persistence/ResolverTest.java
+++ 
b/polaris-core/src/test/java/org/apache/polaris/core/persistence/ResolverTest.java
@@ -120,7 +120,7 @@ public class ResolverTest extends BaseResolverTest {
   }
 
   @Test
-  public void testResolveSelectionsRequiresCallerPrincipalForCatalogRoles() {
+  public void 
testResolveSelectionsRequiresCallerPrincipalForCallerCatalogRoles() {
     Resolver resolver =
         new Resolver(
             diagServices,
@@ -129,11 +129,31 @@ public class ResolverTest extends BaseResolverTest {
             PolarisPrincipal.of("missing", Map.of(), Set.of()),
             null,
             "test");
-    ResolverStatus status = 
resolver.resolveSelections(Set.of(Resolvable.CATALOG_ROLES));
+    ResolverStatus status = 
resolver.resolveSelections(Set.of(Resolvable.CALLER_CATALOG_ROLES));
     Assertions.assertThat(status.getStatus())
         .isEqualTo(ResolverStatus.StatusEnum.CALLER_PRINCIPAL_DOES_NOT_EXIST);
   }
 
+  @Test
+  public void
+      
testResolveSelectionsRequestedTopLevelEntitiesWithCatalogRoleResolvesReferenceCatalog()
 {
+    Resolver resolver =
+        new Resolver(
+            diagServices,
+            callCtx(),
+            metaStoreManager(),
+            PolarisPrincipal.of("missing", Map.of(), Set.of()),
+            null,
+            "test");
+    resolver.addOptionalEntityByName(PolarisEntityType.CATALOG_ROLE, "role1");
+    ResolverStatus status =
+        
resolver.resolveSelections(Set.of(Resolvable.REQUESTED_TOP_LEVEL_ENTITIES));
+    
Assertions.assertThat(status.getStatus()).isEqualTo(ResolverStatus.StatusEnum.SUCCESS);
+    ResolvedPolarisEntity resolvedCatalog = 
resolver.getResolvedReferenceCatalog();
+    Assertions.assertThat(resolvedCatalog).isNotNull();
+    
Assertions.assertThat(resolvedCatalog.getEntity().getName()).isEqualTo("test");
+  }
+
   @Test
   public void testResolveSelectionsRequiresCallerPrincipalForCallerPrincipal() 
{
     Resolver resolver =

Reply via email to