private void validateNoLocationOverlap()

in service/common/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalog.java [1069:1183]


  private void validateNoLocationOverlap(
      String location, List<PolarisEntity> parentPath, String name) {
    ListEntitiesResult siblingNamespacesResult =
        getMetaStoreManager()
            .listEntities(
                callContext.getPolarisCallContext(),
                parentPath.stream().map(PolarisEntity::toCore).collect(Collectors.toList()),
                PolarisEntityType.NAMESPACE,
                PolarisEntitySubType.ANY_SUBTYPE);
    if (!siblingNamespacesResult.isSuccess()) {
      throw new IllegalStateException(
          "Unable to resolve siblings entities to validate location - could not list namespaces");
    }

    // if the entity path has more than just the catalog, check for tables as well as other
    // namespaces
    Optional<NamespaceEntity> parentNamespace =
        parentPath.size() > 1
            ? Optional.of(NamespaceEntity.of(parentPath.getLast()))
            : Optional.empty();

    List<TableIdentifier> siblingTables =
        parentNamespace
            .map(
                ns -> {
                  ListEntitiesResult siblingTablesResult =
                      getMetaStoreManager()
                          .listEntities(
                              callContext.getPolarisCallContext(),
                              parentPath.stream()
                                  .map(PolarisEntity::toCore)
                                  .collect(Collectors.toList()),
                              PolarisEntityType.TABLE_LIKE,
                              PolarisEntitySubType.ANY_SUBTYPE);
                  if (!siblingTablesResult.isSuccess()) {
                    throw new IllegalStateException(
                        "Unable to resolve siblings entities to validate location - could not list tables");
                  }
                  return siblingTablesResult.getEntities().stream()
                      .map(tbl -> TableIdentifier.of(ns.asNamespace(), tbl.getName()))
                      .collect(Collectors.toList());
                })
            .orElse(List.of());

    List<Namespace> siblingNamespaces =
        siblingNamespacesResult.getEntities().stream()
            .map(
                ns -> {
                  String[] nsLevels =
                      parentNamespace
                          .map(parent -> parent.asNamespace().levels())
                          .orElse(new String[0]);
                  String[] newLevels = Arrays.copyOf(nsLevels, nsLevels.length + 1);
                  newLevels[nsLevels.length] = ns.getName();
                  return Namespace.of(newLevels);
                })
            .toList();
    LOGGER.debug(
        "Resolving {} sibling entities to validate location",
        siblingTables.size() + siblingNamespaces.size());
    PolarisResolutionManifest resolutionManifest =
        new PolarisResolutionManifest(
            callContext, entityManager, securityContext, parentPath.getFirst().getName());
    siblingTables.forEach(
        tbl ->
            resolutionManifest.addPath(
                new ResolverPath(
                    PolarisCatalogHelpers.tableIdentifierToList(tbl), PolarisEntityType.TABLE_LIKE),
                tbl));
    siblingNamespaces.forEach(
        ns ->
            resolutionManifest.addPath(
                new ResolverPath(Arrays.asList(ns.levels()), PolarisEntityType.NAMESPACE), ns));
    ResolverStatus status = resolutionManifest.resolveAll();
    if (!status.getStatus().equals(ResolverStatus.StatusEnum.SUCCESS)) {
      String message =
          "Unable to resolve sibling entities to validate location - " + status.getStatus();
      if (status.getStatus().equals(ResolverStatus.StatusEnum.ENTITY_COULD_NOT_BE_RESOLVED)) {
        message += ". Could not resolve entity: " + status.getFailedToResolvedEntityName();
      }
      throw new IllegalStateException(message);
    }

    StorageLocation targetLocation = StorageLocation.of(location);
    Stream.concat(
            siblingTables.stream()
                .filter(tbl -> !tbl.name().equals(name))
                .map(
                    tbl -> {
                      PolarisResolvedPathWrapper resolveTablePath =
                          resolutionManifest.getResolvedPath(tbl);
                      return IcebergTableLikeEntity.of(resolveTablePath.getRawLeafEntity())
                          .getBaseLocation();
                    }),
            siblingNamespaces.stream()
                .filter(ns -> !ns.level(ns.length() - 1).equals(name))
                .map(
                    ns -> {
                      PolarisResolvedPathWrapper resolveNamespacePath =
                          resolutionManifest.getResolvedPath(ns);
                      return NamespaceEntity.of(resolveNamespacePath.getRawLeafEntity())
                          .getBaseLocation();
                    }))
        .filter(java.util.Objects::nonNull)
        .map(StorageLocation::of)
        .forEach(
            siblingLocation -> {
              if (targetLocation.isChildOf(siblingLocation)
                  || siblingLocation.isChildOf(targetLocation)) {
                throw new org.apache.iceberg.exceptions.ForbiddenException(
                    "Unable to create table at location '%s' because it conflicts with existing table or namespace at location '%s'",
                    targetLocation, siblingLocation);
              }
            });
  }