This is an automated email from the ASF dual-hosted git repository.
morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 562f572311 [enhancement](UDF) The user defined functions support
global ('show functions'/'show create') operation (#16973) (#17964)
562f572311 is described below
commit 562f5723113c4f73a2c9e1df872efe16e76f58ba
Author: lexluo09 <[email protected]>
AuthorDate: Fri Mar 24 19:07:38 2023 +0800
[enhancement](UDF) The user defined functions support global ('show
functions'/'show create') operation (#16973) (#17964)
1. add the global keyword.
SHOW [GLOBAL] [FULL] [BUILTIN] FUNCTIONS [IN|FROM db] [LIKE
'function_pattern']
SHOW CREATE GLOBAL FUNCTION function_name(arg_type [, ...]);
2. show the details of the global udf.
---
.../Show-Statements/SHOW-CREATE-FUNCTION.md | 15 +-
.../Show-Statements/SHOW-FUNCTIONS.md | 41 ++++-
.../Show-Statements/SHOW-CREATE-FUNCTION.md | 17 ++-
.../Show-Statements/SHOW-FUNCTIONS.md | 41 ++++-
fe/fe-core/src/main/cup/sql_parser.cup | 8 +-
.../doris/analysis/ShowCreateFunctionStmt.java | 52 +++++--
.../apache/doris/analysis/ShowFunctionsStmt.java | 30 ++--
.../apache/doris/catalog/AggregateFunction.java | 50 ++++---
.../org/apache/doris/catalog/AliasFunction.java | 8 +-
.../java/org/apache/doris/catalog/Function.java | 15 +-
.../org/apache/doris/catalog/FunctionUtil.java | 39 ++++-
.../apache/doris/catalog/GlobalFunctionMgr.java | 2 +
.../org/apache/doris/catalog/ScalarFunction.java | 27 ++--
.../java/org/apache/doris/qe/ShowExecutor.java | 166 +++++++++++++++------
.../doris/analysis/ShowCreateFunctionTest.java | 61 ++++++++
.../apache/doris/analysis/ShowFunctionsTest.java | 62 ++++++++
.../apache/doris/utframe/TestWithFeService.java | 23 ++-
17 files changed, 537 insertions(+), 120 deletions(-)
diff --git
a/docs/en/docs/sql-manual/sql-reference/Show-Statements/SHOW-CREATE-FUNCTION.md
b/docs/en/docs/sql-manual/sql-reference/Show-Statements/SHOW-CREATE-FUNCTION.md
index cdfd25374a..32a665d02b 100644
---
a/docs/en/docs/sql-manual/sql-reference/Show-Statements/SHOW-CREATE-FUNCTION.md
+++
b/docs/en/docs/sql-manual/sql-reference/Show-Statements/SHOW-CREATE-FUNCTION.md
@@ -37,14 +37,16 @@ This statement is used to display the creation statement of
the user-defined fun
grammar:
```sql
-SHOW CREATE FUNCTION function_name(arg_type [, ...]) [FROM db_name]];
+SHOW CREATE [GLOBAL] FUNCTION function_name(arg_type [, ...]) [FROM db_name]];
````
illustrate:
+1. `global`: The show function is global
+2. `function_name`: The name of the function to display
+3. `arg_type`: The parameter list of the function to display
+4. If db_name is not specified, the current default db is used
-1. `function_name`: The name of the function to display
-2. `arg_type`: The parameter list of the function to display
-3. If db_name is not specified, the current default db is used
+**Note: the "global" keyword is only available after v2.0**
### Example
@@ -53,6 +55,11 @@ illustrate:
```sql
SHOW CREATE FUNCTION my_add(INT, INT)
````
+2. Show the creation statement of the specified global function
+
+ ```sql
+ SHOW CREATE GLOBAL FUNCTION my_add(INT, INT)
+ ````
### Keywords
diff --git
a/docs/en/docs/sql-manual/sql-reference/Show-Statements/SHOW-FUNCTIONS.md
b/docs/en/docs/sql-manual/sql-reference/Show-Statements/SHOW-FUNCTIONS.md
index 5602ec09ae..90318dd094 100644
--- a/docs/en/docs/sql-manual/sql-reference/Show-Statements/SHOW-FUNCTIONS.md
+++ b/docs/en/docs/sql-manual/sql-reference/Show-Statements/SHOW-FUNCTIONS.md
@@ -42,13 +42,27 @@ grammar
SHOW [FULL] [BUILTIN] FUNCTIONS [IN|FROM db] [LIKE 'function_pattern']
````
- Parameters
+Parameters
>`full`: Indicates the detailed information of the display function
>`builtin`: Indicates the functions provided by the display system
>`db`: database name to query
>`function_pattern`: parameter used to filter function names
+grammar
+
+```sql
+SHOW GLOBAL [FULL] FUNCTIONS [LIKE 'function_pattern']
+````
+
+Parameters
+
+>`global`: Indicates it means that the show function is a global function
+>`full`: Indicates the detailed information of the display function
+>`function_pattern`: parameter used to filter function names
+
+**Note: the "global" keyword is only available after v2.0**
+
### Example
````sql
@@ -83,6 +97,31 @@ mysql> show builtin functions in testDb like 'year%';
| years_sub |
+---------------+
2 rows in set (0.00 sec)
+
+mysql> show global full functions\G;
+*************************** 1. row ***************************
+ Signature: decimal(ALL, INT, INT)
+ Return Type: VARCHAR
+ Function Type: Alias
+Intermediate Type: NULL
+ Properties: {"parameter":"col, precision,
scale","origin_function":"CAST(`col` AS decimal(`precision`, `scale`))"}
+*************************** 2. row ***************************
+ Signature: id_masking(BIGINT)
+ Return Type: VARCHAR
+ Function Type: Alias
+Intermediate Type: NULL
+ Properties: {"parameter":"id","origin_function":"concat(left(`id`, 3),
`****`, right(`id`, 4))"}
+2 rows in set (0.00 sec)
+
+mysql> show global functions ;
++---------------+
+| Function Name |
++---------------+
+| decimal |
+| id_masking |
++---------------+
+2 rows in set (0.00 sec)
+
````
### Keywords
diff --git
a/docs/zh-CN/docs/sql-manual/sql-reference/Show-Statements/SHOW-CREATE-FUNCTION.md
b/docs/zh-CN/docs/sql-manual/sql-reference/Show-Statements/SHOW-CREATE-FUNCTION.md
index c081019218..f6272bbc7b 100644
---
a/docs/zh-CN/docs/sql-manual/sql-reference/Show-Statements/SHOW-CREATE-FUNCTION.md
+++
b/docs/zh-CN/docs/sql-manual/sql-reference/Show-Statements/SHOW-CREATE-FUNCTION.md
@@ -37,13 +37,16 @@ SHOW CREATE FUNCTION
语法:
```sql
-SHOW CREATE FUNCTION function_name(arg_type [, ...]) [FROM db_name]];
+SHOW CREATE [GLOBAL] FUNCTION function_name(arg_type [, ...]) [FROM db_name]];
```
说明:
- 1. `function_name`: 要展示的函数名称
- 2. `arg_type`: 要展示的函数的参数列表
- 3. 如果不指定 db_name,使用当前默认 db
+ 1. `global`: 要展示的是全局函数
+ 2. `function_name`: 要展示的函数名称
+ 3. `arg_type`: 要展示的函数的参数列表
+ 4. 如果不指定 db_name,使用当前默认 db
+
+**注意: "global"关键字在v2.0版本及以后才可用**
### Example
@@ -53,6 +56,12 @@ SHOW CREATE FUNCTION function_name(arg_type [, ...]) [FROM
db_name]];
SHOW CREATE FUNCTION my_add(INT, INT)
```
+2. 展示指定的全局函数的创建语句
+
+ ```sql
+ SHOW CREATE GLOBAL FUNCTION my_add(INT, INT)
+ ```
+
### Keywords
SHOW, CREATE, FUNCTION
diff --git
a/docs/zh-CN/docs/sql-manual/sql-reference/Show-Statements/SHOW-FUNCTIONS.md
b/docs/zh-CN/docs/sql-manual/sql-reference/Show-Statements/SHOW-FUNCTIONS.md
index 28c0525af5..50d226bc72 100644
--- a/docs/zh-CN/docs/sql-manual/sql-reference/Show-Statements/SHOW-FUNCTIONS.md
+++ b/docs/zh-CN/docs/sql-manual/sql-reference/Show-Statements/SHOW-FUNCTIONS.md
@@ -42,13 +42,27 @@ SHOW FUNCTIONS
SHOW [FULL] [BUILTIN] FUNCTIONS [IN|FROM db] [LIKE 'function_pattern']
```
- Parameters
+Parameters
>`full`:表示显示函数的详细信息
>`builtin`:表示显示系统提供的函数
>`db`: 要查询的数据库名字
>`function_pattern`: 用来过滤函数名称的参数
+语法
+
+```sql
+SHOW GLOBAL [FULL] FUNCTIONS [LIKE 'function_pattern']
+```
+
+Parameters
+
+>`global`:表示要展示的是全局函数
+>`full`:表示显示函数的详细信息
+>`function_pattern`: 用来过滤函数名称的参数
+
+**注意: "global"关键字在v2.0版本及以后才可用**
+
### Example
```sql
@@ -83,6 +97,31 @@ mysql> show builtin functions in testDb like 'year%';
| years_sub |
+---------------+
2 rows in set (0.00 sec)
+
+mysql> show global full functions\G;
+*************************** 1. row ***************************
+ Signature: decimal(ALL, INT, INT)
+ Return Type: VARCHAR
+ Function Type: Alias
+Intermediate Type: NULL
+ Properties: {"parameter":"col, precision,
scale","origin_function":"CAST(`col` AS decimal(`precision`, `scale`))"}
+*************************** 2. row ***************************
+ Signature: id_masking(BIGINT)
+ Return Type: VARCHAR
+ Function Type: Alias
+Intermediate Type: NULL
+ Properties: {"parameter":"id","origin_function":"concat(left(`id`, 3),
`****`, right(`id`, 4))"}
+2 rows in set (0.00 sec)
+
+mysql> show global functions ;
++---------------+
+| Function Name |
++---------------+
+| decimal |
+| id_masking |
++---------------+
+2 rows in set (0.00 sec)
+
```
### Keywords
diff --git a/fe/fe-core/src/main/cup/sql_parser.cup
b/fe/fe-core/src/main/cup/sql_parser.cup
index 3936c9c56a..3faf2ff64d 100644
--- a/fe/fe-core/src/main/cup/sql_parser.cup
+++ b/fe/fe-core/src/main/cup/sql_parser.cup
@@ -3641,9 +3641,9 @@ show_param ::=
RESULT = new ShowCreateCatalogStmt(catalogName);
:}
/* Create Function */
- | KW_CREATE KW_FUNCTION function_name:functionName LPAREN
func_args_def:args RPAREN opt_db:dbName
+ | KW_CREATE opt_var_type:type KW_FUNCTION function_name:functionName
LPAREN func_args_def:args RPAREN opt_db:dbName
{:
- RESULT = new ShowCreateFunctionStmt(dbName, functionName, args);
+ RESULT = new ShowCreateFunctionStmt(type, dbName, functionName, args);
:}
/* Cluster */
| KW_CLUSTERS
@@ -3860,6 +3860,10 @@ show_param ::=
{:
RESULT = new ShowFunctionsStmt(dbName, isBuiltin, parser.isVerbose,
parser.wild, parser.where);
:}
+ | KW_GLOBAL opt_full KW_FUNCTIONS opt_wild_where
+ {:
+ RESULT = new ShowFunctionsStmt(parser.isVerbose, parser.wild,
parser.where);
+ :}
| KW_TYPECAST opt_db:dbName
{:
RESULT = new ShowTypeCastStmt(dbName, parser.where);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowCreateFunctionStmt.java
b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowCreateFunctionStmt.java
index 9b78f44556..3e6a5b6888 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowCreateFunctionStmt.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowCreateFunctionStmt.java
@@ -20,8 +20,10 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.FunctionSearchDesc;
+import org.apache.doris.catalog.FunctionUtil;
import org.apache.doris.catalog.ScalarType;
import org.apache.doris.cluster.ClusterNamespace;
+import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.UserException;
@@ -40,11 +42,13 @@ public class ShowCreateFunctionStmt extends ShowStmt {
private String dbName;
private final FunctionName functionName;
private final FunctionArgsDef argsDef;
+ private SetType type = SetType.DEFAULT;
// set after analyzed
private FunctionSearchDesc function;
- public ShowCreateFunctionStmt(String dbName, FunctionName functionName,
FunctionArgsDef argsDef) {
+ public ShowCreateFunctionStmt(SetType type, String dbName, FunctionName
functionName, FunctionArgsDef argsDef) {
+ this.type = type;
this.dbName = dbName;
this.functionName = functionName;
this.argsDef = argsDef;
@@ -66,20 +70,17 @@ public class ShowCreateFunctionStmt extends ShowStmt {
public void analyze(Analyzer analyzer) throws UserException {
super.analyze(analyzer);
- if (Strings.isNullOrEmpty(dbName)) {
- dbName = analyzer.getDefaultDb();
- if (Strings.isNullOrEmpty(dbName)) {
- ErrorReport.reportAnalysisException(ErrorCode.ERR_NO_DB_ERROR);
- }
- } else {
- dbName = ClusterNamespace.getFullName(getClusterName(), dbName);
+ // the global function does not need to fetch/check the dbName
+ if (!FunctionUtil.isGlobalFunction(this.type)) {
+ dbName = FunctionUtil.reAcquireDbName(analyzer, dbName,
getClusterName());
}
// analyze function name
- functionName.analyze(analyzer, SetType.DEFAULT);
+ functionName.analyze(analyzer, this.type);
- // check operation privilege
- if
(!Env.getCurrentEnv().getAccessManager().checkDbPriv(ConnectContext.get(),
dbName, PrivPredicate.SHOW)) {
+ // check operation privilege , except global function
+ if (!FunctionUtil.isGlobalFunction(this.type) &&
!Env.getCurrentEnv().getAccessManager()
+ .checkDbPriv(ConnectContext.get(), dbName,
PrivPredicate.SHOW)) {
ErrorReport.reportAnalysisException(
ErrorCode.ERR_DBACCESS_DENIED_ERROR,
ConnectContext.get().getQualifiedUser(), dbName);
}
@@ -88,11 +89,32 @@ public class ShowCreateFunctionStmt extends ShowStmt {
function = new FunctionSearchDesc(functionName, argsDef.getArgTypes(),
argsDef.isVariadic());
}
+
+ /***
+ * reAcquire dbName and check "No database selected"
+ * @param analyzer
+ * @throws AnalysisException
+ */
+ private void reAcquireDbName(Analyzer analyzer) throws AnalysisException {
+ if (Strings.isNullOrEmpty(dbName)) {
+ dbName = analyzer.getDefaultDb();
+ if (Strings.isNullOrEmpty(dbName)) {
+ ErrorReport.reportAnalysisException(ErrorCode.ERR_NO_DB_ERROR);
+ }
+ } else {
+ dbName = ClusterNamespace.getFullName(getClusterName(), dbName);
+ }
+ }
+
@Override
public String toSql() {
StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.append("SHOW CREATE FUNCTION
").append(functionName).append(argsDef)
- .append(" IN ").append(dbName);
+ if (FunctionUtil.isGlobalFunction(this.type)) {
+ stringBuilder.append("SHOW CREATE GLOBAL FUNCTION
").append(functionName).append(argsDef);
+ } else {
+ stringBuilder.append("SHOW CREATE FUNCTION
").append(functionName).append(argsDef)
+ .append(" IN ").append(dbName);
+ }
return stringBuilder.toString();
}
@@ -105,4 +127,8 @@ public class ShowCreateFunctionStmt extends ShowStmt {
public ShowResultSetMetaData getMetaData() {
return META_DATA;
}
+
+ public SetType getType() {
+ return type;
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowFunctionsStmt.java
b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowFunctionsStmt.java
index dee678dd37..0c2416d2c0 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowFunctionsStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ShowFunctionsStmt.java
@@ -19,8 +19,8 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.Env;
+import org.apache.doris.catalog.FunctionUtil;
import org.apache.doris.catalog.ScalarType;
-import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
@@ -51,6 +51,8 @@ public class ShowFunctionsStmt extends ShowStmt {
private Expr expr;
+ private SetType type = SetType.DEFAULT;
+
public ShowFunctionsStmt(String dbName, boolean isBuiltin, boolean
isVerbose, String wild,
Expr expr) {
this.dbName = dbName;
@@ -60,6 +62,13 @@ public class ShowFunctionsStmt extends ShowStmt {
this.expr = expr;
}
+ public ShowFunctionsStmt(boolean isVerbose, String wild, Expr expr) {
+ this.type = SetType.GLOBAL;
+ this.isVerbose = isVerbose;
+ this.wild = wild;
+ this.expr = expr;
+ }
+
public String getDbName() {
return dbName;
}
@@ -80,6 +89,10 @@ public class ShowFunctionsStmt extends ShowStmt {
return expr;
}
+ public SetType getType() {
+ return type;
+ }
+
public boolean like(String str) {
str = str.toLowerCase();
return str.matches(wild.replace(".", "\\.").replace("?",
".").replace("%", ".*").toLowerCase());
@@ -89,16 +102,12 @@ public class ShowFunctionsStmt extends ShowStmt {
public void analyze(Analyzer analyzer) throws UserException {
super.analyze(analyzer);
- if (Strings.isNullOrEmpty(dbName)) {
- dbName = analyzer.getDefaultDb();
- if (Strings.isNullOrEmpty(dbName)) {
- ErrorReport.reportAnalysisException(ErrorCode.ERR_NO_DB_ERROR);
- }
- } else {
- dbName = ClusterNamespace.getFullName(getClusterName(), dbName);
+ if (!FunctionUtil.isGlobalFunction(this.type)) {
+ this.dbName = FunctionUtil.reAcquireDbName(analyzer, dbName,
getClusterName());
}
- if
(!Env.getCurrentEnv().getAccessManager().checkDbPriv(ConnectContext.get(),
dbName, PrivPredicate.SHOW)) {
+ if (!FunctionUtil.isGlobalFunction(this.type) &&
!Env.getCurrentEnv().getAccessManager()
+ .checkDbPriv(ConnectContext.get(), dbName,
PrivPredicate.SHOW)) {
ErrorReport.reportAnalysisException(
ErrorCode.ERR_DBACCESS_DENIED_ERROR,
ConnectContext.get().getQualifiedUser(), dbName);
}
@@ -118,6 +127,9 @@ public class ShowFunctionsStmt extends ShowStmt {
public String toSql() {
StringBuilder sb = new StringBuilder();
sb.append("SHOW ");
+ if (FunctionUtil.isGlobalFunction(this.type)) {
+ sb.append("GLOBAL ");
+ }
if (isVerbose) {
sb.append("FULL ");
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/catalog/AggregateFunction.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/AggregateFunction.java
index 885a85866a..324b043541 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/AggregateFunction.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/AggregateFunction.java
@@ -102,7 +102,7 @@ public class AggregateFunction extends Function {
// empty input in BE).
private boolean returnsNonNullOnEmpty;
- //use for java-udaf to point the class of user define
+ // use for java-udaf to point the class of user define
private String symbolName;
// only used for serialization
@@ -154,28 +154,28 @@ public class AggregateFunction extends Function {
}
public AggregateFunction(FunctionName fnName, List<Type> argTypes,
- Type retType, Type intermediateType,
- URI location, String updateFnSymbol, String
initFnSymbol,
- String serializeFnSymbol, String mergeFnSymbol,
String getValueFnSymbol,
- String removeFnSymbol, String finalizeFnSymbol,
boolean vectorized) {
+ Type retType, Type intermediateType,
+ URI location, String updateFnSymbol, String initFnSymbol,
+ String serializeFnSymbol, String mergeFnSymbol, String
getValueFnSymbol,
+ String removeFnSymbol, String finalizeFnSymbol, boolean
vectorized) {
this(fnName, argTypes, retType, intermediateType, false, location,
updateFnSymbol, initFnSymbol, serializeFnSymbol,
mergeFnSymbol, getValueFnSymbol, removeFnSymbol,
finalizeFnSymbol, vectorized);
}
public AggregateFunction(FunctionName fnName, List<Type> argTypes,
- Type retType, Type intermediateType, boolean
hasVarArgs,
- URI location, String updateFnSymbol, String
initFnSymbol,
- String serializeFnSymbol, String mergeFnSymbol,
String getValueFnSymbol,
- String removeFnSymbol, String finalizeFnSymbol,
boolean vectorized) {
+ Type retType, Type intermediateType, boolean hasVarArgs,
+ URI location, String updateFnSymbol, String initFnSymbol,
+ String serializeFnSymbol, String mergeFnSymbol, String
getValueFnSymbol,
+ String removeFnSymbol, String finalizeFnSymbol, boolean
vectorized) {
// only `count` is always not nullable, other aggregate function is
always nullable
super(fnName, argTypes, retType, hasVarArgs, vectorized,
AggregateFunction.NOT_NULLABLE_AGGREGATE_FUNCTION_NAME_SET.contains(fnName.getFunction())
? NullableMode.ALWAYS_NOT_NULLABLE :
-
AggregateFunction.ALWAYS_NULLABLE_AGGREGATE_FUNCTION_NAME_SET.contains(fnName.getFunction())
- ? NullableMode.ALWAYS_NULLABLE :
-
AggregateFunction.CUSTOM_AGGREGATE_FUNCTION_NAME_SET.contains(fnName.getFunction())
- ? NullableMode.CUSTOM :
NullableMode.DEPEND_ON_ARGUMENT);
+
AggregateFunction.ALWAYS_NULLABLE_AGGREGATE_FUNCTION_NAME_SET.contains(fnName.getFunction())
+ ? NullableMode.ALWAYS_NULLABLE :
+
AggregateFunction.CUSTOM_AGGREGATE_FUNCTION_NAME_SET.contains(fnName.getFunction())
+ ? NullableMode.CUSTOM :
NullableMode.DEPEND_ON_ARGUMENT);
setLocation(location);
this.intermediateType = (intermediateType.equals(retType)) ? null :
intermediateType;
this.updateFnSymbol = updateFnSymbol;
@@ -330,10 +330,10 @@ public class AggregateFunction extends Function {
// Used to create UDAF
public AggregateFunction(FunctionName fnName, Type[] argTypes,
- Type retType, boolean hasVarArgs, Type
intermediateType, URI location,
- String initFnSymbol, String updateFnSymbol,
String mergeFnSymbol,
- String serializeFnSymbol, String finalizeFnSymbol,
- String getValueFnSymbol, String removeFnSymbol) {
+ Type retType, boolean hasVarArgs, Type intermediateType, URI
location,
+ String initFnSymbol, String updateFnSymbol, String mergeFnSymbol,
+ String serializeFnSymbol, String finalizeFnSymbol,
+ String getValueFnSymbol, String removeFnSymbol) {
super(fnName, Arrays.asList(argTypes), retType, hasVarArgs);
this.setLocation(location);
this.intermediateType = (intermediateType.equals(retType)) ? null :
intermediateType;
@@ -559,7 +559,13 @@ public class AggregateFunction extends Function {
@Override
public String toSql(boolean ifNotExists) {
- StringBuilder sb = new StringBuilder("CREATE AGGREGATE FUNCTION ");
+ StringBuilder sb = new StringBuilder("CREATE ");
+
+ if (this.isGlobal) {
+ sb.append("GLOBAL ");
+ }
+ sb.append("AGGREGATE FUNCTION ");
+
if (ifNotExists) {
sb.append("IF NOT EXISTS ");
}
@@ -610,13 +616,13 @@ public class AggregateFunction extends Function {
aggFn.setSerializeFnSymbol(serializeFnSymbol);
}
aggFn.setMergeFnSymbol(mergeFnSymbol);
- if (getValueFnSymbol != null) {
+ if (getValueFnSymbol != null) {
aggFn.setGetValueFnSymbol(getValueFnSymbol);
}
- if (removeFnSymbol != null) {
+ if (removeFnSymbol != null) {
aggFn.setRemoveFnSymbol(removeFnSymbol);
}
- if (finalizeFnSymbol != null) {
+ if (finalizeFnSymbol != null) {
aggFn.setFinalizeFnSymbol(finalizeFnSymbol);
}
if (symbolName != null) {
@@ -691,7 +697,7 @@ public class AggregateFunction extends Function {
properties.put(CreateFunctionStmt.SERIALIZE_KEY, serializeFnSymbol);
properties.put(CreateFunctionStmt.FINALIZE_KEY, finalizeFnSymbol);
- //getValueFn and removeFn may be null if not analytic agg
+ // getValueFn and removeFn may be null if not analytic agg
if (getValueFnSymbol != null) {
properties.put(CreateFunctionStmt.GET_VALUE_KEY, getValueFnSymbol);
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/catalog/AliasFunction.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/AliasFunction.java
index ed70173e7a..76d84bc026 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/AliasFunction.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/AliasFunction.java
@@ -234,7 +234,13 @@ public class AliasFunction extends Function {
@Override
public String toSql(boolean ifNotExists) {
setSlotRefLabel(originFunction);
- StringBuilder sb = new StringBuilder("CREATE ALIAS FUNCTION ");
+ StringBuilder sb = new StringBuilder("CREATE ");
+
+ if (this.isGlobal) {
+ sb.append("GLOBAL ");
+ }
+ sb.append("ALIAS FUNCTION ");
+
if (ifNotExists) {
sb.append("IF NOT EXISTS ");
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Function.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/Function.java
index d28448730b..56fe4b4222 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Function.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Function.java
@@ -126,6 +126,9 @@ public class Function implements Writable {
// library's checksum to make sure all backends use one library to serve
user's request
protected String checksum = "";
+ // If true, this function is global function
+ protected boolean isGlobal = false;
+
// Only used for serialization
protected Function() {
}
@@ -144,7 +147,7 @@ public class Function implements Writable {
}
public Function(long id, FunctionName name, List<Type> argTypes, Type
retType, boolean hasVarArgs,
- TFunctionBinaryType binaryType, boolean userVisible,
boolean vectorized, NullableMode mode) {
+ TFunctionBinaryType binaryType, boolean userVisible, boolean
vectorized, NullableMode mode) {
this.id = id;
this.name = name;
this.hasVarArgs = hasVarArgs;
@@ -161,7 +164,7 @@ public class Function implements Writable {
}
public Function(long id, FunctionName name, List<Type> argTypes, Type
retType,
- boolean hasVarArgs, boolean vectorized, NullableMode mode)
{
+ boolean hasVarArgs, boolean vectorized, NullableMode mode) {
this(id, name, argTypes, retType, hasVarArgs,
TFunctionBinaryType.BUILTIN, true, vectorized, mode);
}
@@ -274,6 +277,14 @@ public class Function implements Writable {
return checksum;
}
+ public boolean isGlobal() {
+ return isGlobal;
+ }
+
+ public void setGlobal(boolean global) {
+ isGlobal = global;
+ }
+
// TODO(cmy): Currently we judge whether it is UDF by wheter the
'location' is set.
// Maybe we should use a separate variable to identify,
// but additional variables need to modify the persistence information.
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionUtil.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionUtil.java
index 25155a8599..641d30c1a5 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionUtil.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionUtil.java
@@ -17,10 +17,16 @@
package org.apache.doris.catalog;
+import org.apache.doris.analysis.Analyzer;
+import org.apache.doris.analysis.SetType;
+import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.AnalysisException;
+import org.apache.doris.common.ErrorCode;
+import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.UserException;
import org.apache.doris.common.io.Text;
+import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.apache.logging.log4j.LogManager;
@@ -128,7 +134,7 @@ public class FunctionUtil {
String functionName = function.getName().getFunction();
List<Function> existFuncs = name2Function.get(functionName);
if (existFuncs == null) {
- throw new AnalysisException("Unknown function, function=" +
function.toString());
+ throw new AnalysisException("Unknown function, function=" +
function);
}
for (Function existFunc : existFuncs) {
@@ -136,7 +142,7 @@ public class FunctionUtil {
return existFunc;
}
}
- throw new AnalysisException("Unknown function, function=" +
function.toString());
+ throw new AnalysisException("Unknown function, function=" + function);
}
public static List<Function> getFunctions(ConcurrentMap<String,
ImmutableList<Function>> name2Function) {
@@ -182,4 +188,33 @@ public class FunctionUtil {
name2Function.put(name, builder.build());
}
}
+
+ /***
+ * is global function
+ * @return
+ */
+ public static boolean isGlobalFunction(SetType type) {
+ return SetType.GLOBAL == type;
+ }
+
+ /***
+ * reAcquire dbName and check "No database selected"
+ * @param analyzer
+ * @param dbName
+ * @param clusterName
+ * @return
+ * @throws AnalysisException
+ */
+ public static String reAcquireDbName(Analyzer analyzer, String dbName,
String clusterName)
+ throws AnalysisException {
+ if (Strings.isNullOrEmpty(dbName)) {
+ dbName = analyzer.getDefaultDb();
+ if (Strings.isNullOrEmpty(dbName)) {
+ ErrorReport.reportAnalysisException(ErrorCode.ERR_NO_DB_ERROR);
+ }
+ } else {
+ dbName = ClusterNamespace.getFullName(clusterName, dbName);
+ }
+ return dbName;
+ }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/catalog/GlobalFunctionMgr.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/GlobalFunctionMgr.java
index 02560a26fc..a23306d93d 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/GlobalFunctionMgr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/GlobalFunctionMgr.java
@@ -58,6 +58,7 @@ public class GlobalFunctionMgr extends MetaObject {
}
public synchronized void addFunction(Function function, boolean
ifNotExists) throws UserException {
+ function.setGlobal(true);
function.checkWritable();
if (FunctionUtil.addFunctionImpl(function, ifNotExists, false,
name2Function)) {
Env.getCurrentEnv().getEditLog().logAddGlobalFunction(function);
@@ -67,6 +68,7 @@ public class GlobalFunctionMgr extends MetaObject {
public synchronized void replayAddFunction(Function function) {
try {
+ function.setGlobal(true);
FunctionUtil.addFunctionImpl(function, false, true, name2Function);
} catch (UserException e) {
throw new RuntimeException(e);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/catalog/ScalarFunction.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/ScalarFunction.java
index f5c11fd4c4..6495b8ae70 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/ScalarFunction.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/ScalarFunction.java
@@ -60,7 +60,7 @@ public class ScalarFunction extends Function {
}
public ScalarFunction(FunctionName fnName, List<Type> argTypes, Type
retType, boolean hasVarArgs,
- boolean userVisible) {
+ boolean userVisible) {
this(fnName, argTypes, retType, hasVarArgs,
TFunctionBinaryType.BUILTIN, userVisible, false);
}
@@ -70,12 +70,14 @@ public class ScalarFunction extends Function {
}
public ScalarFunction(FunctionName fnName, List<Type> argTypes, Type
retType, boolean hasVarArgs,
- TFunctionBinaryType binaryType, boolean userVisible,
boolean isVec) {
+ TFunctionBinaryType binaryType, boolean userVisible, boolean
isVec) {
super(0, fnName, argTypes, retType, hasVarArgs, binaryType,
userVisible, isVec,
NullableMode.DEPEND_ON_ARGUMENT);
}
- /** nerieds custom scalar function */
+ /**
+ * nerieds custom scalar function
+ */
public ScalarFunction(FunctionName fnName, List<Type> argTypes, Type
retType, boolean hasVarArgs, String symbolName,
TFunctionBinaryType binaryType, boolean userVisible, boolean
isVec, NullableMode nullableMode) {
super(0, fnName, argTypes, retType, hasVarArgs, binaryType,
userVisible, isVec, nullableMode);
@@ -83,8 +85,8 @@ public class ScalarFunction extends Function {
}
public ScalarFunction(FunctionName fnName, List<Type> argTypes,
- Type retType, URI location, String symbolName,
String initFnSymbol,
- String closeFnSymbol) {
+ Type retType, URI location, String symbolName, String initFnSymbol,
+ String closeFnSymbol) {
super(fnName, argTypes, retType, false);
setLocation(location);
setSymbolName(symbolName);
@@ -97,9 +99,9 @@ public class ScalarFunction extends Function {
* into one call.
*/
public static ScalarFunction createBuiltin(String name, Type retType,
- ArrayList<Type> argTypes,
boolean hasVarArgs,
- String symbol, String
prepareFnSymbol, String closeFnSymbol,
- boolean userVisible) {
+ ArrayList<Type> argTypes, boolean hasVarArgs,
+ String symbol, String prepareFnSymbol, String closeFnSymbol,
+ boolean userVisible) {
return createBuiltin(name, retType, NullableMode.DEPEND_ON_ARGUMENT,
argTypes, hasVarArgs,
symbol, prepareFnSymbol, closeFnSymbol, userVisible);
}
@@ -309,7 +311,7 @@ public class ScalarFunction extends Function {
return createVecBuiltin(name, null, symbol, null, argTypes, false,
retType, false, nullableMode);
}
- //TODO: This method should not be here, move to other place in the future
+ // TODO: This method should not be here, move to other place in the future
public static ScalarFunction createVecBuiltin(String name, String
prepareFnSymbolBName, String symbol,
String closeFnSymbolName, ArrayList<Type> argTypes, boolean
hasVarArgs, Type retType, boolean userVisible,
NullableMode nullableMode) {
@@ -379,7 +381,12 @@ public class ScalarFunction extends Function {
@Override
public String toSql(boolean ifNotExists) {
- StringBuilder sb = new StringBuilder("CREATE FUNCTION ");
+ StringBuilder sb = new StringBuilder("CREATE ");
+ if (this.isGlobal) {
+ sb.append("GLOBAL ");
+ }
+ sb.append("FUNCTION ");
+
if (ifNotExists) {
sb.append("IF NOT EXISTS ");
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/ShowExecutor.java
b/fe/fe-core/src/main/java/org/apache/doris/qe/ShowExecutor.java
index 9aa7a0de5b..7f61e04a16 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/ShowExecutor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/ShowExecutor.java
@@ -111,6 +111,7 @@ import org.apache.doris.catalog.DynamicPartitionProperty;
import org.apache.doris.catalog.EncryptKey;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.Function;
+import org.apache.doris.catalog.FunctionUtil;
import org.apache.doris.catalog.HiveMetaStoreClientHelper;
import org.apache.doris.catalog.Index;
import org.apache.doris.catalog.MaterializedIndex;
@@ -217,6 +218,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
@@ -290,7 +292,7 @@ public class ShowExecutor {
handleShowCreateRoutineLoad();
} else if (stmt instanceof ShowCreateLoadStmt) {
handleShowCreateLoad();
- } else if (stmt instanceof ShowDeleteStmt) {
+ } else if (stmt instanceof ShowDeleteStmt) {
handleShowDelete();
} else if (stmt instanceof ShowAlterStmt) {
handleShowAlter();
@@ -457,43 +459,8 @@ public class ShowExecutor {
// Handle show functions
private void handleShowFunctions() throws AnalysisException {
ShowFunctionsStmt showStmt = (ShowFunctionsStmt) stmt;
- Util.prohibitExternalCatalog(ctx.getDefaultCatalog(),
stmt.getClass().getSimpleName());
- DatabaseIf db =
ctx.getCurrentCatalog().getDbOrAnalysisException(showStmt.getDbName());
-
- List<List<String>> resultRowSet = Lists.newArrayList();
- if (db instanceof Database) {
- List<Function> functions = showStmt.getIsBuiltin() ?
ctx.getEnv().getBuiltinFunctions()
- : ((Database) db).getFunctions();
-
- List<List<Comparable>> rowSet = Lists.newArrayList();
- for (Function function : functions) {
- List<Comparable> row =
function.getInfo(showStmt.getIsVerbose());
- // like predicate
- if (showStmt.getWild() == null ||
showStmt.like(function.functionName())) {
- rowSet.add(row);
- }
- }
- // sort function rows by first column asc
- ListComparator<List<Comparable>> comparator = null;
- OrderByPair orderByPair = new OrderByPair(0, false);
- comparator = new ListComparator<>(orderByPair);
- Collections.sort(rowSet, comparator);
-
- Set<String> functionNameSet = new HashSet<>();
- for (List<Comparable> row : rowSet) {
- List<String> resultRow = Lists.newArrayList();
- // if not verbose, remove duplicate function name
- if (functionNameSet.contains(row.get(0).toString())) {
- continue;
- }
- for (Comparable column : row) {
- resultRow.add(column.toString());
- }
- resultRowSet.add(resultRow);
- functionNameSet.add(resultRow.get(0));
- }
- }
+ List<List<String>> resultRowSet = getResultRowSet(showStmt);
// Only success
ShowResultSetMetaData showMetaData = showStmt.getIsVerbose() ?
showStmt.getMetaData() :
@@ -502,22 +469,125 @@ public class ShowExecutor {
resultSet = new ShowResultSet(showMetaData, resultRowSet);
}
- // Handle show create function
- private void handleShowCreateFunction() throws AnalysisException {
- ShowCreateFunctionStmt showCreateFunctionStmt =
(ShowCreateFunctionStmt) stmt;
- Util.prohibitExternalCatalog(ctx.getDefaultCatalog(),
stmt.getClass().getSimpleName());
- DatabaseIf db =
ctx.getCurrentCatalog().getDbOrAnalysisException(showCreateFunctionStmt.getDbName());
+ /***
+ * get resultRowSet by showFunctionsStmt
+ * @param showStmt
+ * @return
+ * @throws AnalysisException
+ */
+ private List<List<String>> getResultRowSet(ShowFunctionsStmt showStmt)
throws AnalysisException {
+ List<Function> functions = getFunctions(showStmt);
+ return getResultRowSetByFunctions(showStmt, functions);
+ }
+
+ /***
+ * get functions by showFunctionsStmt
+ * @param showStmt
+ * @return
+ * @throws AnalysisException
+ */
+ private List<Function> getFunctions(ShowFunctionsStmt showStmt) throws
AnalysisException {
+ List<Function> functions = Lists.newArrayList();
+ if (!FunctionUtil.isGlobalFunction(showStmt.getType())) {
+ Util.prohibitExternalCatalog(ctx.getDefaultCatalog(),
stmt.getClass().getSimpleName());
+ DatabaseIf db =
ctx.getCurrentCatalog().getDbOrAnalysisException(showStmt.getDbName());
+ if (db instanceof Database) {
+ functions = showStmt.getIsBuiltin() ?
ctx.getEnv().getBuiltinFunctions()
+ : ((Database) db).getFunctions();
+ }
+ } else {
+ functions =
Env.getCurrentEnv().getGlobalFunctionMgr().getFunctions();
+ }
+ return functions;
+ }
+
+ /***
+ * get resultRowSet By showFunctionsStmt and functions
+ * @param showStmt
+ * @param functions
+ * @return
+ */
+ private List<List<String>> getResultRowSetByFunctions(ShowFunctionsStmt
showStmt, List<Function> functions) {
List<List<String>> resultRowSet = Lists.newArrayList();
- if (db instanceof Database) {
- Function function = ((Database)
db).getFunction(showCreateFunctionStmt.getFunction());
+ List<List<Comparable>> rowSet = Lists.newArrayList();
+ for (Function function : functions) {
+ List<Comparable> row = function.getInfo(showStmt.getIsVerbose());
+ // like predicate
+ if (showStmt.getWild() == null ||
showStmt.like(function.functionName())) {
+ rowSet.add(row);
+ }
+ }
+
+ // sort function rows by first column asc
+ ListComparator<List<Comparable>> comparator = null;
+ OrderByPair orderByPair = new OrderByPair(0, false);
+ comparator = new ListComparator<>(orderByPair);
+ Collections.sort(rowSet, comparator);
+
+ Set<String> functionNameSet = new HashSet<>();
+ for (List<Comparable> row : rowSet) {
List<String> resultRow = Lists.newArrayList();
- resultRow.add(function.signatureString());
- resultRow.add(function.toSql(false));
+ // if not verbose, remove duplicate function name
+ if (functionNameSet.contains(row.get(0).toString())) {
+ continue;
+ }
+ for (Comparable column : row) {
+ resultRow.add(column.toString());
+ }
resultRowSet.add(resultRow);
+ functionNameSet.add(resultRow.get(0));
}
+ return resultRowSet;
+ }
+
+ // Handle show create function
+ private void handleShowCreateFunction() throws AnalysisException {
+ ShowCreateFunctionStmt showCreateFunctionStmt =
(ShowCreateFunctionStmt) stmt;
+ List<List<String>> resultRowSet =
getResultRowSet(showCreateFunctionStmt);
resultSet = new ShowResultSet(showCreateFunctionStmt.getMetaData(),
resultRowSet);
}
+ /***
+ * get resultRowSet by showCreateFunctionStmt
+ * @param showCreateFunctionStmt
+ * @return
+ * @throws AnalysisException
+ */
+ private List<List<String>> getResultRowSet(ShowCreateFunctionStmt
showCreateFunctionStmt) throws AnalysisException {
+ Function function = getFunction(showCreateFunctionStmt);
+ return getResultRowSetByFunction(function);
+ }
+
+ private Function getFunction(ShowCreateFunctionStmt
showCreateFunctionStmt) throws AnalysisException {
+ if (!FunctionUtil.isGlobalFunction(showCreateFunctionStmt.getType())) {
+ Util.prohibitExternalCatalog(ctx.getDefaultCatalog(),
stmt.getClass().getSimpleName());
+ DatabaseIf db =
ctx.getCurrentCatalog().getDbOrAnalysisException(showCreateFunctionStmt.getDbName());
+ if (db instanceof Database) {
+ return ((Database)
db).getFunction(showCreateFunctionStmt.getFunction());
+ }
+ } else {
+ return
Env.getCurrentEnv().getGlobalFunctionMgr().getFunction(showCreateFunctionStmt.getFunction());
+ }
+ return null;
+ }
+
+ /***
+ * get resultRowSet by function
+ * @param function
+ * @return
+ */
+ private List<List<String>> getResultRowSetByFunction(Function function) {
+ if (Objects.isNull(function)) {
+ return Lists.newArrayList();
+ }
+ List<List<String>> resultRowSet = Lists.newArrayList();
+ List<String> resultRow = Lists.newArrayList();
+ resultRow.add(function.signatureString());
+ resultRow.add(function.toSql(false));
+ resultRowSet.add(resultRow);
+ return resultRowSet;
+ }
+
// Handle show encryptkeys
private void handleShowEncryptKeys() throws AnalysisException {
ShowEncryptKeysStmt showStmt = (ShowEncryptKeysStmt) stmt;
@@ -996,7 +1066,7 @@ public class ShowExecutor {
resultSet = new ShowResultSet(showStmt.getMetaData(), rows);
}
- //Show view statement.
+ // Show view statement.
private void handleShowView() {
ShowViewStmt showStmt = (ShowViewStmt) stmt;
List<List<String>> rows = Lists.newArrayList();
@@ -1419,7 +1489,7 @@ public class ShowExecutor {
ProcNodeInterface procNodeI = showStmt.getNode();
Preconditions.checkNotNull(procNodeI);
List<List<String>> rows;
- //Only SchemaChangeProc support where/order by/limit syntax
+ // Only SchemaChangeProc support where/order by/limit syntax
if (procNodeI instanceof SchemaChangeProcDir) {
rows = ((SchemaChangeProcDir)
procNodeI).fetchResultByFilter(showStmt.getFilterMap(),
showStmt.getOrderPairs(),
showStmt.getLimitElement()).getRows();
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowCreateFunctionTest.java
b/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowCreateFunctionTest.java
new file mode 100644
index 0000000000..f89f6fdbf3
--- /dev/null
+++
b/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowCreateFunctionTest.java
@@ -0,0 +1,61 @@
+// 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.doris.analysis;
+
+import org.apache.doris.common.FeConstants;
+import org.apache.doris.qe.ShowResultSet;
+import org.apache.doris.utframe.TestWithFeService;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class ShowCreateFunctionTest extends TestWithFeService {
+
+ private String dbName = "testDb";
+
+ @Override
+ protected void runBeforeAll() throws Exception {
+ FeConstants.runningUnitTest = true;
+ createDatabase(dbName);
+ useDatabase(dbName);
+ createFunction(
+ "CREATE ALIAS FUNCTION id_masking(bigint) WITH PARAMETER(id)
AS CONCAT(LEFT(id,3),'****',RIGHT(id,4));");
+
+ createFunction(
+ "CREATE GLOBAL ALIAS FUNCTION id_masking_global(bigint) WITH
PARAMETER(id) AS CONCAT(LEFT(id,3),'****',RIGHT(id,4));");
+ }
+
+
+ @Test
+ public void testNormal() throws Exception {
+ String sql = "SHOW CREATE FUNCTION id_masking(bigint)";
+ ShowResultSet showResultSet = showCreateFunction(sql);
+ String showSql = showResultSet.getResultRows().get(0).get(1);
+ Assertions.assertTrue(showSql.contains("CREATE ALIAS FUNCTION
id_masking(BIGINT) WITH PARAMETER(id)"));
+ }
+
+ @Test
+ public void testShowCreateGlobalFunction() throws Exception {
+ String sql = "SHOW CREATE GLOBAL FUNCTION id_masking_global(bigint)";
+ ShowResultSet showResultSet = showCreateFunction(sql);
+ String showSql = showResultSet.getResultRows().get(0).get(1);
+ Assertions.assertTrue(
+ showSql.contains("CREATE GLOBAL ALIAS FUNCTION
id_masking_global(BIGINT) WITH PARAMETER(id)"));
+ }
+
+}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowFunctionsTest.java
b/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowFunctionsTest.java
new file mode 100644
index 0000000000..381bbb0a74
--- /dev/null
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/ShowFunctionsTest.java
@@ -0,0 +1,62 @@
+// 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.doris.analysis;
+
+import org.apache.doris.common.FeConstants;
+import org.apache.doris.qe.ShowResultSet;
+import org.apache.doris.utframe.TestWithFeService;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class ShowFunctionsTest extends TestWithFeService {
+ private String dbName = "testDb";
+
+ @Override
+ protected void runBeforeAll() throws Exception {
+ FeConstants.runningUnitTest = true;
+ createDatabase(dbName);
+ useDatabase(dbName);
+ createFunction(
+ "CREATE ALIAS FUNCTION id_masking(bigint) WITH PARAMETER(id)
AS CONCAT(LEFT(id,3),'****',RIGHT(id,4));");
+
+ createFunction(
+ "CREATE GLOBAL ALIAS FUNCTION id_masking_global(bigint) WITH
PARAMETER(id) AS CONCAT(LEFT(id,3),'****',RIGHT(id,4));");
+ }
+
+ @Test
+ public void testShowFunctions() throws Exception {
+ String sql = "SHOW FUNCTIONS";
+ ShowResultSet showResultSet = showFunctions(sql);
+ String showSql = showResultSet.getResultRows().get(0).get(0);
+ Assertions.assertTrue("id_masking".equalsIgnoreCase(showSql));
+
+ sql = "SHOW FULL FUNCTIONS";
+ showResultSet = showFunctions(sql);
+ showSql = showResultSet.getResultRows().get(0).get(0);
+ Assertions.assertTrue(showSql.contains("id_masking"));
+ }
+
+ @Test
+ public void testShowGlobalFunctions() throws Exception {
+ String sql = "SHOW GLOBAL FUNCTIONS";
+ ShowResultSet showResultSet = showFunctions(sql);
+ String showSql = showResultSet.getResultRows().get(0).get(0);
+ Assertions.assertTrue("id_masking_global".equalsIgnoreCase(showSql));
+ }
+}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java
b/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java
index 0507e035a3..cf99d6f7f1 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java
@@ -22,6 +22,7 @@ import org.apache.doris.analysis.AlterSqlBlockRuleStmt;
import org.apache.doris.analysis.AlterTableStmt;
import org.apache.doris.analysis.Analyzer;
import org.apache.doris.analysis.CreateDbStmt;
+import org.apache.doris.analysis.CreateFunctionStmt;
import org.apache.doris.analysis.CreateMaterializedViewStmt;
import org.apache.doris.analysis.CreatePolicyStmt;
import org.apache.doris.analysis.CreateSqlBlockRuleStmt;
@@ -33,7 +34,9 @@ import org.apache.doris.analysis.DropSqlBlockRuleStmt;
import org.apache.doris.analysis.DropTableStmt;
import org.apache.doris.analysis.ExplainOptions;
import org.apache.doris.analysis.RecoverTableStmt;
+import org.apache.doris.analysis.ShowCreateFunctionStmt;
import org.apache.doris.analysis.ShowCreateTableStmt;
+import org.apache.doris.analysis.ShowFunctionsStmt;
import org.apache.doris.analysis.SqlParser;
import org.apache.doris.analysis.SqlScanner;
import org.apache.doris.analysis.StatementBase;
@@ -492,6 +495,18 @@ public abstract class TestWithFeService {
return executor.execute();
}
+ protected ShowResultSet showCreateFunction(String sql) throws Exception {
+ ShowCreateFunctionStmt stmt = (ShowCreateFunctionStmt)
parseAndAnalyzeStmt(sql);
+ ShowExecutor executor = new ShowExecutor(connectContext, stmt);
+ return executor.execute();
+ }
+
+ protected ShowResultSet showFunctions(String sql) throws Exception {
+ ShowFunctionsStmt stmt = (ShowFunctionsStmt) parseAndAnalyzeStmt(sql);
+ ShowExecutor executor = new ShowExecutor(connectContext, stmt);
+ return executor.execute();
+ }
+
protected ShowResultSet showCreateTableByName(String table) throws
Exception {
ShowCreateTableStmt stmt = (ShowCreateTableStmt)
parseAndAnalyzeStmt("show create table " + table);
ShowExecutor executor = new ShowExecutor(connectContext, stmt);
@@ -542,6 +557,11 @@ public abstract class TestWithFeService {
Env.getCurrentEnv().getPolicyMgr().createPolicy(createPolicyStmt);
}
+ public void createFunction(String sql) throws Exception {
+ CreateFunctionStmt createFunctionStmt = (CreateFunctionStmt)
parseAndAnalyzeStmt(sql);
+ Env.getCurrentEnv().createFunction(createFunctionStmt);
+ }
+
protected void dropPolicy(String sql) throws Exception {
DropPolicyStmt stmt = (DropPolicyStmt) parseAndAnalyzeStmt(sql);
Env.getCurrentEnv().getPolicyMgr().dropPolicy(stmt);
@@ -600,7 +620,8 @@ public abstract class TestWithFeService {
}
private void updateReplicaPathHash() {
- com.google.common.collect.Table<Long, Long, Replica> replicaMetaTable
= Env.getCurrentInvertedIndex().getReplicaMetaTable();
+ com.google.common.collect.Table<Long, Long, Replica> replicaMetaTable
= Env.getCurrentInvertedIndex()
+ .getReplicaMetaTable();
for (com.google.common.collect.Table.Cell<Long, Long, Replica> cell :
replicaMetaTable.cellSet()) {
long beId = cell.getColumnKey();
Backend be = Env.getCurrentSystemInfo().getBackend(beId);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]