[Function] Support show create function statement (#5197)

* [Function]Support show create function stmt

Co-authored-by: caiconghui [蔡聪辉] <caiconghui@xiaomi.com>
This commit is contained in:
caiconghui
2021-01-28 10:52:37 +08:00
committed by GitHub
parent 41ef9ccda9
commit ca10205137
10 changed files with 264 additions and 32 deletions

View File

@ -0,0 +1,43 @@
---
{
"title": "SHOW CREATE FUNCTION",
"language": "en"
}
---
<!--
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 CREATE FUNCTION
## description
The statement is used to show the creation statement of user-defined function
grammar:
SHOW CREATE FUNTION function_name(arg_type [, ...]) [FROM db_name]];
Description:
`function_name`: the name of the function to be displayed
`arg_type`: the parameter list of the function to be displayed
If you do not specify db_name, use the current default db
## example
1. Show the creation statement of the specified function under the default db
SHOW CREATE FUNCTION my_add(INT, INT)
## keyword
SHOW,CREATE,FUNCTION

View File

@ -0,0 +1,43 @@
---
{
"title": "SHOW CREATE FUNCTION",
"language": "zh-CN"
}
---
<!--
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 CREATE FUNCTION
## description
该语句用于展示用户自定义函数的创建语句
语法:
SHOW CREATE FUNTION function_name(arg_type [, ...]) [FROM db_name]];
说明:
`function_name`: 要展示的函数名称
`arg_type`: 要展示的函数的参数列表
如果不指定 db_name,使用当前默认 db
## example
1. 展示默认db下指定函数的创建语句
SHOW CREATE FUNCTION my_add(INT, INT)
## keyword
SHOW,CREATE,FUNCTION

View File

@ -2261,6 +2261,11 @@ show_param ::=
{:
RESULT = new ShowCreateDbStmt(db);
:}
/* Create Function */
| KW_CREATE KW_FUNCTION function_name:functionName LPAREN func_args_def:args RPAREN opt_db:dbName
{:
RESULT = new ShowCreateFunctionStmt(dbName, functionName, args);
:}
/* Cluster */
| KW_CLUSTERS
{:

View File

@ -60,7 +60,7 @@ public class DropFunctionStmt extends DdlStmt {
@Override
public String toSql() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("DROP FUNCTION ").append(functionName);
stringBuilder.append("DROP FUNCTION ").append(functionName).append(argsDef);
return stringBuilder.toString();
}

View File

@ -0,0 +1,103 @@
// 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 com.google.common.base.Strings;
import org.apache.doris.catalog.Catalog;
import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.FunctionSearchDesc;
import org.apache.doris.catalog.ScalarType;
import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.ErrorCode;
import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.UserException;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.qe.ConnectContext;
import org.apache.doris.qe.ShowResultSetMetaData;
public class ShowCreateFunctionStmt extends ShowStmt {
private static final ShowResultSetMetaData META_DATA =
ShowResultSetMetaData.builder()
.addColumn(new Column("Function Signature", ScalarType.createVarchar(256)))
.addColumn(new Column("Create Function", ScalarType.createVarchar(1024)))
.build();
private String dbName;
private final FunctionName functionName;
private final FunctionArgsDef argsDef;
// set after analyzed
private FunctionSearchDesc function;
public ShowCreateFunctionStmt(String dbName, FunctionName functionName, FunctionArgsDef argsDef) {
this.dbName = dbName;
this.functionName = functionName;
this.argsDef = argsDef;
}
public String getDbName() {
return dbName;
}
public FunctionName getFunctionName() { return functionName; }
public FunctionSearchDesc getFunction() { return function; }
@Override
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);
}
// analyze function name
functionName.analyze(analyzer);
// check operation privilege
if (!Catalog.getCurrentCatalog().getAuth().checkDbPriv(ConnectContext.get(), dbName, PrivPredicate.SHOW)) {
ErrorReport.reportAnalysisException(
ErrorCode.ERR_DB_ACCESS_DENIED, ConnectContext.get().getQualifiedUser(), dbName);
}
// analyze arguments
argsDef.analyze(analyzer);
function = new FunctionSearchDesc(functionName, argsDef.getArgTypes(), argsDef.isVariadic());
}
@Override
public String toSql() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("SHOW CREATE FUNCTION ").append(functionName).append(argsDef)
.append(" IN ").append(dbName);
return stringBuilder.toString();
}
@Override
public String toString() {
return toSql();
}
@Override
public ShowResultSetMetaData getMetaData() {
return META_DATA;
}
}

