[Stmt] Support new show functions syntax to make user search function more conveniently (#2800)
SHOW [FULL] [BUILTIN] FUNCTIONS [IN|FROM db] [LIKE 'function_pattern'];
This commit is contained in:
@ -17,42 +17,56 @@ specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# SHOW FUNCTION
|
||||
# SHOW FUNCTIONS
|
||||
## description
|
||||
### Syntax
|
||||
|
||||
```
|
||||
SHOW FUNCTION [FROM db]
|
||||
SHOW [FULL] [BUILTIN] FUNCTIONS [IN|FROM db] [LIKE 'function_pattern']
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
> `db`: 要查询的数据库名字
|
||||
>`full`:表示显示函数的详细信息
|
||||
>`builtin`:表示显示系统提供的函数
|
||||
>`db`: 要查询的数据库名字
|
||||
>`function_pattern`: 用来过滤函数名称的参数
|
||||
|
||||
|
||||
查看数据库下所有的自定义函数。如果用户指定了数据库,那么查看对应数据库的,否则直接查询当前会话所在数据库
|
||||
查看数据库下所有的自定义(系统提供)的函数。如果用户指定了数据库,那么查看对应数据库的,否则直接查询当前会话所在数据库
|
||||
|
||||
需要对这个数据库拥有 `SHOW` 权限
|
||||
|
||||
## example
|
||||
|
||||
```
|
||||
mysql> show function in testDb\G
|
||||
mysql> show full functions in testDb\G
|
||||
*************************** 1. row ***************************
|
||||
Signature: my_count(BIGINT)
|
||||
Return Type: BIGINT
|
||||
Function Type: Aggregate
|
||||
Intermediate Type: NULL
|
||||
Properties: {"object_file":"http://host:port/libudasample.so","finalize_fn":"_ZN9doris_udf13CountFinalizeEPNS_15FunctionContextERKNS_9BigIntValE","init_fn":"_ZN9doris_udf9CountInitEPNS_15FunctionContextEPNS_9BigIntValE","merge_fn":"_ZN9doris_udf10CountMergeEPNS_15FunctionContextERKNS_9BigIntValEPS2_","md5":"37d185f80f95569e2676da3d5b5b9d2f","update_fn":"_ZN9doris_udf11CountUpdateEPNS_15FunctionContextERKNS_6IntValEPNS_9BigIntValE"}
|
||||
*************************** 2. row ***************************
|
||||
Signature: my_add(INT,INT)
|
||||
Return Type: INT
|
||||
Function Type: Scalar
|
||||
Intermediate Type: NULL
|
||||
Properties: {"symbol":"_ZN9doris_udf6AddUdfEPNS_15FunctionContextERKNS_6IntValES4_","object_file":"http://host:port/libudfsample.so","md5":"cfe7a362d10f3aaf6c49974ee0f1f878"}
|
||||
*************************** 2. row ***************************
|
||||
Signature: my_count(BIGINT)
|
||||
Return Type: BIGINT
|
||||
Function Type: Aggregate
|
||||
Intermediate Type: NULL
|
||||
Properties: {"object_file":"http://host:port/libudasample.so","finalize_fn":"_ZN9doris_udf13CountFinalizeEPNS_15FunctionContextERKNS_9BigIntValE","init_fn":"_ZN9doris_udf9CountInitEPNS_15FunctionContextEPNS_9BigIntValE","merge_fn":"_ZN9doris_udf10CountMergeEPNS_15FunctionContextERKNS_9BigIntValEPS2_","md5":"37d185f80f95569e2676da3d5b5b9d2f","update_fn":"_ZN9doris_udf11CountUpdateEPNS_15FunctionContextERKNS_6IntValEPNS_9BigIntValE"}
|
||||
|
||||
2 rows in set (0.00 sec)
|
||||
mysql> show builtin functions in testDb like 'year%';
|
||||
+---------------+
|
||||
| Function Name |
|
||||
+---------------+
|
||||
| year |
|
||||
| years_add |
|
||||
| years_diff |
|
||||
| years_sub |
|
||||
+---------------+
|
||||
2 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
## keyword
|
||||
|
||||
SHOW,FUNCTION
|
||||
SHOW,FUNCTIONS
|
||||
@ -1,56 +0,0 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
# SHOW FUNCTION
|
||||
## Description
|
||||
### Syntax
|
||||
|
||||
```
|
||||
SHOW FUNCTION [FROM db]
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
>` DB `: The name of the database to query
|
||||
|
||||
|
||||
Look at all the custom functions under the database. If the user specifies the database, then look at the corresponding database, otherwise directly query the database where the current session is located.
|
||||
|
||||
You need `SHOW'privileges for this database
|
||||
|
||||
## example
|
||||
|
||||
```
|
||||
mysql> show function in testDb\G
|
||||
*********************************1. row ************************
|
||||
Signature: my_count(BIGINT)
|
||||
Return Type: BIGINT
|
||||
Function Type: Aggregate
|
||||
Intermediate Type: NULL
|
||||
Properties: {"object_file":"http://host:port/libudasample.so","finalize_fn":"_ZN9doris_udf13CountFinalizeEPNS_15FunctionContextERKNS_9BigIntValE","init_fn":"_ZN9doris_udf9CountInitEPNS_15FunctionContextEPNS_9BigIntValE","merge_fn":"_ZN9doris_udf10CountMergeEPNS_15FunctionContextERKNS_9BigIntValEPS2_","md5":"37d185f80f95569e2676da3d5b5b9d2f","update_fn":"_ZN9doris_udf11CountUpdateEPNS_15FunctionContextERKNS_6IntValEPNS_9BigIntValE"}
|
||||
*********************************2. row ************************
|
||||
Signature: my_add(INT,INT)
|
||||
Return Type: INT
|
||||
Function Type: Scalar
|
||||
Intermediate Type: NULL
|
||||
Properties: {"symbol":"_ZN9doris_udf6AddUdfEPNS_15FunctionContextERKNS_6IntValES4_","object_file":"http://host:port/libudfsample.so","md5":"cfe7a362d10f3aaf6c49974ee0f1f878"}
|
||||
2 rows in set (0.00 sec)
|
||||
```
|
||||
##keyword
|
||||
SHOW,FUNCTION
|
||||
@ -0,0 +1,70 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
# SHOW FUNCTIONS
|
||||
## Description
|
||||
### Syntax
|
||||
|
||||
```
|
||||
SHOW [FULL] [BUILTIN] FUNCTIONS [IN|FROM db] [LIKE 'function_pattern']
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
>`full`: Indicate to show the details of function
|
||||
>`builtin`: Indicate to show the functions that doris provides
|
||||
>`db`: The name of the database to query
|
||||
>`function_pattern`: The parameter to filter function name
|
||||
|
||||
Look at all the custom(builtin) functions under the database. If the user specifies the database, then look at the corresponding database, otherwise directly query the database where the current session is located.
|
||||
|
||||
You need `SHOW'privileges for this database
|
||||
|
||||
## example
|
||||
|
||||
```
|
||||
mysql> show full functions in testDb\G
|
||||
*************************** 1. row ***************************
|
||||
Signature: my_add(INT,INT)
|
||||
Return Type: INT
|
||||
Function Type: Scalar
|
||||
Intermediate Type: NULL
|
||||
Properties: {"symbol":"_ZN9doris_udf6AddUdfEPNS_15FunctionContextERKNS_6IntValES4_","object_file":"http://host:port/libudfsample.so","md5":"cfe7a362d10f3aaf6c49974ee0f1f878"}
|
||||
*************************** 2. row ***************************
|
||||
Signature: my_count(BIGINT)
|
||||
Return Type: BIGINT
|
||||
Function Type: Aggregate
|
||||
Intermediate Type: NULL
|
||||
Properties: {"object_file":"http://host:port/libudasample.so","finalize_fn":"_ZN9doris_udf13CountFinalizeEPNS_15FunctionContextERKNS_9BigIntValE","init_fn":"_ZN9doris_udf9CountInitEPNS_15FunctionContextEPNS_9BigIntValE","merge_fn":"_ZN9doris_udf10CountMergeEPNS_15FunctionContextERKNS_9BigIntValEPS2_","md5":"37d185f80f95569e2676da3d5b5b9d2f","update_fn":"_ZN9doris_udf11CountUpdateEPNS_15FunctionContextERKNS_6IntValEPNS_9BigIntValE"}
|
||||
|
||||
2 rows in set (0.00 sec)
|
||||
mysql> show builtin functions in testDb like 'year%';
|
||||
+---------------+
|
||||
| Function Name |
|
||||
+---------------+
|
||||
| year |
|
||||
| years_add |
|
||||
| years_diff |
|
||||
| years_sub |
|
||||
+---------------+
|
||||
2 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
##keyword
|
||||
SHOW,FUNCTIONS
|
||||
@ -194,14 +194,14 @@ parser code {:
|
||||
|
||||
// Total keywords of doris
|
||||
terminal String KW_ADD, KW_ADMIN, KW_AFTER, KW_AGGREGATE, KW_ALL, KW_ALTER, KW_AND, KW_ANTI, KW_AS, KW_ASC, KW_AUTHORS,
|
||||
KW_BACKEND, KW_BACKUP, KW_BETWEEN, KW_BEGIN, KW_BIGINT, KW_BITMAP, KW_BITMAP_UNION, KW_BOOLEAN, KW_BOTH, KW_BROKER, KW_BACKENDS, KW_BY,
|
||||
KW_BACKEND, KW_BACKUP, KW_BETWEEN, KW_BEGIN, KW_BIGINT, KW_BITMAP, KW_BITMAP_UNION, KW_BOOLEAN, KW_BOTH, KW_BROKER, KW_BACKENDS, KW_BY, KW_BUILTIN,
|
||||
KW_CANCEL, KW_CASE, KW_CAST, KW_CHAIN, KW_CHAR, KW_CHARSET, KW_CLUSTER, KW_CLUSTERS,
|
||||
KW_COLLATE, KW_COLLATION, KW_COLUMN, KW_COLUMNS, KW_COMMENT, KW_COMMIT, KW_COMMITTED,
|
||||
KW_CONFIG, KW_CONNECTION, KW_CONNECTION_ID, KW_CONSISTENT, KW_COUNT, KW_CREATE, KW_CROSS, KW_CUBE, KW_CURRENT, KW_CURRENT_USER,
|
||||
KW_DATA, KW_DATABASE, KW_DATABASES, KW_DATE, KW_DATETIME, KW_DAY, KW_DECIMAL, KW_DECOMMISSION, KW_DEFAULT, KW_DESC, KW_DESCRIBE,
|
||||
KW_DELETE, KW_DISTINCT, KW_DISTINCTPC, KW_DISTINCTPCSA, KW_DISTRIBUTED, KW_DISTRIBUTION, KW_DYNAMIC, KW_BUCKETS, KW_DIV, KW_DOUBLE, KW_DROP, KW_DROPP, KW_DUPLICATE,
|
||||
KW_ELSE, KW_END, KW_ENGINE, KW_ENGINES, KW_ENTER, KW_ERRORS, KW_EVENTS, KW_EXISTS, KW_EXPORT, KW_EXTERNAL, KW_EXTRACT,
|
||||
KW_FALSE, KW_FOLLOWER, KW_FOLLOWING, KW_FREE, KW_FROM, KW_FILE, KW_FIRST, KW_FLOAT, KW_FOR, KW_FORMAT, KW_FRONTEND, KW_FRONTENDS, KW_FULL, KW_FUNCTION,
|
||||
KW_FALSE, KW_FOLLOWER, KW_FOLLOWING, KW_FREE, KW_FROM, KW_FILE, KW_FIRST, KW_FLOAT, KW_FOR, KW_FORMAT, KW_FRONTEND, KW_FRONTENDS, KW_FULL, KW_FUNCTION, KW_FUNCTIONS,
|
||||
KW_GLOBAL, KW_GRANT, KW_GRANTS, KW_GROUP, KW_GROUPING,
|
||||
KW_HASH, KW_HAVING, KW_HELP,KW_HLL, KW_HLL_UNION, KW_HOUR, KW_HUB,
|
||||
KW_IDENTIFIED, KW_IF, KW_IN, KW_INDEX, KW_INDEXES, KW_INFILE,
|
||||
@ -429,6 +429,7 @@ nonterminal Boolean opt_external;
|
||||
nonterminal IndexDef.IndexType opt_index_type;
|
||||
|
||||
nonterminal ShowAlterStmt.AlterType opt_alter_type;
|
||||
nonterminal Boolean opt_builtin;
|
||||
|
||||
precedence left KW_FULL, KW_MERGE;
|
||||
precedence left DOT;
|
||||
@ -2094,9 +2095,9 @@ show_param ::=
|
||||
{:
|
||||
RESULT = new ShowRolesStmt();
|
||||
:}
|
||||
| KW_FUNCTION opt_db:dbName
|
||||
| opt_full opt_builtin:isBuiltin KW_FUNCTIONS opt_db:dbName opt_wild_where
|
||||
{:
|
||||
RESULT = new ShowFunctionStmt(dbName);
|
||||
RESULT = new ShowFunctionsStmt(dbName, isBuiltin, parser.isVerbose, parser.wild, parser.where);
|
||||
:}
|
||||
| KW_FILE opt_db:dbName
|
||||
{:
|
||||
@ -2247,6 +2248,16 @@ opt_alter_type ::=
|
||||
:}
|
||||
;
|
||||
|
||||
opt_builtin ::=
|
||||
{:
|
||||
RESULT = false;
|
||||
:}
|
||||
| KW_BUILTIN
|
||||
{:
|
||||
RESULT = true;
|
||||
:}
|
||||
;
|
||||
|
||||
// Describe statement
|
||||
describe_stmt ::=
|
||||
describe_command table_name:table
|
||||
@ -4189,6 +4200,8 @@ keyword ::=
|
||||
{: RESULT = id; :}
|
||||
| KW_BACKENDS:id
|
||||
{: RESULT = id; :}
|
||||
| KW_BUILTIN:id
|
||||
{: RESULT = id; :}
|
||||
| KW_CHAIN:id
|
||||
{: RESULT = id; :}
|
||||
| KW_CHARSET:id
|
||||
|
||||
@ -22,6 +22,7 @@ import org.apache.doris.catalog.Catalog;
|
||||
import org.apache.doris.catalog.Column;
|
||||
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;
|
||||
@ -29,7 +30,7 @@ import org.apache.doris.mysql.privilege.PrivPredicate;
|
||||
import org.apache.doris.qe.ConnectContext;
|
||||
import org.apache.doris.qe.ShowResultSetMetaData;
|
||||
|
||||
public class ShowFunctionStmt extends ShowStmt {
|
||||
public class ShowFunctionsStmt extends ShowStmt {
|
||||
private static final ShowResultSetMetaData META_DATA =
|
||||
ShowResultSetMetaData.builder()
|
||||
.addColumn(new Column("Signature", ScalarType.createVarchar(256)))
|
||||
@ -41,15 +42,49 @@ public class ShowFunctionStmt extends ShowStmt {
|
||||
|
||||
private String dbName;
|
||||
|
||||
public ShowFunctionStmt(String dbName) {
|
||||
private boolean isBuiltin;
|
||||
|
||||
private boolean isVerbose;
|
||||
|
||||
private String wild;
|
||||
|
||||
private Expr expr;
|
||||
|
||||
public ShowFunctionsStmt(String dbName, boolean isBuiltin, boolean isVerbose, String wild, Expr expr) {
|
||||
this.dbName = dbName;
|
||||
this.isBuiltin = isBuiltin;
|
||||
this.isVerbose = isVerbose;
|
||||
this.wild = wild;
|
||||
this.expr = expr;
|
||||
}
|
||||
|
||||
public String getDbName() { return dbName; }
|
||||
|
||||
public boolean getIsBuiltin() {
|
||||
return isBuiltin;
|
||||
}
|
||||
|
||||
public boolean getIsVerbose() {
|
||||
return isVerbose;
|
||||
}
|
||||
|
||||
public String getWild() {
|
||||
return wild;
|
||||
}
|
||||
|
||||
public Expr getExpr() {
|
||||
return expr;
|
||||
}
|
||||
|
||||
public boolean like(String str) {
|
||||
str = str.toLowerCase();
|
||||
return str.matches(wild.replace(".", "\\.").replace("?", ".").replace("%", ".*").toLowerCase());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void analyze(Analyzer analyzer) throws UserException {
|
||||
super.analyze(analyzer);
|
||||
|
||||
if (Strings.isNullOrEmpty(dbName)) {
|
||||
dbName = analyzer.getDefaultDb();
|
||||
if (Strings.isNullOrEmpty(dbName)) {
|
||||
@ -61,7 +96,11 @@ public class ShowFunctionStmt extends ShowStmt {
|
||||
|
||||
if (!Catalog.getCurrentCatalog().getAuth().checkDbPriv(ConnectContext.get(), dbName, PrivPredicate.SHOW)) {
|
||||
ErrorReport.reportAnalysisException(
|
||||
ErrorCode.ERR_DB_ACCESS_DENIED, ConnectContext.get().getQualifiedUser(), dbName);
|
||||
ErrorCode.ERR_DB_ACCESS_DENIED, ConnectContext.get().getQualifiedUser(), dbName);
|
||||
}
|
||||
|
||||
if (expr != null) {
|
||||
throw new AnalysisException("Only support like 'function_pattern' syntax.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,4 +108,31 @@ public class ShowFunctionStmt extends ShowStmt {
|
||||
public ShowResultSetMetaData getMetaData() {
|
||||
return META_DATA;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toSql() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("SHOW ");
|
||||
if (isVerbose) {
|
||||
sb.append("FULL ");
|
||||
}
|
||||
if (isBuiltin) {
|
||||
sb.append("BUILTIN ");
|
||||
}
|
||||
sb.append("FUNCTIONS FROM ");
|
||||
if (!Strings.isNullOrEmpty(dbName)) {
|
||||
sb.append("`").append(dbName).append("` ");
|
||||
}
|
||||
if (wild != null) {
|
||||
sb.append("LIKE ").append("`").append(wild).append("`");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toSql();
|
||||
}
|
||||
|
||||
}
|
||||
@ -457,7 +457,7 @@ public class AggregateFunction extends Function {
|
||||
@Override
|
||||
public String getProperties() {
|
||||
Map<String, String> properties = Maps.newHashMap();
|
||||
properties.put(CreateFunctionStmt.OBJECT_FILE_KEY, getLocation().toString());
|
||||
properties.put(CreateFunctionStmt.OBJECT_FILE_KEY, getLocation() == null ? "" : getLocation().toString());
|
||||
properties.put(CreateFunctionStmt.MD5_CHECKSUM, checksum);
|
||||
properties.put(CreateFunctionStmt.INIT_KEY, initFnSymbol);
|
||||
properties.put(CreateFunctionStmt.UPDATE_KEY, updateFnSymbol);
|
||||
|
||||
@ -5268,6 +5268,10 @@ public class Catalog {
|
||||
return functionSet.getFunction(desc, mode);
|
||||
}
|
||||
|
||||
public List<Function> getBuiltinFunctions() {
|
||||
return functionSet.getBulitinFunctions();
|
||||
}
|
||||
|
||||
/**
|
||||
* create cluster
|
||||
*
|
||||
|
||||
@ -21,6 +21,7 @@ import static org.apache.doris.common.io.IOUtils.writeOptionString;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.apache.doris.analysis.FunctionName;
|
||||
import org.apache.doris.analysis.HdfsURI;
|
||||
import org.apache.doris.common.io.Text;
|
||||
@ -668,4 +669,34 @@ public class Function implements Writable {
|
||||
public String getProperties() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public List<Comparable> getInfo(boolean isVerbose) {
|
||||
List<Comparable> row = Lists.newArrayList();
|
||||
if (isVerbose) {
|
||||
// signature
|
||||
row.add(getSignature());
|
||||
// return type
|
||||
row.add(getReturnType().getPrimitiveType().toString());
|
||||
// function type
|
||||
// intermediate type
|
||||
if (this instanceof ScalarFunction) {
|
||||
row.add("Scalar");
|
||||
row.add("NULL");
|
||||
} else {
|
||||
row.add("Aggregate");
|
||||
AggregateFunction aggFunc = (AggregateFunction) this;
|
||||
Type intermediateType = aggFunc.getIntermediateType();
|
||||
if (intermediateType != null) {
|
||||
row.add(intermediateType.getPrimitiveType().toString());
|
||||
} else {
|
||||
row.add("NULL");
|
||||
}
|
||||
}
|
||||
// property
|
||||
row.add(getProperties());
|
||||
} else {
|
||||
row.add(functionName());
|
||||
}
|
||||
return row;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1320,4 +1320,12 @@ public class FunctionSet {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public List<Function> getBulitinFunctions() {
|
||||
List<Function> builtinFunctions = Lists.newArrayList();
|
||||
for (Map.Entry<String, List<Function>> entry : functions.entrySet()) {
|
||||
builtinFunctions.addAll(entry.getValue());
|
||||
}
|
||||
return builtinFunctions;
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,7 +304,7 @@ public class ScalarFunction extends Function {
|
||||
@Override
|
||||
public String getProperties() {
|
||||
Map<String, String> properties = Maps.newHashMap();
|
||||
properties.put(CreateFunctionStmt.OBJECT_FILE_KEY, getLocation().toString());
|
||||
properties.put(CreateFunctionStmt.OBJECT_FILE_KEY, getLocation() == null ? "" : getLocation().toString());
|
||||
properties.put(CreateFunctionStmt.MD5_CHECKSUM, checksum);
|
||||
properties.put(CreateFunctionStmt.SYMBOL_KEY, symbolName);
|
||||
return new Gson().toJson(properties);
|
||||
|
||||
@ -39,7 +39,7 @@ import org.apache.doris.analysis.ShowDynamicPartitionStmt;
|
||||
import org.apache.doris.analysis.ShowEnginesStmt;
|
||||
import org.apache.doris.analysis.ShowExportStmt;
|
||||
import org.apache.doris.analysis.ShowFrontendsStmt;
|
||||
import org.apache.doris.analysis.ShowFunctionStmt;
|
||||
import org.apache.doris.analysis.ShowFunctionsStmt;
|
||||
import org.apache.doris.analysis.ShowGrantsStmt;
|
||||
import org.apache.doris.analysis.ShowIndexStmt;
|
||||
import org.apache.doris.analysis.ShowLoadStmt;
|
||||
@ -67,7 +67,6 @@ import org.apache.doris.backup.AbstractJob;
|
||||
import org.apache.doris.backup.BackupJob;
|
||||
import org.apache.doris.backup.Repository;
|
||||
import org.apache.doris.backup.RestoreJob;
|
||||
import org.apache.doris.catalog.AggregateFunction;
|
||||
import org.apache.doris.catalog.Catalog;
|
||||
import org.apache.doris.catalog.Column;
|
||||
import org.apache.doris.catalog.Database;
|
||||
@ -80,11 +79,10 @@ import org.apache.doris.catalog.MetadataViewer;
|
||||
import org.apache.doris.catalog.OlapTable;
|
||||
import org.apache.doris.catalog.Partition;
|
||||
import org.apache.doris.catalog.Replica;
|
||||
import org.apache.doris.catalog.ScalarFunction;
|
||||
import org.apache.doris.catalog.ScalarType;
|
||||
import org.apache.doris.catalog.Table;
|
||||
import org.apache.doris.catalog.Tablet;
|
||||
import org.apache.doris.catalog.TabletInvertedIndex;
|
||||
import org.apache.doris.catalog.Type;
|
||||
import org.apache.doris.catalog.View;
|
||||
import org.apache.doris.clone.DynamicPartitionScheduler;
|
||||
import org.apache.doris.cluster.BaseParam;
|
||||
@ -138,6 +136,7 @@ import java.net.URLConnection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -183,8 +182,8 @@ public class ShowExecutor {
|
||||
handleShowProcesslist();
|
||||
} else if (stmt instanceof ShowEnginesStmt) {
|
||||
handleShowEngines();
|
||||
} else if (stmt instanceof ShowFunctionStmt) {
|
||||
handleShowFunction();
|
||||
} else if (stmt instanceof ShowFunctionsStmt) {
|
||||
handleShowFunctions();
|
||||
} else if (stmt instanceof ShowVariablesStmt) {
|
||||
handleShowVariables();
|
||||
} else if (stmt instanceof ShowColumnStmt) {
|
||||
@ -302,44 +301,51 @@ public class ShowExecutor {
|
||||
resultSet = new ShowResultSet(showStmt.getMetaData(), rowSet);
|
||||
}
|
||||
|
||||
// Handle show function
|
||||
private void handleShowFunction() throws AnalysisException {
|
||||
ShowFunctionStmt showStmt = (ShowFunctionStmt) stmt;
|
||||
|
||||
// Handle show functions
|
||||
private void handleShowFunctions() throws AnalysisException {
|
||||
ShowFunctionsStmt showStmt = (ShowFunctionsStmt) stmt;
|
||||
Database db = ctx.getCatalog().getDb(showStmt.getDbName());
|
||||
if (db == null) {
|
||||
ErrorReport.reportAnalysisException(ErrorCode.ERR_BAD_DB_ERROR, showStmt.getDbName());
|
||||
}
|
||||
List<Function> functions = db.getFunctions();
|
||||
List<Function> functions = showStmt.getIsBuiltin() ? ctx.getCatalog().getBuiltinFunctions() :
|
||||
db.getFunctions();
|
||||
|
||||
List<List<String>> rowSet = Lists.newArrayList();
|
||||
List<List<Comparable>> rowSet = Lists.newArrayList();
|
||||
for (Function function : functions) {
|
||||
List<String> row = Lists.newArrayList();
|
||||
// signature
|
||||
row.add(function.getSignature());
|
||||
// return type
|
||||
row.add(function.getReturnType().getPrimitiveType().toString());
|
||||
// function type
|
||||
// intermediate type
|
||||
if (function instanceof ScalarFunction) {
|
||||
row.add("Scalar");
|
||||
row.add("NULL");
|
||||
} else {
|
||||
row.add("Aggregate");
|
||||
AggregateFunction aggFunc = (AggregateFunction) function;
|
||||
Type intermediateType = aggFunc.getIntermediateType();
|
||||
if (intermediateType != null) {
|
||||
row.add(intermediateType.getPrimitiveType().toString());
|
||||
} else {
|
||||
row.add("NULL");
|
||||
}
|
||||
List<Comparable> row = function.getInfo(showStmt.getIsVerbose());
|
||||
// like predicate
|
||||
if (showStmt.getWild() == null || showStmt.like(function.functionName())) {
|
||||
rowSet.add(row);
|
||||
}
|
||||
// property
|
||||
row.add(function.getProperties());
|
||||
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);
|
||||
List<List<String>> resultRowSet = Lists.newArrayList();
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
// Only success
|
||||
resultSet = new ShowResultSet(showStmt.getMetaData(), rowSet);
|
||||
ShowResultSetMetaData showMetaData = showStmt.getIsVerbose() ? showStmt.getMetaData() :
|
||||
ShowResultSetMetaData.builder()
|
||||
.addColumn(new Column("Function Name", ScalarType.createVarchar(256))).build();
|
||||
resultSet = new ShowResultSet(showMetaData, resultRowSet);
|
||||
}
|
||||
|
||||
private void handleShowProc() throws AnalysisException {
|
||||
|
||||
@ -111,6 +111,7 @@ import org.apache.doris.qe.SqlModeHelper;
|
||||
keywordMap.put("both", new Integer(SqlParserSymbols.KW_BOTH));
|
||||
keywordMap.put("broker", new Integer(SqlParserSymbols.KW_BROKER));
|
||||
keywordMap.put("buckets", new Integer(SqlParserSymbols.KW_BUCKETS));
|
||||
keywordMap.put("builtin", new Integer(SqlParserSymbols.KW_BUILTIN));
|
||||
keywordMap.put("by", new Integer(SqlParserSymbols.KW_BY));
|
||||
keywordMap.put("cancel", new Integer(SqlParserSymbols.KW_CANCEL));
|
||||
keywordMap.put("case", new Integer(SqlParserSymbols.KW_CASE));
|
||||
@ -189,6 +190,7 @@ import org.apache.doris.qe.SqlModeHelper;
|
||||
keywordMap.put("frontends", new Integer(SqlParserSymbols.KW_FRONTENDS));
|
||||
keywordMap.put("full", new Integer(SqlParserSymbols.KW_FULL));
|
||||
keywordMap.put("function", new Integer(SqlParserSymbols.KW_FUNCTION));
|
||||
keywordMap.put("functions", new Integer(SqlParserSymbols.KW_FUNCTIONS));
|
||||
keywordMap.put("global", new Integer(SqlParserSymbols.KW_GLOBAL));
|
||||
keywordMap.put("grant", new Integer(SqlParserSymbols.KW_GRANT));
|
||||
keywordMap.put("grants", new Integer(SqlParserSymbols.KW_GRANTS));
|
||||
|
||||
@ -0,0 +1,92 @@
|
||||
// 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 mockit.Expectations;
|
||||
import mockit.Mocked;
|
||||
import org.apache.doris.catalog.Catalog;
|
||||
import org.apache.doris.catalog.FakeCatalog;
|
||||
import org.apache.doris.common.AnalysisException;
|
||||
import org.apache.doris.common.UserException;
|
||||
import org.apache.doris.mysql.privilege.MockedAuth;
|
||||
import org.apache.doris.mysql.privilege.PaloAuth;
|
||||
import org.apache.doris.qe.ConnectContext;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
public class ShowFunctionsStmtTest {
|
||||
@Mocked
|
||||
private Analyzer analyzer;
|
||||
private Catalog catalog;
|
||||
|
||||
@Mocked
|
||||
private PaloAuth auth;
|
||||
@Mocked
|
||||
private ConnectContext ctx;
|
||||
private FakeCatalog fakeCatalog;
|
||||
|
||||
@Rule
|
||||
public ExpectedException expectedEx = ExpectedException.none();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
fakeCatalog = new FakeCatalog();
|
||||
catalog = AccessTestUtil.fetchAdminCatalog();
|
||||
MockedAuth.mockedAuth(auth);
|
||||
MockedAuth.mockedConnectContext(ctx, "root", "192.188.3.1");
|
||||
FakeCatalog.setCatalog(catalog);
|
||||
|
||||
new Expectations() {
|
||||
{
|
||||
analyzer.getDefaultDb();
|
||||
minTimes = 0;
|
||||
result = "testDb";
|
||||
|
||||
analyzer.getCatalog();
|
||||
minTimes = 0;
|
||||
result = catalog;
|
||||
|
||||
analyzer.getClusterName();
|
||||
minTimes = 0;
|
||||
result = "testCluster";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNormal() throws UserException {
|
||||
ShowFunctionsStmt stmt = new ShowFunctionsStmt(null, true, true, "%year%", null);
|
||||
stmt.analyze(analyzer);
|
||||
Assert.assertEquals("SHOW FULL BUILTIN FUNCTIONS FROM `testDb` LIKE `%year%`", stmt.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnsupportFilter() throws UserException {
|
||||
SlotRef slotRef = new SlotRef(null, "Signature");
|
||||
StringLiteral stringLiteral = new StringLiteral("year(DATETIME)");
|
||||
BinaryPredicate binaryPredicate = new BinaryPredicate(BinaryPredicate.Operator.EQ, slotRef, stringLiteral);
|
||||
ShowFunctionsStmt stmt = new ShowFunctionsStmt(null, true, true, null, binaryPredicate);
|
||||
expectedEx.expect(AnalysisException.class);
|
||||
expectedEx.expectMessage("Only support like 'function_pattern' syntax.");
|
||||
stmt.analyze(analyzer);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user