Skip to content

Commit

Permalink
Core: Use HEAD request to check if namespace exists (#11761)
Browse files Browse the repository at this point in the history
  • Loading branch information
nastra authored Dec 12, 2024
1 parent 3053540 commit 1e126e2
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,12 @@ public static CreateNamespaceResponse createNamespace(
.build();
}

public static void namespaceExists(SupportsNamespaces catalog, Namespace namespace) {
if (!catalog.namespaceExists(namespace)) {
throw new NoSuchNamespaceException("Namespace does not exist: %s", namespace);
}
}

public static GetNamespaceResponse loadNamespace(
SupportsNamespaces catalog, Namespace namespace) {
Map<String, String> properties = catalog.loadNamespaceMetadata(namespace);
Expand Down
5 changes: 5 additions & 0 deletions core/src/main/java/org/apache/iceberg/rest/RESTCatalog.java
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,11 @@ public List<Namespace> listNamespaces(Namespace ns) throws NoSuchNamespaceExcept
return nsDelegate.listNamespaces(ns);
}

@Override
public boolean namespaceExists(Namespace namespace) {
return nsDelegate.namespaceExists(namespace);
}

@Override
public Map<String, String> loadNamespaceMetadata(Namespace ns) throws NoSuchNamespaceException {
return nsDelegate.loadNamespaceMetadata(ns);
Expand Down
13 changes: 13 additions & 0 deletions core/src/main/java/org/apache/iceberg/rest/RESTSessionCatalog.java
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,19 @@ public List<Namespace> listNamespaces(SessionContext context, Namespace namespac
return namespaces.build();
}

@Override
public boolean namespaceExists(SessionContext context, Namespace namespace) {
checkNamespaceIsValid(namespace);

try {
client.head(
paths.namespace(namespace), headers(context), ErrorHandlers.namespaceErrorHandler());
return true;
} catch (NoSuchNamespaceException e) {
return false;
}
}

@Override
public Map<String, String> loadNamespaceMetadata(SessionContext context, Namespace ns) {
Endpoint.check(endpoints, Endpoint.V1_LOAD_NAMESPACE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ enum Route {
ResourcePaths.V1_NAMESPACES,
CreateNamespaceRequest.class,
CreateNamespaceResponse.class),
NAMESPACE_EXISTS(HTTPMethod.HEAD, ResourcePaths.V1_NAMESPACE),
LOAD_NAMESPACE(HTTPMethod.GET, ResourcePaths.V1_NAMESPACE, null, GetNamespaceResponse.class),
DROP_NAMESPACE(HTTPMethod.DELETE, ResourcePaths.V1_NAMESPACE),
UPDATE_NAMESPACE(
Expand Down Expand Up @@ -331,6 +332,13 @@ public <T extends RESTResponse> T handleRequest(
}
break;

case NAMESPACE_EXISTS:
if (asNamespaceCatalog != null) {
CatalogHandlers.namespaceExists(asNamespaceCatalog, namespaceFromPathVars(vars));
return null;
}
break;

case LOAD_NAMESPACE:
if (asNamespaceCatalog != null) {
Namespace namespace = namespaceFromPathVars(vars);
Expand Down
29 changes: 29 additions & 0 deletions core/src/test/java/org/apache/iceberg/rest/TestRESTCatalog.java
Original file line number Diff line number Diff line change
Expand Up @@ -2634,6 +2634,35 @@ public void testNoCleanupForNonCleanableReplaceTransaction() {
.isTrue();
}

@Test
public void testNamespaceExistsViaHEADRequest() {
RESTCatalogAdapter adapter = Mockito.spy(new RESTCatalogAdapter(backendCatalog));
RESTCatalog catalog =
new RESTCatalog(SessionCatalog.SessionContext.createEmpty(), (config) -> adapter);
catalog.initialize("test", ImmutableMap.of());

assertThat(catalog.namespaceExists(Namespace.of("non-existing"))).isFalse();

Mockito.verify(adapter)
.execute(
eq(HTTPMethod.GET),
eq("v1/config"),
any(),
any(),
eq(ConfigResponse.class),
any(),
any());
Mockito.verify(adapter)
.execute(
eq(HTTPMethod.HEAD),
eq("v1/namespaces/non-existing"),
any(),
any(),
any(),
any(),
any());
}

private RESTCatalog catalog(RESTCatalogAdapter adapter) {
RESTCatalog catalog =
new RESTCatalog(SessionCatalog.SessionContext.createEmpty(), (config) -> adapter);
Expand Down

0 comments on commit 1e126e2

Please sign in to comment.