View File

@ -361,21 +361,27 @@ public class AggregateFunction extends Function {
if (ifNotExists) {
sb.append("IF NOT EXISTS ");
}
sb.append(dbName() + "." + signatureString() + "\n")
.append(" RETURNS " + getReturnType() + "\n");
sb.append(signatureString()).append(" RETURNS " + getReturnType());
if (getIntermediateType() != null) {
sb.append(" INTERMEDIATE " + getIntermediateType() + "\n");
sb.append(" INTERMEDIATE " + getIntermediateType());
}
sb.append(" LOCATION '" + getLocation() + "'\n")
.append(" UPDATE_FN='" + getUpdateFnSymbol() + "'\n")
.append(" INIT_FN='" + getInitFnSymbol() + "'\n")
.append(" MERGE_FN='" + getMergeFnSymbol() + "'\n");
sb.append(" PROPERTIES (")
.append("\n \"INIT_FN\"=\"" + getUpdateFnSymbol() + "\"")
.append(",\n \"UPDATE_FN\"=\"" + getInitFnSymbol() + "\"")
.append(",\n \"MERGE_FN\"=\"" + getMergeFnSymbol() + "\"");
if (getSerializeFnSymbol() != null) {
sb.append(" SERIALIZE_FN='" + getSerializeFnSymbol() + "'\n");
sb.append(",\n \"SERIALIZE_FN\"=\"" + getSerializeFnSymbol() + "\"");
}
if (getFinalizeFnSymbol() != null) {
sb.append(" FINALIZE_FN='" + getFinalizeFnSymbol() + "'\n");
sb.append(",\n \"FINALIZE_FN\"=\"" + getFinalizeFnSymbol() + "\"");
}
sb.append(",\n \"OBJECT_FILE\"=")
.append("\"" + (getLocation() == null ? "" : getLocation().toString()) + "\"");
sb.append(",\n \"MD5\"=").append("\"" + getChecksum() + "\"");
sb.append("\n);");
return sb.toString();
}

View File

