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

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


The following commit(s) were added to refs/heads/main by this push:
     new 62ed9c34dc [#7116] fix: properly support nested namespaces in Iceberg 
REST catalog (#7125)
62ed9c34dc is described below

commit 62ed9c34dc0ae9996eb943ab381b46ec15c24584
Author: Sébastien Brochet <[email protected]>
AuthorDate: Mon May 12 02:26:10 2025 +0200

    [#7116] fix: properly support nested namespaces in Iceberg REST catalog 
(#7125)
    
    ### What changes were proposed in this pull request?
    
    The query and path parameters for the namespace were automatically
    url-decoded, while the `decodeNamespace` utility method provided by
    Iceberg expected the namespace to be
    
[url-encoded](https://github.com/apache/iceberg/blob/apache-iceberg-1.5.2/core/src/main/java/org/apache/iceberg/rest/RESTUtil.java#L207-L217).
    
    The solution is to add the `@Encoded` annotation to all API routes to
    explicitly keep the namespace encoded.
    
    I've also fixed and extended the unit tests:
    
    - the namespaces were not properly encoded as expected by the Iceberg
    REST protocol (using `\u001f` as namespace delimiter)
    - I added test cases with nested namespaces
    
    ### Why are the changes needed?
    
    Nested namespaces should work.
    Fix: #7116
    
    ### Does this PR introduce _any_ user-facing change?
    
    No
    
    ### How was this patch tested?
    
    Existing + new unit and integration tests.
    
    Co-authored-by: Sébastien Brochet <[email protected]>
---
 .../service/rest/IcebergNamespaceOperations.java   |  14 +-
 .../service/rest/IcebergTableOperations.java       |  17 +-
 .../service/rest/IcebergViewOperations.java        |  15 +-
 .../integration/test/IcebergRESTHiveCatalogIT.java |   5 +
 .../integration/test/IcebergRESTS3TokenIT.java     |   2 +-
 .../integration/test/IcebergRESTServiceIT.java     | 362 ++++++++++++++-------
 .../service/rest/IcebergNamespaceTestBase.java     |  63 ++--
 .../iceberg/service/rest/IcebergRestTestUtil.java  |  26 +-
 .../iceberg/service/rest/IcebergTestBase.java      |  47 +--
 .../rest/TestIcebergNamespaceOperations.java       |  81 +++--
 .../service/rest/TestIcebergTableOperations.java   | 254 +++++++--------
 .../service/rest/TestIcebergViewOperations.java    | 216 ++++++------
 12 files changed, 654 insertions(+), 448 deletions(-)

diff --git 
a/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergNamespaceOperations.java
 
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergNamespaceOperations.java
index 125fb3d127..d1d4273869 100644
--- 
a/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergNamespaceOperations.java
+++ 
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergNamespaceOperations.java
@@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.DefaultValue;
+import javax.ws.rs.Encoded;
 import javax.ws.rs.GET;
 import javax.ws.rs.HEAD;
 import javax.ws.rs.POST;
@@ -80,7 +81,8 @@ public class IcebergNamespaceOperations {
   @Timed(name = "list-namespace." + MetricNames.HTTP_PROCESS_DURATION, 
absolute = true)
   @ResponseMetered(name = "list-namespace", absolute = true)
   public Response listNamespaces(
-      @DefaultValue("") @QueryParam("parent") String parent, 
@PathParam("prefix") String prefix) {
+      @DefaultValue("") @Encoded() @QueryParam("parent") String parent,
+      @PathParam("prefix") String prefix) {
     String catalogName = IcebergRestUtils.getCatalogName(prefix);
     Namespace parentNamespace =
         parent.isEmpty() ? Namespace.empty() : 
RESTUtil.decodeNamespace(parent);
@@ -98,7 +100,7 @@ public class IcebergNamespaceOperations {
   @Timed(name = "load-namespace." + MetricNames.HTTP_PROCESS_DURATION, 
absolute = true)
   @ResponseMetered(name = "load-namespace", absolute = true)
   public Response loadNamespace(
-      @PathParam("prefix") String prefix, @PathParam("namespace") String 
namespace) {
+      @PathParam("prefix") String prefix, @Encoded() @PathParam("namespace") 
String namespace) {
     String catalogName = IcebergRestUtils.getCatalogName(prefix);
     Namespace icebergNS = RESTUtil.decodeNamespace(namespace);
     LOG.info("Load Iceberg namespace, catalog: {}, namespace: {}", 
catalogName, icebergNS);
@@ -115,7 +117,7 @@ public class IcebergNamespaceOperations {
   @Timed(name = "namespace-exists." + MetricNames.HTTP_PROCESS_DURATION, 
absolute = true)
   @ResponseMetered(name = "namespace-exists", absolute = true)
   public Response namespaceExists(
-      @PathParam("prefix") String prefix, @PathParam("namespace") String 
namespace) {
+      @PathParam("prefix") String prefix, @Encoded() @PathParam("namespace") 
String namespace) {
     String catalogName = IcebergRestUtils.getCatalogName(prefix);
     Namespace icebergNS = RESTUtil.decodeNamespace(namespace);
     LOG.info("Check Iceberg namespace exists, catalog: {}, namespace: {}", 
catalogName, icebergNS);
@@ -135,7 +137,7 @@ public class IcebergNamespaceOperations {
   @Timed(name = "drop-namespace." + MetricNames.HTTP_PROCESS_DURATION, 
absolute = true)
   @ResponseMetered(name = "drop-namespace", absolute = true)
   public Response dropNamespace(
-      @PathParam("prefix") String prefix, @PathParam("namespace") String 
namespace) {
+      @PathParam("prefix") String prefix, @Encoded() @PathParam("namespace") 
String namespace) {
     // todo check if table exists in namespace after table ops is added
     String catalogName = IcebergRestUtils.getCatalogName(prefix);
     Namespace icebergNS = RESTUtil.decodeNamespace(namespace);
@@ -169,7 +171,7 @@ public class IcebergNamespaceOperations {
   @ResponseMetered(name = "update-namespace", absolute = true)
   public Response updateNamespace(
       @PathParam("prefix") String prefix,
-      @PathParam("namespace") String namespace,
+      @Encoded() @PathParam("namespace") String namespace,
       UpdateNamespacePropertiesRequest updateNamespacePropertiesRequest) {
     String catalogName = IcebergRestUtils.getCatalogName(prefix);
     Namespace icebergNS = RESTUtil.decodeNamespace(namespace);
@@ -192,7 +194,7 @@ public class IcebergNamespaceOperations {
   @ResponseMetered(name = "register-table", absolute = true)
   public Response registerTable(
       @PathParam("prefix") String prefix,
-      @PathParam("namespace") String namespace,
+      @Encoded() @PathParam("namespace") String namespace,
       RegisterTableRequest registerTableRequest) {
     String catalogName = IcebergRestUtils.getCatalogName(prefix);
     Namespace icebergNS = RESTUtil.decodeNamespace(namespace);
diff --git 
a/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergTableOperations.java
 
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergTableOperations.java
index 96fc98921f..a8ad24d9e0 100644
--- 
a/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergTableOperations.java
+++ 
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergTableOperations.java
@@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.DefaultValue;
+import javax.ws.rs.Encoded;
 import javax.ws.rs.GET;
 import javax.ws.rs.HEAD;
 import javax.ws.rs.HeaderParam;
@@ -88,7 +89,7 @@ public class IcebergTableOperations {
   @Timed(name = "list-table." + MetricNames.HTTP_PROCESS_DURATION, absolute = 
true)
   @ResponseMetered(name = "list-table", absolute = true)
   public Response listTable(
-      @PathParam("prefix") String prefix, @PathParam("namespace") String 
namespace) {
+      @PathParam("prefix") String prefix, @Encoded() @PathParam("namespace") 
String namespace) {
     String catalogName = IcebergRestUtils.getCatalogName(prefix);
     Namespace icebergNS = RESTUtil.decodeNamespace(namespace);
     LOG.info("List Iceberg tables, catalog: {}, namespace: {}", catalogName, 
icebergNS);
@@ -103,7 +104,7 @@ public class IcebergTableOperations {
   @ResponseMetered(name = "create-table", absolute = true)
   public Response createTable(
       @PathParam("prefix") String prefix,
-      @PathParam("namespace") String namespace,
+      @Encoded() @PathParam("namespace") String namespace,
       CreateTableRequest createTableRequest,
       @HeaderParam(X_ICEBERG_ACCESS_DELEGATION) String accessDelegation) {
     boolean isCredentialVending = isCredentialVending(accessDelegation);
@@ -131,7 +132,7 @@ public class IcebergTableOperations {
   @ResponseMetered(name = "update-table", absolute = true)
   public Response updateTable(
       @PathParam("prefix") String prefix,
-      @PathParam("namespace") String namespace,
+      @Encoded() @PathParam("namespace") String namespace,
       @PathParam("table") String table,
       UpdateTableRequest updateTableRequest) {
     String catalogName = IcebergRestUtils.getCatalogName(prefix);
@@ -158,7 +159,7 @@ public class IcebergTableOperations {
   @ResponseMetered(name = "drop-table", absolute = true)
   public Response dropTable(
       @PathParam("prefix") String prefix,
-      @PathParam("namespace") String namespace,
+      @Encoded() @PathParam("namespace") String namespace,
       @PathParam("table") String table,
       @DefaultValue("false") @QueryParam("purgeRequested") boolean 
purgeRequested) {
     String catalogName = IcebergRestUtils.getCatalogName(prefix);
@@ -169,7 +170,7 @@ public class IcebergTableOperations {
         icebergNS,
         table,
         purgeRequested);
-    TableIdentifier tableIdentifier = TableIdentifier.of(namespace, table);
+    TableIdentifier tableIdentifier = TableIdentifier.of(icebergNS, table);
     IcebergRequestContext context = new 
IcebergRequestContext(httpServletRequest(), catalogName);
     tableOperationDispatcher.dropTable(context, tableIdentifier, 
purgeRequested);
     return IcebergRestUtils.noContent();
@@ -182,7 +183,7 @@ public class IcebergTableOperations {
   @ResponseMetered(name = "load-table", absolute = true)
   public Response loadTable(
       @PathParam("prefix") String prefix,
-      @PathParam("namespace") String namespace,
+      @Encoded() @PathParam("namespace") String namespace,
       @PathParam("table") String table,
       @DefaultValue("all") @QueryParam("snapshots") String snapshots,
       @HeaderParam(X_ICEBERG_ACCESS_DELEGATION) String accessDelegation) {
@@ -213,7 +214,7 @@ public class IcebergTableOperations {
   @ResponseMetered(name = "table-exits", absolute = true)
   public Response tableExists(
       @PathParam("prefix") String prefix,
-      @PathParam("namespace") String namespace,
+      @Encoded() @PathParam("namespace") String namespace,
       @PathParam("table") String table) {
     String catalogName = IcebergRestUtils.getCatalogName(prefix);
     Namespace icebergNS = RESTUtil.decodeNamespace(namespace);
@@ -239,7 +240,7 @@ public class IcebergTableOperations {
   @ResponseMetered(name = "report-table-metrics", absolute = true)
   public Response reportTableMetrics(
       @PathParam("prefix") String prefix,
-      @PathParam("namespace") String namespace,
+      @Encoded() @PathParam("namespace") String namespace,
       @PathParam("table") String table,
       ReportMetricsRequest request) {
     icebergMetricsManager.recordMetric(request.report());
diff --git 
a/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergViewOperations.java
 
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergViewOperations.java
index ddcff8d987..175ab8fbd5 100644
--- 
a/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergViewOperations.java
+++ 
b/iceberg/iceberg-rest-server/src/main/java/org/apache/gravitino/iceberg/service/rest/IcebergViewOperations.java
@@ -27,6 +27,7 @@ import javax.inject.Inject;
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
+import javax.ws.rs.Encoded;
 import javax.ws.rs.GET;
 import javax.ws.rs.HEAD;
 import javax.ws.rs.POST;
@@ -74,7 +75,7 @@ public class IcebergViewOperations {
   @Timed(name = "list-view." + MetricNames.HTTP_PROCESS_DURATION, absolute = 
true)
   @ResponseMetered(name = "list-view", absolute = true)
   public Response listView(
-      @PathParam("prefix") String prefix, @PathParam("namespace") String 
namespace) {
+      @PathParam("prefix") String prefix, @Encoded() @PathParam("namespace") 
String namespace) {
     String catalogName = IcebergRestUtils.getCatalogName(prefix);
     Namespace icebergNS = RESTUtil.decodeNamespace(namespace);
     LOG.info("List Iceberg views, catalog: {}, namespace: {}", catalogName, 
icebergNS);
@@ -89,7 +90,7 @@ public class IcebergViewOperations {
   @ResponseMetered(name = "create-view", absolute = true)
   public Response createView(
       @PathParam("prefix") String prefix,
-      @PathParam("namespace") String namespace,
+      @Encoded() @PathParam("namespace") String namespace,
       CreateViewRequest createViewRequest) {
     String catalogName = IcebergRestUtils.getCatalogName(prefix);
     Namespace icebergNS = RESTUtil.decodeNamespace(namespace);
@@ -112,7 +113,7 @@ public class IcebergViewOperations {
   @ResponseMetered(name = "load-view", absolute = true)
   public Response loadView(
       @PathParam("prefix") String prefix,
-      @PathParam("namespace") String namespace,
+      @Encoded() @PathParam("namespace") String namespace,
       @PathParam("view") String view) {
     String catalogName = IcebergRestUtils.getCatalogName(prefix);
     Namespace icebergNS = RESTUtil.decodeNamespace(namespace);
@@ -132,7 +133,7 @@ public class IcebergViewOperations {
   @ResponseMetered(name = "replace-view", absolute = true)
   public Response replaceView(
       @PathParam("prefix") String prefix,
-      @PathParam("namespace") String namespace,
+      @Encoded() @PathParam("namespace") String namespace,
       @PathParam("view") String view,
       UpdateTableRequest replaceViewRequest) {
     String catalogName = IcebergRestUtils.getCatalogName(prefix);
@@ -157,13 +158,13 @@ public class IcebergViewOperations {
   @ResponseMetered(name = "drop-view", absolute = true)
   public Response dropView(
       @PathParam("prefix") String prefix,
-      @PathParam("namespace") String namespace,
+      @Encoded() @PathParam("namespace") String namespace,
       @PathParam("view") String view) {
     String catalogName = IcebergRestUtils.getCatalogName(prefix);
     Namespace icebergNS = RESTUtil.decodeNamespace(namespace);
     LOG.info(
         "Drop Iceberg view, catalog: {}, namespace: {}, view: {}", 
catalogName, icebergNS, view);
-    TableIdentifier viewIdentifier = TableIdentifier.of(namespace, view);
+    TableIdentifier viewIdentifier = TableIdentifier.of(icebergNS, view);
     IcebergRequestContext context = new 
IcebergRequestContext(httpServletRequest(), catalogName);
     viewOperationDispatcher.dropView(context, viewIdentifier);
     return IcebergRestUtils.noContent();
@@ -176,7 +177,7 @@ public class IcebergViewOperations {
   @ResponseMetered(name = "view-exits", absolute = true)
   public Response viewExists(
       @PathParam("prefix") String prefix,
-      @PathParam("namespace") String namespace,
+      @Encoded() @PathParam("namespace") String namespace,
       @PathParam("view") String view) {
     String catalogName = IcebergRestUtils.getCatalogName(prefix);
     Namespace icebergNS = RESTUtil.decodeNamespace(namespace);
diff --git 
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTHiveCatalogIT.java
 
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTHiveCatalogIT.java
index 338a7e5a6f..9c39a58a81 100644
--- 
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTHiveCatalogIT.java
+++ 
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTHiveCatalogIT.java
@@ -34,6 +34,11 @@ import org.junit.jupiter.api.TestInstance.Lifecycle;
 public class IcebergRESTHiveCatalogIT extends IcebergRESTServiceIT {
   protected static final ContainerSuite containerSuite = 
ContainerSuite.getInstance();
 
+  @Override
+  protected boolean supportsNestedNamespaces() {
+    return false;
+  }
+
   public IcebergRESTHiveCatalogIT() {
     catalogType = IcebergCatalogBackend.HIVE;
   }
diff --git 
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTS3TokenIT.java
 
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTS3TokenIT.java
index 989dce834c..b393833db8 100644
--- 
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTS3TokenIT.java
+++ 
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTS3TokenIT.java
@@ -151,7 +151,7 @@ public class IcebergRESTS3TokenIT extends 
IcebergRESTJdbcCatalogIT {
 
   @Test
   void testCredentialWithMultiLocations() {
-    String namespaceName = ICEBERG_REST_NS_PREFIX + "credential";
+    String namespaceName = getTestNamespace("credential");
     String tableName = namespaceName + ".multi_location";
 
     String writeDataPath = this.s3Warehouse + "/test_data_location";
diff --git 
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTServiceIT.java
 
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTServiceIT.java
index f8bd016a94..5d7fc3e314 100644
--- 
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTServiceIT.java
+++ 
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/integration/test/IcebergRESTServiceIT.java
@@ -24,6 +24,7 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import javax.annotation.Nullable;
 import org.apache.iceberg.exceptions.BadRequestException;
 import org.apache.iceberg.exceptions.ValidationException;
 import org.apache.spark.sql.AnalysisException;
@@ -45,14 +46,50 @@ import org.junit.jupiter.api.condition.EnabledIf;
 @TestInstance(Lifecycle.PER_CLASS)
 public abstract class IcebergRESTServiceIT extends IcebergRESTServiceBaseIT {
 
-  protected static final String ICEBERG_REST_NS_PREFIX = "iceberg_rest_";
+  protected boolean supportsNestedNamespaces() {
+    return true;
+  }
+
+  protected String getTestNamespace() {
+    return getTestNamespace(null);
+  }
+
+  protected String getTestNamespace(@Nullable String childNamespace) {
+    String separator;
+    String parentNamespace;
+
+    if (supportsNestedNamespaces()) {
+      parentNamespace = "iceberg_rest.nested.table_test";
+      separator = ".";
+    } else {
+      parentNamespace = "iceberg_rest";
+      separator = "_";
+    }
+
+    if (childNamespace != null) {
+      return parentNamespace + separator + childNamespace;
+    } else {
+      return parentNamespace;
+    }
+  }
 
   @BeforeAll
   void prepareSQLContext() {
     // use rest catalog
     sql("USE rest");
     purgeAllIcebergTestNamespaces();
-    sql("CREATE DATABASE IF NOT EXISTS iceberg_rest_table_test");
+    if (supportsNestedNamespaces()) {
+      // create all parent namespaces
+      final String[] parentNamespace = {""};
+      Arrays.stream(getTestNamespace().split("\\."))
+          .forEach(
+              ns -> {
+                sql("CREATE DATABASE IF NOT EXISTS " + parentNamespace[0] + 
ns);
+                parentNamespace[0] += ns + ".";
+              });
+    }
+
+    sql(String.format("CREATE DATABASE IF NOT EXISTS %s", getTestNamespace()));
   }
 
   @AfterAll
@@ -60,28 +97,59 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
     purgeAllIcebergTestNamespaces();
   }
 
+  private boolean namespaceExists(String namespace) {
+    try {
+      sql(String.format("DESCRIBE DATABASE %s ", namespace));
+      return true;
+    } catch (Exception e) {
+      // can't directly catch NoSuchNamespaceException because it's a checked 
exception,
+      // and it's not thrown by sparkSession.sql
+      if (e instanceof NoSuchNamespaceException) {
+        // ignore non existing namespace
+        return false;
+      } else {
+        throw e;
+      }
+    }
+  }
+
   private void purgeTable(String namespace, String table) {
     sql(String.format("DROP TABLE %s.%s PURGE", namespace, table));
   }
 
-  private void purgeNameSpace(String namespace) {
+  private void purgeNamespace(String namespace) {
+    if (!namespaceExists(namespace)) {
+      return;
+    }
+
+    if (supportsNestedNamespaces()) {
+      // list and purge child namespaces
+      List<Object[]> childNamespaces = sql(String.format("SHOW DATABASES IN %s 
", namespace));
+      Set<String> childNamespacesString = convertToStringSet(childNamespaces, 
0);
+      childNamespacesString.forEach(this::purgeNamespace);
+    }
+
     Set<String> tables = convertToStringSet(sql("SHOW TABLES IN " + 
namespace), 1);
     tables.forEach(table -> purgeTable(namespace, table));
     sql("DROP database " + namespace);
   }
 
   private void purgeAllIcebergTestNamespaces() {
-    List<Object[]> databases =
-        sql(String.format("SHOW DATABASES like '%s*'", 
ICEBERG_REST_NS_PREFIX));
-    Set<String> databasesString = convertToStringSet(databases, 0);
-    databasesString.stream()
-        .filter(ns -> ns.startsWith(ICEBERG_REST_NS_PREFIX))
-        .forEach(ns -> purgeNameSpace(ns));
+    if (supportsNestedNamespaces()) {
+      purgeNamespace(getTestNamespace());
+    } else {
+      List<Object[]> databases =
+          sql(String.format("SHOW DATABASES like '%s*'", getTestNamespace()));
+      Set<String> databasesString = convertToStringSet(databases, 0);
+      databasesString.stream()
+          .filter(ns -> ns.startsWith(getTestNamespace() + '.'))
+          .forEach(this::purgeNamespace);
+    }
   }
 
   @Test
   void testCreateNamespace() {
-    String namespaceName = ICEBERG_REST_NS_PREFIX + "create";
+    String namespaceName = getTestNamespace("create");
     sql(
         String.format(
             "CREATE DATABASE %s COMMENT 'This is customer database' "
@@ -109,19 +177,28 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
 
   @Test
   void testListNamespace() {
-    sql(String.format("CREATE DATABASE %slist_foo1", ICEBERG_REST_NS_PREFIX));
-    sql(String.format("CREATE DATABASE %slist_foo2", ICEBERG_REST_NS_PREFIX));
-    List<Object[]> databases =
-        sql(String.format("SHOW DATABASES like '%slist_foo*'", 
ICEBERG_REST_NS_PREFIX));
+    String separator = supportsNestedNamespaces() ? "." : "_";
+    sql(String.format("CREATE DATABASE %s%slist_foo1", getTestNamespace(), 
separator));
+    sql(String.format("CREATE DATABASE %s%slist_foo2", getTestNamespace(), 
separator));
+    List<Object[]> databases;
+    if (supportsNestedNamespaces()) {
+      databases = sql(String.format("SHOW DATABASES IN %s LIKE '*list_foo*'", 
getTestNamespace()));
+    } else {
+      databases =
+          sql(String.format("SHOW DATABASES '%s%slist_foo*'", 
getTestNamespace(), separator));
+    }
+
     Set<String> databasesString = convertToStringSet(databases, 0);
     Assertions.assertEquals(
-        ImmutableSet.of(ICEBERG_REST_NS_PREFIX + "list_foo1", 
ICEBERG_REST_NS_PREFIX + "list_foo2"),
+        ImmutableSet.of(
+            getTestNamespace() + separator + "list_foo1",
+            getTestNamespace() + separator + "list_foo2"),
         databasesString);
   }
 
   @Test
   void testDropNameSpace() {
-    String namespaceName = ICEBERG_REST_NS_PREFIX + "foo1";
+    String namespaceName = getTestNamespace("foo1");
     sql("CREATE DATABASE IF NOT EXISTS " + namespaceName);
     sql("DESC DATABASE " + namespaceName);
     sql(
@@ -145,7 +222,7 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
 
   @Test
   void testNameSpaceProperties() {
-    String namespaceName = ICEBERG_REST_NS_PREFIX + "alter_foo1";
+    String namespaceName = getTestNamespace("alter_foo1");
     sql("DROP DATABASE if exists " + namespaceName);
     sql("CREATE DATABASE if not exists " + namespaceName);
     sql(String.format("ALTER DATABASE %s SET PROPERTIES(id = 2)", 
namespaceName));
@@ -164,7 +241,7 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
 
   @Test
   void testDML() {
-    String namespaceName = ICEBERG_REST_NS_PREFIX + "dml";
+    String namespaceName = getTestNamespace("dml");
     String tableName = namespaceName + ".test";
     sql("CREATE DATABASE IF NOT EXISTS " + namespaceName);
     sql(
@@ -196,10 +273,11 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
   @Test
   void testCreateTable() {
     sql(
-        "CREATE TABLE iceberg_rest_table_test.create_foo1"
+        String.format("CREATE TABLE %s.create_foo1", getTestNamespace())
             + "( id bigint, data string, ts timestamp)"
             + "USING iceberg PARTITIONED BY (bucket(16, id), days(ts))");
-    Map<String, String> tableInfo = 
getTableInfo("iceberg_rest_table_test.create_foo1");
+    Map<String, String> tableInfo =
+        getTableInfo(String.format("%s.create_foo1", getTestNamespace()));
     Map<String, String> m =
         ImmutableMap.of(
             "id", "bigint",
@@ -212,25 +290,27 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
 
     Assertions.assertThrowsExactly(
         TableAlreadyExistsException.class,
-        () -> sql("CREATE TABLE iceberg_rest_table_test.create_foo1"));
+        () -> sql(String.format("CREATE TABLE %s.create_foo1", 
getTestNamespace())));
   }
 
   @Test
   void testDropTable() {
     sql(
-        "CREATE TABLE iceberg_rest_table_test.drop_foo1"
+        String.format("CREATE TABLE %s.drop_foo1", getTestNamespace())
             + "(id bigint COMMENT 'unique id',data string) using iceberg");
-    sql("DROP TABLE iceberg_rest_table_test.drop_foo1");
+    sql(String.format("DROP TABLE %s.drop_foo1", getTestNamespace()));
     Assertions.assertThrowsExactly(
-        AnalysisException.class, () -> sql("DESC TABLE 
iceberg_rest_table_test.drop_foo1"));
+        AnalysisException.class,
+        () -> sql(String.format("DESC TABLE %s.drop_foo1", 
getTestNamespace())));
 
     Assertions.assertThrowsExactly(
-        NoSuchTableException.class, () -> sql("DROP TABLE 
iceberg_rest_table_test.drop_foo1"));
+        NoSuchTableException.class,
+        () -> sql(String.format("DROP TABLE %s.drop_foo1", 
getTestNamespace())));
   }
 
   @Test
   void testListTable() {
-    String namespaceName = ICEBERG_REST_NS_PREFIX + "list_db";
+    String namespaceName = getTestNamespace("list_db");
     sql("CREATE DATABASE if not exists " + namespaceName);
     sql(
         String.format(
@@ -248,49 +328,52 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
   @Test
   void testRenameTable() {
     sql(
-        "CREATE TABLE iceberg_rest_table_test.rename_foo1"
+        String.format("CREATE TABLE %s.rename_foo1", getTestNamespace())
             + "(id bigint COMMENT 'unique id',data string) using iceberg");
     sql(
-        "ALTER TABLE iceberg_rest_table_test.rename_foo1 "
-            + "RENAME TO iceberg_rest_table_test.rename_foo2");
-    sql("desc table iceberg_rest_table_test.rename_foo2");
+        String.format("ALTER TABLE %s.rename_foo1 ", getTestNamespace())
+            + String.format("RENAME TO %s.rename_foo2", getTestNamespace()));
+    sql(String.format("desc table %s.rename_foo2", getTestNamespace()));
     Assertions.assertThrowsExactly(
-        AnalysisException.class, () -> sql("desc table 
iceberg_rest_table_test.rename_foo1"));
+        AnalysisException.class,
+        () -> sql(String.format("desc table %s.rename_foo1", 
getTestNamespace())));
 
     sql(
-        "CREATE TABLE iceberg_rest_table_test.rename_foo1"
+        String.format("CREATE TABLE %s.rename_foo1", getTestNamespace())
             + "(id bigint COMMENT 'unique id',data string) using iceberg");
 
     Assertions.assertThrowsExactly(
         TableAlreadyExistsException.class,
         () ->
             sql(
-                "ALTER TABLE iceberg_rest_table_test.rename_foo2 "
-                    + "RENAME TO iceberg_rest_table_test.rename_foo1"));
+                String.format("ALTER TABLE %s.rename_foo2 ", 
getTestNamespace())
+                    + String.format("RENAME TO %s.rename_foo1", 
getTestNamespace())));
   }
 
   @Test
   void testSetTableProperties() {
     sql(
-        "CREATE TABLE iceberg_rest_table_test.set_foo1"
+        String.format("CREATE TABLE %s.set_foo1", getTestNamespace())
             + " (id bigint COMMENT 'unique id',data string) using iceberg");
     sql(
-        "ALTER TABLE iceberg_rest_table_test.set_foo1 SET TBLPROPERTIES "
+        String.format("ALTER TABLE %s.set_foo1 SET TBLPROPERTIES ", 
getTestNamespace())
             + "('read.split.target-size'='268435456')");
-    Map<String, String> m = getTableInfo("iceberg_rest_table_test.set_foo1");
+    Map<String, String> m = getTableInfo(getTestNamespace() + ".set_foo1");
     Assertions.assertTrue(
         m.getOrDefault("Table Properties", 
"").contains("read.split.target-size=268435456"));
 
     sql(
-        "ALTER TABLE iceberg_rest_table_test.set_foo1 "
+        String.format("ALTER TABLE %s.set_foo1 ", getTestNamespace())
             + "UNSET TBLPROPERTIES ('read.split.target-size')");
-    m = getTableInfo("iceberg_rest_table_test.set_foo1");
+    m = getTableInfo(getTestNamespace() + ".set_foo1");
     Assertions.assertFalse(
         m.getOrDefault("Table Properties", "read.split.target-size")
             .contains("read.split.target-size"));
 
-    sql("ALTER TABLE iceberg_rest_table_test.set_foo1 SET TBLPROPERTIES 
('comment'='a')");
-    m = getTableInfo("iceberg_rest_table_test.set_foo1");
+    sql(
+        String.format(
+            "ALTER TABLE %s.set_foo1 SET TBLPROPERTIES ('comment'='a')", 
getTestNamespace()));
+    m = getTableInfo(getTestNamespace() + ".set_foo1");
     // comment is hidden
     Assertions.assertFalse(m.getOrDefault("Table Properties", 
"").contains("comment=a"));
   }
@@ -298,26 +381,30 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
   @Test
   void testAddColumns() {
     sql(
-        "CREATE TABLE iceberg_rest_table_test.add_foo1"
+        String.format("CREATE TABLE %s.add_foo1", getTestNamespace())
             + " (id string COMMENT 'unique id',data string) using iceberg");
 
     Assertions.assertThrowsExactly(
         AnalysisException.class,
         () ->
             sql(
-                "ALTER TABLE iceberg_rest_table_test.add_foo1 "
+                String.format("ALTER TABLE %s.add_foo1 ", getTestNamespace())
                     + "ADD COLUMNS foo_after String After not_exits"));
 
-    sql("ALTER TABLE iceberg_rest_table_test.add_foo1 ADD COLUMNS foo_after 
String After id");
-    List<String> columns = getTableColumns("iceberg_rest_table_test.add_foo1");
+    sql(
+        String.format(
+            "ALTER TABLE %s.add_foo1 ADD COLUMNS foo_after String After id", 
getTestNamespace()));
+    List<String> columns = getTableColumns(getTestNamespace() + ".add_foo1");
     Assertions.assertEquals(Arrays.asList("id", "foo_after", "data"), columns);
 
-    sql("ALTER TABLE iceberg_rest_table_test.add_foo1 ADD COLUMNS foo_last 
String");
-    columns = getTableColumns("iceberg_rest_table_test.add_foo1");
+    sql(String.format("ALTER TABLE %s.add_foo1 ADD COLUMNS foo_last String", 
getTestNamespace()));
+    columns = getTableColumns(getTestNamespace() + ".add_foo1");
     Assertions.assertEquals(Arrays.asList("id", "foo_after", "data", 
"foo_last"), columns);
 
-    sql("ALTER TABLE iceberg_rest_table_test.add_foo1 ADD COLUMNS foo_first 
String FIRST");
-    columns = getTableColumns("iceberg_rest_table_test.add_foo1");
+    sql(
+        String.format(
+            "ALTER TABLE %s.add_foo1 ADD COLUMNS foo_first String FIRST", 
getTestNamespace()));
+    columns = getTableColumns(getTestNamespace() + ".add_foo1");
     Assertions.assertEquals(
         Arrays.asList("foo_first", "id", "foo_after", "data", "foo_last"), 
columns);
   }
@@ -325,11 +412,13 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
   @Test
   void testRenameColumns() {
     sql(
-        "CREATE TABLE iceberg_rest_table_test.renameC_foo1"
+        String.format("CREATE TABLE %s.renameC_foo1", getTestNamespace())
             + " (id bigint COMMENT 'unique id',data string) using iceberg");
-    sql("ALTER TABLE iceberg_rest_table_test.renameC_foo1 RENAME COLUMN data 
TO data1");
+    sql(
+        String.format(
+            "ALTER TABLE %s.renameC_foo1 RENAME COLUMN data TO data1", 
getTestNamespace()));
 
-    Map<String, String> tableInfo = 
getTableInfo("iceberg_rest_table_test.renameC_foo1");
+    Map<String, String> tableInfo = getTableInfo(getTestNamespace() + 
".renameC_foo1");
     Map<String, String> m =
         ImmutableMap.of(
             "id", "bigint",
@@ -341,15 +430,18 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
   @Test
   void testDropColumns() {
     sql(
-        "CREATE TABLE iceberg_rest_table_test.dropC_foo1 "
+        String.format("CREATE TABLE %s.dropC_foo1 ", getTestNamespace())
             + "(id bigint COMMENT 'unique id',data string) using iceberg");
 
     Assertions.assertThrowsExactly(
         AnalysisException.class,
-        () -> sql("ALTER TABLE iceberg_rest_table_test.dropC_foo1 DROP COLUMNS 
not_exits"));
+        () ->
+            sql(
+                String.format(
+                    "ALTER TABLE %s.dropC_foo1 DROP COLUMNS not_exits", 
getTestNamespace())));
 
-    sql("ALTER TABLE iceberg_rest_table_test.dropC_foo1 DROP COLUMNS data");
-    Map<String, String> tableInfo = 
getTableInfo("iceberg_rest_table_test.dropC_foo1");
+    sql(String.format("ALTER TABLE %s.dropC_foo1 DROP COLUMNS data", 
getTestNamespace()));
+    Map<String, String> tableInfo = getTableInfo(getTestNamespace() + 
".dropC_foo1");
     Map<String, String> m = ImmutableMap.of("id", "bigint");
     checkMapContains(m, tableInfo);
     Assertions.assertFalse(m.containsKey("data"));
@@ -358,14 +450,16 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
   @Test
   void testUpdateColumnType() {
     sql(
-        "CREATE TABLE iceberg_rest_table_test.updateC_foo1 "
+        String.format("CREATE TABLE %s.updateC_foo1 ", getTestNamespace())
             + "(id int COMMENT 'unique id',data string) using iceberg");
-    Map<String, String> tableInfo = 
getTableInfo("iceberg_rest_table_test.updateC_foo1");
+    Map<String, String> tableInfo = getTableInfo(getTestNamespace() + 
".updateC_foo1");
     Map<String, String> m = ImmutableMap.of("id", "int");
     checkMapContains(m, tableInfo);
 
-    sql("ALTER TABLE iceberg_rest_table_test.updateC_foo1 ALTER COLUMN id TYPE 
bigint");
-    tableInfo = getTableInfo("iceberg_rest_table_test.updateC_foo1");
+    sql(
+        String.format(
+            "ALTER TABLE %s.updateC_foo1 ALTER COLUMN id TYPE bigint", 
getTestNamespace()));
+    tableInfo = getTableInfo(getTestNamespace() + ".updateC_foo1");
     m = ImmutableMap.of("id", "bigint");
     checkMapContains(m, tableInfo);
   }
@@ -373,30 +467,38 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
   @Test
   void testUpdateColumnPosition() {
     sql(
-        "CREATE TABLE iceberg_rest_table_test.updateP_foo1 "
+        String.format("CREATE TABLE %s.updateP_foo1 ", getTestNamespace())
             + "(id string COMMENT 'unique id',data string) using iceberg");
-    List<String> columns = 
getTableColumns("iceberg_rest_table_test.updateP_foo1");
+    List<String> columns = getTableColumns(getTestNamespace() + 
".updateP_foo1");
     Assertions.assertEquals(Arrays.asList("id", "data"), columns);
 
-    sql("ALTER TABLE iceberg_rest_table_test.updateP_foo1 ALTER COLUMN id 
AFTER data");
-    columns = getTableColumns("iceberg_rest_table_test.updateP_foo1");
+    sql(
+        String.format(
+            "ALTER TABLE %s.updateP_foo1 ALTER COLUMN id AFTER data", 
getTestNamespace()));
+    columns = getTableColumns(getTestNamespace() + ".updateP_foo1");
     Assertions.assertEquals(Arrays.asList("data", "id"), columns);
 
-    sql("ALTER TABLE iceberg_rest_table_test.updateP_foo1 ALTER COLUMN id 
FIRST");
-    columns = getTableColumns("iceberg_rest_table_test.updateP_foo1");
+    sql(String.format("ALTER TABLE %s.updateP_foo1 ALTER COLUMN id FIRST", 
getTestNamespace()));
+    columns = getTableColumns(getTestNamespace() + ".updateP_foo1");
     Assertions.assertEquals(Arrays.asList("id", "data"), columns);
   }
 
   @Test
   void testAlterPartitions() {
     sql(
-        "CREATE TABLE iceberg_rest_table_test.part_foo1"
+        String.format("CREATE TABLE %s.part_foo1", getTestNamespace())
             + "( id bigint, data string, ts timestamp) USING iceberg");
-    sql("ALTER TABLE iceberg_rest_table_test.part_foo1 ADD PARTITION FIELD 
bucket(16, id)");
-    sql("ALTER TABLE iceberg_rest_table_test.part_foo1 ADD PARTITION FIELD 
truncate(4, data)");
-    sql("ALTER TABLE iceberg_rest_table_test.part_foo1 ADD PARTITION FIELD 
years(ts)");
+    sql(
+        String.format(
+            "ALTER TABLE %s.part_foo1 ADD PARTITION FIELD bucket(16, id)", 
getTestNamespace()));
+    sql(
+        String.format(
+            "ALTER TABLE %s.part_foo1 ADD PARTITION FIELD truncate(4, data)", 
getTestNamespace()));
+    sql(
+        String.format(
+            "ALTER TABLE %s.part_foo1 ADD PARTITION FIELD years(ts)", 
getTestNamespace()));
 
-    Map<String, String> tableInfo = 
getTableInfo("iceberg_rest_table_test.part_foo1");
+    Map<String, String> tableInfo = getTableInfo(getTestNamespace() + 
".part_foo1");
     Map<String, String> partitions =
         ImmutableMap.of(
             "Part 0", "bucket(16, id)",
@@ -409,10 +511,12 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
         IllegalArgumentException.class,
         () ->
             sql(
-                "ALTER TABLE iceberg_rest_table_test.part_foo1 "
+                String.format("ALTER TABLE %s.part_foo1 ", getTestNamespace())
                     + "DROP PARTITION FIELD bucket(8, id)"));
-    sql("ALTER TABLE iceberg_rest_table_test.part_foo1 DROP PARTITION FIELD 
bucket(16, id)");
-    tableInfo = getTableInfo("iceberg_rest_table_test.part_foo1");
+    sql(
+        String.format(
+            "ALTER TABLE %s.part_foo1 DROP PARTITION FIELD bucket(16, id)", 
getTestNamespace()));
+    tableInfo = getTableInfo(getTestNamespace() + ".part_foo1");
     partitions =
         ImmutableMap.of(
             "Part 0", "truncate(4, data)",
@@ -424,12 +528,12 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
         IllegalArgumentException.class,
         () ->
             sql(
-                "ALTER TABLE iceberg_rest_table_test.part_foo1 "
+                String.format("ALTER TABLE %s.part_foo1 ", getTestNamespace())
                     + "REPLACE PARTITION FIELD months(ts) WITH days(ts)"));
     sql(
-        "ALTER TABLE iceberg_rest_table_test.part_foo1 "
+        String.format("ALTER TABLE %s.part_foo1 ", getTestNamespace())
             + "REPLACE PARTITION FIELD years(ts) WITH days(ts)");
-    tableInfo = getTableInfo("iceberg_rest_table_test.part_foo1");
+    tableInfo = getTableInfo(getTestNamespace() + ".part_foo1");
     partitions =
         ImmutableMap.of(
             "Part 0", "truncate(4, data)",
@@ -441,23 +545,28 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
   @Test
   void testAlterSortBy() {
     sql(
-        "CREATE TABLE iceberg_rest_table_test.sort_foo1"
+        String.format("CREATE TABLE %s.sort_foo1", getTestNamespace())
             + "( id bigint, data string, ts timestamp) USING iceberg");
     Assertions.assertThrowsExactly(
         ValidationException.class,
-        () -> sql("ALTER TABLE iceberg_rest_table_test.sort_foo1 WRITE ORDERED 
BY xx, id"));
+        () ->
+            sql(
+                String.format(
+                    "ALTER TABLE %s.sort_foo1 WRITE ORDERED BY xx, id", 
getTestNamespace())));
     sql(
-        "ALTER TABLE iceberg_rest_table_test.sort_foo1 "
+        String.format("ALTER TABLE %s.sort_foo1 ", getTestNamespace())
             + "WRITE ORDERED BY data ASC NULLS FIRST, id ASC NULLS FIRST");
-    Map<String, String> tableInfo = 
getTableInfo("iceberg_rest_table_test.sort_foo1");
+    Map<String, String> tableInfo = getTableInfo(getTestNamespace() + 
".sort_foo1");
     Assertions.assertTrue(
         tableInfo
             .get("Table Properties")
             .contains("sort-order=data ASC NULLS FIRST, id ASC NULLS FIRST,"));
 
     // replace with new one
-    sql("ALTER TABLE iceberg_rest_table_test.sort_foo1 WRITE ORDERED BY ts ASC 
NULLS FIRST");
-    tableInfo = getTableInfo("iceberg_rest_table_test.sort_foo1");
+    sql(
+        String.format(
+            "ALTER TABLE %s.sort_foo1 WRITE ORDERED BY ts ASC NULLS FIRST", 
getTestNamespace()));
+    tableInfo = getTableInfo(getTestNamespace() + ".sort_foo1");
     Assertions.assertTrue(
         tableInfo.get("Table Properties").contains("sort-order=ts ASC NULLS 
FIRST,"));
   }
@@ -465,10 +574,12 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
   @Test
   void testAlterPartitionBy() {
     sql(
-        "CREATE TABLE iceberg_rest_table_test.partby_foo1"
+        String.format("CREATE TABLE %s.partby_foo1", getTestNamespace())
             + "( id bigint, data string, ts timestamp) USING iceberg");
-    sql("ALTER TABLE iceberg_rest_table_test.partby_foo1 WRITE DISTRIBUTED BY 
PARTITION");
-    Map<String, String> tableInfo = 
getTableInfo("iceberg_rest_table_test.partby_foo1");
+    sql(
+        String.format(
+            "ALTER TABLE %s.partby_foo1 WRITE DISTRIBUTED BY PARTITION", 
getTestNamespace()));
+    Map<String, String> tableInfo = getTableInfo(getTestNamespace() + 
".partby_foo1");
     Assertions.assertTrue(
         tableInfo.get("Table 
Properties").contains("write.distribution-mode=hash"));
   }
@@ -476,14 +587,18 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
   @Test
   void testAlterIdentifier() {
     sql(
-        "CREATE TABLE iceberg_rest_table_test.identifier_foo1"
+        String.format("CREATE TABLE %s.identifier_foo1", getTestNamespace())
             + "( id bigint NOT NULL, data string, ts timestamp) USING 
iceberg");
-    sql("ALTER TABLE iceberg_rest_table_test.identifier_foo1 SET IDENTIFIER 
FIELDS id");
-    Map<String, String> tableInfo = 
getTableInfo("iceberg_rest_table_test.identifier_foo1");
+    sql(
+        String.format(
+            "ALTER TABLE %s.identifier_foo1 SET IDENTIFIER FIELDS id", 
getTestNamespace()));
+    Map<String, String> tableInfo = getTableInfo(getTestNamespace() + 
".identifier_foo1");
     Assertions.assertTrue(tableInfo.get("Table 
Properties").contains("identifier-fields=[id]"));
 
-    sql("ALTER TABLE iceberg_rest_table_test.identifier_foo1 DROP IDENTIFIER 
FIELDS id");
-    tableInfo = getTableInfo("iceberg_rest_table_test.identifier_foo1");
+    sql(
+        String.format(
+            "ALTER TABLE %s.identifier_foo1 DROP IDENTIFIER FIELDS id", 
getTestNamespace()));
+    tableInfo = getTableInfo(getTestNamespace() + ".identifier_foo1");
     Assertions.assertFalse(tableInfo.get("Table 
Properties").contains("identifier-fields"));
 
     // java.lang.IllegalArgumentException: Cannot add field id as an 
identifier field: not a
@@ -491,7 +606,10 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
     Assertions.assertThrowsExactly(
         IllegalArgumentException.class,
         () ->
-            sql("ALTER TABLE iceberg_rest_table_test.identifier_foo1 SET 
IDENTIFIER FIELDS data"));
+            sql(
+                String.format(
+                    "ALTER TABLE %s.identifier_foo1 SET IDENTIFIER FIELDS 
data",
+                    getTestNamespace())));
   }
 
   @Test
@@ -502,22 +620,27 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
   @EnabledIf("catalogTypeNotMemory")
   void testSnapshot() {
     sql(
-        "CREATE TABLE iceberg_rest_table_test.snapshot_foo1 "
+        String.format("CREATE TABLE %s.snapshot_foo1 ", getTestNamespace())
             + "(id bigint COMMENT 'unique id',data string) using iceberg");
-    sql(" INSERT INTO iceberg_rest_table_test.snapshot_foo1 VALUES (1, 'a'), 
(2, 'b');");
-    sql(" INSERT INTO iceberg_rest_table_test.snapshot_foo1 VALUES (3, 'c'), 
(4, 'd');");
+    sql(
+        String.format(
+            " INSERT INTO %s.snapshot_foo1 VALUES (1, 'a'), (2, 'b');", 
getTestNamespace()));
+    sql(
+        String.format(
+            " INSERT INTO %s.snapshot_foo1 VALUES (3, 'c'), (4, 'd');", 
getTestNamespace()));
     List<String> snapshots =
         convertToStringList(
-            sql("SELECT * FROM 
iceberg_rest_table_test.snapshot_foo1.snapshots"), 1);
+            sql(String.format("SELECT * FROM %s.snapshot_foo1.snapshots", 
getTestNamespace())), 1);
 
     Assertions.assertEquals(2, snapshots.size());
     String oldSnapshotId = snapshots.get(0);
     sql(
         String.format(
-            "CALL 
rest.system.rollback_to_snapshot('iceberg_rest_table_test.snapshot_foo1', %s)",
-            oldSnapshotId));
+            "CALL rest.system.rollback_to_snapshot('%s.snapshot_foo1', %s)",
+            getTestNamespace(), oldSnapshotId));
     Map<String, String> result =
-        convertToStringMap(sql("select * from 
iceberg_rest_table_test.snapshot_foo1"));
+        convertToStringMap(
+            sql(String.format("select * from %s.snapshot_foo1", 
getTestNamespace())));
     Assertions.assertEquals(ImmutableMap.of("1", "a", "2", "b"), result);
   }
 
@@ -545,25 +668,28 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
     // register table
     String register =
         String.format(
-            "CALL rest.system.register_table(table => 
'iceberg_rest_table_test.register_foo2', metadata_file=> '%s')",
-            metadataLocation);
+            "CALL rest.system.register_table(table => '%s.register_foo2', 
metadata_file=> '%s')",
+            getTestNamespace(), metadataLocation);
     sql(register);
 
     Map<String, String> result =
-        convertToStringMap(sql("SELECT * FROM 
iceberg_rest_table_test.register_foo2"));
+        convertToStringMap(
+            sql(String.format("SELECT * FROM %s.register_foo2", 
getTestNamespace())));
     Assertions.assertEquals(ImmutableMap.of("1", "a"), result);
 
     // insert other data
-    sql("INSERT INTO iceberg_rest_table_test.register_foo2 VALUES (2, 'b')");
-    result = convertToStringMap(sql("SELECT * FROM 
iceberg_rest_table_test.register_foo2"));
+    sql(String.format("INSERT INTO %s.register_foo2 VALUES (2, 'b')", 
getTestNamespace()));
+    result =
+        convertToStringMap(
+            sql(String.format("SELECT * FROM %s.register_foo2", 
getTestNamespace())));
     Assertions.assertEquals(ImmutableMap.of("1", "a", "2", "b"), result);
   }
 
   @Test
   @EnabledIf("isSupportsViewCatalog")
   void testCreateViewAndDisplayView() {
-    String originTableName = "iceberg_rest_table_test.create_table_for_view_1";
-    String viewName = "iceberg_rest_table_test.test_create_view";
+    String originTableName = getTestNamespace() + ".create_table_for_view_1";
+    String viewName = getTestNamespace() + ".test_create_view";
 
     sql(
         String.format(
@@ -584,8 +710,8 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
   @Test
   @EnabledIf("isSupportsViewCatalog")
   void testViewProperties() {
-    String originTableName = "iceberg_rest_table_test.create_table_for_view_2";
-    String viewName = 
"iceberg_rest_table_test.test_create_view_with_properties";
+    String originTableName = getTestNamespace() + ".create_table_for_view_2";
+    String viewName = getTestNamespace() + ".test_create_view_with_properties";
     sql(
         String.format(
             "CREATE TABLE %s ( id bigint, data string, ts timestamp) USING 
iceberg",
@@ -624,8 +750,8 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
   @Test
   @EnabledIf("isSupportsViewCatalog")
   void testDropView() {
-    String originTableName = "iceberg_rest_table_test.create_table_for_view_3";
-    String viewName = "iceberg_rest_table_test.test_drop_view";
+    String originTableName = getTestNamespace() + ".create_table_for_view_3";
+    String viewName = getTestNamespace() + ".test_drop_view";
 
     sql(
         String.format(
@@ -642,8 +768,8 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
   @Test
   @EnabledIf("isSupportsViewCatalog")
   void testReplaceView() {
-    String originTableName = "iceberg_rest_table_test.create_table_for_view_4";
-    String viewName = "iceberg_rest_table_test.test_replace_view";
+    String originTableName = getTestNamespace() + ".create_table_for_view_4";
+    String viewName = getTestNamespace() + ".test_replace_view";
 
     sql(
         String.format(
@@ -664,9 +790,9 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
   @Test
   @EnabledIf("isSupportsViewCatalog")
   void testShowAvailableViews() {
-    String originTableName = "iceberg_rest_table_test.create_table_for_view_5";
-    String viewName1 = "iceberg_rest_table_test.show_available_views_1";
-    String viewName2 = "iceberg_rest_table_test.show_available_views_2";
+    String originTableName = getTestNamespace() + ".create_table_for_view_5";
+    String viewName1 = getTestNamespace() + ".show_available_views_1";
+    String viewName2 = getTestNamespace() + ".show_available_views_2";
 
     sql(
         String.format(
@@ -675,15 +801,15 @@ public abstract class IcebergRESTServiceIT extends 
IcebergRESTServiceBaseIT {
     sql(String.format("CREATE VIEW %s AS SELECT * FROM %s", viewName1, 
originTableName));
     sql(String.format("CREATE VIEW %s AS SELECT * FROM %s", viewName2, 
originTableName));
 
-    List<Object[]> views = sql("SHOW VIEWS IN iceberg_rest_table_test");
+    List<Object[]> views = sql("SHOW VIEWS IN " + getTestNamespace());
     Assertions.assertEquals(2, views.size());
   }
 
   @Test
   @EnabledIf("isSupportsViewCatalog")
   void testShowCreateStatementView() {
-    String originTableName = "iceberg_rest_table_test.create_table_for_view_6";
-    String viewName = "iceberg_rest_table_test.show_create_statement_view";
+    String originTableName = getTestNamespace() + ".create_table_for_view_6";
+    String viewName = getTestNamespace() + ".show_create_statement_view";
 
     sql(
         String.format(
diff --git 
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/IcebergNamespaceTestBase.java
 
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/IcebergNamespaceTestBase.java
index 0b5f1d7627..1362bb2461 100644
--- 
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/IcebergNamespaceTestBase.java
+++ 
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/IcebergNamespaceTestBase.java
@@ -29,6 +29,7 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.rest.RESTUtil;
 import org.apache.iceberg.rest.requests.CreateNamespaceRequest;
 import org.apache.iceberg.rest.requests.ImmutableRegisterTableRequest;
 import org.apache.iceberg.rest.requests.RegisterTableRequest;
@@ -44,33 +45,29 @@ public class IcebergNamespaceTestBase extends 
IcebergTestBase {
   private final Map<String, String> properties = ImmutableMap.of("a", "b");
   private final Map<String, String> updatedProperties = ImmutableMap.of("b", 
"c");
 
-  protected Response doCreateNamespace(String... name) {
+  protected Response doCreateNamespace(Namespace name) {
     CreateNamespaceRequest request =
-        CreateNamespaceRequest.builder()
-            .withNamespace(Namespace.of(name))
-            .setProperties(properties)
-            .build();
+        
CreateNamespaceRequest.builder().withNamespace(name).setProperties(properties).build();
     return getNamespaceClientBuilder()
         .post(Entity.entity(request, MediaType.APPLICATION_JSON_TYPE));
   }
 
-  private Response doRegisterTable(String tableName) {
+  private Response doRegisterTable(String tableName, Namespace ns) {
     RegisterTableRequest request =
         
ImmutableRegisterTableRequest.builder().name(tableName).metadataLocation("mock").build();
-    return getNamespaceClientBuilder(
-            Optional.of("register_ns"), Optional.of("register"), 
Optional.empty())
+    return getNamespaceClientBuilder(Optional.of(ns), Optional.of("register"), 
Optional.empty())
         .post(Entity.entity(request, MediaType.APPLICATION_JSON_TYPE));
   }
 
-  private Response doListNamespace(Optional<String> parent) {
+  private Response doListNamespace(Optional<Namespace> parent) {
     Optional<Map<String, String>> queryParam =
         parent.isPresent()
-            ? Optional.of(ImmutableMap.of("parent", parent.get()))
+            ? Optional.of(ImmutableMap.of("parent", 
RESTUtil.encodeNamespace(parent.get())))
             : Optional.empty();
     return getNamespaceClientBuilder(Optional.empty(), Optional.empty(), 
queryParam).get();
   }
 
-  private Response doUpdateNamespace(String name) {
+  private Response doUpdateNamespace(Namespace name) {
     UpdateNamespacePropertiesRequest request =
         UpdateNamespacePropertiesRequest.builder()
             .removeAll(Arrays.asList("a", "a1"))
@@ -80,68 +77,72 @@ public class IcebergNamespaceTestBase extends 
IcebergTestBase {
         .post(Entity.entity(request, MediaType.APPLICATION_JSON_TYPE));
   }
 
-  private Response doLoadNamespace(String name) {
+  private Response doLoadNamespace(Namespace name) {
     return getNamespaceClientBuilder(Optional.of(name)).get();
   }
 
-  private Response doNamespaceExists(String name) {
+  private Response doNamespaceExists(Namespace name) {
     return getNamespaceClientBuilder(Optional.of(name)).head();
   }
 
-  private Response doDropNamespace(String name) {
+  private Response doDropNamespace(Namespace name) {
     return getNamespaceClientBuilder(Optional.of(name)).delete();
   }
 
-  protected void verifyLoadNamespaceFail(int status, String name) {
+  protected void verifyLoadNamespaceFail(int status, Namespace name) {
     Response response = doLoadNamespace(name);
     Assertions.assertEquals(status, response.getStatus());
   }
 
-  protected void verifyLoadNamespaceSucc(String name) {
+  protected void verifyLoadNamespaceSucc(Namespace name) {
     Response response = doLoadNamespace(name);
     Assertions.assertEquals(Status.OK.getStatusCode(), response.getStatus());
 
     GetNamespaceResponse r = response.readEntity(GetNamespaceResponse.class);
-    Assertions.assertEquals(name, r.namespace().toString());
+    Assertions.assertEquals(name, r.namespace());
     Assertions.assertEquals(properties, r.properties());
   }
 
-  protected void verifyDropNamespaceSucc(String name) {
+  protected void verifyDropNamespaceSucc(Namespace name) {
     Response response = doDropNamespace(name);
     Assertions.assertEquals(Status.NO_CONTENT.getStatusCode(), 
response.getStatus());
   }
 
-  protected void verifyDropNamespaceFail(int status, String name) {
+  protected void verifyDropNamespaceFail(int status, Namespace name) {
     Response response = doDropNamespace(name);
     Assertions.assertEquals(status, response.getStatus());
   }
 
-  protected void verifyNamespaceExistsStatusCode(int status, String name) {
+  protected void verifyNamespaceExistsStatusCode(int status, Namespace name) {
     Response response = doNamespaceExists(name);
     Assertions.assertEquals(status, response.getStatus());
   }
 
   protected void verifyCreateNamespaceSucc(String... name) {
+    verifyCreateNamespaceSucc(Namespace.of(name));
+  }
+
+  protected void verifyCreateNamespaceSucc(Namespace name) {
     Response response = doCreateNamespace(name);
     Assertions.assertEquals(Status.OK.getStatusCode(), response.getStatus());
 
     CreateNamespaceResponse namespaceResponse = 
response.readEntity(CreateNamespaceResponse.class);
-    
Assertions.assertTrue(namespaceResponse.namespace().equals(Namespace.of(name)));
+    Assertions.assertTrue(namespaceResponse.namespace().equals(name));
 
     Assertions.assertEquals(namespaceResponse.properties(), properties);
   }
 
-  protected void verifyRegisterTableSucc(String tableName) {
-    Response response = doRegisterTable(tableName);
+  protected void verifyRegisterTableSucc(String tableName, Namespace ns) {
+    Response response = doRegisterTable(tableName, ns);
     Assertions.assertEquals(Status.OK.getStatusCode(), response.getStatus());
   }
 
-  protected void verifyRegisterTableFail(int statusCode, String tableName) {
-    Response response = doRegisterTable(tableName);
+  protected void verifyRegisterTableFail(int statusCode, String tableName, 
Namespace ns) {
+    Response response = doRegisterTable(tableName, ns);
     Assertions.assertEquals(statusCode, response.getStatus());
   }
 
-  protected void verifyCreateNamespaceFail(int statusCode, String... name) {
+  protected void verifyCreateNamespaceFail(int statusCode, Namespace name) {
     Response response = doCreateNamespace(name);
     Assertions.assertEquals(statusCode, response.getStatus());
   }
@@ -151,15 +152,15 @@ public class IcebergNamespaceTestBase extends 
IcebergTestBase {
     Assertions.assertEquals(Status.OK.getStatusCode(), response.getStatus());
 
     ListNamespacesResponse r = 
response.readEntity(ListNamespacesResponse.class);
-    r.namespaces().forEach(n -> doDropNamespace(n.toString()));
+    r.namespaces().forEach(n -> doDropNamespace(n));
   }
 
-  protected void verifyListNamespaceFail(Optional<String> parent, int status) {
+  protected void verifyListNamespaceFail(Optional<Namespace> parent, int 
status) {
     Response response = doListNamespace(parent);
     Assertions.assertEquals(status, response.getStatus());
   }
 
-  protected void verifyListNamespaceSucc(Optional<String> parent, List<String> 
schemas) {
+  protected void verifyListNamespaceSucc(Optional<Namespace> parent, 
List<String> schemas) {
     Response response = doListNamespace(parent);
     Assertions.assertEquals(Status.OK.getStatusCode(), response.getStatus());
 
@@ -168,7 +169,7 @@ public class IcebergNamespaceTestBase extends 
IcebergTestBase {
     Assertions.assertEquals(schemas, ns);
   }
 
-  protected void verifyUpdateNamespaceSucc(String name) {
+  protected void verifyUpdateNamespaceSucc(Namespace name) {
     Response response = doUpdateNamespace(name);
     Assertions.assertEquals(Status.OK.getStatusCode(), response.getStatus());
 
@@ -179,7 +180,7 @@ public class IcebergNamespaceTestBase extends 
IcebergTestBase {
     Assertions.assertEquals(Arrays.asList("b"), r.updated());
   }
 
-  protected void verifyUpdateNamespaceFail(int status, String name) {
+  protected void verifyUpdateNamespaceFail(int status, Namespace name) {
     Response response = doUpdateNamespace(name);
     Assertions.assertEquals(status, response.getStatus());
   }
diff --git 
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/IcebergRestTestUtil.java
 
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/IcebergRestTestUtil.java
index 01c063f49c..3d322a7a8a 100644
--- 
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/IcebergRestTestUtil.java
+++ 
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/IcebergRestTestUtil.java
@@ -29,6 +29,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import java.util.stream.Stream;
 import javax.servlet.http.HttpServletRequest;
 import org.apache.gravitino.catalog.lakehouse.iceberg.IcebergConstants;
 import org.apache.gravitino.credential.CredentialConstants;
@@ -52,11 +53,14 @@ import 
org.apache.gravitino.iceberg.service.provider.IcebergConfigProviderFactor
 import 
org.apache.gravitino.iceberg.service.provider.StaticIcebergConfigProvider;
 import org.apache.gravitino.listener.EventBus;
 import org.apache.gravitino.listener.api.EventListenerPlugin;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.rest.RESTUtil;
 import org.glassfish.hk2.utilities.binding.AbstractBinder;
 import org.glassfish.jersey.jackson.JacksonFeature;
 import org.glassfish.jersey.logging.LoggingFeature;
 import org.glassfish.jersey.logging.LoggingFeature.Verbosity;
 import org.glassfish.jersey.server.ResourceConfig;
+import org.junit.jupiter.params.provider.Arguments;
 
 public class IcebergRestTestUtil {
 
@@ -65,10 +69,12 @@ public class IcebergRestTestUtil {
   public static final String CONFIG_PATH = V_1 + "/config";
   public static final String NAMESPACE_PATH = V_1 + "/namespaces";
   public static final String UPDATE_NAMESPACE_POSTFIX = "properties";
-  public static final String TEST_NAMESPACE_NAME = "gravitino-test";
-  public static final String TABLE_PATH = NAMESPACE_PATH + "/" + 
TEST_NAMESPACE_NAME + "/tables";
+  public static final Namespace TEST_NAMESPACE_NAME = 
Namespace.of("gravitino-test");
+  public static final Namespace TEST_NESTED_NAMESPACE_NAME =
+      Namespace.of("gravitino-test-2", "nested");
 
-  public static final String VIEW_PATH = NAMESPACE_PATH + "/" + 
TEST_NAMESPACE_NAME + "/views";
+  public static final String VIEW_PATH =
+      NAMESPACE_PATH + "/" + RESTUtil.encodeNamespace(TEST_NAMESPACE_NAME) + 
"/views";
   public static final String RENAME_TABLE_PATH = V_1 + "/tables/rename";
 
   public static final String RENAME_VIEW_PATH = V_1 + "/views/rename";
@@ -153,4 +159,18 @@ public class IcebergRestTestUtil {
     
when(mockRequest.getHeaderNames()).thenReturn(Collections.emptyEnumeration());
     return mockRequest;
   }
+
+  public static Namespace[] testNamespaces() {
+    return new Namespace[] {TEST_NAMESPACE_NAME, TEST_NESTED_NAMESPACE_NAME};
+  }
+
+  public static Stream<Arguments> testPrefixesAndNamespaces() {
+    Namespace[] namespaces = testNamespaces();
+    String[] prefixes = {"", PREFIX};
+    return Arrays.stream(prefixes)
+        .flatMap(
+            prefix ->
+                Arrays.stream(namespaces)
+                    .flatMap(ns -> Stream.of(Arguments.arguments(prefix, 
ns))));
+  }
 }
diff --git 
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/IcebergTestBase.java
 
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/IcebergTestBase.java
index 03d9a49eb2..d9e51cac8f 100644
--- 
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/IcebergTestBase.java
+++ 
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/IcebergTestBase.java
@@ -29,6 +29,8 @@ import javax.ws.rs.core.MediaType;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.gravitino.iceberg.service.IcebergObjectMapperProvider;
+import org.apache.iceberg.catalog.Namespace;
+import org.apache.iceberg.rest.RESTUtil;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
 import org.junit.jupiter.api.Assertions;
@@ -49,31 +51,38 @@ public class IcebergTestBase extends JerseyTest {
     return getIcebergClientBuilder(IcebergRestTestUtil.RENAME_VIEW_PATH, 
Optional.empty());
   }
 
-  public Invocation.Builder getTableClientBuilder() {
-    return getTableClientBuilder(Optional.empty());
-  }
-
-  public Invocation.Builder getViewClientBuilder() {
-    return getViewClientBuilder(Optional.empty());
-  }
-
-  public Invocation.Builder getTableClientBuilder(Optional<String> name) {
+  public Invocation.Builder getTableClientBuilder(Namespace ns, 
Optional<String> name) {
     String path =
-        Joiner.on("/").skipNulls().join(IcebergRestTestUtil.TABLE_PATH, 
name.orElseGet(() -> null));
+        Joiner.on("/")
+            .skipNulls()
+            .join(
+                IcebergRestTestUtil.NAMESPACE_PATH + "/" + 
RESTUtil.encodeNamespace(ns) + "/tables",
+                name.orElseGet(() -> null));
     return getIcebergClientBuilder(path, Optional.empty());
   }
 
-  public Invocation.Builder getViewClientBuilder(Optional<String> name) {
+  public Invocation.Builder getViewClientBuilder(Namespace ns) {
+    return getViewClientBuilder(ns, Optional.empty());
+  }
+
+  public Invocation.Builder getViewClientBuilder(Namespace ns, 
Optional<String> name) {
     String path =
-        Joiner.on("/").skipNulls().join(IcebergRestTestUtil.VIEW_PATH, 
name.orElseGet(() -> null));
+        Joiner.on("/")
+            .skipNulls()
+            .join(
+                IcebergRestTestUtil.NAMESPACE_PATH + "/" + 
RESTUtil.encodeNamespace(ns) + "/views",
+                name.orElseGet(() -> null));
     return getIcebergClientBuilder(path, Optional.empty());
   }
 
-  public Invocation.Builder getReportMetricsClientBuilder(String name) {
+  public Invocation.Builder getReportMetricsClientBuilder(String name, 
Namespace ns) {
     String path =
         Joiner.on("/")
             .skipNulls()
-            .join(IcebergRestTestUtil.TABLE_PATH, name, 
IcebergRestTestUtil.REPORT_METRICS_POSTFIX);
+            .join(
+                IcebergRestTestUtil.NAMESPACE_PATH + "/" + 
RESTUtil.encodeNamespace(ns) + "/tables",
+                name,
+                IcebergRestTestUtil.REPORT_METRICS_POSTFIX);
     return getIcebergClientBuilder(path, Optional.empty());
   }
 
@@ -81,12 +90,12 @@ public class IcebergTestBase extends JerseyTest {
     return getNamespaceClientBuilder(Optional.empty(), Optional.empty(), 
Optional.empty());
   }
 
-  public Invocation.Builder getNamespaceClientBuilder(Optional<String> 
namespace) {
+  public Invocation.Builder getNamespaceClientBuilder(Optional<Namespace> 
namespace) {
     return getNamespaceClientBuilder(namespace, Optional.empty(), 
Optional.empty());
   }
 
   public Invocation.Builder getNamespaceClientBuilder(
-      Optional<String> namespace,
+      Optional<Namespace> namespace,
       Optional<String> extraPath,
       Optional<Map<String, String>> queryParams) {
     String path =
@@ -94,18 +103,18 @@ public class IcebergTestBase extends JerseyTest {
             .skipNulls()
             .join(
                 IcebergRestTestUtil.NAMESPACE_PATH,
-                namespace.orElseGet(() -> null),
+                namespace.map(RESTUtil::encodeNamespace).orElseGet(() -> null),
                 extraPath.orElseGet(() -> null));
     return getIcebergClientBuilder(path, queryParams);
   }
 
-  public Invocation.Builder getUpdateNamespaceClientBuilder(String namespace) {
+  public Invocation.Builder getUpdateNamespaceClientBuilder(Namespace 
namespace) {
     String path =
         Joiner.on("/")
             .skipNulls()
             .join(
                 IcebergRestTestUtil.NAMESPACE_PATH,
-                namespace,
+                RESTUtil.encodeNamespace(namespace),
                 IcebergRestTestUtil.UPDATE_NAMESPACE_POSTFIX);
     return getIcebergClientBuilder(path, Optional.empty());
   }
diff --git 
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/TestIcebergNamespaceOperations.java
 
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/TestIcebergNamespaceOperations.java
index 248bf9393d..220623b95b 100644
--- 
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/TestIcebergNamespaceOperations.java
+++ 
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/TestIcebergNamespaceOperations.java
@@ -39,6 +39,7 @@ import 
org.apache.gravitino.listener.api.event.IcebergRegisterTablePreEvent;
 import org.apache.gravitino.listener.api.event.IcebergUpdateNamespaceEvent;
 import 
org.apache.gravitino.listener.api.event.IcebergUpdateNamespaceFailureEvent;
 import org.apache.gravitino.listener.api.event.IcebergUpdateNamespacePreEvent;
+import org.apache.iceberg.catalog.Namespace;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
@@ -66,7 +67,7 @@ public class TestIcebergNamespaceOperations extends 
IcebergNamespaceTestBase {
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergCreateNamespaceEvent);
 
     // Already Exists Exception
-    verifyCreateNamespaceFail(409, "create_foo1");
+    verifyCreateNamespaceFail(409, Namespace.of("create_foo1"));
     Assertions.assertTrue(
         dummyEventListener.popPreEvent() instanceof 
IcebergCreateNamespacePreEvent);
     Assertions.assertTrue(
@@ -75,7 +76,7 @@ public class TestIcebergNamespaceOperations extends 
IcebergNamespaceTestBase {
     // multi level namespaces
     verifyCreateNamespaceSucc("create_foo2", "create_foo3");
 
-    verifyCreateNamespaceFail(400, "");
+    verifyCreateNamespaceFail(400, Namespace.of(""));
   }
 
   @Test
@@ -83,20 +84,23 @@ public class TestIcebergNamespaceOperations extends 
IcebergNamespaceTestBase {
     verifyCreateNamespaceSucc("load_foo1");
     dummyEventListener.clearEvent();
 
-    verifyLoadNamespaceSucc("load_foo1");
+    verifyLoadNamespaceSucc(Namespace.of("load_foo1"));
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergLoadNamespacePreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergLoadNamespaceEvent);
 
     // load a schema not exists
-    verifyLoadNamespaceFail(404, "load_foo2");
+    verifyLoadNamespaceFail(404, Namespace.of("load_foo2"));
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergLoadNamespacePreEvent);
     Assertions.assertTrue(
         dummyEventListener.popPostEvent() instanceof 
IcebergLoadNamespaceFailureEvent);
+
+    verifyCreateNamespaceSucc(Namespace.of("load_foo3", "a"));
+    verifyLoadNamespaceSucc(Namespace.of("load_foo3", "a"));
   }
 
   @Test
   void testNamespaceExists() {
-    verifyNamespaceExistsStatusCode(404, "exists_foo1");
+    verifyNamespaceExistsStatusCode(404, Namespace.of("exists_foo1"));
     Assertions.assertTrue(
         dummyEventListener.popPreEvent() instanceof 
IcebergNamespaceExistsPreEvent);
     Event postEvent = dummyEventListener.popPostEvent();
@@ -105,46 +109,69 @@ public class TestIcebergNamespaceOperations extends 
IcebergNamespaceTestBase {
 
     verifyCreateNamespaceSucc("exists_foo1");
     dummyEventListener.clearEvent();
-    verifyNamespaceExistsStatusCode(204, "exists_foo1");
+    verifyNamespaceExistsStatusCode(204, Namespace.of("exists_foo1"));
     Assertions.assertTrue(
         dummyEventListener.popPreEvent() instanceof 
IcebergNamespaceExistsPreEvent);
     postEvent = dummyEventListener.popPostEvent();
     Assertions.assertTrue(postEvent instanceof IcebergNamespaceExistsEvent);
     Assertions.assertEquals(true, ((IcebergNamespaceExistsEvent) 
postEvent).isExists());
+
+    verifyNamespaceExistsStatusCode(404, Namespace.of("exists_foo2", "a"));
+    verifyCreateNamespaceSucc("exists_foo2");
+    verifyNamespaceExistsStatusCode(204, Namespace.of("exists_foo2"));
+    verifyNamespaceExistsStatusCode(404, Namespace.of("exists_foo2", "a"));
+    verifyCreateNamespaceSucc(Namespace.of("exists_foo2", "a"));
+    verifyNamespaceExistsStatusCode(204, Namespace.of("exists_foo2"));
+    verifyNamespaceExistsStatusCode(204, Namespace.of("exists_foo2", "a"));
+    verifyNamespaceExistsStatusCode(404, Namespace.of("exists_foo2", "b"));
+
+    verifyDropNamespaceSucc(Namespace.of("exists_foo2"));
+    verifyNamespaceExistsStatusCode(404, Namespace.of("exists_foo2"));
+    verifyNamespaceExistsStatusCode(204, Namespace.of("exists_foo2", "a"));
+
+    verifyDropNamespaceSucc(Namespace.of("exists_foo2", "a"));
+    verifyNamespaceExistsStatusCode(404, Namespace.of("exists_foo2"));
+    verifyNamespaceExistsStatusCode(404, Namespace.of("exists_foo2", "a"));
   }
 
   @Test
   void testDropNamespace() {
     verifyCreateNamespaceSucc("drop_foo1");
     dummyEventListener.clearEvent();
-    verifyDropNamespaceSucc("drop_foo1");
+    verifyDropNamespaceSucc(Namespace.of("drop_foo1"));
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergDropNamespacePreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergDropNamespaceEvent);
 
-    verifyLoadNamespaceFail(404, "drop_foo1");
+    verifyLoadNamespaceFail(404, Namespace.of("drop_foo1"));
 
     // drop fail, no such namespace
     dummyEventListener.clearEvent();
-    verifyDropNamespaceFail(404, "drop_foo2");
+    verifyDropNamespaceFail(404, Namespace.of("drop_foo2"));
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergDropNamespacePreEvent);
     Assertions.assertTrue(
         dummyEventListener.popPostEvent() instanceof 
IcebergDropNamespaceFailureEvent);
 
     // jersery route failed
-    verifyDropNamespaceFail(500, "");
+    verifyDropNamespaceFail(500, Namespace.of(""));
+
+    verifyCreateNamespaceSucc(Namespace.of("drop_foo3", "a"));
+    verifyDropNamespaceFail(404, Namespace.of("drop_foo3", "b"));
+    verifyDropNamespaceSucc(Namespace.of("drop_foo3", "a"));
   }
 
   @Test
   void testRegisterTable() {
-    verifyRegisterTableSucc("register_foo1");
+    verifyRegisterTableSucc("register_foo1", Namespace.of("register_ns"));
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergRegisterTablePreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergRegisterTableEvent);
 
     // Iceberg REST service will throw AlreadyExistsException in test if table 
name contains 'fail'
-    verifyRegisterTableFail(409, "fail_register_foo1");
+    verifyRegisterTableFail(409, "fail_register_foo1", 
Namespace.of("register_ns"));
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergRegisterTablePreEvent);
     Assertions.assertTrue(
         dummyEventListener.popPostEvent() instanceof 
IcebergRegisterTableFailureEvent);
+
+    verifyRegisterTableSucc("register_foo2", Namespace.of("register_ns_2", 
"a"));
   }
 
   @ParameterizedTest
@@ -154,30 +181,42 @@ public class TestIcebergNamespaceOperations extends 
IcebergNamespaceTestBase {
     dropAllExistingNamespace();
     verifyListNamespaceSucc(Optional.empty(), Arrays.asList());
 
-    doCreateNamespace("list_foo1");
-    doCreateNamespace("list_foo2");
-    doCreateNamespace("list_foo3", "a");
-    doCreateNamespace("list_foo3", "b");
+    doCreateNamespace(Namespace.of("list_foo1"));
+    doCreateNamespace(Namespace.of("list_foo2"));
+    doCreateNamespace(Namespace.of("list_foo3", "a"));
+    doCreateNamespace(Namespace.of("list_foo3", "b"));
+    doCreateNamespace(Namespace.of("list_foo3", "a", "z"));
+    doCreateNamespace(Namespace.of("list_foo3", "a", "y"));
 
     verifyListNamespaceSucc(Optional.empty(), Arrays.asList("list_foo1", 
"list_foo2", "list_foo3"));
-    verifyListNamespaceSucc(Optional.of("list_foo3"), 
Arrays.asList("list_foo3.a", "list_foo3.b"));
-
-    verifyListNamespaceFail(Optional.of("list_fooxx"), 404);
+    verifyListNamespaceSucc(
+        Optional.of(Namespace.of("list_foo3")), Arrays.asList("list_foo3.a", 
"list_foo3.b"));
+    verifyListNamespaceSucc(
+        Optional.of(Namespace.of("list_foo3", "a")),
+        Arrays.asList("list_foo3.a.y", "list_foo3.a.z"));
+
+    verifyListNamespaceFail(Optional.of(Namespace.of("list_fooxx")), 404);
+    verifyListNamespaceFail(Optional.of(Namespace.of("list_foo3", "c")), 404);
+    verifyListNamespaceFail(Optional.of(Namespace.of("list_foo3", "a", "x")), 
404);
   }
 
   @Test
   void testUpdateNamespace() {
     verifyCreateNamespaceSucc("update_foo1");
     dummyEventListener.clearEvent();
-    verifyUpdateNamespaceSucc("update_foo1");
+    verifyUpdateNamespaceSucc(Namespace.of("update_foo1"));
     Assertions.assertTrue(
         dummyEventListener.popPreEvent() instanceof 
IcebergUpdateNamespacePreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergUpdateNamespaceEvent);
 
-    verifyUpdateNamespaceFail(404, "update_foo2");
+    verifyUpdateNamespaceFail(404, Namespace.of("update_foo2"));
     Assertions.assertTrue(
         dummyEventListener.popPreEvent() instanceof 
IcebergUpdateNamespacePreEvent);
     Assertions.assertTrue(
         dummyEventListener.popPostEvent() instanceof 
IcebergUpdateNamespaceFailureEvent);
+
+    verifyCreateNamespaceSucc(Namespace.of("update_foo3", "a"));
+    dummyEventListener.clearEvent();
+    verifyUpdateNamespaceSucc(Namespace.of("update_foo3", "a"));
   }
 }
diff --git 
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/TestIcebergTableOperations.java
 
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/TestIcebergTableOperations.java
index 568044441a..d19d654224 100644
--- 
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/TestIcebergTableOperations.java
+++ 
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/TestIcebergTableOperations.java
@@ -73,9 +73,8 @@ import org.apache.iceberg.types.Types.NestedField;
 import org.apache.iceberg.types.Types.StringType;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.ValueSource;
+import org.junit.jupiter.params.provider.MethodSource;
 
 public class TestIcebergTableOperations extends IcebergNamespaceTestBase {
 
@@ -100,160 +99,166 @@ public class TestIcebergTableOperations extends 
IcebergNamespaceTestBase {
     return resourceConfig;
   }
 
-  @Test
-  void testCreateTable() {
-    verifyCreateTableFail("create_foo1", 404);
+  @ParameterizedTest
+  
@MethodSource("org.apache.gravitino.iceberg.service.rest.IcebergRestTestUtil#testNamespaces")
+  void testCreateTable(Namespace namespace) {
+    verifyCreateTableFail(namespace, "create_foo1", 404);
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergCreateTablePreEvent);
     Assertions.assertTrue(
         dummyEventListener.popPostEvent() instanceof 
IcebergCreateTableFailureEvent);
 
-    verifyCreateNamespaceSucc(IcebergRestTestUtil.TEST_NAMESPACE_NAME);
+    verifyCreateNamespaceSucc(namespace);
 
-    verifyCreateTableSucc("create_foo1");
+    verifyCreateTableSucc(namespace, "create_foo1");
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergCreateTablePreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergCreateTableEvent);
 
-    verifyCreateTableFail("create_foo1", 409);
-    verifyCreateTableFail("", 400);
+    verifyCreateTableFail(namespace, "create_foo1", 409);
+    verifyCreateTableFail(namespace, "", 400);
   }
 
-  @Test
-  void testLoadTable() {
-    verifyLoadTableFail("load_foo1", 404);
+  @ParameterizedTest
+  
@MethodSource("org.apache.gravitino.iceberg.service.rest.IcebergRestTestUtil#testNamespaces")
+  void testLoadTable(Namespace namespace) {
+    verifyLoadTableFail(namespace, "load_foo1", 404);
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergLoadTablePreEvent);
     Assertions.assertTrue(
         dummyEventListener.popPostEvent() instanceof 
IcebergLoadTableFailureEvent);
 
-    verifyCreateNamespaceSucc(IcebergRestTestUtil.TEST_NAMESPACE_NAME);
-    verifyCreateTableSucc("load_foo1");
+    verifyCreateNamespaceSucc(namespace);
+    verifyCreateTableSucc(namespace, "load_foo1");
 
     dummyEventListener.clearEvent();
-    verifyLoadTableSucc("load_foo1");
+    verifyLoadTableSucc(namespace, "load_foo1");
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergLoadTablePreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergLoadTableEvent);
-
-    verifyLoadTableFail("load_foo2", 404);
   }
 
-  @Test
-  void testDropTable() {
-    verifyDropTableFail("drop_foo1", 404);
+  @ParameterizedTest
+  
@MethodSource("org.apache.gravitino.iceberg.service.rest.IcebergRestTestUtil#testNamespaces")
+  void testDropTable(Namespace namespace) {
+    verifyDropTableFail(namespace, "drop_foo1", 404);
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergDropTablePreEvent);
     Assertions.assertTrue(
         dummyEventListener.popPostEvent() instanceof 
IcebergDropTableFailureEvent);
 
-    verifyCreateNamespaceSucc(IcebergRestTestUtil.TEST_NAMESPACE_NAME);
-    verifyDropTableFail("drop_foo1", 404);
+    verifyCreateNamespaceSucc(namespace);
+    verifyDropTableFail(namespace, "drop_foo1", 404);
 
-    verifyCreateTableSucc("drop_foo1");
+    verifyCreateTableSucc(namespace, "drop_foo1");
 
     dummyEventListener.clearEvent();
-    verifyDropTableSucc("drop_foo1");
+    verifyDropTableSucc(namespace, "drop_foo1");
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergDropTablePreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergDropTableEvent);
 
-    verifyLoadTableFail("drop_foo1", 404);
+    verifyLoadTableFail(namespace, "drop_foo1", 404);
   }
 
-  @Test
-  void testUpdateTable() {
-    verifyCreateNamespaceSucc(IcebergRestTestUtil.TEST_NAMESPACE_NAME);
-    verifyCreateTableSucc("update_foo1");
-    TableMetadata metadata = getTableMeta("update_foo1");
+  @ParameterizedTest
+  
@MethodSource("org.apache.gravitino.iceberg.service.rest.IcebergRestTestUtil#testNamespaces")
+  void testUpdateTable(Namespace namespace) {
+    verifyCreateNamespaceSucc(namespace);
+    verifyCreateTableSucc(namespace, "update_foo1");
+    TableMetadata metadata = getTableMeta(namespace, "update_foo1");
 
     dummyEventListener.clearEvent();
-    verifyUpdateSucc("update_foo1", metadata);
+    verifyUpdateSucc(namespace, "update_foo1", metadata);
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergUpdateTablePreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergUpdateTableEvent);
 
-    verifyDropTableSucc("update_foo1");
+    verifyDropTableSucc(namespace, "update_foo1");
 
     dummyEventListener.clearEvent();
-    verifyUpdateTableFail("update_foo1", 404, metadata);
+    verifyUpdateTableFail(namespace, "update_foo1", 404, metadata);
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergUpdateTablePreEvent);
     Assertions.assertTrue(
         dummyEventListener.popPostEvent() instanceof 
IcebergUpdateTableFailureEvent);
 
-    verifyDropNamespaceSucc(IcebergRestTestUtil.TEST_NAMESPACE_NAME);
-    verifyUpdateTableFail("update_foo1", 404, metadata);
+    verifyDropNamespaceSucc(namespace);
+    verifyUpdateTableFail(namespace, "update_foo1", 404, metadata);
   }
 
   @ParameterizedTest
-  @ValueSource(strings = {"", IcebergRestTestUtil.PREFIX})
-  void testListTables(String prefix) {
+  @MethodSource(
+      
"org.apache.gravitino.iceberg.service.rest.IcebergRestTestUtil#testPrefixesAndNamespaces")
+  void testListTables(String prefix, Namespace namespace) {
     setUrlPathWithPrefix(prefix);
-    verifyListTableFail(404);
+    verifyListTableFail(namespace, 404);
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergListTablePreEvent);
     Assertions.assertTrue(
         dummyEventListener.popPostEvent() instanceof 
IcebergListTableFailureEvent);
 
-    verifyCreateNamespaceSucc(IcebergRestTestUtil.TEST_NAMESPACE_NAME);
-    verifyCreateTableSucc("list_foo1");
-    verifyCreateTableSucc("list_foo2");
+    verifyCreateNamespaceSucc(namespace);
+    verifyCreateTableSucc(namespace, "list_foo1");
+    verifyCreateTableSucc(namespace, "list_foo2");
 
     dummyEventListener.clearEvent();
-    verifyListTableSucc(ImmutableSet.of("list_foo1", "list_foo2"));
+    verifyListTableSucc(namespace, ImmutableSet.of("list_foo1", "list_foo2"));
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergListTablePreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergListTableEvent);
   }
 
-  @Test
-  void testTableExits() {
-    verifyTableExistsStatusCode("exists_foo2", 404);
+  @ParameterizedTest
+  
@MethodSource("org.apache.gravitino.iceberg.service.rest.IcebergRestTestUtil#testNamespaces")
+  void testTableExits(Namespace namespace) {
+    verifyTableExistsStatusCode(namespace, "exists_foo2", 404);
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergTableExistsPreEvent);
     Event postEvent = dummyEventListener.popPostEvent();
     Assertions.assertTrue(postEvent instanceof IcebergTableExistsEvent);
     Assertions.assertEquals(false, ((IcebergTableExistsEvent) 
postEvent).isExists());
 
-    verifyCreateNamespaceSucc(IcebergRestTestUtil.TEST_NAMESPACE_NAME);
-    verifyTableExistsStatusCode("exists_foo2", 404);
+    verifyCreateNamespaceSucc(namespace);
+    verifyTableExistsStatusCode(namespace, "exists_foo2", 404);
 
-    verifyCreateTableSucc("exists_foo1");
+    verifyCreateTableSucc(namespace, "exists_foo1");
     dummyEventListener.clearEvent();
-    verifyTableExistsStatusCode("exists_foo1", 204);
+    verifyTableExistsStatusCode(namespace, "exists_foo1", 204);
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergTableExistsPreEvent);
     postEvent = dummyEventListener.popPostEvent();
     Assertions.assertTrue(postEvent instanceof IcebergTableExistsEvent);
     Assertions.assertEquals(true, ((IcebergTableExistsEvent) 
postEvent).isExists());
 
-    verifyLoadTableSucc("exists_foo1");
+    verifyLoadTableSucc(namespace, "exists_foo1");
   }
 
   @ParameterizedTest
-  @ValueSource(strings = {"", IcebergRestTestUtil.PREFIX})
-  void testRenameTable(String prefix) {
+  @MethodSource(
+      
"org.apache.gravitino.iceberg.service.rest.IcebergRestTestUtil#testPrefixesAndNamespaces")
+  void testRenameTable(String prefix, Namespace namespace) {
     setUrlPathWithPrefix(prefix);
     // namespace not exits
-    verifyRenameTableFail("rename_foo1", "rename_foo3", 404);
+    verifyRenameTableFail(namespace, "rename_foo1", "rename_foo3", 404);
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergRenameTablePreEvent);
     Assertions.assertTrue(
         dummyEventListener.popPostEvent() instanceof 
IcebergRenameTableFailureEvent);
 
-    verifyCreateNamespaceSucc(IcebergRestTestUtil.TEST_NAMESPACE_NAME);
-    verifyCreateTableSucc("rename_foo1");
+    verifyCreateNamespaceSucc(namespace);
+    verifyCreateTableSucc(namespace, "rename_foo1");
 
     dummyEventListener.clearEvent();
     // rename
-    verifyRenameTableSucc("rename_foo1", "rename_foo2");
+    verifyRenameTableSucc(namespace, "rename_foo1", "rename_foo2");
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergRenameTablePreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergRenameTableEvent);
 
-    verifyLoadTableFail("rename_foo1", 404);
-    verifyLoadTableSucc("rename_foo2");
+    verifyLoadTableFail(namespace, "rename_foo1", 404);
+    verifyLoadTableSucc(namespace, "rename_foo2");
 
     // source table not exists
-    verifyRenameTableFail("rename_foo1", "rename_foo3", 404);
+    verifyRenameTableFail(namespace, "rename_foo1", "rename_foo3", 404);
 
     // dest table exists
-    verifyCreateTableSucc("rename_foo3");
-    verifyRenameTableFail("rename_foo2", "rename_foo3", 409);
+    verifyCreateTableSucc(namespace, "rename_foo3");
+    verifyRenameTableFail(namespace, "rename_foo2", "rename_foo3", 409);
   }
 
-  @Test
-  void testReportTableMetrics() {
+  @ParameterizedTest
+  
@MethodSource("org.apache.gravitino.iceberg.service.rest.IcebergRestTestUtil#testNamespaces")
+  void testReportTableMetrics(Namespace namespace) {
 
-    verifyCreateNamespaceSucc(IcebergRestTestUtil.TEST_NAMESPACE_NAME);
-    verifyCreateTableSucc("metrics_foo1");
+    verifyCreateNamespaceSucc(namespace);
+    verifyCreateTableSucc(namespace, "metrics_foo1");
 
     ImmutableCommitMetricsResult commitMetrics = 
ImmutableCommitMetricsResult.builder().build();
     CommitReport commitReport =
@@ -266,25 +271,26 @@ public class TestIcebergTableOperations extends 
IcebergNamespaceTestBase {
             .build();
     ReportMetricsRequest request = ReportMetricsRequest.of(commitReport);
     Response response =
-        getReportMetricsClientBuilder("metrics_foo1")
+        getReportMetricsClientBuilder("metrics_foo1", namespace)
             .post(Entity.entity(request, MediaType.APPLICATION_JSON_TYPE));
 
     Assertions.assertEquals(Status.NO_CONTENT.getStatusCode(), 
response.getStatus());
   }
 
-  @Test
-  void testCreateTableWithCredentialVending() {
-    verifyCreateNamespaceSucc(IcebergRestTestUtil.TEST_NAMESPACE_NAME);
+  @ParameterizedTest
+  
@MethodSource("org.apache.gravitino.iceberg.service.rest.IcebergRestTestUtil#testNamespaces")
+  void testCreateTableWithCredentialVending(Namespace namespace) {
+    verifyCreateNamespaceSucc(namespace);
 
     // create the table without credential vending
-    Response response = doCreateTable("create_without_credential_vending");
+    Response response = doCreateTable(namespace, 
"create_without_credential_vending");
     Assertions.assertEquals(Status.OK.getStatusCode(), response.getStatus());
     LoadTableResponse loadTableResponse = 
response.readEntity(LoadTableResponse.class);
     
Assertions.assertTrue(!loadTableResponse.config().containsKey(Credential.CREDENTIAL_TYPE));
 
     // create the table with credential vending
     String tableName = "create_with_credential_vending";
-    response = doCreateTableWithCredentialVending(tableName);
+    response = doCreateTableWithCredentialVending(namespace, tableName);
     Assertions.assertEquals(Status.OK.getStatusCode(), response.getStatus());
     loadTableResponse = response.readEntity(LoadTableResponse.class);
     Assertions.assertEquals(
@@ -292,13 +298,13 @@ public class TestIcebergTableOperations extends 
IcebergNamespaceTestBase {
         loadTableResponse.config().get(Credential.CREDENTIAL_TYPE));
 
     // load the table without credential vending
-    response = doLoadTable(tableName);
+    response = doLoadTable(namespace, tableName);
     Assertions.assertEquals(Status.OK.getStatusCode(), response.getStatus());
     loadTableResponse = response.readEntity(LoadTableResponse.class);
     
Assertions.assertTrue(!loadTableResponse.config().containsKey(Credential.CREDENTIAL_TYPE));
 
     // load the table with credential vending
-    response = doLoadTableWithCredentialVending(tableName);
+    response = doLoadTableWithCredentialVending(namespace, tableName);
     Assertions.assertEquals(Status.OK.getStatusCode(), response.getStatus());
     loadTableResponse = response.readEntity(LoadTableResponse.class);
     Assertions.assertEquals(
@@ -306,96 +312,88 @@ public class TestIcebergTableOperations extends 
IcebergNamespaceTestBase {
         loadTableResponse.config().get(Credential.CREDENTIAL_TYPE));
   }
 
-  private Response doCreateTableWithCredentialVending(String name) {
+  private Response doCreateTableWithCredentialVending(Namespace ns, String 
name) {
     CreateTableRequest createTableRequest =
         
CreateTableRequest.builder().withName(name).withSchema(tableSchema).build();
-    return getTableClientBuilder()
+    return getTableClientBuilder(ns, Optional.empty())
         .header(IcebergTableOperations.X_ICEBERG_ACCESS_DELEGATION, 
"vended-credentials")
         .post(Entity.entity(createTableRequest, 
MediaType.APPLICATION_JSON_TYPE));
   }
 
-  private Response doCreateTable(String name) {
+  private Response doCreateTable(Namespace ns, String name) {
     CreateTableRequest createTableRequest =
         
CreateTableRequest.builder().withName(name).withSchema(tableSchema).build();
-    return getTableClientBuilder()
+    return getTableClientBuilder(ns, Optional.empty())
         .post(Entity.entity(createTableRequest, 
MediaType.APPLICATION_JSON_TYPE));
   }
 
-  private Response doRenameTable(String source, String dest) {
+  private Response doRenameTable(Namespace ns, String source, String dest) {
     RenameTableRequest renameTableRequest =
         RenameTableRequest.builder()
-            .withSource(
-                
TableIdentifier.of(Namespace.of(IcebergRestTestUtil.TEST_NAMESPACE_NAME), 
source))
-            .withDestination(
-                
TableIdentifier.of(Namespace.of(IcebergRestTestUtil.TEST_NAMESPACE_NAME), dest))
+            .withSource(TableIdentifier.of(ns, source))
+            .withDestination(TableIdentifier.of(ns, dest))
             .build();
     return getRenameTableClientBuilder()
         .post(Entity.entity(renameTableRequest, 
MediaType.APPLICATION_JSON_TYPE));
   }
 
-  private Response doListTable() {
-    return getTableClientBuilder().get();
+  private Response doListTable(Namespace ns) {
+    return getTableClientBuilder(ns, Optional.empty()).get();
   }
 
-  private Response doDropTable(String name) {
-    return getTableClientBuilder(Optional.of(name)).delete();
+  private Response doDropTable(Namespace ns, String name) {
+    return getTableClientBuilder(ns, Optional.of(name)).delete();
   }
 
-  private Response doTableExists(String name) {
-    return getTableClientBuilder(Optional.of(name)).head();
+  private Response doTableExists(Namespace ns, String name) {
+    return getTableClientBuilder(ns, Optional.of(name)).head();
   }
 
-  private Response doLoadTableWithCredentialVending(String name) {
-    return getTableClientBuilder(Optional.of(name))
+  private Response doLoadTableWithCredentialVending(Namespace ns, String name) 
{
+    return getTableClientBuilder(ns, Optional.of(name))
         .header(IcebergTableOperations.X_ICEBERG_ACCESS_DELEGATION, 
"vended-credentials")
         .get();
   }
 
-  private Response doLoadTable(String name) {
-    return getTableClientBuilder(Optional.of(name)).get();
+  private Response doLoadTable(Namespace ns, String name) {
+    return getTableClientBuilder(ns, Optional.of(name)).get();
   }
 
-  private Response doUpdateTable(String name, TableMetadata base) {
+  private Response doUpdateTable(Namespace ns, String name, TableMetadata 
base) {
     TableMetadata newMetadata = base.updateSchema(newTableSchema, 
base.lastColumnId());
     List<MetadataUpdate> metadataUpdates = newMetadata.changes();
     List<UpdateRequirement> requirements = 
UpdateRequirements.forUpdateTable(base, metadataUpdates);
     UpdateTableRequest updateTableRequest = new 
UpdateTableRequest(requirements, metadataUpdates);
-    return getTableClientBuilder(Optional.of(name))
+    return getTableClientBuilder(ns, Optional.of(name))
         .post(Entity.entity(updateTableRequest, 
MediaType.APPLICATION_JSON_TYPE));
   }
 
-  private TableMetadata getTableMeta(String tableName) {
-    Response response = doLoadTable(tableName);
+  private TableMetadata getTableMeta(Namespace ns, String tableName) {
+    Response response = doLoadTable(ns, tableName);
     LoadTableResponse loadTableResponse = 
response.readEntity(LoadTableResponse.class);
     return loadTableResponse.tableMetadata();
   }
 
-  private void verifyUpdateTableFail(String name, int status, TableMetadata 
base) {
-    Response response = doUpdateTable(name, base);
+  private void verifyUpdateTableFail(Namespace ns, String name, int status, 
TableMetadata base) {
+    Response response = doUpdateTable(ns, name, base);
     Assertions.assertEquals(status, response.getStatus());
   }
 
-  private void verifyUpdateSucc(String name, TableMetadata base) {
-    Response response = doUpdateTable(name, base);
+  private void verifyUpdateSucc(Namespace ns, String name, TableMetadata base) 
{
+    Response response = doUpdateTable(ns, name, base);
     Assertions.assertEquals(Status.OK.getStatusCode(), response.getStatus());
     LoadTableResponse loadTableResponse = 
response.readEntity(LoadTableResponse.class);
     Assertions.assertEquals(
         newTableSchema.columns(), 
loadTableResponse.tableMetadata().schema().columns());
   }
 
-  private TableMetadata doGetTableMetaData(String name) {
-    Response response = doLoadTable(name);
-    LoadTableResponse loadTableResponse = 
response.readEntity(LoadTableResponse.class);
-    return loadTableResponse.tableMetadata();
-  }
-
-  private void verifyLoadTableFail(String name, int status) {
-    Response response = doLoadTable(name);
+  private void verifyLoadTableFail(Namespace ns, String name, int status) {
+    Response response = doLoadTable(ns, name);
     Assertions.assertEquals(status, response.getStatus());
   }
 
-  private void verifyLoadTableSucc(String name) {
-    Response response = doLoadTable(name);
+  private void verifyLoadTableSucc(Namespace ns, String name) {
+    Response response = doLoadTable(ns, name);
     Assertions.assertEquals(Status.OK.getStatusCode(), response.getStatus());
 
     LoadTableResponse loadTableResponse = 
response.readEntity(LoadTableResponse.class);
@@ -403,48 +401,48 @@ public class TestIcebergTableOperations extends 
IcebergNamespaceTestBase {
         tableSchema.columns(), 
loadTableResponse.tableMetadata().schema().columns());
   }
 
-  private void verifyDropTableSucc(String name) {
-    Response response = doDropTable(name);
+  private void verifyDropTableSucc(Namespace ns, String name) {
+    Response response = doDropTable(ns, name);
     Assertions.assertEquals(Status.NO_CONTENT.getStatusCode(), 
response.getStatus());
   }
 
-  private void verifyTableExistsStatusCode(String name, int status) {
-    Response response = doTableExists(name);
+  private void verifyTableExistsStatusCode(Namespace ns, String name, int 
status) {
+    Response response = doTableExists(ns, name);
     Assertions.assertEquals(status, response.getStatus());
   }
 
-  private void verifyDropTableFail(String name, int status) {
-    Response response = doDropTable(name);
+  private void verifyDropTableFail(Namespace ns, String name, int status) {
+    Response response = doDropTable(ns, name);
     Assertions.assertEquals(status, response.getStatus());
   }
 
-  private void verifyCreateTableSucc(String name) {
-    Response response = doCreateTable(name);
+  private void verifyCreateTableSucc(Namespace ns, String name) {
+    Response response = doCreateTable(ns, name);
     Assertions.assertEquals(Status.OK.getStatusCode(), response.getStatus());
     LoadTableResponse loadTableResponse = 
response.readEntity(LoadTableResponse.class);
     Schema schema = loadTableResponse.tableMetadata().schema();
     Assertions.assertEquals(schema.columns(), tableSchema.columns());
   }
 
-  private void verifyRenameTableSucc(String source, String dest) {
-    Response response = doRenameTable(source, dest);
+  private void verifyRenameTableSucc(Namespace ns, String source, String dest) 
{
+    Response response = doRenameTable(ns, source, dest);
     System.out.println(response);
     System.out.flush();
     Assertions.assertEquals(Status.NO_CONTENT.getStatusCode(), 
response.getStatus());
   }
 
-  private void verifyRenameTableFail(String source, String dest, int status) {
-    Response response = doRenameTable(source, dest);
+  private void verifyRenameTableFail(Namespace ns, String source, String dest, 
int status) {
+    Response response = doRenameTable(ns, source, dest);
     Assertions.assertEquals(status, response.getStatus());
   }
 
-  private void verifyListTableFail(int status) {
-    Response response = doListTable();
+  private void verifyListTableFail(Namespace ns, int status) {
+    Response response = doListTable(ns);
     Assertions.assertEquals(status, response.getStatus());
   }
 
-  private void verifyListTableSucc(Set<String> expectedTableNames) {
-    Response response = doListTable();
+  private void verifyListTableSucc(Namespace ns, Set<String> 
expectedTableNames) {
+    Response response = doListTable(ns);
     Assertions.assertEquals(Status.OK.getStatusCode(), response.getStatus());
     ListTablesResponse listTablesResponse = 
response.readEntity(ListTablesResponse.class);
     Set<String> tableNames =
@@ -454,8 +452,8 @@ public class TestIcebergTableOperations extends 
IcebergNamespaceTestBase {
     Assertions.assertEquals(expectedTableNames, tableNames);
   }
 
-  private void verifyCreateTableFail(String name, int status) {
-    Response response = doCreateTable(name);
+  private void verifyCreateTableFail(Namespace ns, String name, int status) {
+    Response response = doCreateTable(ns, name);
     Assertions.assertEquals(status, response.getStatus());
   }
 }
diff --git 
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/TestIcebergViewOperations.java
 
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/TestIcebergViewOperations.java
index 0de6db8022..8a2a2e226f 100644
--- 
a/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/TestIcebergViewOperations.java
+++ 
b/iceberg/iceberg-rest-server/src/test/java/org/apache/gravitino/iceberg/service/rest/TestIcebergViewOperations.java
@@ -65,9 +65,8 @@ import org.apache.iceberg.view.ImmutableViewVersion;
 import org.apache.iceberg.view.ViewMetadata;
 import org.glassfish.jersey.server.ResourceConfig;
 import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.ValueSource;
+import org.junit.jupiter.params.provider.MethodSource;
 
 public class TestIcebergViewOperations extends IcebergNamespaceTestBase {
   private static final Schema viewSchema =
@@ -94,152 +93,159 @@ public class TestIcebergViewOperations extends 
IcebergNamespaceTestBase {
   }
 
   @ParameterizedTest
-  @ValueSource(strings = {"", IcebergRestTestUtil.PREFIX})
-  void testListViews(String prefix) {
+  @MethodSource(
+      
"org.apache.gravitino.iceberg.service.rest.IcebergRestTestUtil#testPrefixesAndNamespaces")
+  void testListViews(String prefix, Namespace namespace) {
     setUrlPathWithPrefix(prefix);
-    verifyListViewFail(404);
+    verifyListViewFail(namespace, 404);
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergListViewPreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergListViewFailureEvent);
 
-    verifyCreateNamespaceSucc(IcebergRestTestUtil.TEST_NAMESPACE_NAME);
-    verifyCreateViewSucc("list_foo1");
-    verifyCreateViewSucc("list_foo2");
+    verifyCreateNamespaceSucc(namespace);
+    verifyCreateViewSucc(namespace, "list_foo1");
+    verifyCreateViewSucc(namespace, "list_foo2");
 
     dummyEventListener.clearEvent();
-    verifyLisViewSucc(ImmutableSet.of("list_foo1", "list_foo2"));
+    verifyLisViewSucc(namespace, ImmutableSet.of("list_foo1", "list_foo2"));
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergListViewPreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergListViewEvent);
   }
 
-  @Test
-  void testCreateView() {
-    verifyCreateViewFail("create_foo1", 404);
+  @ParameterizedTest
+  
@MethodSource("org.apache.gravitino.iceberg.service.rest.IcebergRestTestUtil#testNamespaces")
+  void testCreateView(Namespace namespace) {
+    verifyCreateViewFail(namespace, "create_foo1", 404);
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergCreateViewPreEvent);
     Assertions.assertTrue(
         dummyEventListener.popPostEvent() instanceof 
IcebergCreateViewFailureEvent);
 
-    verifyCreateNamespaceSucc(IcebergRestTestUtil.TEST_NAMESPACE_NAME);
+    verifyCreateNamespaceSucc(namespace);
 
-    verifyCreateViewSucc("create_foo1");
+    verifyCreateViewSucc(namespace, "create_foo1");
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergCreateViewPreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergCreateViewEvent);
 
-    verifyCreateViewFail("create_foo1", 409);
-    verifyCreateViewFail("", 400);
+    verifyCreateViewFail(namespace, "create_foo1", 409);
+    verifyCreateViewFail(namespace, "", 400);
   }
 
-  @Test
-  void testLoadView() {
-    verifyLoadViewFail("load_foo1", 404);
+  @ParameterizedTest
+  
@MethodSource("org.apache.gravitino.iceberg.service.rest.IcebergRestTestUtil#testNamespaces")
+  void testLoadView(Namespace namespace) {
+    verifyLoadViewFail(namespace, "load_foo1", 404);
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergLoadViewPreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergLoadViewFailureEvent);
 
-    verifyCreateNamespaceSucc(IcebergRestTestUtil.TEST_NAMESPACE_NAME);
-    verifyCreateViewSucc("load_foo1");
+    verifyCreateNamespaceSucc(namespace);
+    verifyCreateViewSucc(namespace, "load_foo1");
 
     dummyEventListener.clearEvent();
-    verifyLoadViewSucc("load_foo1");
+    verifyLoadViewSucc(namespace, "load_foo1");
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergLoadViewPreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergLoadViewEvent);
 
-    verifyLoadViewFail("load_foo2", 404);
+    verifyLoadViewFail(namespace, "load_foo2", 404);
   }
 
-  @Test
-  void testReplaceView() {
-    verifyCreateNamespaceSucc(IcebergRestTestUtil.TEST_NAMESPACE_NAME);
-    verifyCreateViewSucc("replace_foo1");
-    ViewMetadata metadata = getViewMeta("replace_foo1");
+  @ParameterizedTest
+  
@MethodSource("org.apache.gravitino.iceberg.service.rest.IcebergRestTestUtil#testNamespaces")
+  void testReplaceView(Namespace namespace) {
+    verifyCreateNamespaceSucc(namespace);
+    verifyCreateViewSucc(namespace, "replace_foo1");
+    ViewMetadata metadata = getViewMeta(namespace, "replace_foo1");
 
     dummyEventListener.clearEvent();
-    verifyReplaceSucc("replace_foo1", metadata);
+    verifyReplaceSucc(namespace, "replace_foo1", metadata);
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergReplaceViewPreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergReplaceViewEvent);
 
-    verifyDropViewSucc("replace_foo1");
+    verifyDropViewSucc(namespace, "replace_foo1");
 
     dummyEventListener.clearEvent();
-    verifyUpdateViewFail("replace_foo1", 404, metadata);
+    verifyUpdateViewFail(namespace, "replace_foo1", 404, metadata);
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergReplaceViewPreEvent);
     Assertions.assertTrue(
         dummyEventListener.popPostEvent() instanceof 
IcebergReplaceViewFailureEvent);
 
-    verifyDropNamespaceSucc(IcebergRestTestUtil.TEST_NAMESPACE_NAME);
-    verifyUpdateViewFail("replace_foo1", 404, metadata);
+    verifyDropNamespaceSucc(namespace);
+    verifyUpdateViewFail(namespace, "replace_foo1", 404, metadata);
   }
 
-  @Test
-  void testDropView() {
-    verifyDropViewFail("drop_foo1", 404);
+  @ParameterizedTest
+  
@MethodSource("org.apache.gravitino.iceberg.service.rest.IcebergRestTestUtil#testNamespaces")
+  void testDropView(Namespace namespace) {
+    verifyDropViewFail(namespace, "drop_foo1", 404);
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergDropViewPreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergDropViewFailureEvent);
 
-    verifyCreateNamespaceSucc(IcebergRestTestUtil.TEST_NAMESPACE_NAME);
-    verifyDropViewFail("drop_foo1", 404);
+    verifyCreateNamespaceSucc(namespace);
+    verifyDropViewFail(namespace, "drop_foo1", 404);
 
-    verifyCreateViewSucc("drop_foo1");
+    verifyCreateViewSucc(namespace, "drop_foo1");
 
     dummyEventListener.clearEvent();
-    verifyDropViewSucc("drop_foo1");
+    verifyDropViewSucc(namespace, "drop_foo1");
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergDropViewPreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergDropViewEvent);
 
-    verifyLoadViewFail("drop_foo1", 404);
+    verifyLoadViewFail(namespace, "drop_foo1", 404);
   }
 
-  @Test
-  void testViewExits() {
-    verifyViewExistsStatusCode("exists_foo2", 404);
+  @ParameterizedTest
+  
@MethodSource("org.apache.gravitino.iceberg.service.rest.IcebergRestTestUtil#testNamespaces")
+  void testViewExits(Namespace namespace) {
+    verifyViewExistsStatusCode(namespace, "exists_foo2", 404);
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergViewExistsPreEvent);
     Event postEvent = dummyEventListener.popPostEvent();
     Assertions.assertTrue(postEvent instanceof IcebergViewExistsEvent);
     Assertions.assertEquals(false, ((IcebergViewExistsEvent) 
postEvent).isExists());
 
-    verifyCreateNamespaceSucc(IcebergRestTestUtil.TEST_NAMESPACE_NAME);
-    verifyViewExistsStatusCode("exists_foo2", 404);
+    verifyCreateNamespaceSucc(namespace);
+    verifyViewExistsStatusCode(namespace, "exists_foo2", 404);
 
-    verifyCreateViewSucc("exists_foo1");
+    verifyCreateViewSucc(namespace, "exists_foo1");
     dummyEventListener.clearEvent();
-    verifyViewExistsStatusCode("exists_foo1", 204);
+    verifyViewExistsStatusCode(namespace, "exists_foo1", 204);
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergViewExistsPreEvent);
     postEvent = dummyEventListener.popPostEvent();
     Assertions.assertTrue(postEvent instanceof IcebergViewExistsEvent);
     Assertions.assertEquals(true, ((IcebergViewExistsEvent) 
postEvent).isExists());
 
-    verifyLoadViewSucc("exists_foo1");
+    verifyLoadViewSucc(namespace, "exists_foo1");
   }
 
   @ParameterizedTest
-  @ValueSource(strings = {"", IcebergRestTestUtil.PREFIX})
-  void testRenameTable(String prefix) {
+  @MethodSource(
+      
"org.apache.gravitino.iceberg.service.rest.IcebergRestTestUtil#testPrefixesAndNamespaces")
+  void testRenameTable(String prefix, Namespace namespace) {
     setUrlPathWithPrefix(prefix);
     // namespace not exits
-    verifyRenameViewFail("rename_foo1", "rename_foo3", 404);
+    verifyRenameViewFail(namespace, "rename_foo1", "rename_foo3", 404);
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergRenameViewPreEvent);
     Assertions.assertTrue(
         dummyEventListener.popPostEvent() instanceof 
IcebergRenameViewFailureEvent);
 
-    verifyCreateNamespaceSucc(IcebergRestTestUtil.TEST_NAMESPACE_NAME);
-    verifyCreateViewSucc("rename_foo1");
+    verifyCreateNamespaceSucc(namespace);
+    verifyCreateViewSucc(namespace, "rename_foo1");
 
     dummyEventListener.clearEvent();
     // rename
-    verifyRenameViewSucc("rename_foo1", "rename_foo2");
+    verifyRenameViewSucc(namespace, "rename_foo1", "rename_foo2");
     Assertions.assertTrue(dummyEventListener.popPreEvent() instanceof 
IcebergRenameViewPreEvent);
     Assertions.assertTrue(dummyEventListener.popPostEvent() instanceof 
IcebergRenameViewEvent);
 
-    verifyLoadViewFail("rename_foo1", 404);
-    verifyLoadViewSucc("rename_foo2");
+    verifyLoadViewFail(namespace, "rename_foo1", 404);
+    verifyLoadViewSucc(namespace, "rename_foo2");
 
     // source view not exists
-    verifyRenameViewFail("rename_foo1", "rename_foo3", 404);
+    verifyRenameViewFail(namespace, "rename_foo1", "rename_foo3", 404);
 
     // dest view exists
-    verifyCreateViewSucc("rename_foo3");
-    verifyRenameViewFail("rename_foo2", "rename_foo3", 409);
+    verifyCreateViewSucc(namespace, "rename_foo3");
+    verifyRenameViewFail(namespace, "rename_foo2", "rename_foo3", 409);
   }
 
-  private Response doCreateView(String name) {
+  private Response doCreateView(Namespace ns, String name) {
     CreateViewRequest createViewRequest =
         ImmutableCreateViewRequest.builder()
             .name(name)
@@ -249,7 +255,7 @@ public class TestIcebergViewOperations extends 
IcebergNamespaceTestBase {
                     .versionId(1)
                     .timestampMillis(System.currentTimeMillis())
                     .schemaId(1)
-                    
.defaultNamespace(Namespace.of(IcebergRestTestUtil.TEST_NAMESPACE_NAME))
+                    .defaultNamespace(IcebergRestTestUtil.TEST_NAMESPACE_NAME)
                     .addRepresentations(
                         ImmutableSQLViewRepresentation.builder()
                             .sql(VIEW_QUERY)
@@ -257,49 +263,49 @@ public class TestIcebergViewOperations extends 
IcebergNamespaceTestBase {
                             .build())
                     .build())
             .build();
-    return getViewClientBuilder()
+    return getViewClientBuilder(ns)
         .post(Entity.entity(createViewRequest, 
MediaType.APPLICATION_JSON_TYPE));
   }
 
-  private Response doLoadView(String name) {
-    return getViewClientBuilder(Optional.of(name)).get();
+  private Response doLoadView(Namespace ns, String name) {
+    return getViewClientBuilder(ns, Optional.of(name)).get();
   }
 
-  private void verifyLoadViewSucc(String name) {
-    Response response = doLoadView(name);
+  private void verifyLoadViewSucc(Namespace ns, String name) {
+    Response response = doLoadView(ns, name);
     Assertions.assertEquals(Response.Status.OK.getStatusCode(), 
response.getStatus());
 
     LoadViewResponse loadViewResponse = 
response.readEntity(LoadViewResponse.class);
     Assertions.assertEquals(viewSchema.columns(), 
loadViewResponse.metadata().schema().columns());
   }
 
-  private void verifyCreateViewFail(String name, int status) {
-    Response response = doCreateView(name);
+  private void verifyCreateViewFail(Namespace ns, String name, int status) {
+    Response response = doCreateView(ns, name);
     Assertions.assertEquals(status, response.getStatus());
   }
 
-  private void verifyCreateViewSucc(String name) {
-    Response response = doCreateView(name);
+  private void verifyCreateViewSucc(Namespace ns, String name) {
+    Response response = doCreateView(ns, name);
     Assertions.assertEquals(Response.Status.OK.getStatusCode(), 
response.getStatus());
     LoadViewResponse loadViewResponse = 
response.readEntity(LoadViewResponse.class);
     Schema schema = loadViewResponse.metadata().schema();
     Assertions.assertEquals(schema.columns(), viewSchema.columns());
   }
 
-  private void verifyLoadViewFail(String name, int status) {
-    Response response = doLoadView(name);
+  private void verifyLoadViewFail(Namespace ns, String name, int status) {
+    Response response = doLoadView(ns, name);
     Assertions.assertEquals(status, response.getStatus());
   }
 
-  private void verifyReplaceSucc(String name, ViewMetadata base) {
-    Response response = doReplaceView(name, base);
+  private void verifyReplaceSucc(Namespace ns, String name, ViewMetadata base) 
{
+    Response response = doReplaceView(ns, name, base);
     Assertions.assertEquals(Response.Status.OK.getStatusCode(), 
response.getStatus());
     LoadViewResponse loadViewResponse = 
response.readEntity(LoadViewResponse.class);
     Assertions.assertEquals(
         newViewSchema.columns(), 
loadViewResponse.metadata().schema().columns());
   }
 
-  private Response doReplaceView(String name, ViewMetadata base) {
+  private Response doReplaceView(Namespace ns, String name, ViewMetadata base) 
{
     ViewMetadata.Builder builder =
         ViewMetadata.buildFrom(base).setCurrentVersion(base.currentVersion(), 
newViewSchema);
     ViewMetadata replacement = builder.build();
@@ -308,55 +314,55 @@ public class TestIcebergViewOperations extends 
IcebergNamespaceTestBase {
             null,
             UpdateRequirements.forReplaceView(base, replacement.changes()),
             replacement.changes());
-    return getViewClientBuilder(Optional.of(name))
+    return getViewClientBuilder(ns, Optional.of(name))
         .post(Entity.entity(updateTableRequest, 
MediaType.APPLICATION_JSON_TYPE));
   }
 
-  private ViewMetadata getViewMeta(String viewName) {
-    Response response = doLoadView(viewName);
+  private ViewMetadata getViewMeta(Namespace ns, String viewName) {
+    Response response = doLoadView(ns, viewName);
     LoadViewResponse loadViewResponse = 
response.readEntity(LoadViewResponse.class);
     return loadViewResponse.metadata();
   }
 
-  private void verifyUpdateViewFail(String name, int status, ViewMetadata 
base) {
-    Response response = doReplaceView(name, base);
+  private void verifyUpdateViewFail(Namespace ns, String name, int status, 
ViewMetadata base) {
+    Response response = doReplaceView(ns, name, base);
     Assertions.assertEquals(status, response.getStatus());
   }
 
-  private void verifyDropViewSucc(String name) {
-    Response response = doDropView(name);
+  private void verifyDropViewSucc(Namespace ns, String name) {
+    Response response = doDropView(ns, name);
     Assertions.assertEquals(Response.Status.NO_CONTENT.getStatusCode(), 
response.getStatus());
   }
 
-  private Response doDropView(String name) {
-    return getViewClientBuilder(Optional.of(name)).delete();
+  private Response doDropView(Namespace ns, String name) {
+    return getViewClientBuilder(ns, Optional.of(name)).delete();
   }
 
-  private void verifyDropViewFail(String name, int status) {
-    Response response = doDropView(name);
+  private void verifyDropViewFail(Namespace ns, String name, int status) {
+    Response response = doDropView(ns, name);
     Assertions.assertEquals(status, response.getStatus());
   }
 
-  private void verifyViewExistsStatusCode(String name, int status) {
-    Response response = doViewExists(name);
+  private void verifyViewExistsStatusCode(Namespace ns, String name, int 
status) {
+    Response response = doViewExists(ns, name);
     Assertions.assertEquals(status, response.getStatus());
   }
 
-  private Response doViewExists(String name) {
-    return getViewClientBuilder(Optional.of(name)).head();
+  private Response doViewExists(Namespace ns, String name) {
+    return getViewClientBuilder(ns, Optional.of(name)).head();
   }
 
-  private void verifyListViewFail(int status) {
-    Response response = doListView();
+  private void verifyListViewFail(Namespace ns, int status) {
+    Response response = doListView(ns);
     Assertions.assertEquals(status, response.getStatus());
   }
 
-  private Response doListView() {
-    return getViewClientBuilder().get();
+  private Response doListView(Namespace ns) {
+    return getViewClientBuilder(ns).get();
   }
 
-  private void verifyLisViewSucc(Set<String> expectedTableNames) {
-    Response response = doListView();
+  private void verifyLisViewSucc(Namespace ns, Set<String> expectedTableNames) 
{
+    Response response = doListView(ns);
     Assertions.assertEquals(Response.Status.OK.getStatusCode(), 
response.getStatus());
     ListTablesResponse listTablesResponse = 
response.readEntity(ListTablesResponse.class);
     Set<String> tableNames =
@@ -366,25 +372,23 @@ public class TestIcebergViewOperations extends 
IcebergNamespaceTestBase {
     Assertions.assertEquals(expectedTableNames, tableNames);
   }
 
-  private void verifyRenameViewFail(String source, String dest, int status) {
-    Response response = doRenameView(source, dest);
+  private void verifyRenameViewFail(Namespace ns, String source, String dest, 
int status) {
+    Response response = doRenameView(ns, source, dest);
     Assertions.assertEquals(status, response.getStatus());
   }
 
-  private Response doRenameView(String source, String dest) {
+  private Response doRenameView(Namespace ns, String source, String dest) {
     RenameTableRequest renameTableRequest =
         RenameTableRequest.builder()
-            .withSource(
-                
TableIdentifier.of(Namespace.of(IcebergRestTestUtil.TEST_NAMESPACE_NAME), 
source))
-            .withDestination(
-                
TableIdentifier.of(Namespace.of(IcebergRestTestUtil.TEST_NAMESPACE_NAME), dest))
+            .withSource(TableIdentifier.of(ns, source))
+            .withDestination(TableIdentifier.of(ns, dest))
             .build();
     return getRenameViewClientBuilder()
         .post(Entity.entity(renameTableRequest, 
MediaType.APPLICATION_JSON_TYPE));
   }
 
-  private void verifyRenameViewSucc(String source, String dest) {
-    Response response = doRenameView(source, dest);
+  private void verifyRenameViewSucc(Namespace ns, String source, String dest) {
+    Response response = doRenameView(ns, source, dest);
     Assertions.assertEquals(Response.Status.NO_CONTENT.getStatusCode(), 
response.getStatus());
   }
 }

Reply via email to