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

lzljs3620320 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git


The following commit(s) were added to refs/heads/master by this push:
     new 622e41b990 [core] rest: support function paged api (#5774)
622e41b990 is described below

commit 622e41b99090394638d7323526e5e81c44cd2b4d
Author: jerry <[email protected]>
AuthorDate: Thu Jun 19 19:10:04 2025 +0800

    [core] rest: support function paged api (#5774)
---
 docs/static/rest-catalog-open-api.yaml             | 114 ++++++++++++-
 .../java/org/apache/paimon/catalog/Identifier.java |   2 +-
 .../main/java/org/apache/paimon/rest/RESTApi.java  | 124 ++++++++++++++
 .../java/org/apache/paimon/rest/ResourcePaths.java |   9 +
 ...ponse.java => ListFunctionDetailsResponse.java} |  31 ++--
 ...nse.java => ListFunctionsGloballyResponse.java} |  18 +-
 .../rest/responses/ListFunctionsResponse.java      |   4 -
 .../java/org/apache/paimon/catalog/Catalog.java    |  92 +++++++++-
 .../java/org/apache/paimon/rest/RESTCatalog.java   |  48 ++++++
 .../org/apache/paimon/rest/RESTCatalogServer.java  | 190 +++++++++++++++++----
 .../org/apache/paimon/rest/RESTCatalogTest.java    |  60 ++++++-
 .../org/apache/paimon/flink/RESTCatalogITCase.java |   3 +-
 .../flink/procedure/FunctionProcedureITCase.java   |   9 +-
 13 files changed, 631 insertions(+), 73 deletions(-)

diff --git a/docs/static/rest-catalog-open-api.yaml 
b/docs/static/rest-catalog-open-api.yaml
index 402a4553b3..8e2202729a 100644
--- a/docs/static/rest-catalog-open-api.yaml
+++ b/docs/static/rest-catalog-open-api.yaml
@@ -1398,6 +1398,11 @@ paths:
           in: query
           schema:
             type: string
+        - name: functionNamePattern
+          description: A sql LIKE pattern (%) for function names. Currently, 
only prefix matching is supported.
+          in: query
+          schema:
+            type: string
       responses:
         "200":
           description: OK
@@ -1414,7 +1419,7 @@ paths:
     post:
       tags:
         - function
-      summary: Create Function
+      summary: Create function
       operationId: createFunction
       parameters:
         - name: prefix
@@ -1446,6 +1451,97 @@ paths:
         "500":
           $ref: '#/components/responses/ServerErrorResponse'
 
+  /v1/{prefix}/databases/{database}/function-details:
+    get:
+      tags:
+        - function
+      summary: List function details
+      operationId: listFunctionDetails
+      parameters:
+        - name: prefix
+          in: path
+          required: true
+          schema:
+            type: string
+        - name: database
+          in: path
+          required: true
+          schema:
+            type: string
+        - name: maxResults
+          in: query
+          schema:
+            type: integer
+            format: int32
+        - name: pageToken
+          in: query
+          schema:
+            type: string
+        - name: functionNamePattern
+          description: A sql LIKE pattern (%) for function names. Currently, 
only prefix matching is supported.
+          in: query
+          schema:
+            type: string
+      responses:
+        "200":
+          description: OK
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ListFunctionDetailsResponse'
+        "401":
+          $ref: '#/components/responses/UnauthorizedErrorResponse'
+        "404":
+          $ref: '#/components/responses/DatabaseNotExistErrorResponse'
+        "500":
+          $ref: '#/components/responses/ServerErrorResponse'
+
+  /v1/{prefix}/functions:
+    get:
+      tags:
+        - function
+      summary: List functions globally
+      operationId: listFunctionsGlobally
+      description: List functions globally which matches the given database 
name pattern and function name pattern both.
+      parameters:
+        - name: prefix
+          in: path
+          required: true
+          schema:
+            type: string
+        - name: databaseNamePattern
+          description: A sql LIKE pattern (%) for database names. All 
databases will be returned if not set or empty. Currently, only prefix matching 
is supported.
+          in: path
+          schema:
+            type: string
+        - name: functionNamePattern
+          description: A sql LIKE pattern (%) for function names. All 
functions will be returned if not set or empty. Currently, only prefix matching 
is supported.
+          in: query
+          schema:
+            type: string
+        - name: maxResults
+          in: query
+          schema:
+            type: integer
+            format: int32
+        - name: pageToken
+          in: query
+          schema:
+            type: string
+
+      responses:
+        "200":
+          description: OK
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ListFunctionsGloballyResponse'
+        "401":
+          $ref: '#/components/responses/UnauthorizedErrorResponse'
+        "500":
+          $ref: '#/components/responses/ServerErrorResponse'
+
+
   /v1/{prefix}/databases/{database}/functions/{function}:
     get:
       tags:
@@ -2739,6 +2835,13 @@ components:
             $ref: '#/components/schemas/GetViewResponse'
         nextPageToken:
           type: string
+    ListFunctionsGloballyResponse:
+      type: object
+      properties:
+        functions:
+          type: array
+          items:
+            $ref: '#/components/schemas/Identifier'
     ListViewsGloballyResponse:
       type: object
       properties:
@@ -2758,6 +2861,15 @@ components:
             type: string
         nextPageToken:
           type: string
+    ListFunctionDetailsResponse:
+      type: object
+      properties:
+        functionDetails:
+          type: array
+          items:
+            $ref: '#/components/schemas/GetFunctionResponse'
+        nextPageToken:
+          type: string
     GetFunctionResponse:
       type: object
       properties:
