This is an automated email from the ASF dual-hosted git repository.
etudenhoefner pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg.git
The following commit(s) were added to refs/heads/main by this push:
new 1e126e24e2 Core: Use HEAD request to check if namespace exists (#11761)
1e126e24e2 is described below
commit 1e126e24e2c4b639e2509d3f8194e5ceaace6d56
Author: Eduard Tudenhoefner <[email protected]>
AuthorDate: Thu Dec 12 18:17:14 2024 +0100
Core: Use HEAD request to check if namespace exists (#11761)
---
.../org/apache/iceberg/rest/CatalogHandlers.java | 6 +++++
.../java/org/apache/iceberg/rest/RESTCatalog.java | 5 ++++
.../apache/iceberg/rest/RESTSessionCatalog.java | 13 ++++++++++
.../apache/iceberg/rest/RESTCatalogAdapter.java | 8 ++++++
.../org/apache/iceberg/rest/TestRESTCatalog.java | 29 ++++++++++++++++++++++
5 files changed, 61 insertions(+)
diff --git a/core/src/main/java/org/apache/iceberg/rest/CatalogHandlers.java
b/core/src/main/java/org/apache/iceberg/rest/CatalogHandlers.java
index 344308e4ca..aeb3108547 100644
--- a/core/src/main/java/org/apache/iceberg/rest/CatalogHandlers.java
+++ b/core/src/main/java/org/apache/iceberg/rest/CatalogHandlers.java
@@ -163,6 +163,12 @@ public class CatalogHandlers {
.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);
diff --git a/core/src/main/java/org/apache/iceberg/rest/RESTCatalog.java
b/core/src/main/java/org/apache/iceberg/rest/RESTCatalog.java
index 61a7eca272..73a53de906 100644
--- a/core/src/main/java/org/apache/iceberg/rest/RESTCatalog.java
+++ b/core/src/main/java/org/apache/iceberg/rest/RESTCatalog.java
@@ -228,6 +228,11 @@ public class RESTCatalog
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);
diff --git a/core/src/main/java/org/apache/iceberg/rest/RESTSessionCatalog.java
b/core/src/main/java/org/apache/iceberg/rest/RESTSessionCatalog.java
index 8e8bd2bb70..37b70aff3d 100644
--- a/core/src/main/java/org/apache/iceberg/rest/RESTSessionCatalog.java
+++ b/core/src/main/java/org/apache/iceberg/rest/RESTSessionCatalog.java
@@ -652,6 +652,19 @@ public class RESTSessionCatalog extends
BaseViewSessionCatalog
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);
diff --git a/core/src/test/java/org/apache/iceberg/rest/RESTCatalogAdapter.java
b/core/src/test/java/org/apache/iceberg/rest/RESTCatalogAdapter.java
index 94dd45d4f2..2fb4defd12 100644
--- a/core/src/test/java/org/apache/iceberg/rest/RESTCatalogAdapter.java
+++ b/core/src/test/java/org/apache/iceberg/rest/RESTCatalogAdapter.java
@@ -124,6 +124,7 @@ public class RESTCatalogAdapter implements RESTClient {
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(
@@ -331,6 +332,13 @@ public class RESTCatalogAdapter implements RESTClient {
}
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);
diff --git a/core/src/test/java/org/apache/iceberg/rest/TestRESTCatalog.java
b/core/src/test/java/org/apache/iceberg/rest/TestRESTCatalog.java
index 973e394b30..768d6c3777 100644
--- a/core/src/test/java/org/apache/iceberg/rest/TestRESTCatalog.java
+++ b/core/src/test/java/org/apache/iceberg/rest/TestRESTCatalog.java
@@ -2634,6 +2634,35 @@ public class TestRESTCatalog extends
CatalogTests<RESTCatalog> {
.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);