Skip to content

Commit df6e3d6

Browse files
authored
Unblock test listNamespacesWithEmptyNamespace (#1289)
* Unblock test `listNamespacesWithEmptyNamespace` * Use `containsExactly` to simplify the test * Fix empty namespace behavior * Address comments * Block dropping empty namespace * Improve error messages
1 parent 1c924d4 commit df6e3d6

File tree

2 files changed

+56
-19
lines changed

2 files changed

+56
-19
lines changed

quarkus/service/src/test/java/org/apache/polaris/service/quarkus/catalog/IcebergCatalogTest.java

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,11 @@
123123
import org.apache.polaris.service.types.NotificationType;
124124
import org.apache.polaris.service.types.TableUpdateNotification;
125125
import org.assertj.core.api.Assertions;
126+
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
126127
import org.junit.jupiter.api.AfterEach;
127128
import org.junit.jupiter.api.Assumptions;
128129
import org.junit.jupiter.api.BeforeAll;
129130
import org.junit.jupiter.api.BeforeEach;
130-
import org.junit.jupiter.api.Disabled;
131131
import org.junit.jupiter.api.Test;
132132
import org.junit.jupiter.api.TestInfo;
133133
import org.junit.jupiter.params.ParameterizedTest;
@@ -164,6 +164,7 @@ public Map<String, String> getConfigOverrides() {
164164
new Schema(
165165
required(3, "id", Types.IntegerType.get(), "unique ID 🤪"),
166166
required(4, "data", Types.StringType.get()));
167+
private static final String VIEW_QUERY = "select * from ns1.layer1_table";
167168
public static final String CATALOG_NAME = "polaris-catalog";
168169
public static final String TEST_ACCESS_KEY = "test_access_key";
169170
public static final String SECRET_ACCESS_KEY = "secret_access_key";
@@ -386,18 +387,48 @@ public Map<String, BaseResult> purgeRealms(Iterable<String> realms) {
386387
};
387388
}
388389

389-
/** TODO: Unblock this test, see: https://github.com/apache/polaris/issues/1272 */
390-
@Override
391390
@Test
392-
@Disabled(
393-
"""
394-
Disabled because the behavior is not applicable to Polaris.
395-
To unblock:
396-
1) Align Polaris behavior with the superclass by handling empty namespaces the same way, or
397-
2) Modify this test to expect an exception and add a Polaris-specific version.
398-
""")
399-
public void listNamespacesWithEmptyNamespace() {
400-
super.listNamespacesWithEmptyNamespace();
391+
public void testEmptyNamespace() {
392+
IcebergCatalog catalog = catalog();
393+
TableIdentifier tableInRootNs = TableIdentifier.of("table");
394+
String expectedMessage = "Namespace does not exist: ''";
395+
396+
ThrowingCallable createEmptyNamespace = () -> catalog.createNamespace(Namespace.empty());
397+
Assertions.assertThatThrownBy(createEmptyNamespace)
398+
.isInstanceOf(AlreadyExistsException.class)
399+
.hasMessage("Cannot create root namespace, as it already exists implicitly.");
400+
401+
ThrowingCallable dropEmptyNamespace = () -> catalog.dropNamespace(Namespace.empty());
402+
Assertions.assertThatThrownBy(dropEmptyNamespace)
403+
.isInstanceOf(IllegalArgumentException.class)
404+
.hasMessage("Cannot drop root namespace");
405+
406+
ThrowingCallable createTable = () -> catalog.createTable(tableInRootNs, SCHEMA);
407+
Assertions.assertThatThrownBy(createTable)
408+
.isInstanceOf(NoSuchNamespaceException.class)
409+
.hasMessageContaining(expectedMessage);
410+
411+
ThrowingCallable createView =
412+
() ->
413+
catalog
414+
.buildView(tableInRootNs)
415+
.withSchema(SCHEMA)
416+
.withDefaultNamespace(Namespace.empty())
417+
.withQuery("spark", VIEW_QUERY)
418+
.create();
419+
Assertions.assertThatThrownBy(createView)
420+
.isInstanceOf(NoSuchNamespaceException.class)
421+
.hasMessageContaining(expectedMessage);
422+
423+
ThrowingCallable listTables = () -> catalog.listTables(Namespace.empty());
424+
Assertions.assertThatThrownBy(listTables)
425+
.isInstanceOf(NoSuchNamespaceException.class)
426+
.hasMessageContaining(expectedMessage);
427+
428+
ThrowingCallable listViews = () -> catalog.listViews(Namespace.empty());
429+
Assertions.assertThatThrownBy(listViews)
430+
.isInstanceOf(NoSuchNamespaceException.class)
431+
.hasMessageContaining(expectedMessage);
401432
}
402433

403434
@Test

service/common/src/main/java/org/apache/polaris/service/catalog/iceberg/IcebergCatalog.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -462,9 +462,9 @@ public boolean dropTable(TableIdentifier tableIdentifier, boolean purge) {
462462

463463
@Override
464464
public List<TableIdentifier> listTables(Namespace namespace) {
465-
if (!namespaceExists(namespace) && !namespace.isEmpty()) {
465+
if (!namespaceExists(namespace)) {
466466
throw new NoSuchNamespaceException(
467-
"Cannot list tables for namespace. Namespace does not exist: %s", namespace);
467+
"Cannot list tables for namespace. Namespace does not exist: '%s'", namespace);
468468
}
469469

470470
return listTableLike(PolarisEntitySubType.ICEBERG_TABLE, namespace);
@@ -633,11 +633,17 @@ private PolarisResolvedPathWrapper getResolvedParentNamespace(Namespace namespac
633633

634634
@Override
635635
public boolean namespaceExists(Namespace namespace) {
636-
return resolvedEntityView.getResolvedPath(namespace) != null;
636+
return Optional.ofNullable(namespace)
637+
.filter(ns -> !ns.isEmpty())
638+
.map(resolvedEntityView::getResolvedPath)
639+
.isPresent();
637640
}
638641

639642
@Override
640643
public boolean dropNamespace(Namespace namespace) throws NamespaceNotEmptyException {
644+
if (namespace.isEmpty()) {
645+
throw new IllegalArgumentException("Cannot drop root namespace");
646+
}
641647
PolarisResolvedPathWrapper resolvedEntities = resolvedEntityView.getResolvedPath(namespace);
642648
if (resolvedEntities == null) {
643649
return false;
@@ -798,9 +804,9 @@ public void close() throws IOException {
798804

799805
@Override
800806
public List<TableIdentifier> listViews(Namespace namespace) {
801-
if (!namespaceExists(namespace) && !namespace.isEmpty()) {
807+
if (!namespaceExists(namespace)) {
802808
throw new NoSuchNamespaceException(
803-
"Cannot list views for namespace. Namespace does not exist: %s", namespace);
809+
"Cannot list views for namespace. Namespace does not exist: '%s'", namespace);
804810
}
805811

806812
return listTableLike(PolarisEntitySubType.ICEBERG_VIEW, namespace);
@@ -1251,7 +1257,7 @@ public void doCommit(TableMetadata base, TableMetadata metadata) {
12511257
// TODO: Maybe avoid writing metadata if there's definitely a transaction conflict
12521258
if (null == base && !namespaceExists(tableIdentifier.namespace())) {
12531259
throw new NoSuchNamespaceException(
1254-
"Cannot create table %s. Namespace does not exist: %s",
1260+
"Cannot create table '%s'. Namespace does not exist: '%s'",
12551261
tableIdentifier, tableIdentifier.namespace());
12561262
}
12571263

@@ -1492,7 +1498,7 @@ public void doCommit(ViewMetadata base, ViewMetadata metadata) {
14921498
LOGGER.debug("doCommit for view {} with base {}, metadata {}", identifier, base, metadata);
14931499
if (null == base && !namespaceExists(identifier.namespace())) {
14941500
throw new NoSuchNamespaceException(
1495-
"Cannot create view %s. Namespace does not exist: %s",
1501+
"Cannot create view '%s'. Namespace does not exist: '%s'",
14961502
identifier, identifier.namespace());
14971503
}
14981504

0 commit comments

Comments
 (0)