diff --git a/paimon-api/src/main/java/org/apache/paimon/catalog/Identifier.java 
b/paimon-api/src/main/java/org/apache/paimon/catalog/Identifier.java
index f88431924e..309ddad3be 100644
--- a/paimon-api/src/main/java/org/apache/paimon/catalog/Identifier.java
+++ b/paimon-api/src/main/java/org/apache/paimon/catalog/Identifier.java
@@ -204,7 +204,7 @@ public class Identifier implements Serializable {
         checkArgument(
                 !StringUtils.isNullOrWhitespaceOnly(fullName), "fullName 
cannot be null or empty");
 
-        String[] paths = fullName.split("\\.");
+        String[] paths = fullName.split("\\.", 2);
 
         if (paths.length != 2) {
             throw new IllegalArgumentException(
diff --git a/paimon-api/src/main/java/org/apache/paimon/rest/RESTApi.java 
b/paimon-api/src/main/java/org/apache/paimon/rest/RESTApi.java
index d80cb566ea..e615ca99db 100644
--- a/paimon-api/src/main/java/org/apache/paimon/rest/RESTApi.java
+++ b/paimon-api/src/main/java/org/apache/paimon/rest/RESTApi.java
@@ -61,6 +61,8 @@ import 
org.apache.paimon.rest.responses.GetVersionSnapshotResponse;
 import org.apache.paimon.rest.responses.GetViewResponse;
 import org.apache.paimon.rest.responses.ListBranchesResponse;
 import org.apache.paimon.rest.responses.ListDatabasesResponse;
+import org.apache.paimon.rest.responses.ListFunctionDetailsResponse;
+import org.apache.paimon.rest.responses.ListFunctionsGloballyResponse;
 import org.apache.paimon.rest.responses.ListFunctionsResponse;
 import org.apache.paimon.rest.responses.ListPartitionsResponse;
 import org.apache.paimon.rest.responses.ListSnapshotsResponse;
@@ -139,6 +141,7 @@ public class RESTApi {
     public static final String DATABASE_NAME_PATTERN = "databaseNamePattern";
     public static final String TABLE_NAME_PATTERN = "tableNamePattern";
     public static final String VIEW_NAME_PATTERN = "viewNamePattern";
+    public static final String FUNCTION_NAME_PATTERN = "functionNamePattern";
     public static final String PARTITION_NAME_PATTERN = "partitionNamePattern";
 
     public static final long TOKEN_EXPIRATION_SAFE_TIME_MILLIS = 3_600_000L;
@@ -847,6 +850,127 @@ public class RESTApi {
                                 restAuthFunction));
     }
 
+    /**
+     * List functions by page.
+     *
+     * <p>Gets an array of functions for a database. There is no guarantee of 
a specific ordering of
+     * the elements in the array.
+     *
+     * @param databaseName database name
+     * @param maxResults Optional parameter indicating the maximum number of 
results to include in
+     *     the result. If maxResults is not specified or set to 0, will return 
the default number of
+     *     max results.
+     * @param pageToken Optional parameter indicating the next page token 
allows list to be start
+     *     from a specific point.
+     * @param functionNamePattern A sql LIKE pattern (%) for function names. 
All functions will be
+     *     returned if not set or empty. Currently, only prefix matching is 
supported.
+     * @return {@link PagedList}: elements and nextPageToken.
+     * @throws NoSuchResourceException Exception thrown on HTTP 404 means the 
database not exists
+     * @throws ForbiddenException Exception thrown on HTTP 403 means don't 
have the permission for
+     *     this database
+     */
+    public PagedList<String> listFunctionsPaged(
+            String databaseName,
+            @Nullable Integer maxResults,
+            @Nullable String pageToken,
+            @Nullable String functionNamePattern) {
+        ListFunctionsResponse response =
+                client.get(
+                        resourcePaths.functions(databaseName),
+                        buildPagedQueryParams(
+                                maxResults,
+                                pageToken,
+                                Pair.of(FUNCTION_NAME_PATTERN, 
functionNamePattern)),
+                        ListFunctionsResponse.class,
+                        restAuthFunction);
+        List<String> functions = response.functions();
+        if (functions == null) {
+            return new PagedList<>(emptyList(), null);
+        }
+        return new PagedList<>(functions, response.getNextPageToken());
+    }
+
+    /**
+     * List function details.
+     *
+     * <p>Gets an array of function details for a database. There is no 
guarantee of a specific
+     * ordering of the elements in the array.
+     *
+     * @param databaseName database name
+     * @param maxResults Optional parameter indicating the maximum number of 
results to include in
+     *     the result. If maxResults is not specified or set to 0, will return 
the default number of
+     *     max results.
+     * @param pageToken Optional parameter indicating the next page token 
allows list to be start
+     *     from a specific point.
+     * @param functionNamePattern A sql LIKE pattern (%) for function names. 
All functions will be
+     *     returned if not set or empty. Currently, only prefix matching is 
supported.
+     * @return {@link PagedList}: elements and nextPageToken.
+     * @throws NoSuchResourceException Exception thrown on HTTP 404 means the 
database not exists
+     * @throws ForbiddenException Exception thrown on HTTP 403 means don't 
have the permission for
+     *     this database
+     */
+    public PagedList<GetFunctionResponse> listFunctionDetailsPaged(
+            String databaseName,
+            @Nullable Integer maxResults,
+            @Nullable String pageToken,
+            @Nullable String functionNamePattern) {
+        ListFunctionDetailsResponse response =
+                client.get(
+                        resourcePaths.functionDetails(databaseName),
+                        buildPagedQueryParams(
+                                maxResults,
+                                pageToken,
+                                Pair.of(FUNCTION_NAME_PATTERN, 
functionNamePattern)),
+                        ListFunctionDetailsResponse.class,
+                        restAuthFunction);
+        List<GetFunctionResponse> functionDetails = response.data();
+        if (functionDetails == null) {
+            return new PagedList<>(emptyList(), null);
+        }
+        return new PagedList<>(functionDetails, response.getNextPageToken());
+    }
+
+    /**
+     * List functions for a catalog.
+     *
+     * <p>Gets an array of functions for a catalog. There is no guarantee of a 
specific ordering of
+     * the elements in the array.
+     *
+     * @param databaseNamePattern A sql LIKE pattern (%) for database names. 
All databases will be
+     *     returned if not set or empty. Currently, only prefix matching is 
supported.
+     * @param functionNamePattern A sql LIKE pattern (%) for function names. 
All functions will be
+     *     returned if not set or empty. Currently, only prefix matching is 
supported.
+     * @param maxResults Optional parameter indicating the maximum number of 
results to include in
+     *     the result. If maxResults is not specified or set to 0, will return 
the default number of
+     *     max results.
+     * @param pageToken Optional parameter indicating the next page token 
allows list to be start
+     *     from a specific point.
+     * @return {@link PagedList}: elements and nextPageToken.
+     * @throws ForbiddenException Exception thrown on HTTP 403 means don't 
have the permission for
+     *     this database
+     */
+    public PagedList<Identifier> listFunctionsPagedGlobally(
+            @Nullable String databaseNamePattern,
+            @Nullable String functionNamePattern,
+            @Nullable Integer maxResults,
+            @Nullable String pageToken) {
+        ListFunctionsGloballyResponse response =
+                client.get(
+                        resourcePaths.functions(),
+                        buildPagedQueryParams(
+                                maxResults,
+                                pageToken,
+                                Pair.of(DATABASE_NAME_PATTERN, 
databaseNamePattern),
+                                Pair.of(FUNCTION_NAME_PATTERN, 
functionNamePattern)),
+                        ListFunctionsGloballyResponse.class,
+                        restAuthFunction);
+        List<Identifier> functions = response.data();
+        if (functions == null) {
+            return new PagedList<>(emptyList(), null);
+        }
+        return new PagedList<>(functions, response.getNextPageToken());
+    }
+
     /**
      * Get a function by identifier.
      *
diff --git a/paimon-api/src/main/java/org/apache/paimon/rest/ResourcePaths.java 
b/paimon-api/src/main/java/org/apache/paimon/rest/ResourcePaths.java
index 99020f65d2..25f7ab9a2d 100644
--- a/paimon-api/src/main/java/org/apache/paimon/rest/ResourcePaths.java
+++ b/paimon-api/src/main/java/org/apache/paimon/rest/ResourcePaths.java
@@ -38,6 +38,7 @@ public class ResourcePaths {
     protected static final String VIEW_DETAILS = "view-details";
     protected static final String ROLLBACK = "rollback";
     protected static final String FUNCTIONS = "functions";
+    protected static final String FUNCTION_DETAILS = "function-details";
 
     private static final Joiner SLASH = Joiner.on("/").skipNulls();
 
@@ -251,6 +252,14 @@ public class ResourcePaths {
         return SLASH.join(V1, prefix, DATABASES, encodeString(databaseName), 
FUNCTIONS);
     }
 
+    public String functions() {
+        return SLASH.join(V1, prefix, FUNCTIONS);
+    }
+
+    public String functionDetails(String databaseName) {
+        return SLASH.join(V1, prefix, DATABASES, encodeString(databaseName), 
FUNCTION_DETAILS);
+    }
+
     public String function(String databaseName, String functionName) {
         return SLASH.join(
                 V1,
diff --git 
a/paimon-api/src/main/java/org/apache/paimon/rest/responses/ListFunctionsResponse.java
 
b/paimon-api/src/main/java/org/apache/paimon/rest/responses/ListFunctionDetailsResponse.java
similarity index 66%
copy from 
paimon-api/src/main/java/org/apache/paimon/rest/responses/ListFunctionsResponse.java
copy to 
paimon-api/src/main/java/org/apache/paimon/rest/responses/ListFunctionDetailsResponse.java
index 0c2165077a..c0d9919ba9 100644
--- 
a/paimon-api/src/main/java/org/apache/paimon/rest/responses/ListFunctionsResponse.java
+++ 
b/paimon-api/src/main/java/org/apache/paimon/rest/responses/ListFunctionDetailsResponse.java
@@ -25,34 +25,35 @@ import 
org.apache.paimon.shade.jackson2.com.fasterxml.jackson.annotation.JsonPro
 
 import java.util.List;
 
-/** Response for listing functions. */
+/** Response for listing function details. */
 @JsonIgnoreProperties(ignoreUnknown = true)
-public class ListFunctionsResponse implements PagedResponse<String> {
+public class ListFunctionDetailsResponse implements 
PagedResponse<GetFunctionResponse> {
 
-    private static final String FIELD_FUNCTIONS = "functions";
+    private static final String FIELD_FUNCTION_DETAILS = "functionDetails";
     private static final String FIELD_NEXT_PAGE_TOKEN = "nextPageToken";
 
-    @JsonProperty(FIELD_FUNCTIONS)
-    private final List<String> functions;
+    @JsonProperty(FIELD_FUNCTION_DETAILS)
+    private final List<GetFunctionResponse> functionDetails;
 
     @JsonProperty(FIELD_NEXT_PAGE_TOKEN)
     private final String nextPageToken;
 
-    public ListFunctionsResponse(@JsonProperty(FIELD_FUNCTIONS) List<String> 
functions) {
-        this(functions, null);
+    public ListFunctionDetailsResponse(
+            @JsonProperty(FIELD_FUNCTION_DETAILS) List<GetFunctionResponse> 
functionDetails) {
+        this(functionDetails, null);
     }
 
     @JsonCreator
-    public ListFunctionsResponse(
-            @JsonProperty(FIELD_FUNCTIONS) List<String> functions,
+    public ListFunctionDetailsResponse(
+            @JsonProperty(FIELD_FUNCTION_DETAILS) List<GetFunctionResponse> 
functionDetails,
             @JsonProperty(FIELD_NEXT_PAGE_TOKEN) String nextPageToken) {
-        this.functions = functions;
+        this.functionDetails = functionDetails;
         this.nextPageToken = nextPageToken;
     }
 
-    @JsonGetter(FIELD_FUNCTIONS)
-    public List<String> functions() {
-        return this.functions;
+    @JsonGetter(FIELD_FUNCTION_DETAILS)
+    public List<GetFunctionResponse> getFunctionDetails() {
+        return this.functionDetails;
     }
 
     @JsonGetter(FIELD_NEXT_PAGE_TOKEN)
@@ -61,7 +62,7 @@ public class ListFunctionsResponse implements 
PagedResponse<String> {
     }
 
     @Override
-    public List<String> data() {
-        return functions();
+    public List<GetFunctionResponse> data() {
+        return getFunctionDetails();
     }
 }
diff --git 
a/paimon-api/src/main/java/org/apache/paimon/rest/responses/ListFunctionsResponse.java
 
b/paimon-api/src/main/java/org/apache/paimon/rest/responses/ListFunctionsGloballyResponse.java
similarity index 82%
copy from 
paimon-api/src/main/java/org/apache/paimon/rest/responses/ListFunctionsResponse.java
copy to 
paimon-api/src/main/java/org/apache/paimon/rest/responses/ListFunctionsGloballyResponse.java
index 0c2165077a..4a077114d2 100644
--- 
a/paimon-api/src/main/java/org/apache/paimon/rest/responses/ListFunctionsResponse.java
+++ 
b/paimon-api/src/main/java/org/apache/paimon/rest/responses/ListFunctionsGloballyResponse.java
@@ -18,6 +18,8 @@
 
 package org.apache.paimon.rest.responses;
 
+import org.apache.paimon.catalog.Identifier;
+
 import 
org.apache.paimon.shade.jackson2.com.fasterxml.jackson.annotation.JsonCreator;
 import 
org.apache.paimon.shade.jackson2.com.fasterxml.jackson.annotation.JsonGetter;
 import 
org.apache.paimon.shade.jackson2.com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@@ -27,31 +29,27 @@ import java.util.List;
 
 /** Response for listing functions. */
 @JsonIgnoreProperties(ignoreUnknown = true)
-public class ListFunctionsResponse implements PagedResponse<String> {
+public class ListFunctionsGloballyResponse implements 
PagedResponse<Identifier> {
 
     private static final String FIELD_FUNCTIONS = "functions";
     private static final String FIELD_NEXT_PAGE_TOKEN = "nextPageToken";
 
     @JsonProperty(FIELD_FUNCTIONS)
-    private final List<String> functions;
+    private final List<Identifier> functions;
 
     @JsonProperty(FIELD_NEXT_PAGE_TOKEN)
     private final String nextPageToken;
 
-    public ListFunctionsResponse(@JsonProperty(FIELD_FUNCTIONS) List<String> 
functions) {
-        this(functions, null);
-    }
-
     @JsonCreator
-    public ListFunctionsResponse(
-            @JsonProperty(FIELD_FUNCTIONS) List<String> functions,
+    public ListFunctionsGloballyResponse(
+            @JsonProperty(FIELD_FUNCTIONS) List<Identifier> functions,
             @JsonProperty(FIELD_NEXT_PAGE_TOKEN) String nextPageToken) {
         this.functions = functions;
         this.nextPageToken = nextPageToken;
     }
 
     @JsonGetter(FIELD_FUNCTIONS)
-    public List<String> functions() {
+    public List<Identifier> functions() {
         return this.functions;
     }
 
@@ -61,7 +59,7 @@ public class ListFunctionsResponse implements 
PagedResponse<String> {
     }
 
     @Override
-    public List<String> data() {
+    public List<Identifier> data() {
         return functions();
     }
 }
diff --git 
a/paimon-api/src/main/java/org/apache/paimon/rest/responses/ListFunctionsResponse.java
 
b/paimon-api/src/main/java/org/apache/paimon/rest/responses/ListFunctionsResponse.java
index 0c2165077a..0ac536dc4a 100644
--- 
a/paimon-api/src/main/java/org/apache/paimon/rest/responses/ListFunctionsResponse.java
+++ 
b/paimon-api/src/main/java/org/apache/paimon/rest/responses/ListFunctionsResponse.java
@@ -38,10 +38,6 @@ public class ListFunctionsResponse implements 
PagedResponse<String> {
     @JsonProperty(FIELD_NEXT_PAGE_TOKEN)
     private final String nextPageToken;
 
-    public ListFunctionsResponse(@JsonProperty(FIELD_FUNCTIONS) List<String> 
functions) {
-        this(functions, null);
-    }
-
     @JsonCreator
     public ListFunctionsResponse(
             @JsonProperty(FIELD_FUNCTIONS) List<String> functions,
diff --git a/paimon-core/src/main/java/org/apache/paimon/catalog/Catalog.java 
b/paimon-core/src/main/java/org/apache/paimon/catalog/Catalog.java
index 0ae69f84d2..6eda935c26 100644
--- a/paimon-core/src/main/java/org/apache/paimon/catalog/Catalog.java
+++ b/paimon-core/src/main/java/org/apache/paimon/catalog/Catalog.java
@@ -443,7 +443,7 @@ public interface Catalog extends AutoCloseable {
      *     token, or a list of the names of all views in this database if the 
catalog does not
      *     {@link #supportsListObjectsPaged()}.
      * @throws DatabaseNotExistException if the database does not exist
-     * @throws UnsupportedOperationException if does not {@link 
#supportsListByPattern()}
+     * @throws UnsupportedOperationException if it does not {@link 
#supportsListByPattern()}
      */
     default PagedList<String> listViewsPaged(
             String databaseName,
@@ -470,7 +470,7 @@ public interface Catalog extends AutoCloseable {
      *     database and next page token, or a list of the details of all views 
in this database if
      *     the catalog does not {@link #supportsListObjectsPaged()}.
      * @throws DatabaseNotExistException if the database does not exist
-     * @throws UnsupportedOperationException if does not {@link 
#supportsListByPattern()}
+     * @throws UnsupportedOperationException if it does not {@link 
#supportsListByPattern()}
      */
     default PagedList<View> listViewDetailsPaged(
             String databaseName,
@@ -484,8 +484,6 @@ public interface Catalog extends AutoCloseable {
     /**
      * Gets an array of views for a catalog.
      *
-     * <p>NOTE: System tables will not be listed.
-     *
      * @param databaseNamePattern A sql LIKE pattern (%) for database names. 
All databases will be
      *     returned if not set or empty. Currently, only prefix matching is 
supported.
      * @param viewNamePattern A sql LIKE pattern (%) for view names. All views 
will be returned if
@@ -496,9 +494,9 @@ public interface Catalog extends AutoCloseable {
      * @param pageToken Optional parameter indicating the next page token 
allows list to be start
      *     from a specific point.
      * @return a list of the views with provided page size under this 
databaseNamePattern &
-     *     tableNamePattern and next page token
-     * @throws UnsupportedOperationException if does not {@link 
#supportsListObjectsPaged()} or does
-     *     not {@link #supportsListByPattern()}}.
+     *     viewNamePattern and next page token
+     * @throws UnsupportedOperationException if it does not {@link 
#supportsListObjectsPaged()} or
+     *     does not {@link #supportsListByPattern()}}.
      */
     default PagedList<Identifier> listViewsPagedGlobally(
             @Nullable String databaseNamePattern,
@@ -785,6 +783,86 @@ public interface Catalog extends AutoCloseable {
      */
     List<String> listFunctions(String databaseName) throws 
DatabaseNotExistException;
 
+    /**
+     * Get paged list names of function under this database. An empty list is 
returned if none
+     * function exists.
+     *
+     * @param databaseName Name of the database to list function.
+     * @param maxResults Optional parameter indicating the maximum number of 
results to include in
+     *     the result. If maxResults is not specified or set to 0, will return 
the default number of
+     *     max results.
+     * @param pageToken Optional parameter indicating the next page token 
allows list to be start
+     *     from a specific point.
+     * @param functionNamePattern A sql LIKE pattern (%) for function names. 
All function will be
+     *     returned if not set or empty. Currently, only prefix matching is 
supported.
+     * @return a list of the names of function with provided page size in this 
database and next
+     *     page token, or a list of the names of all function in this database 
if the catalog does
+     *     not {@link #supportsListObjectsPaged()}.
+     * @throws DatabaseNotExistException if the database does not exist
+     * @throws UnsupportedOperationException if it does not {@link 
#supportsListByPattern()}
+     */
+    default PagedList<String> listFunctionsPaged(
+            String databaseName,
+            @Nullable Integer maxResults,
+            @Nullable String pageToken,
+            @Nullable String functionNamePattern)
+            throws DatabaseNotExistException {
+        return new PagedList<>(listFunctions(databaseName), null);
+    }
+
+    /**
+     * Gets an array of function for a catalog.
+     *
+     * @param databaseNamePattern A sql LIKE pattern (%) for database names. 
All databases will be
+     *     returned if not set or empty. Currently, only prefix matching is 
supported.
+     * @param functionNamePattern A sql LIKE pattern (%) for function names. 
All functions will be
+     *     returned if not set or empty. Currently, only prefix matching is 
supported.
+     * @param maxResults Optional parameter indicating the maximum number of 
results to include in
+     *     the result. If maxResults is not specified or set to 0, will return 
the default number of
+     *     max results.
+     * @param pageToken Optional parameter indicating the next page token 
allows list to be start
+     *     from a specific point.
+     * @return a list of the function identifier with provided page size under 
this
+     *     databaseNamePattern & functionNamePattern and next page token
+     * @throws UnsupportedOperationException if it does not {@link 
#supportsListObjectsPaged()} or
+     *     does not {@link #supportsListByPattern()}}.
+     */
+    default PagedList<Identifier> listFunctionsPagedGlobally(
+            @Nullable String databaseNamePattern,
+            @Nullable String functionNamePattern,
+            @Nullable Integer maxResults,
+            @Nullable String pageToken) {
+        throw new UnsupportedOperationException(
+                "Current Catalog does not support listFunctionsPagedGlobally");
+    }
+
+    /**
+     * Get paged list function details under this database. An empty list is 
returned if none
+     * function exists.
+     *
+     * @param databaseName Name of the database to list function detail.
+     * @param maxResults Optional parameter indicating the maximum number of 
results to include in
+     *     the result. If maxResults is not specified or set to 0, will return 
the default number of
+     *     max results.
+     * @param pageToken Optional parameter indicating the next page token 
allows list to be start
+     *     from a specific point.
+     * @param functionNamePattern A sql LIKE pattern (%) for function names. 
All function details
+     *     will be returned if not set or empty. Currently, only prefix 
matching is supported.
+     * @return a list of the function detail with provided page size (@param 
maxResults) in this
+     *     database and next page token, or a list of the details of all 
functions in this database
+     *     if the catalog does not {@link #supportsListObjectsPaged()}.
+     * @throws DatabaseNotExistException if the database does not exist
+     * @throws UnsupportedOperationException if it does not {@link 
#supportsListByPattern()}
+     */
+    default PagedList<Function> listFunctionDetailsPaged(
+            String databaseName,
+            @Nullable Integer maxResults,
+            @Nullable String pageToken,
+            @Nullable String functionNamePattern)
+            throws DatabaseNotExistException {
+        return new PagedList<>(Collections.emptyList(), null);
+    }
+
     /**
      * Get function by name.
      *
diff --git a/paimon-core/src/main/java/org/apache/paimon/rest/RESTCatalog.java 
b/paimon-core/src/main/java/org/apache/paimon/rest/RESTCatalog.java
index 72ff174c88..b84903dafa 100644
--- a/paimon-core/src/main/java/org/apache/paimon/rest/RESTCatalog.java
+++ b/paimon-core/src/main/java/org/apache/paimon/rest/RESTCatalog.java
@@ -30,6 +30,7 @@ import org.apache.paimon.catalog.PropertyChange;
 import org.apache.paimon.catalog.TableMetadata;
 import org.apache.paimon.fs.FileIO;
 import org.apache.paimon.fs.Path;
+import org.apache.paimon.function.Function;
 import org.apache.paimon.function.FunctionChange;
 import org.apache.paimon.partition.Partition;
 import org.apache.paimon.partition.PartitionStatistics;
@@ -730,6 +731,53 @@ public class RESTCatalog implements Catalog {
         }
     }
 
+    @Override
+    public PagedList<String> listFunctionsPaged(
+            String databaseName,
+            @Nullable Integer maxResults,
+            @Nullable String pageToken,
+            @Nullable String functionNamePattern)
+            throws DatabaseNotExistException {
+        try {
+            return api.listFunctionsPaged(databaseName, maxResults, pageToken, 
functionNamePattern);
+        } catch (NoSuchResourceException e) {
+            throw new DatabaseNotExistException(databaseName);
+        }
+    }
+
+    @Override
+    public PagedList<Identifier> listFunctionsPagedGlobally(
+            @Nullable String databaseNamePattern,
+            @Nullable String functionNamePattern,
+            @Nullable Integer maxResults,
+            @Nullable String pageToken) {
+        PagedList<Identifier> functions =
+                api.listFunctionsPagedGlobally(
+                        databaseNamePattern, functionNamePattern, maxResults, 
pageToken);
+        return new PagedList<>(functions.getElements(), 
functions.getNextPageToken());
+    }
+
+    @Override
+    public PagedList<Function> listFunctionDetailsPaged(
+            String databaseName,
+            @Nullable Integer maxResults,
+            @Nullable String pageToken,
+            @Nullable String functionNamePattern)
+            throws DatabaseNotExistException {
+        try {
+            PagedList<GetFunctionResponse> functions =
+                    api.listFunctionDetailsPaged(
+                            databaseName, maxResults, pageToken, 
functionNamePattern);
+            return new PagedList<>(
+                    functions.getElements().stream()
+                            .map(v -> 
v.toFunction(Identifier.create(databaseName, v.name())))
+                            .collect(Collectors.toList()),
+                    functions.getNextPageToken());
+        } catch (NoSuchResourceException e) {
+            throw new DatabaseNotExistException(databaseName);
+        }
+    }
+
     @Override
     public View getView(Identifier identifier) throws ViewNotExistException {
         try {
diff --git 
a/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogServer.java 
b/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogServer.java
index e330362c3c..f46621913c 100644
--- a/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogServer.java
+++ b/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogServer.java
@@ -72,6 +72,8 @@ import 
org.apache.paimon.rest.responses.GetVersionSnapshotResponse;
 import org.apache.paimon.rest.responses.GetViewResponse;
 import org.apache.paimon.rest.responses.ListBranchesResponse;
 import org.apache.paimon.rest.responses.ListDatabasesResponse;
+import org.apache.paimon.rest.responses.ListFunctionDetailsResponse;
+import org.apache.paimon.rest.responses.ListFunctionsGloballyResponse;
 import org.apache.paimon.rest.responses.ListFunctionsResponse;
 import org.apache.paimon.rest.responses.ListPartitionsResponse;
 import org.apache.paimon.rest.responses.ListSnapshotsResponse;
@@ -132,11 +134,17 @@ import static org.apache.paimon.CoreOptions.TYPE;
 import static org.apache.paimon.TableType.FORMAT_TABLE;
 import static org.apache.paimon.options.CatalogOptions.WAREHOUSE;
 import static org.apache.paimon.rest.RESTApi.DATABASE_NAME_PATTERN;
+import static org.apache.paimon.rest.RESTApi.FUNCTION_NAME_PATTERN;
 import static org.apache.paimon.rest.RESTApi.MAX_RESULTS;
 import static org.apache.paimon.rest.RESTApi.PAGE_TOKEN;
 import static org.apache.paimon.rest.RESTApi.PARTITION_NAME_PATTERN;
 import static org.apache.paimon.rest.RESTApi.TABLE_NAME_PATTERN;
 import static org.apache.paimon.rest.RESTApi.VIEW_NAME_PATTERN;
+import static org.apache.paimon.rest.ResourcePaths.FUNCTIONS;
+import static org.apache.paimon.rest.ResourcePaths.FUNCTION_DETAILS;
+import static org.apache.paimon.rest.ResourcePaths.TABLE_DETAILS;
+import static org.apache.paimon.rest.ResourcePaths.VIEWS;
+import static org.apache.paimon.rest.ResourcePaths.VIEW_DETAILS;
 
 /** Mock REST server for testing. */
 public class RESTCatalogServer {
@@ -292,6 +300,9 @@ public class RESTCatalogServer {
                         return tablesHandle(parameters);
                     } else if (StringUtils.startsWith(request.getPath(), 
resourcePaths.views())) {
                         return viewsHandle(parameters);
+                    } else if (StringUtils.startsWith(
+                            request.getPath(), resourcePaths.functions())) {
+                        return functionsHandle(parameters);
                     } else if (request.getPath().startsWith(databaseUri)) {
                         String[] resources =
                                 request.getPath()
@@ -305,17 +316,19 @@ public class RESTCatalogServer {
                             throw new 
Catalog.DatabaseNotExistException(databaseName);
                         }
                         boolean isFunctions =
-                                resources.length == 2 && 
resources[1].startsWith("functions");
+                                resources.length == 2 && 
resources[1].startsWith(FUNCTIONS);
                         boolean isFunction =
-                                resources.length == 3 && 
resources[1].startsWith("functions");
-                        boolean isViews = resources.length == 2 && 
resources[1].startsWith("views");
+                                resources.length == 3 && 
resources[1].startsWith(FUNCTIONS);
+                        boolean isFunctionsDetails =
+                                resources.length == 2 && 
resources[1].startsWith(FUNCTION_DETAILS);
+                        boolean isViews = resources.length == 2 && 
resources[1].startsWith(VIEWS);
                         boolean isViewsDetails =
-                                resources.length == 2 && 
resources[1].startsWith("view-details");
+                                resources.length == 2 && 
resources[1].startsWith(VIEW_DETAILS);
                         boolean isTables =
                                 resources.length == 2
                                         && 
resources[1].startsWith(ResourcePaths.TABLES);
                         boolean isTableDetails =
-                                resources.length == 2 && 
resources[1].startsWith("table-details");
+                                resources.length == 2 && 
resources[1].startsWith(TABLE_DETAILS);
                         boolean isView =
                                 resources.length == 3
                                         && "views".equals(resources[1])
@@ -460,6 +473,9 @@ public class RESTCatalogServer {
                         } else if (isFunction) {
                             return functionApiHandler(
                                     identifier, restAuthParameter.method(), 
data, parameters);
+                        } else if (isFunctionsDetails) {
+                            return functionDetailsHandle(
+                                    restAuthParameter.method(), databaseName, 
parameters);
                         } else if (isViews) {
                             return viewsHandle(
                                     restAuthParameter.method(),
@@ -846,23 +862,40 @@ public class RESTCatalogServer {
             throws Exception {
         switch (method) {
             case "GET":
-                List<String> functions = new 
ArrayList<>(functionStore.keySet());
+                String namePattern = parameters.get(FUNCTION_NAME_PATTERN);
+                List<String> functions =
+                        (new ArrayList<>(functionStore.keySet()))
+                                .stream()
+                                        .map(n -> Identifier.fromString(n))
+                                        .filter(
+                                                identifier ->
+                                                        identifier
+                                                                        
.getDatabaseName()
+                                                                        
.equals(databaseName)
+                                                                && 
(Objects.isNull(namePattern)
+                                                                        || 
matchNamePattern(
+                                                                               
 identifier
+                                                                               
         .getObjectName(),
+                                                                               
 namePattern)))
+                                        .map(i -> i.getObjectName())
+                                        .collect(Collectors.toList());
                 return generateFinalListFunctionsResponse(parameters, 
functions);
             case "POST":
                 CreateFunctionRequest requestBody =
                         RESTApi.fromJson(data, CreateFunctionRequest.class);
                 String functionName = requestBody.name();
-                if (!functionStore.containsKey(functionName)) {
+                Identifier identity = Identifier.create(databaseName, 
functionName);
+                if (!functionStore.containsKey(identity.getFullName())) {
                     Function function =
                             new FunctionImpl(
-                                    Identifier.create(databaseName, 
functionName),
+                                    identity,
                                     requestBody.inputParams(),
                                     requestBody.returnParams(),
                                     requestBody.isDeterministic(),
                                     requestBody.definitions(),
                                     requestBody.comment(),
                                     requestBody.options());
-                    functionStore.put(functionName, function);
+                    functionStore.put(identity.getFullName(), function);
                     return new MockResponse().setResponseCode(200);
                 } else {
                     throw new Catalog.FunctionAlreadyExistException(
@@ -876,31 +909,16 @@ public class RESTCatalogServer {
     private MockResponse functionApiHandler(
             Identifier identifier, String method, String data, Map<String, 
String> parameters)
             throws Exception {
-        String functionName = identifier.getObjectName();
-        if (!functionStore.containsKey(functionName)) {
+        if (!functionStore.containsKey(identifier.getFullName())) {
             throw new Catalog.FunctionNotExistException(identifier);
         }
-        Function function = functionStore.get(functionName);
+        Function function = functionStore.get(identifier.getFullName());
         switch (method) {
             case "DELETE":
-                functionStore.remove(functionName);
+                functionStore.remove(identifier.getFullName());
                 break;
             case "GET":
-                GetFunctionResponse response =
-                        new GetFunctionResponse(
-                                UUID.randomUUID().toString(),
-                                function.name(),
-                                function.inputParams().orElse(null),
-                                function.returnParams().orElse(null),
-                                function.isDeterministic(),
-                                function.definitions(),
-                                function.comment(),
-                                function.options(),
-                                "owner",
-                                1L,
-                                "owner",
-                                1L,
-                                "owner");
+                GetFunctionResponse response = toGetFunctionResponse(function);
                 return mockResponse(response, 200);
             case "POST":
                 AlterFunctionRequest requestBody =
@@ -956,14 +974,14 @@ public class RESTCatalogServer {
                 }
                 function =
                         new FunctionImpl(
-                                Identifier.create(null, functionName),
+                                identifier,
                                 function.inputParams().orElse(null),
                                 function.returnParams().orElse(null),
                                 function.isDeterministic(),
                                 newDefinitions,
                                 newComment,
                                 newOptions);
-                functionStore.put(functionName, function);
+                functionStore.put(identifier.getFullName(), function);
                 break;
             default:
                 return new MockResponse().setResponseCode(404);
@@ -971,6 +989,74 @@ public class RESTCatalogServer {
         return new MockResponse().setResponseCode(200);
     }
 
+    private MockResponse functionDetailsHandle(
+            String method, String databaseName, Map<String, String> 
parameters) {
+        RESTResponse response;
+        if ("GET".equals(method)) {
+
+            List<GetFunctionResponse> functionsDetails =
+                    listFunctionDetails(databaseName, parameters);
+            if (!functionsDetails.isEmpty()) {
+
+                int maxResults;
+                try {
+                    maxResults = getMaxResults(parameters);
+                } catch (NumberFormatException e) {
+                    return handleInvalidMaxResults(parameters);
+                }
+                String pageToken = parameters.getOrDefault(PAGE_TOKEN, null);
+
+                PagedList<GetFunctionResponse> pagedFunctionDetails =
+                        buildPagedEntities(functionsDetails, maxResults, 
pageToken);
+                response =
+                        new ListFunctionDetailsResponse(
+                                pagedFunctionDetails.getElements(),
+                                pagedFunctionDetails.getNextPageToken());
+            } else {
+                response = new 
ListFunctionDetailsResponse(Collections.emptyList(), null);
+            }
+            return mockResponse(response, 200);
+        } else {
+            return new MockResponse().setResponseCode(404);
+        }
+    }
+
+    private List<GetFunctionResponse> listFunctionDetails(
+            String databaseName, Map<String, String> parameters) {
+        String namePattern = parameters.get(FUNCTION_NAME_PATTERN);
+        return functionStore.keySet().stream()
+                .map(Identifier::fromString)
+                .filter(identifier -> 
identifier.getDatabaseName().equals(databaseName))
+                .filter(
+                        identifier ->
+                                (Objects.isNull(namePattern)
+                                        || matchNamePattern(
+                                                identifier.getObjectName(), 
namePattern)))
+                .map(
+                        identifier -> {
+                            return toGetFunctionResponse(
+                                    
functionStore.get(identifier.getFullName()));
+                        })
+                .collect(Collectors.toList());
+    }
+
+    private GetFunctionResponse toGetFunctionResponse(Function function) {
+        return new GetFunctionResponse(
+                UUID.randomUUID().toString(),
+                function.name(),
+                function.inputParams().orElse(null),
+                function.returnParams().orElse(null),
+                function.isDeterministic(),
+                function.definitions(),
+                function.comment(),
+                function.options(),
+                "owner",
+                1L,
+                "owner",
+                1L,
+                "owner");
+    }
+
     private MockResponse databasesApiHandler(
             String method, String data, Map<String, String> parameters) throws 
Exception {
         switch (method) {
@@ -1675,6 +1761,44 @@ public class RESTCatalogServer {
                 .collect(Collectors.toList());
     }
 
+    private MockResponse functionsHandle(Map<String, String> parameters) {
+        RESTResponse response;
+        List<Identifier> functions = listFunctions(parameters);
+        if (!functions.isEmpty()) {
+            int maxResults;
+            try {
+                maxResults = getMaxResults(parameters);
+            } catch (NumberFormatException e) {
+                return handleInvalidMaxResults(parameters);
+            }
+            String pageToken = parameters.get(PAGE_TOKEN);
+            PagedList<Identifier> pagedFunctions =
+                    buildPagedEntities(functions, maxResults, pageToken);
+            response =
+                    new ListFunctionsGloballyResponse(
+                            pagedFunctions.getElements(), 
pagedFunctions.getNextPageToken());
+        } else {
+            response = new 
ListFunctionsGloballyResponse(Collections.emptyList(), null);
+        }
+        return mockResponse(response, 200);
+    }
+
+    private List<Identifier> listFunctions(Map<String, String> parameters) {
+        String namePattern = parameters.get(FUNCTION_NAME_PATTERN);
+        String databaseNamePattern = parameters.get(DATABASE_NAME_PATTERN);
+        List<Identifier> fullFunctions = new ArrayList<>();
+        for (Map.Entry<String, Function> entry : functionStore.entrySet()) {
+            Identifier identifier = Identifier.fromString(entry.getKey());
+            if ((Objects.isNull(databaseNamePattern))
+                    || matchNamePattern(identifier.getDatabaseName(), 
databaseNamePattern)
+                            && (Objects.isNull(namePattern)
+                                    || 
matchNamePattern(identifier.getObjectName(), namePattern))) {
+                fullFunctions.add(identifier);
+            }
+        }
+        return fullFunctions;
+    }
+
     private MockResponse viewsHandle(Map<String, String> parameters) {
         RESTResponse response;
         List<Identifier> views = listViews(parameters);
@@ -2106,6 +2230,12 @@ public class RESTCatalogServer {
             return ((GetViewResponse) entity).getName();
         } else if (entity instanceof Partition) {
             return PartitionUtils.buildPartitionName(((Partition) 
entity).spec());
+        } else if (entity instanceof GetFunctionResponse) {
+            GetFunctionResponse functionResponse = (GetFunctionResponse) 
entity;
+            return functionResponse.name();
+        } else if (entity instanceof Identifier) {
+            Identifier identifier = (Identifier) entity;
+            return identifier.getFullName();
         } else {
             return entity.toString();
         }
diff --git 
a/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogTest.java 
b/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogTest.java
index 6aabce23a4..c476cbc78b 100644
--- a/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogTest.java
+++ b/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogTest.java
@@ -82,6 +82,7 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
 
 import static java.util.Collections.emptyMap;
 import static java.util.Collections.singletonList;
@@ -1662,7 +1663,7 @@ public abstract class RESTCatalogTest extends 
CatalogTestBase {
                 IllegalArgumentException.class,
                 () -> catalog.dropFunction(identifierWithoutAlphabet, true));
 
-        Identifier identifier = new Identifier("rest_catalog_db", 
"function.na_me-01");
+        Identifier identifier = 
Identifier.fromString("rest_catalog_db.function.na_me-01");
         Function function = MockRESTMessage.function(identifier);
 
         catalog.createFunction(identifier, function, true);
@@ -1689,6 +1690,63 @@ public abstract class RESTCatalogTest extends 
CatalogTestBase {
                 Catalog.FunctionNotExistException.class, () -> 
catalog.getFunction(identifier));
     }
 
+    @Test
+    void testListFunctions() throws Exception {
+        String db1 = "db_rest_catalog_db";
+        String db2 = "db2_rest_catalog";
+        Identifier identifier = new Identifier(db1, "list_function");
+        Identifier identifier1 = new Identifier(db1, "function");
+        Identifier identifier2 = new Identifier(db2, "list_function");
+        Identifier identifier3 = new Identifier(db2, "function");
+        catalog.createDatabase(db1, false);
+        catalog.createDatabase(db2, false);
+        catalog.createFunction(identifier, 
MockRESTMessage.function(identifier), true);
+        catalog.createFunction(identifier1, 
MockRESTMessage.function(identifier1), true);
+        catalog.createFunction(identifier2, 
MockRESTMessage.function(identifier2), true);
+        catalog.createFunction(identifier3, 
MockRESTMessage.function(identifier3), true);
+        assertThat(catalog.listFunctionsPaged(db1, null, null, 
null).getElements())
+                .containsExactlyInAnyOrder(identifier.getObjectName(), 
identifier1.getObjectName());
+        assertThat(catalog.listFunctionsPaged(db1, 1, null, 
null).getElements())
+                .containsAnyOf(identifier.getObjectName(), 
identifier1.getObjectName());
+        assertThat(
+                        catalog.listFunctionsPaged(db1, 1, 
identifier1.getObjectName(), null)
+                                .getElements())
+                .containsExactlyInAnyOrder(identifier.getObjectName());
+        assertThat(catalog.listFunctionsPaged(db1, null, null, 
"func%").getElements())
+                .containsExactlyInAnyOrder(identifier1.getObjectName());
+        assertThat(
+                        catalog.listFunctionsPagedGlobally("db2_rest%", 
"func%", null, null)
+                                .getElements())
+                .containsExactlyInAnyOrder(identifier3);
+        assertThat(catalog.listFunctionsPagedGlobally("db2_rest%", null, 1, 
null).getElements())
+                .containsAnyOf(identifier2, identifier3);
+        assertThat(
+                        catalog.listFunctionsPagedGlobally(
+                                        "db2_rest%", null, 1, 
identifier3.getFullName())
+                                .getElements())
+                .containsExactlyInAnyOrder(identifier2);
+
+        assertThat(
+                        catalog.listFunctionDetailsPaged(db1, 1, null, 
null).getElements().stream()
+                                .map(f -> f.fullName())
+                                .collect(Collectors.toList()))
+                .containsAnyOf(identifier.getFullName(), 
identifier1.getFullName());
+
+        assertThat(
+                        catalog.listFunctionDetailsPaged(db2, 4, null, 
"func%").getElements()
+                                .stream()
+                                .map(f -> f.fullName())
+                                .collect(Collectors.toList()))
+                .containsExactly(identifier3.getFullName());
+
+        assertThat(
+                        catalog.listFunctionDetailsPaged(db2, 1, 
identifier3.getObjectName(), null)
+                                .getElements().stream()
+                                .map(f -> f.fullName())
+                                .collect(Collectors.toList()))
+                .contains(identifier2.getFullName());
+    }
+
     @Test
     void testAlterFunction() throws Exception {
         Identifier identifier = new Identifier("rest_catalog_db", 
"alter_function_name");
diff --git 
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/RESTCatalogITCase.java
 
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/RESTCatalogITCase.java
index 7742bbb3f3..d79aa713c9 100644
--- 
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/RESTCatalogITCase.java
+++ 
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/RESTCatalogITCase.java
@@ -136,7 +136,8 @@ class RESTCatalogITCase extends RESTCatalogITCaseBase {
                         jarResourcePath,
                         ResourceType.JAR,
                         jarResourcePath2));
-        assertThat(batchSql(String.format("SHOW 
FUNCTIONS"))).contains(Row.of(functionName));
+        assertThat(batchSql(String.format("SHOW FUNCTIONS in %s", 
DATABASE_NAME)))
+                .contains(Row.of(functionName));
         ObjectPath functionObjectPath = new ObjectPath(DATABASE_NAME, 
functionName);
         CatalogFunction getFunction = catalog.getFunction(functionObjectPath);
         assertThat(getFunction).isEqualTo(function);
diff --git 
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/procedure/FunctionProcedureITCase.java
 
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/procedure/FunctionProcedureITCase.java
index 33ba3e9a3f..ce784c8b88 100644
--- 
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/procedure/FunctionProcedureITCase.java
+++ 
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/procedure/FunctionProcedureITCase.java
@@ -45,7 +45,8 @@ public class FunctionProcedureITCase extends 
RESTCatalogITCaseBase {
                                         + "'[{\"id\": 0, \"name\":\"area\", 
\"type\":\"BIGINT\"}]', true, 'comment', 'k1=v1,k2=v2')",
                                 DATABASE_NAME, functionName));
         assertThat(result.toString()).contains("Success");
-        assertThat(batchSql(String.format("SHOW 
FUNCTIONS"))).contains(Row.of(functionName));
+        assertThat(batchSql(String.format("SHOW FUNCTIONS in %s", 
DATABASE_NAME)))
+                .contains(Row.of(functionName));
         result =
                 sql(
                         String.format(
@@ -54,11 +55,13 @@ public class FunctionProcedureITCase extends 
RESTCatalogITCaseBase {
         assertThat(result.toString()).contains("Success");
         Catalog catalog = tEnv.getCatalog("PAIMON").get();
         ObjectPath functionObjectPath = new ObjectPath(DATABASE_NAME, 
functionName);
-        assertThat(batchSql(String.format("SHOW 
FUNCTIONS"))).contains(Row.of(functionName));
+        assertThat(batchSql(String.format("SHOW FUNCTIONS in %s", 
DATABASE_NAME)))
+                .contains(Row.of(functionName));
         CatalogFunction getFunction = catalog.getFunction(functionObjectPath);
         assertThat(getFunction.getClassName()).isEqualTo("xxxx");
         result = sql(String.format("CALL sys.drop_function('%s.%s')", 
DATABASE_NAME, functionName));
         assertThat(result.toString()).contains("Success");
-        assertThat(batchSql(String.format("SHOW 
FUNCTIONS"))).doesNotContain(Row.of(functionName));
+        assertThat(batchSql(String.format("SHOW FUNCTIONS in %s", 
DATABASE_NAME)))
+                .doesNotContain(Row.of(functionName));
     }
 }

Reply via email to