You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flink.apache.org by dw...@apache.org on 2024/10/15 07:39:41 UTC
(flink) branch master updated: [FLINK-35822] Introduce DESCRIBE FUNCTION (#25115)
This is an automated email from the ASF dual-hosted git repository.
dwysakowicz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink.git
The following commit(s) were added to refs/heads/master by this push:
new 1e40fa5ccc0 [FLINK-35822] Introduce DESCRIBE FUNCTION (#25115)
1e40fa5ccc0 is described below
commit 1e40fa5ccc0ae814281a94098ef0a6e8d9403608
Author: nateab <nb...@confluent.io>
AuthorDate: Tue Oct 15 00:39:34 2024 -0700
[FLINK-35822] Introduce DESCRIBE FUNCTION (#25115)
---
docs/content.zh/docs/dev/table/sql/describe.md | 118 ++++++++++++++-
docs/content/docs/dev/table/sql/describe.md | 161 ++++++++++++++++++++-
.../src/test/resources/sql/function.q | 158 +++++++++++++++++++-
.../service/operation/OperationExecutor.java | 4 +-
.../src/main/codegen/data/Parser.tdd | 2 +
.../src/main/codegen/includes/parserImpls.ftl | 19 +++
...ribeModel.java => SqlRichDescribeFunction.java} | 32 ++--
.../flink/sql/parser/dql/SqlRichDescribeModel.java | 2 +-
.../flink/sql/parser/dql/SqlRichDescribeTable.java | 2 +-
.../flink/sql/parser/FlinkSqlParserImplTest.java | 11 ++
.../table/catalog/ContextResolvedFunction.java | 41 +++++-
.../flink/table/catalog/FunctionCatalog.java | 6 +-
.../operations/DescribeFunctionOperation.java | 132 +++++++++++++++++
.../converters/SqlDescribeFunctionConverter.java | 37 +++++
.../operations/converters/SqlNodeConverters.java | 1 +
.../table/planner/calcite/FlinkPlannerImpl.scala | 1 +
.../operations/SqlOtherOperationConverterTest.java | 27 ++++
17 files changed, 724 insertions(+), 30 deletions(-)
diff --git a/docs/content.zh/docs/dev/table/sql/describe.md b/docs/content.zh/docs/dev/table/sql/describe.md
index 5f7480da1b5..d4219d6eea9 100644
--- a/docs/content.zh/docs/dev/table/sql/describe.md
+++ b/docs/content.zh/docs/dev/table/sql/describe.md
@@ -90,6 +90,12 @@ tableEnv.executeSql("DESCRIBE CATALOG cat2").print();
// 打印完整的元数据
tableEnv.executeSql("DESC CATALOG EXTENDED cat2").print();
+
+tableEnv.executeSql("CREATE FUNCTION MySum as 'org.example.SumScalarFunction' USING JAR 'file://home/users/mysum-udf.jar';").print();
+
+tableEnv.executeSql("DESCRIBE FUNCTION MySum").print();
+
+tableEnv.executeSql("DESC FUNCTION EXTENDED MySum").print();
```
{{< /tab >}}
{{< tab "Scala" >}}
@@ -122,6 +128,14 @@ tableEnv.executeSql("DESCRIBE CATALOG cat2").print()
// 打印完整的元数据
tableEnv.executeSql("DESC CATALOG EXTENDED cat2").print()
+
+tableEnv.executeSql("CREATE FUNCTION MySum as 'org.example.SumScalarFunction' USING JAR 'file://home/users/mysum-udf.jar';").print()
+
+// print the metadata
+tableEnv.executeSql("DESCRIBE FUNCTION MySum").print()
+
+// print the complete metadata
+tableEnv.executeSql("DESC FUNCTION EXTENDED MySum").print()
```
{{< /tab >}}
{{< tab "Python" >}}
@@ -154,6 +168,12 @@ table_env.execute_sql("DESCRIBE CATALOG cat2").print()
# 打印完整的元数据
table_env.execute_sql("DESC CATALOG EXTENDED cat2").print()
+
+table_env.execute_sql("CREATE FUNCTION MySum as 'org.example.SumScalarFunction' USING JAR 'file://home/users/mysum-udf.jar';").print()
+
+table_env.execute_sql("DESCRIBE FUNCTION MySum").print()
+
+table_env.execute_sql("DESC FUNCTION EXTENDED MySum").print()
```
{{< /tab >}}
{{< tab "SQL CLI" >}}
@@ -181,6 +201,12 @@ Flink SQL> CREATE CATALOG cat2 WITH ('type'='generic_in_memory', 'default-databa
Flink SQL> DESCRIBE CATALOG cat2;
Flink SQL> DESC CATALOG EXTENDED cat2;
+
+Flink SQL> CREATE FUNCTION MySum as 'org.example.SumScalarFunction' USING JAR 'file://home/users/mysum-udf.jar';
+
+Flink SQL> DESCRIBE FUNCTION MySum;
+
+Flink SQL> DESC FUNCTION EXTENDED MySum;
Flink SQL> DESCRIBE JOB '228d70913eab60dda85c5e7f78b5782c';
@@ -261,6 +287,34 @@ Flink SQL> DESC JOB '228d70913eab60dda85c5e7f78b5782c';
| option:default-database | db |
+-------------------------+-------------------+
4 rows in set
+
+# DESCRIBE FUNCTION MySum
++-------------------+---------------------------------------------------------------------+
+| info name | info value |
++-------------------+---------------------------------------------------------------------+
+| system function | false |
+| temporary | false |
+| class name | org.example.SumScalarFunction |
+| function language | JAVA |
+| resource uris | ResourceUri{resourceType=JAR, uri='file:/home/users/mysum-udf.jar'} |
++-------------------+---------------------------------------------------------------------+
+5 rows in set
+# DESCRIBE FUNCTION EXTENDED MySum
++-------------------+---------------------------------------------------------------------+
+| info name | info value |
++-------------------+---------------------------------------------------------------------+
+| system function | false |
+| temporary | false |
+| class name | org.example.SumScalarFunction |
+| function language | JAVA |
+| resource uris | ResourceUri{resourceType=JAR, uri='file:/home/users/mysum-udf.jar'} |
+| kind | SCALAR |
+| requirements | [] |
+| deterministic | true |
+| constant folding | true |
+| signature | MySum(<INTEGER NOT NULL>, <INTEGER NOT NULL>) |
++-------------------+---------------------------------------------------------------------+
+10 rows in set
```
{{< /tab >}}
{{< tab "Python" >}}
@@ -297,6 +351,34 @@ Flink SQL> DESC JOB '228d70913eab60dda85c5e7f78b5782c';
| option:default-database | db |
+-------------------------+-------------------+
4 rows in set
+
+# DESCRIBE FUNCTION MySum
++-------------------+---------------------------------------------------------------------+
+| info name | info value |
++-------------------+---------------------------------------------------------------------+
+| system function | false |
+| temporary | false |
+| class name | org.example.SumScalarFunction |
+| function language | JAVA |
+| resource uris | ResourceUri{resourceType=JAR, uri='file:/home/users/mysum-udf.jar'} |
++-------------------+---------------------------------------------------------------------+
+5 rows in set
+# DESCRIBE FUNCTION EXTENDED MySum
++-------------------+---------------------------------------------------------------------+
+| info name | info value |
++-------------------+---------------------------------------------------------------------+
+| system function | false |
+| temporary | false |
+| class name | org.example.SumScalarFunction |
+| function language | JAVA |
+| resource uris | ResourceUri{resourceType=JAR, uri='file:/home/users/mysum-udf.jar'} |
+| kind | SCALAR |
+| requirements | [] |
+| deterministic | true |
+| constant folding | true |
+| signature | MySum(<INTEGER NOT NULL>, <INTEGER NOT NULL>) |
++-------------------+---------------------------------------------------------------------+
+10 rows in set
```
{{< /tab >}}
{{< tab "SQL CLI" >}}
@@ -334,6 +416,34 @@ Flink SQL> DESC JOB '228d70913eab60dda85c5e7f78b5782c';
+-------------------------+-------------------+
4 rows in set
+# DESCRIBE FUNCTION MySum
++-------------------+---------------------------------------------------------------------+
+| info name | info value |
++-------------------+---------------------------------------------------------------------+
+| system function | false |
+| temporary | false |
+| class name | org.example.SumScalarFunction |
+| function language | JAVA |
+| resource uris | ResourceUri{resourceType=JAR, uri='file:/home/users/mysum-udf.jar'} |
++-------------------+---------------------------------------------------------------------+
+5 rows in set
+# DESCRIBE FUNCTION EXTENDED MySum
++-------------------+---------------------------------------------------------------------+
+| info name | info value |
++-------------------+---------------------------------------------------------------------+
+| system function | false |
+| temporary | false |
+| class name | org.example.SumScalarFunction |
+| function language | JAVA |
+| resource uris | ResourceUri{resourceType=JAR, uri='file:/home/users/mysum-udf.jar'} |
+| kind | SCALAR |
+| requirements | [] |
+| deterministic | true |
+| constant folding | true |
+| signature | MySum(<INTEGER NOT NULL>, <INTEGER NOT NULL>) |
++-------------------+---------------------------------------------------------------------+
+10 rows in set
+
# DESCRIBE JOB '228d70913eab60dda85c5e7f78b5782c'
+----------------------------------+----------+---------+-------------------------+
| job id | job name | status | start time |
@@ -363,10 +473,16 @@ Flink SQL> DESC JOB '228d70913eab60dda85c5e7f78b5782c';
{ DESCRIBE | DESC } CATALOG [EXTENDED] catalog_name
```
+### DESCRIBE FUNCTION
+
+```sql
+{ DESCRIBE | DESC } FUNCTION [EXTENDED] [catalog_name.][db_name.]function_name
+```
+
### DESCRIBE JOB
```sql
{ DESCRIBE | DESC } JOB '<job_id>'
```
-<span class="label label-danger">Attention</span> DESCRIBE JOB 语句仅适用于 [SQL CLI]({{< ref "docs/dev/table/sqlClient" >}}) 或者 [SQL Gateway]({{< ref "docs/dev/table/sql-gateway/overview" >}}).
\ No newline at end of file
+<span class="label label-danger">Attention</span> DESCRIBE JOB 语句仅适用于 [SQL CLI]({{< ref "docs/dev/table/sqlClient" >}}) 或者 [SQL Gateway]({{< ref "docs/dev/table/sql-gateway/overview" >}}).
diff --git a/docs/content/docs/dev/table/sql/describe.md b/docs/content/docs/dev/table/sql/describe.md
index 4fdde4a29a8..185224bfeb5 100644
--- a/docs/content/docs/dev/table/sql/describe.md
+++ b/docs/content/docs/dev/table/sql/describe.md
@@ -26,7 +26,7 @@ under the License.
# DESCRIBE Statements
-DESCRIBE statements are used to describe the schema of a table or a view, or the metadata of a catalog, or the specified job in the Flink cluster.
+DESCRIBE statements are used to describe the schema of a table or a view, or the metadata of a catalog or a function, or the specified job in the Flink cluster.
## Run a DESCRIBE statement
@@ -89,6 +89,15 @@ tableEnv.executeSql("DESCRIBE CATALOG cat2").print();
// print the complete metadata
tableEnv.executeSql("DESC CATALOG EXTENDED cat2").print();
+
+// register a function named "MySum"
+tableEnv.executeSql("CREATE FUNCTION MySum as 'org.example.SumScalarFunction' USING JAR 'file://home/users/mysum-udf.jar';").print();
+
+// print the metadata
+tableEnv.executeSql("DESCRIBE FUNCTION MySum").print();
+
+// print the complete metadata
+tableEnv.executeSql("DESC FUNCTION EXTENDED MySum").print();
```
{{< /tab >}}
{{< tab "Scala" >}}
@@ -121,6 +130,16 @@ tableEnv.executeSql("DESCRIBE CATALOG cat2").print()
// print the complete metadata
tableEnv.executeSql("DESC CATALOG EXTENDED cat2").print()
+
+
+// register a function named "MySum"
+tableEnv.executeSql("CREATE FUNCTION MySum as 'org.example.SumScalarFunction' USING JAR 'file://home/users/mysum-udf.jar';").print()
+
+// print the metadata
+tableEnv.executeSql("DESCRIBE FUNCTION MySum").print()
+
+// print the complete metadata
+tableEnv.executeSql("DESC FUNCTION EXTENDED MySum").print()
```
{{< /tab >}}
{{< tab "Python" >}}
@@ -153,6 +172,16 @@ table_env.execute_sql("DESCRIBE CATALOG cat2").print()
# print the complete metadata
table_env.execute_sql("DESC CATALOG EXTENDED cat2").print()
+
+
+// register a function named "MySum"
+table_env.execute_sql("CREATE FUNCTION MySum as 'org.example.SumScalarFunction' USING JAR 'file://home/users/mysum-udf.jar';").print()
+
+// print the metadata
+table_env.execute_sql("DESCRIBE FUNCTION MySum").print()
+
+// print the complete metadata
+table_env.execute_sql("DESC FUNCTION EXTENDED MySum").print()
```
{{< /tab >}}
{{< tab "SQL CLI" >}}
@@ -180,6 +209,12 @@ Flink SQL> CREATE CATALOG cat2 WITH ('type'='generic_in_memory', 'default-databa
Flink SQL> DESCRIBE CATALOG cat2;
Flink SQL> DESC CATALOG EXTENDED cat2;
+
+Flink SQL> CREATE FUNCTION MySum as 'org.example.SumScalarFunction' USING JAR 'file://home/users/mysum-udf.jar';
+
+Flink SQL> DESCRIBE FUNCTION MySum;
+
+Flink SQL> DESC FUNCTION EXTENDED MySum;
Flink SQL> DESCRIBE JOB '228d70913eab60dda85c5e7f78b5782c';
@@ -224,6 +259,35 @@ The result of the above example is:
| option:default-database | db |
+-------------------------+-------------------+
4 rows in set
+
+# DESCRIBE FUNCTION MySum
++-------------------+---------------------------------------------------------------------+
+| info name | info value |
++-------------------+---------------------------------------------------------------------+
+| system function | false |
+| temporary | false |
+| class name | org.example.SumScalarFunction |
+| function language | JAVA |
+| resource uris | ResourceUri{resourceType=JAR, uri='file:/home/users/mysum-udf.jar'} |
++-------------------+---------------------------------------------------------------------+
+5 rows in set
+
+# DESCRIBE FUNCTION EXTENDED MySum
++-------------------+---------------------------------------------------------------------+
+| info name | info value |
++-------------------+---------------------------------------------------------------------+
+| system function | false |
+| temporary | false |
+| class name | org.example.SumScalarFunction |
+| function language | JAVA |
+| resource uris | ResourceUri{resourceType=JAR, uri='file:/home/users/mysum-udf.jar'} |
+| kind | SCALAR |
+| requirements | [] |
+| deterministic | true |
+| constant folding | true |
+| signature | MySum(<INTEGER NOT NULL>, <INTEGER NOT NULL>) |
++-------------------+---------------------------------------------------------------------+
+10 rows in set
```
{{< /tab >}}
{{< tab "Scala" >}}
@@ -260,6 +324,35 @@ The result of the above example is:
| option:default-database | db |
+-------------------------+-------------------+
4 rows in set
+
+# DESCRIBE FUNCTION MySum
++-------------------+---------------------------------------------------------------------+
+| info name | info value |
++-------------------+---------------------------------------------------------------------+
+| system function | false |
+| temporary | false |
+| class name | org.example.SumScalarFunction |
+| function language | JAVA |
+| resource uris | ResourceUri{resourceType=JAR, uri='file:/home/users/mysum-udf.jar'} |
++-------------------+---------------------------------------------------------------------+
+5 rows in set
+
+# DESCRIBE FUNCTION EXTENDED MySum
++-------------------+---------------------------------------------------------------------+
+| info name | info value |
++-------------------+---------------------------------------------------------------------+
+| system function | false |
+| temporary | false |
+| class name | org.example.SumScalarFunction |
+| function language | JAVA |
+| resource uris | ResourceUri{resourceType=JAR, uri='file:/home/users/mysum-udf.jar'} |
+| kind | SCALAR |
+| requirements | [] |
+| deterministic | true |
+| constant folding | true |
+| signature | MySum(<INTEGER NOT NULL>, <INTEGER NOT NULL>) |
++-------------------+---------------------------------------------------------------------+
+10 rows in set
```
{{< /tab >}}
{{< tab "Python" >}}
@@ -296,6 +389,35 @@ The result of the above example is:
| option:default-database | db |
+-------------------------+-------------------+
4 rows in set
+
+# DESCRIBE FUNCTION MySum
++-------------------+---------------------------------------------------------------------+
+| info name | info value |
++-------------------+---------------------------------------------------------------------+
+| system function | false |
+| temporary | false |
+| class name | org.example.SumScalarFunction |
+| function language | JAVA |
+| resource uris | ResourceUri{resourceType=JAR, uri='file:/home/users/mysum-udf.jar'} |
++-------------------+---------------------------------------------------------------------+
+5 rows in set
+
+# DESCRIBE FUNCTION EXTENDED MySum
++-------------------+---------------------------------------------------------------------+
+| info name | info value |
++-------------------+---------------------------------------------------------------------+
+| system function | false |
+| temporary | false |
+| class name | org.example.SumScalarFunction |
+| function language | JAVA |
+| resource uris | ResourceUri{resourceType=JAR, uri='file:/home/users/mysum-udf.jar'} |
+| kind | SCALAR |
+| requirements | [] |
+| deterministic | true |
+| constant folding | true |
+| signature | MySum(<INTEGER NOT NULL>, <INTEGER NOT NULL>) |
++-------------------+---------------------------------------------------------------------+
+10 rows in set
```
{{< /tab >}}
{{< tab "SQL CLI" >}}
@@ -333,6 +455,35 @@ The result of the above example is:
+-------------------------+-------------------+
4 rows in set
+# DESCRIBE FUNCTION MySum
++-------------------+---------------------------------------------------------------------+
+| info name | info value |
++-------------------+---------------------------------------------------------------------+
+| system function | false |
+| temporary | false |
+| class name | org.example.SumScalarFunction |
+| function language | JAVA |
+| resource uris | ResourceUri{resourceType=JAR, uri='file:/home/users/mysum-udf.jar'} |
++-------------------+---------------------------------------------------------------------+
+5 rows in set
+
+# DESCRIBE FUNCTION EXTENDED MySum
++-------------------+---------------------------------------------------------------------+
+| info name | info value |
++-------------------+---------------------------------------------------------------------+
+| system function | false |
+| temporary | false |
+| class name | org.example.SumScalarFunction |
+| function language | JAVA |
+| resource uris | ResourceUri{resourceType=JAR, uri='file:/home/users/mysum-udf.jar'} |
+| kind | SCALAR |
+| requirements | [] |
+| deterministic | true |
+| constant folding | true |
+| signature | MySum(<INTEGER NOT NULL>, <INTEGER NOT NULL>) |
++-------------------+---------------------------------------------------------------------+
+10 rows in set
+
# DESCRIBE JOB '228d70913eab60dda85c5e7f78b5782c'
+----------------------------------+----------+---------+-------------------------+
| job id | job name | status | start time |
@@ -362,9 +513,15 @@ The result of the above example is:
{ DESCRIBE | DESC } CATALOG [EXTENDED] catalog_name
```
+### DESCRIBE FUNCTION
+
+```sql
+{ DESCRIBE | DESC } FUNCTION [EXTENDED] [catalog_name.][db_name.]function_name
+```
+
### DESCRIBE JOB
```sql
{ DESCRIBE | DESC } JOB '<job_id>'
```
-<span class="label label-danger">Attention</span> DESCRIBE JOB statements only work in [SQL CLI]({{< ref "docs/dev/table/sqlClient" >}}) or [SQL Gateway]({{< ref "docs/dev/table/sql-gateway/overview" >}}).
\ No newline at end of file
+<span class="label label-danger">Attention</span> DESCRIBE JOB statements only work in [SQL CLI]({{< ref "docs/dev/table/sqlClient" >}}) or [SQL Gateway]({{< ref "docs/dev/table/sql-gateway/overview" >}}).
diff --git a/flink-table/flink-sql-client/src/test/resources/sql/function.q b/flink-table/flink-sql-client/src/test/resources/sql/function.q
index 0bca632de4f..270ad9ff1f1 100644
--- a/flink-table/flink-sql-client/src/test/resources/sql/function.q
+++ b/flink-table/flink-sql-client/src/test/resources/sql/function.q
@@ -1,4 +1,4 @@
-# function.q - CREATE/DROP/ALTER FUNCTION
+# function.q - CREATE/DROP/ALTER/SHOW/DESCRIBE FUNCTION
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
@@ -346,3 +346,159 @@ show user functions;
SHOW JARS;
Empty set
!ok
+
+# ==========================================================================
+# test describe function
+# ==========================================================================
+
+ADD JAR '$VAR_UDF_JAR_PATH';
+[INFO] Execute statement succeeded.
+!info
+
+describe function `SUM`;
++--------------------+------------+
+| info name | info value |
++--------------------+------------+
+| is system function | true |
+| is temporary | false |
++--------------------+------------+
+2 rows in set
+!ok
+
+describe function extended `SUM`;
++---------------------------+----------------+
+| info name | info value |
++---------------------------+----------------+
+| is system function | true |
+| is temporary | false |
+| kind | AGGREGATE |
+| requirements | [] |
+| is deterministic | true |
+| supports constant folding | true |
+| signature | SUM(<NUMERIC>) |
++---------------------------+----------------+
+7 rows in set
+!ok
+
+describe function temp_upperudf;
++--------------------+---------------------------------------------$VAR_UDF_JAR_PATH_DASH+
+| info name | $VAR_UDF_JAR_PATH_SPACE info value |
++--------------------+---------------------------------------------$VAR_UDF_JAR_PATH_DASH+
+| is system function | $VAR_UDF_JAR_PATH_SPACE false |
+| is temporary | $VAR_UDF_JAR_PATH_SPACE true |
+| class name | $VAR_UDF_JAR_PATH_SPACE UpperUDF |
+| function language | $VAR_UDF_JAR_PATH_SPACE JAVA |
+| resource uris | [ResourceUri{resourceType=JAR, uri='$VAR_UDF_JAR_PATH'}] |
++--------------------+---------------------------------------------$VAR_UDF_JAR_PATH_DASH+
+5 rows in set
+!ok
+
+describe function extended temp_upperudf;
++---------------------------+---------------------------------------------$VAR_UDF_JAR_PATH_DASH+
+| info name | $VAR_UDF_JAR_PATH_SPACE info value |
++---------------------------+---------------------------------------------$VAR_UDF_JAR_PATH_DASH+
+| is system function | $VAR_UDF_JAR_PATH_SPACE false |
+| is temporary | $VAR_UDF_JAR_PATH_SPACE true |
+| class name | $VAR_UDF_JAR_PATH_SPACE UpperUDF |
+| function language | $VAR_UDF_JAR_PATH_SPACE JAVA |
+| resource uris | [ResourceUri{resourceType=JAR, uri='$VAR_UDF_JAR_PATH'}] |
+| kind | $VAR_UDF_JAR_PATH_SPACE SCALAR |
+| requirements | $VAR_UDF_JAR_PATH_SPACE [] |
+| is deterministic | $VAR_UDF_JAR_PATH_SPACE true |
+| supports constant folding | $VAR_UDF_JAR_PATH_SPACE true |
+| signature | $VAR_UDF_JAR_PATH_SPACE c1.db.temp_upperudf(STRING) |
++---------------------------+---------------------------------------------$VAR_UDF_JAR_PATH_DASH+
+10 rows in set
+!ok
+
+desc function temp_upperudf;
++--------------------+---------------------------------------------$VAR_UDF_JAR_PATH_DASH+
+| info name | $VAR_UDF_JAR_PATH_SPACE info value |
++--------------------+---------------------------------------------$VAR_UDF_JAR_PATH_DASH+
+| is system function | $VAR_UDF_JAR_PATH_SPACE false |
+| is temporary | $VAR_UDF_JAR_PATH_SPACE true |
+| class name | $VAR_UDF_JAR_PATH_SPACE UpperUDF |
+| function language | $VAR_UDF_JAR_PATH_SPACE JAVA |
+| resource uris | [ResourceUri{resourceType=JAR, uri='$VAR_UDF_JAR_PATH'}] |
++--------------------+---------------------------------------------$VAR_UDF_JAR_PATH_DASH+
+5 rows in set
+!ok
+
+desc function extended temp_upperudf;
++---------------------------+---------------------------------------------$VAR_UDF_JAR_PATH_DASH+
+| info name | $VAR_UDF_JAR_PATH_SPACE info value |
++---------------------------+---------------------------------------------$VAR_UDF_JAR_PATH_DASH+
+| is system function | $VAR_UDF_JAR_PATH_SPACE false |
+| is temporary | $VAR_UDF_JAR_PATH_SPACE true |
+| class name | $VAR_UDF_JAR_PATH_SPACE UpperUDF |
+| function language | $VAR_UDF_JAR_PATH_SPACE JAVA |
+| resource uris | [ResourceUri{resourceType=JAR, uri='$VAR_UDF_JAR_PATH'}] |
+| kind | $VAR_UDF_JAR_PATH_SPACE SCALAR |
+| requirements | $VAR_UDF_JAR_PATH_SPACE [] |
+| is deterministic | $VAR_UDF_JAR_PATH_SPACE true |
+| supports constant folding | $VAR_UDF_JAR_PATH_SPACE true |
+| signature | $VAR_UDF_JAR_PATH_SPACE c1.db.temp_upperudf(STRING) |
++---------------------------+---------------------------------------------$VAR_UDF_JAR_PATH_DASH+
+10 rows in set
+!ok
+
+# test that system functions get resolved before catalog functions
+create temporary system function temp_upperudf AS 'UpperUDF' using jar '$VAR_UDF_JAR_PATH';
+[INFO] Execute statement succeeded.
+!info
+
+# we see both the temp system function and the catalog function for temp_upperudf
+show user functions;
++---------------+
+| function name |
++---------------+
+| func11 |
+| func3 |
+| func4 |
+| temp_upperudf |
+| temp_upperudf |
+| tmp_func |
+| upperudf |
++---------------+
+7 rows in set
+!ok
+
+# but the system function gets resolved first
+describe function temp_upperudf;
++--------------------+------------+
+| info name | info value |
++--------------------+------------+
+| is system function | true |
+| is temporary | true |
++--------------------+------------+
+2 rows in set
+!ok
+
+# but the catalog function should get resolved when using the full name
+describe function `c1`.`db`.temp_upperudf;
++--------------------+---------------------------------------------$VAR_UDF_JAR_PATH_DASH+
+| info name | $VAR_UDF_JAR_PATH_SPACE info value |
++--------------------+---------------------------------------------$VAR_UDF_JAR_PATH_DASH+
+| is system function | $VAR_UDF_JAR_PATH_SPACE false |
+| is temporary | $VAR_UDF_JAR_PATH_SPACE true |
+| class name | $VAR_UDF_JAR_PATH_SPACE UpperUDF |
+| function language | $VAR_UDF_JAR_PATH_SPACE JAVA |
+| resource uris | [ResourceUri{resourceType=JAR, uri='$VAR_UDF_JAR_PATH'}] |
++--------------------+---------------------------------------------$VAR_UDF_JAR_PATH_DASH+
+5 rows in set
+!ok
+
+describe function extended temp_upperudf;
++---------------------------+-----------------------+
+| info name | info value |
++---------------------------+-----------------------+
+| is system function | true |
+| is temporary | true |
+| kind | SCALAR |
+| requirements | [] |
+| is deterministic | true |
+| supports constant folding | true |
+| signature | temp_upperudf(STRING) |
++---------------------------+-----------------------+
+7 rows in set
+!ok
diff --git a/flink-table/flink-sql-gateway/src/main/java/org/apache/flink/table/gateway/service/operation/OperationExecutor.java b/flink-table/flink-sql-gateway/src/main/java/org/apache/flink/table/gateway/service/operation/OperationExecutor.java
index c6683bd0b2b..4288668accc 100644
--- a/flink-table/flink-sql-gateway/src/main/java/org/apache/flink/table/gateway/service/operation/OperationExecutor.java
+++ b/flink-table/flink-sql-gateway/src/main/java/org/apache/flink/table/gateway/service/operation/OperationExecutor.java
@@ -72,6 +72,7 @@ import org.apache.flink.table.operations.BeginStatementSetOperation;
import org.apache.flink.table.operations.CallProcedureOperation;
import org.apache.flink.table.operations.CompileAndExecutePlanOperation;
import org.apache.flink.table.operations.DeleteFromFilterOperation;
+import org.apache.flink.table.operations.DescribeFunctionOperation;
import org.apache.flink.table.operations.EndStatementSetOperation;
import org.apache.flink.table.operations.ExecutableOperation;
import org.apache.flink.table.operations.LoadModuleOperation;
@@ -510,7 +511,8 @@ public class OperationExecutor {
|| op instanceof ShowJarsOperation
|| op instanceof CreateTempSystemFunctionOperation
|| op instanceof CreateCatalogFunctionOperation
- || op instanceof ShowFunctionsOperation) {
+ || op instanceof ShowFunctionsOperation
+ || op instanceof DescribeFunctionOperation) {
return callExecutableOperation(handle, (ExecutableOperation) op);
} else if (op instanceof MaterializedTableOperation) {
return sessionContext
diff --git a/flink-table/flink-sql-parser/src/main/codegen/data/Parser.tdd b/flink-table/flink-sql-parser/src/main/codegen/data/Parser.tdd
index 722d7fdf086..64c450d573e 100644
--- a/flink-table/flink-sql-parser/src/main/codegen/data/Parser.tdd
+++ b/flink-table/flink-sql-parser/src/main/codegen/data/Parser.tdd
@@ -135,6 +135,7 @@
"org.apache.flink.sql.parser.dql.SqlShowCreateView"
"org.apache.flink.sql.parser.dql.SqlShowCreateCatalog"
"org.apache.flink.sql.parser.dql.SqlShowViews"
+ "org.apache.flink.sql.parser.dql.SqlRichDescribeFunction"
"org.apache.flink.sql.parser.dql.SqlRichDescribeModel"
"org.apache.flink.sql.parser.dql.SqlRichDescribeTable"
"org.apache.flink.sql.parser.dql.SqlUnloadModule"
@@ -635,6 +636,7 @@
"SqlShowJobs()"
"SqlTruncateTable()"
"SqlDescribeJob()"
+ "SqlRichDescribeFunction()"
"SqlRichDescribeModel()"
"SqlRichDescribeTable()"
]
diff --git a/flink-table/flink-sql-parser/src/main/codegen/includes/parserImpls.ftl b/flink-table/flink-sql-parser/src/main/codegen/includes/parserImpls.ftl
index 38c4c85227d..b02be2ad72c 100644
--- a/flink-table/flink-sql-parser/src/main/codegen/includes/parserImpls.ftl
+++ b/flink-table/flink-sql-parser/src/main/codegen/includes/parserImpls.ftl
@@ -803,6 +803,25 @@ SqlShowCreate SqlShowCreate() :
)
}
+/**
+ * DESCRIBE | DESC FUNCTION [ EXTENDED] [[catalogName.] dataBasesName].functionName sql call.
+ * Here we add Rich in className to match the naming of SqlRichDescribeTable.
+ */
+SqlRichDescribeFunction SqlRichDescribeFunction() :
+{
+ SqlIdentifier functionName;
+ SqlParserPos pos;
+ boolean isExtended = false;
+}
+{
+ ( <DESCRIBE> | <DESC> ) <FUNCTION> { pos = getPos();}
+ [ <EXTENDED> { isExtended = true;} ]
+ functionName = CompoundIdentifier()
+ {
+ return new SqlRichDescribeFunction(pos, functionName, isExtended);
+ }
+}
+
/**
* DESCRIBE | DESC MODEL [ EXTENDED] [[catalogName.] dataBasesName].modelName sql call.
* Here we add Rich in className to match the naming of SqlRichDescribeTable.
diff --git a/flink-table/flink-sql-parser/src/main/java/org/apache/flink/sql/parser/dql/SqlRichDescribeModel.java b/flink-table/flink-sql-parser/src/main/java/org/apache/flink/sql/parser/dql/SqlRichDescribeFunction.java
similarity index 63%
copy from flink-table/flink-sql-parser/src/main/java/org/apache/flink/sql/parser/dql/SqlRichDescribeModel.java
copy to flink-table/flink-sql-parser/src/main/java/org/apache/flink/sql/parser/dql/SqlRichDescribeFunction.java
index b756122cd1b..57bce5fa7d7 100644
--- a/flink-table/flink-sql-parser/src/main/java/org/apache/flink/sql/parser/dql/SqlRichDescribeModel.java
+++ b/flink-table/flink-sql-parser/src/main/java/org/apache/flink/sql/parser/dql/SqlRichDescribeFunction.java
@@ -31,22 +31,22 @@ import java.util.Collections;
import java.util.List;
/**
- * DESCRIBE MODEL [EXTENDED] [[catalogName.] dataBasesName].sqlIdentifier sql call. Here we add Rich
- * in className to follow the convention of {@link org.apache.calcite.sql.SqlDescribeTable}, which
- * only had it to distinguish from calcite's original SqlDescribeTable, even though calcite does not
- * have SqlDescribeModel.
+ * DESCRIBE FUNCTION [EXTENDED] [[catalogName.] dataBasesName].sqlIdentifier sql call. Here we add
+ * Rich in className to follow the convention of {@link org.apache.calcite.sql.SqlDescribeTable},
+ * which only had it to distinguish from calcite's original SqlDescribeTable, even though calcite
+ * does not have SqlDescribeFunction.
*/
-public class SqlRichDescribeModel extends SqlCall {
+public class SqlRichDescribeFunction extends SqlCall {
public static final SqlSpecialOperator OPERATOR =
- new SqlSpecialOperator("DESCRIBE MODEL", SqlKind.OTHER);
- protected final SqlIdentifier modelNameIdentifier;
- private boolean isExtended;
+ new SqlSpecialOperator("DESCRIBE FUNCTION", SqlKind.OTHER);
+ protected final SqlIdentifier functionNameIdentifier;
+ private final boolean isExtended;
- public SqlRichDescribeModel(
- SqlParserPos pos, SqlIdentifier modelNameIdentifier, boolean isExtended) {
+ public SqlRichDescribeFunction(
+ SqlParserPos pos, SqlIdentifier functionNameIdentifier, boolean isExtended) {
super(pos);
- this.modelNameIdentifier = modelNameIdentifier;
+ this.functionNameIdentifier = functionNameIdentifier;
this.isExtended = isExtended;
}
@@ -57,23 +57,23 @@ public class SqlRichDescribeModel extends SqlCall {
@Override
public List<SqlNode> getOperandList() {
- return Collections.singletonList(modelNameIdentifier);
+ return Collections.singletonList(functionNameIdentifier);
}
public boolean isExtended() {
return isExtended;
}
- public String[] fullModelName() {
- return modelNameIdentifier.names.toArray(new String[0]);
+ public String[] fullFunctionName() {
+ return functionNameIdentifier.names.toArray(new String[0]);
}
@Override
public void unparse(SqlWriter writer, int leftPrec, int rightPrec) {
- writer.keyword("DESCRIBE MODEL");
+ writer.keyword("DESCRIBE FUNCTION");
if (isExtended) {
writer.keyword("EXTENDED");
}
- modelNameIdentifier.unparse(writer, leftPrec, rightPrec);
+ functionNameIdentifier.unparse(writer, leftPrec, rightPrec);
}
}
diff --git a/flink-table/flink-sql-parser/src/main/java/org/apache/flink/sql/parser/dql/SqlRichDescribeModel.java b/flink-table/flink-sql-parser/src/main/java/org/apache/flink/sql/parser/dql/SqlRichDescribeModel.java
index b756122cd1b..6a5f5acfc50 100644
--- a/flink-table/flink-sql-parser/src/main/java/org/apache/flink/sql/parser/dql/SqlRichDescribeModel.java
+++ b/flink-table/flink-sql-parser/src/main/java/org/apache/flink/sql/parser/dql/SqlRichDescribeModel.java
@@ -41,7 +41,7 @@ public class SqlRichDescribeModel extends SqlCall {
public static final SqlSpecialOperator OPERATOR =
new SqlSpecialOperator("DESCRIBE MODEL", SqlKind.OTHER);
protected final SqlIdentifier modelNameIdentifier;
- private boolean isExtended;
+ private final boolean isExtended;
public SqlRichDescribeModel(
SqlParserPos pos, SqlIdentifier modelNameIdentifier, boolean isExtended) {
diff --git a/flink-table/flink-sql-parser/src/main/java/org/apache/flink/sql/parser/dql/SqlRichDescribeTable.java b/flink-table/flink-sql-parser/src/main/java/org/apache/flink/sql/parser/dql/SqlRichDescribeTable.java
index 6a0174d4ed2..c6ce0117a13 100644
--- a/flink-table/flink-sql-parser/src/main/java/org/apache/flink/sql/parser/dql/SqlRichDescribeTable.java
+++ b/flink-table/flink-sql-parser/src/main/java/org/apache/flink/sql/parser/dql/SqlRichDescribeTable.java
@@ -39,7 +39,7 @@ public class SqlRichDescribeTable extends SqlCall {
public static final SqlSpecialOperator OPERATOR =
new SqlSpecialOperator("DESCRIBE TABLE", SqlKind.DESCRIBE_TABLE);
protected final SqlIdentifier tableNameIdentifier;
- private boolean isExtended = false;
+ private final boolean isExtended;
public SqlRichDescribeTable(
SqlParserPos pos, SqlIdentifier tableNameIdentifier, boolean isExtended) {
diff --git a/flink-table/flink-sql-parser/src/test/java/org/apache/flink/sql/parser/FlinkSqlParserImplTest.java b/flink-table/flink-sql-parser/src/test/java/org/apache/flink/sql/parser/FlinkSqlParserImplTest.java
index 39c9a41c18c..4245ff492cc 100644
--- a/flink-table/flink-sql-parser/src/test/java/org/apache/flink/sql/parser/FlinkSqlParserImplTest.java
+++ b/flink-table/flink-sql-parser/src/test/java/org/apache/flink/sql/parser/FlinkSqlParserImplTest.java
@@ -462,6 +462,17 @@ class FlinkSqlParserImplTest extends SqlParserTest {
sql("desc model catalog1.db1.mdl").ok("DESCRIBE MODEL `CATALOG1`.`DB1`.`MDL`");
}
+ @Test
+ void testDescribeFunction() {
+ sql("describe function fn").ok("DESCRIBE FUNCTION `FN`");
+ sql("describe function catalog1.db1.fn").ok("DESCRIBE FUNCTION `CATALOG1`.`DB1`.`FN`");
+ sql("describe function extended fn").ok("DESCRIBE FUNCTION EXTENDED `FN`");
+
+ sql("desc function fn").ok("DESCRIBE FUNCTION `FN`");
+ sql("desc function catalog1.db1.fn").ok("DESCRIBE FUNCTION `CATALOG1`.`DB1`.`FN`");
+ sql("desc function extended fn").ok("DESCRIBE FUNCTION EXTENDED `FN`");
+ }
+
@Test
void testShowColumns() {
sql("show columns from tbl").ok("SHOW COLUMNS FROM `TBL`");
diff --git a/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/catalog/ContextResolvedFunction.java b/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/catalog/ContextResolvedFunction.java
index 313a4cf94e0..ea7dca69b58 100644
--- a/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/catalog/ContextResolvedFunction.java
+++ b/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/catalog/ContextResolvedFunction.java
@@ -68,12 +68,25 @@ public final class ContextResolvedFunction {
private final FunctionDefinition functionDefinition;
+ private final @Nullable CatalogFunction catalogFunction;
+
public static ContextResolvedFunction permanent(
FunctionIdentifier functionIdentifier, FunctionDefinition functionDefinition) {
Preconditions.checkNotNull(
functionIdentifier,
"Function identifier should not be null for a permanent function.");
- return new ContextResolvedFunction(false, functionIdentifier, functionDefinition);
+ return new ContextResolvedFunction(false, functionIdentifier, functionDefinition, null);
+ }
+
+ public static ContextResolvedFunction permanent(
+ FunctionIdentifier functionIdentifier,
+ FunctionDefinition functionDefinition,
+ CatalogFunction catalogFunction) {
+ Preconditions.checkNotNull(
+ functionIdentifier,
+ "Function identifier should not be null for a permanent function.");
+ return new ContextResolvedFunction(
+ false, functionIdentifier, functionDefinition, catalogFunction);
}
public static ContextResolvedFunction temporary(
@@ -81,29 +94,43 @@ public final class ContextResolvedFunction {
Preconditions.checkNotNull(
functionIdentifier,
"Function identifier should not be null for a temporary function.");
- return new ContextResolvedFunction(true, functionIdentifier, functionDefinition);
+ return new ContextResolvedFunction(true, functionIdentifier, functionDefinition, null);
+ }
+
+ public static ContextResolvedFunction temporary(
+ FunctionIdentifier functionIdentifier,
+ FunctionDefinition functionDefinition,
+ CatalogFunction catalogFunction) {
+ Preconditions.checkNotNull(
+ functionIdentifier,
+ "Function identifier should not be null for a temporary function.");
+ return new ContextResolvedFunction(
+ true, functionIdentifier, functionDefinition, catalogFunction);
}
public static ContextResolvedFunction anonymous(FunctionDefinition functionDefinition) {
- return new ContextResolvedFunction(true, null, functionDefinition);
+ return new ContextResolvedFunction(true, null, functionDefinition, null);
}
public static ContextResolvedFunction fromCallExpression(CallExpression callExpression) {
return new ContextResolvedFunction(
callExpression.isTemporary(),
callExpression.getFunctionIdentifier().orElse(null),
- callExpression.getFunctionDefinition());
+ callExpression.getFunctionDefinition(),
+ null);
}
private ContextResolvedFunction(
boolean isTemporary,
@Nullable FunctionIdentifier functionIdentifier,
- FunctionDefinition functionDefinition) {
+ FunctionDefinition functionDefinition,
+ @Nullable CatalogFunction catalogFunction) {
this.isTemporary = isTemporary;
this.functionIdentifier = functionIdentifier;
this.functionDefinition =
Preconditions.checkNotNull(
functionDefinition, "Function definition must not be null.");
+ this.catalogFunction = catalogFunction;
}
public boolean isAnonymous() {
@@ -127,6 +154,10 @@ public final class ContextResolvedFunction {
return functionDefinition;
}
+ public CatalogFunction getCatalogFunction() {
+ return catalogFunction;
+ }
+
public String asSummaryString() {
if (functionIdentifier == null) {
return functionDefinition.toString();
diff --git a/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/catalog/FunctionCatalog.java b/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/catalog/FunctionCatalog.java
index 83074cd020b..de4b24114dc 100644
--- a/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/catalog/FunctionCatalog.java
+++ b/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/catalog/FunctionCatalog.java
@@ -629,7 +629,8 @@ public final class FunctionCatalog {
return Optional.of(
ContextResolvedFunction.temporary(
FunctionIdentifier.of(oi),
- getFunctionDefinition(oi.getObjectName(), potentialResult)));
+ getFunctionDefinition(oi.getObjectName(), potentialResult),
+ potentialResult));
}
Optional<Catalog> catalogOptional = catalogManager.getCatalog(oi.getCatalogName());
@@ -658,7 +659,8 @@ public final class FunctionCatalog {
}
return Optional.of(
- ContextResolvedFunction.permanent(FunctionIdentifier.of(oi), fd));
+ ContextResolvedFunction.permanent(
+ FunctionIdentifier.of(oi), fd, catalogFunction));
} catch (FunctionNotExistException e) {
// Ignore
}
diff --git a/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/operations/DescribeFunctionOperation.java b/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/operations/DescribeFunctionOperation.java
new file mode 100644
index 00000000000..7fa63bdb9c7
--- /dev/null
+++ b/flink-table/flink-table-api-java/src/main/java/org/apache/flink/table/operations/DescribeFunctionOperation.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.flink.table.operations;
+
+import org.apache.flink.annotation.Internal;
+import org.apache.flink.table.api.DataTypes;
+import org.apache.flink.table.api.ValidationException;
+import org.apache.flink.table.api.internal.TableResultInternal;
+import org.apache.flink.table.catalog.CatalogFunction;
+import org.apache.flink.table.catalog.ContextResolvedFunction;
+import org.apache.flink.table.catalog.UnresolvedIdentifier;
+import org.apache.flink.table.functions.FunctionDefinition;
+import org.apache.flink.table.types.DataType;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import static org.apache.flink.table.api.internal.TableResultUtils.buildTableResult;
+import static org.apache.flink.table.types.inference.TypeInferenceUtil.generateSignature;
+
+/**
+ * Operation to describe a FUNCTION.
+ *
+ * <p>Syntax:
+ *
+ * <pre>
+ * DESCRIBE FUNCTION [EXTENDED] [[catalogName.] dataBasesName].sqlIdentifier
+ * </pre>
+ */
+@Internal
+public class DescribeFunctionOperation implements Operation, ExecutableOperation {
+
+ private final UnresolvedIdentifier sqlIdentifier;
+ private final boolean isExtended;
+
+ public DescribeFunctionOperation(UnresolvedIdentifier sqlIdentifier, boolean isExtended) {
+ this.sqlIdentifier = sqlIdentifier;
+ this.isExtended = isExtended;
+ }
+
+ public UnresolvedIdentifier getSqlIdentifier() {
+ return sqlIdentifier;
+ }
+
+ public boolean isExtended() {
+ return isExtended;
+ }
+
+ @Override
+ public String asSummaryString() {
+ Map<String, Object> params = new LinkedHashMap<>();
+ params.put("identifier", sqlIdentifier);
+ params.put("isExtended", isExtended);
+ return OperationUtils.formatWithChildren(
+ "DESCRIBE FUNCTION", params, Collections.emptyList(), Operation::asSummaryString);
+ }
+
+ @Override
+ public TableResultInternal execute(Context ctx) {
+ // DESCRIBE FUNCTION <function> shows all the function properties.
+ Optional<ContextResolvedFunction> functionOpt =
+ ctx.getFunctionCatalog().lookupFunction(sqlIdentifier);
+ if (!functionOpt.isPresent()) {
+ throw new ValidationException(
+ String.format(
+ "Function with the identifier '%s' doesn't exist.",
+ sqlIdentifier.asSummaryString()));
+ }
+ final ContextResolvedFunction function = functionOpt.get();
+ final CatalogFunction catalogFunction = function.getCatalogFunction();
+
+ List<List<Object>> rows = new ArrayList<>();
+ rows.add(Arrays.asList("is system function", String.valueOf(catalogFunction == null)));
+ rows.add(Arrays.asList("is temporary", String.valueOf(function.isTemporary())));
+ if (catalogFunction != null) {
+ rows.add(Arrays.asList("class name", catalogFunction.getClassName()));
+ rows.add(
+ Arrays.asList(
+ "function language", catalogFunction.getFunctionLanguage().toString()));
+ rows.add(
+ Arrays.asList(
+ "resource uris", catalogFunction.getFunctionResources().toString()));
+ }
+
+ if (isExtended) {
+ final FunctionDefinition definition = function.getDefinition();
+ rows.add(Arrays.asList("kind", definition.getKind().toString()));
+ rows.add(Arrays.asList("requirements", definition.getRequirements().toString()));
+ rows.add(
+ Arrays.asList(
+ "is deterministic", String.valueOf(definition.isDeterministic())));
+ rows.add(
+ Arrays.asList(
+ "supports constant folding",
+ String.valueOf(definition.supportsConstantFolding())));
+ rows.add(
+ Arrays.asList(
+ "signature",
+ generateSignature(
+ definition.getTypeInference(
+ ctx.getCatalogManager().getDataTypeFactory()),
+ function.toString(),
+ definition)));
+ }
+
+ return buildTableResult(
+ new String[] {"info name", "info value"},
+ new DataType[] {DataTypes.STRING(), DataTypes.STRING()},
+ rows.stream().map(List::toArray).toArray(Object[][]::new));
+ }
+}
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/operations/converters/SqlDescribeFunctionConverter.java b/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/operations/converters/SqlDescribeFunctionConverter.java
new file mode 100644
index 00000000000..2da2e434091
--- /dev/null
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/operations/converters/SqlDescribeFunctionConverter.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.flink.table.planner.operations.converters;
+
+import org.apache.flink.sql.parser.dql.SqlRichDescribeFunction;
+import org.apache.flink.table.catalog.UnresolvedIdentifier;
+import org.apache.flink.table.operations.DescribeFunctionOperation;
+import org.apache.flink.table.operations.Operation;
+
+/** A converter for {@link org.apache.flink.sql.parser.dql.SqlRichDescribeFunction}. */
+public class SqlDescribeFunctionConverter implements SqlNodeConverter<SqlRichDescribeFunction> {
+
+ @Override
+ public Operation convertSqlNode(
+ SqlRichDescribeFunction sqlRichDescribeFunction, ConvertContext context) {
+ UnresolvedIdentifier unresolvedIdentifier =
+ UnresolvedIdentifier.of(sqlRichDescribeFunction.fullFunctionName());
+ return new DescribeFunctionOperation(
+ unresolvedIdentifier, sqlRichDescribeFunction.isExtended());
+ }
+}
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/operations/converters/SqlNodeConverters.java b/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/operations/converters/SqlNodeConverters.java
index a2126791e4b..25ab375469f 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/operations/converters/SqlNodeConverters.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/operations/converters/SqlNodeConverters.java
@@ -67,6 +67,7 @@ public class SqlNodeConverters {
register(new SqlShowTablesConverter());
register(new SqlShowViewsConverter());
register(new SqlShowCatalogsConverter());
+ register(new SqlDescribeFunctionConverter());
}
/**
diff --git a/flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/calcite/FlinkPlannerImpl.scala b/flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/calcite/FlinkPlannerImpl.scala
index 4420ec96372..649ba8d90a2 100644
--- a/flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/calcite/FlinkPlannerImpl.scala
+++ b/flink-table/flink-table-planner/src/main/scala/org/apache/flink/table/planner/calcite/FlinkPlannerImpl.scala
@@ -148,6 +148,7 @@ class FlinkPlannerImpl(
|| sqlNode.isInstanceOf[SqlShowProcedures]
|| sqlNode.isInstanceOf[SqlShowJobs]
|| sqlNode.isInstanceOf[SqlDescribeJob]
+ || sqlNode.isInstanceOf[SqlRichDescribeFunction]
|| sqlNode.isInstanceOf[SqlRichDescribeModel]
|| sqlNode.isInstanceOf[SqlRichDescribeTable]
|| sqlNode.isInstanceOf[SqlUnloadModule]
diff --git a/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/operations/SqlOtherOperationConverterTest.java b/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/operations/SqlOtherOperationConverterTest.java
index e4dabb3c4d2..07e62ca75eb 100644
--- a/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/operations/SqlOtherOperationConverterTest.java
+++ b/flink-table/flink-table-planner/src/test/java/org/apache/flink/table/planner/operations/SqlOtherOperationConverterTest.java
@@ -20,7 +20,9 @@ package org.apache.flink.table.planner.operations;
import org.apache.flink.table.api.SqlParserException;
import org.apache.flink.table.api.ValidationException;
+import org.apache.flink.table.catalog.UnresolvedIdentifier;
import org.apache.flink.table.operations.DescribeCatalogOperation;
+import org.apache.flink.table.operations.DescribeFunctionOperation;
import org.apache.flink.table.operations.LoadModuleOperation;
import org.apache.flink.table.operations.Operation;
import org.apache.flink.table.operations.ShowCatalogsOperation;
@@ -106,6 +108,31 @@ public class SqlOtherOperationConverterTest extends SqlNodeToOperationConversion
catalogName, extended));
}
+ @ParameterizedTest
+ @CsvSource({"true,true", "true,false", "false,true", "false,false"})
+ void testDescribeFunction(boolean abbr, boolean extended) {
+ final String functionName = "f1";
+ final UnresolvedIdentifier functionIdentifier = UnresolvedIdentifier.of(functionName);
+ final String sql =
+ String.format(
+ "%s FUNCTION %s %s",
+ abbr ? "DESC" : "DESCRIBE", extended ? "EXTENDED" : "", functionName);
+ Operation operation = parse(sql);
+ assertThat(operation)
+ .isInstanceOf(DescribeFunctionOperation.class)
+ .asInstanceOf(InstanceOfAssertFactories.type(DescribeFunctionOperation.class))
+ .extracting(
+ DescribeFunctionOperation::getSqlIdentifier,
+ DescribeFunctionOperation::isExtended,
+ DescribeFunctionOperation::asSummaryString)
+ .containsExactly(
+ functionIdentifier,
+ extended,
+ String.format(
+ "DESCRIBE FUNCTION: (identifier: [%s], isExtended: [%b])",
+ functionIdentifier, extended));
+ }
+
@Test
void testUseDatabase() {
final String sql1 = "USE db1";