@ -19,6 +19,7 @@ package org.apache.doris.catalog;
import org.apache.doris.catalog.Table.TableType;
import org.apache.doris.cluster.ClusterNamespace;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.Config;
import org.apache.doris.common.DdlException;
import org.apache.doris.common.FeConstants;
@ -712,6 +713,21 @@ public class Database extends MetaObject implements Writable {
return Function.getFunction(fns, desc, mode);
}
public synchronized Function getFunction(FunctionSearchDesc function) throws AnalysisException {
String functionName = function.getName().getFunction();
List<Function> existFuncs = name2Function.get(functionName);
if (existFuncs == null) {
throw new AnalysisException("Unknown function, function=" + function.toString());
}
for (Function existFunc : existFuncs) {
if (function.isIdentical(existFunc)) {
return existFunc;
}
}
throw new AnalysisException("Unknown function, function=" + function.toString());
}
public synchronized List<Function> getFunctions() {
List<Function> functions = Lists.newArrayList();
for (Map.Entry<String, ImmutableList<Function>> entry : name2Function.entrySet()) {

View File

@ -659,22 +659,6 @@ public class Function implements Writable {
return function;
}
public String getSignature() {
StringBuilder sb = new StringBuilder();
sb.append(name.getFunction()).append("(");
for (int i = 0; i < argTypes.length; ++i) {
if (i != 0) {
sb.append(',');
}
sb.append(argTypes[i].getPrimitiveType().toString());
}
if (hasVarArgs) {
sb.append(", ...");
}
sb.append(")");
return sb.toString();
}
public String getProperties() {
return "";
}
@ -683,7 +667,7 @@ public class Function implements Writable {
List<Comparable> row = Lists.newArrayList();
if (isVerbose) {
// signature
row.add(getSignature());
row.add(signatureString());
// return type
row.add(getReturnType().getPrimitiveType().toString());
// function type

View File

@ -256,11 +256,23 @@ public class ScalarFunction extends Function {
@Override
public String toSql(boolean ifNotExists) {
StringBuilder sb = new StringBuilder("CREATE FUNCTION ");
if (ifNotExists) sb.append("IF NOT EXISTS ");
sb.append(dbName() + "." + signatureString() + "\n")
.append(" RETURNS " + getReturnType() + "\n")
.append(" LOCATION '" + getLocation() + "'\n")
.append(" SYMBOL='" + getSymbolName() + "'\n");
if (ifNotExists) {
sb.append("IF NOT EXISTS ");
}
sb.append(signatureString())
.append(" RETURNS " + getReturnType())
.append(" PROPERTIES (");
sb.append("\n \"SYMBOL\"=").append("\"" + getSymbolName() + "\"");
if (getPrepareFnSymbol() != null) {
sb.append(",\n \"PREPARE_FN\"=").append("\"" + getPrepareFnSymbol() + "\"");
}
if (getCloseFnSymbol() != null) {
sb.append(",\n \"CLOSE_FN\"=").append("\"" + getCloseFnSymbol() + "\"");
}
sb.append(",\n \"OBJECT_FILE\"=")
.append("\"" + (getLocation() == null ? "" : getLocation().toString()) + "\"");
sb.append(",\n \"MD5\"=").append("\"" + getChecksum() + "\"");
sb.append("\n);");
return sb.toString();
}

View File

@ -32,6 +32,7 @@ import org.apache.doris.analysis.ShowClusterStmt;
import org.apache.doris.analysis.ShowCollationStmt;
import org.apache.doris.analysis.ShowColumnStmt;
import org.apache.doris.analysis.ShowCreateDbStmt;
import org.apache.doris.analysis.ShowCreateFunctionStmt;
import org.apache.doris.analysis.ShowCreateTableStmt;
import org.apache.doris.analysis.ShowDataStmt;
import org.apache.doris.analysis.ShowDbStmt;
@ -192,6 +193,8 @@ public class ShowExecutor {
handleShowEngines();
} else if (stmt instanceof ShowFunctionsStmt) {
handleShowFunctions();
} else if (stmt instanceof ShowCreateFunctionStmt) {
handleShowCreateFunction();
} else if (stmt instanceof ShowVariablesStmt) {
handleShowVariables();
} else if (stmt instanceof ShowColumnStmt) {
@ -360,6 +363,23 @@ public class ShowExecutor {
resultSet = new ShowResultSet(showMetaData, resultRowSet);
}
// Handle show create function
private void handleShowCreateFunction() throws AnalysisException {
ShowCreateFunctionStmt showCreateFunctionStmt = (ShowCreateFunctionStmt) stmt;
Database db = ctx.getCatalog().getDb(showCreateFunctionStmt.getDbName());
if (db == null) {
ErrorReport.reportAnalysisException(ErrorCode.ERR_BAD_DB_ERROR, showCreateFunctionStmt.getDbName());
}
Function function = db.getFunction(showCreateFunctionStmt.getFunction());
List<List<String>> resultRowSet = Lists.newArrayList();
List<String> resultRow = Lists.newArrayList();
resultRow.add(function.signatureString());
resultRow.add(function.toSql(false));
resultRowSet.add(resultRow);
resultSet = new ShowResultSet(showCreateFunctionStmt.getMetaData(), resultRowSet);
}
private void handleShowProc() throws AnalysisException {
ShowProcStmt showProcStmt = (ShowProcStmt) stmt;
ShowResultSetMetaData metaData = showProcStmt.getMetaData();