From ed97bf51ba3b88fdfeeba2e868c93278b72b94af Mon Sep 17 00:00:00 2001 From: linzhenqi Date: Thu, 12 Feb 2026 00:32:34 +0800 Subject: [PATCH] 1 --- .../plans/commands/ShowFunctionsCommand.java | 146 +++++++++++++++--- .../commands/ShowFunctionsCommandTest.java | 31 ++-- .../ShowGlobalFunctionsCommandTest.java | 41 ++--- .../show/test_nereids_show_functions.groovy | 133 ++++++++++++++-- .../test_nereids_show_global_functions.groovy | 10 +- 5 files changed, 283 insertions(+), 78 deletions(-) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowFunctionsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowFunctionsCommand.java index 881f188456b726..d49e2d8351c49b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowFunctionsCommand.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowFunctionsCommand.java @@ -18,12 +18,15 @@ package org.apache.doris.nereids.trees.plans.commands; import org.apache.doris.analysis.SetType; +import org.apache.doris.catalog.AggregateFunction; +import org.apache.doris.catalog.AliasFunction; import org.apache.doris.catalog.Column; import org.apache.doris.catalog.Database; import org.apache.doris.catalog.DatabaseIf; import org.apache.doris.catalog.Env; -import org.apache.doris.catalog.FunctionRegistry; +import org.apache.doris.catalog.Function; import org.apache.doris.catalog.FunctionUtil; +import org.apache.doris.catalog.ScalarFunction; import org.apache.doris.catalog.ScalarType; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.ErrorCode; @@ -33,7 +36,6 @@ import org.apache.doris.common.util.Util; import org.apache.doris.datasource.InternalCatalog; import org.apache.doris.mysql.privilege.PrivPredicate; -import org.apache.doris.nereids.trees.expressions.functions.FunctionBuilder; import org.apache.doris.nereids.trees.plans.PlanType; import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor; import org.apache.doris.qe.ConnectContext; @@ -45,13 +47,13 @@ import com.google.common.base.Strings; import com.google.common.collect.Lists; -import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; /** * show functions command @@ -97,21 +99,21 @@ public ShowFunctionsCommand(boolean isVerbose, String likeCondition, boolean isG * get Info by nereids. * To make the code in nereids more concise, all irrelevant information here will use an empty string. */ - private List getInfo(boolean isVerbose, String funcName) { + private List getInfo(boolean isVerbose, Function function) { List row = Lists.newArrayList(); if (isVerbose) { // signature - row.add(funcName); + row.add(function.signatureString()); // return type - row.add(""); + row.add(function.getReturnType().toString()); // function type // intermediate type - row.add(""); - row.add(""); + row.add(buildFunctionType(function)); + row.add(buildIntermediateType(function)); // property - row.add(""); + row.add(buildProperties(function)); } else { - row.add(funcName); + row.add(function.functionName()); } return row; } @@ -126,13 +128,13 @@ protected boolean like(String funcName, String likeCondition) { * get resultRowSet */ @VisibleForTesting - protected List> getResultRowSetByFunctions(List functions) { + protected List> getResultRowSetByFunctions(List functions) { List> resultRowSet = Lists.newArrayList(); List> rowSet = Lists.newArrayList(); - for (String function : functions) { + for (Function function : functions) { List row = getInfo(isVerbose, function); // like predicate - if (likeCondition == null || like(function, likeCondition)) { + if (likeCondition == null || like(function.functionName(), likeCondition)) { rowSet.add(row); } } @@ -163,7 +165,7 @@ protected List> getResultRowSetByFunctions(List functions) * get resultRowSet */ private List> getResultRowSet(ConnectContext ctx) throws AnalysisException { - List functions = getFunctions(ctx); + List functions = getFunctions(ctx); return getResultRowSetByFunctions(functions); } @@ -172,23 +174,23 @@ private List> getResultRowSet(ConnectContext ctx) throws AnalysisEx * All functions including builtin and udf are registered in FunctionRegistry */ @VisibleForTesting - protected List getFunctions(ConnectContext ctx) throws AnalysisException { - List functions = Lists.newArrayList(); + protected List getFunctions(ConnectContext ctx) throws AnalysisException { + List functions = Lists.newArrayList(); if (ctx == null || ctx.getEnv() == null || ctx.getEnv().getFunctionRegistry() == null) { return functions; } - FunctionRegistry functionRegistry = ctx.getEnv().getFunctionRegistry(); - Map>> udfFunctions = functionRegistry.getName2UdfBuilders(); + if (!FunctionUtil.isGlobalFunction(type)) { + dbName = reAcquireDbName(ctx, dbName); + } + if (FunctionUtil.isGlobalFunction(type)) { - // handle show global functions - functions = new ArrayList<>(udfFunctions - .getOrDefault(functionRegistry.getGlobalFunctionDbName(), new HashMap<>()).keySet()); + functions = Env.getCurrentEnv().getGlobalFunctionMgr().getFunctions(); } else { Util.prohibitExternalCatalog(ctx.getDefaultCatalog(), this.getClass().getSimpleName()); DatabaseIf db = ctx.getCurrentCatalog().getDbOrAnalysisException(dbName); if (db instanceof Database) { - functions = new ArrayList<>(udfFunctions.getOrDefault(dbName, new HashMap<>()).keySet()); + functions = ((Database) db).getFunctions(); } } return functions; @@ -244,4 +246,102 @@ public R accept(PlanVisitor visitor, C context) { return visitor.visitShowFunctionsCommand(this, context); } + private String buildFunctionType(Function function) { + if (function instanceof AggregateFunction) { + return "AGGREGATE/" + function.getBinaryType(); + } + if (function.isUDTFunction()) { + return "UDTF/" + function.getBinaryType(); + } + if (function instanceof AliasFunction) { + return "ALIAS/" + function.getBinaryType(); + } + return "SCALAR/" + function.getBinaryType(); + } + + private String buildIntermediateType(Function function) { + if (function instanceof AggregateFunction) { + AggregateFunction aggregateFunction = (AggregateFunction) function; + return aggregateFunction.getIntermediateType() == null + ? "" + : aggregateFunction.getIntermediateType().toString(); + } + return ""; + } + + private String buildProperties(Function function) { + Map properties = new LinkedHashMap<>(); + if (function.getId() > 0) { + properties.put("ID", String.valueOf(function.getId())); + } + if (!Strings.isNullOrEmpty(function.getChecksum())) { + properties.put("CHECKSUM", function.getChecksum()); + } + if (function.getLocation() != null) { + String locationKey = function.getBinaryType() == null + || function.getBinaryType().name().startsWith("JAVA") + ? "FILE" + : "OBJECT_FILE"; + properties.put(locationKey, function.getLocation().toString()); + } + properties.put("NULLABLE_MODE", function.getNullableMode().name()); + if (function.isStaticLoad()) { + properties.put("STATIC_LOAD", String.valueOf(function.isStaticLoad())); + } + if (!Strings.isNullOrEmpty(function.getRuntimeVersion())) { + properties.put("RUNTIME_VERSION", function.getRuntimeVersion()); + } + + if (function instanceof ScalarFunction) { + ScalarFunction scalarFunction = (ScalarFunction) function; + properties.put("SYMBOL", Strings.nullToEmpty(scalarFunction.getSymbolName())); + if (scalarFunction.getPrepareFnSymbol() != null) { + properties.put("PREPARE_FN", scalarFunction.getPrepareFnSymbol()); + } + if (scalarFunction.getCloseFnSymbol() != null) { + properties.put("CLOSE_FN", scalarFunction.getCloseFnSymbol()); + } + } + + if (function instanceof AggregateFunction) { + AggregateFunction aggregateFunction = (AggregateFunction) function; + properties.put("INIT_FN", Strings.nullToEmpty(aggregateFunction.getInitFnSymbol())); + properties.put("UPDATE_FN", Strings.nullToEmpty(aggregateFunction.getUpdateFnSymbol())); + properties.put("MERGE_FN", Strings.nullToEmpty(aggregateFunction.getMergeFnSymbol())); + if (aggregateFunction.getSerializeFnSymbol() != null) { + properties.put("SERIALIZE_FN", aggregateFunction.getSerializeFnSymbol()); + } + if (aggregateFunction.getFinalizeFnSymbol() != null) { + properties.put("FINALIZE_FN", aggregateFunction.getFinalizeFnSymbol()); + } + if (aggregateFunction.getGetValueFnSymbol() != null) { + properties.put("GET_VALUE_FN", aggregateFunction.getGetValueFnSymbol()); + } + if (aggregateFunction.getRemoveFnSymbol() != null) { + properties.put("REMOVE_FN", aggregateFunction.getRemoveFnSymbol()); + } + if (aggregateFunction.getSymbolName() != null) { + properties.put("SYMBOL", aggregateFunction.getSymbolName()); + } + } + + if (function instanceof AliasFunction) { + AliasFunction aliasFunction = (AliasFunction) function; + properties.put("ALIAS_OF", aliasFunction.getOriginFunction().toSqlWithoutTbl()); + if (aliasFunction.getParameters() != null && !aliasFunction.getParameters().isEmpty()) { + properties.put("PARAMETERS", String.join(",", aliasFunction.getParameters())); + } + } + + // inline python UDF/UDTF/UDAF code + if (function.getBinaryType() != null && function.getBinaryType().name().contains("PYTHON") + && !Strings.isNullOrEmpty(function.getFunctionCode())) { + properties.put("INLINE_CODE", function.getFunctionCode()); + } + + return properties.entrySet().stream() + .map(entry -> entry.getKey() + "=" + entry.getValue()) + .collect(Collectors.joining(", ")); + } + } diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ShowFunctionsCommandTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ShowFunctionsCommandTest.java index 5825a57e74f841..ba42ef9c6e241c 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ShowFunctionsCommandTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ShowFunctionsCommandTest.java @@ -23,6 +23,7 @@ import org.apache.doris.catalog.AccessPrivilege; import org.apache.doris.catalog.AccessPrivilegeWithCols; import org.apache.doris.catalog.Env; +import org.apache.doris.catalog.Function; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.UserException; import org.apache.doris.mysql.privilege.Auth; @@ -59,13 +60,13 @@ void testGetFunctions() throws AnalysisException { // test for not builtin functions sf = new ShowFunctionsCommand("test", false, null); - List re2 = sf.getFunctions(connectContext); + List re2 = sf.getFunctions(connectContext); Assertions.assertEquals(1, re2.size()); - Assertions.assertEquals("test_for_create_function", re2.get(0)); + Assertions.assertEquals("test_for_create_function", re2.get(0).functionName()); // test for full not builtin functions sf = new ShowFunctionsCommand("test", true, null); - List re4 = sf.getFunctions(connectContext); + List re4 = sf.getFunctions(connectContext); Assertions.assertEquals(1, re4.size()); } @@ -75,7 +76,7 @@ void testGetResultRowSetByFunctions() throws AnalysisException { ShowFunctionsCommand sf; connectContext.setDatabase("test"); sf = new ShowFunctionsCommand("test", false, null); - List func2 = sf.getFunctions(connectContext); + List func2 = sf.getFunctions(connectContext); List> re2 = sf.getResultRowSetByFunctions(func2); Assertions.assertEquals(1, re2.get(0).size()); Assertions.assertEquals("test_for_create_function", re2.get(0).get(0)); @@ -83,26 +84,24 @@ void testGetResultRowSetByFunctions() throws AnalysisException { // test for full not builtin functions connectContext.setDatabase("test"); sf = new ShowFunctionsCommand("test", true, null); - List func4 = sf.getFunctions(connectContext); + List func4 = sf.getFunctions(connectContext); List> re4 = sf.getResultRowSetByFunctions(func4); Assertions.assertEquals(5, re4.get(0).size()); - Assertions.assertEquals("test_for_create_function", re4.get(0).get(0)); - Assertions.assertEquals("", re4.get(0).get(1)); - Assertions.assertEquals("", re4.get(0).get(2)); - Assertions.assertEquals("", re4.get(0).get(3)); - Assertions.assertEquals("", re4.get(0).get(4)); + Assertions.assertTrue(re4.get(0).get(0).startsWith("test_for_create_function")); + Assertions.assertFalse(re4.get(0).get(1).isEmpty()); + Assertions.assertFalse(re4.get(0).get(2).isEmpty()); + Assertions.assertFalse(re4.get(0).get(4).isEmpty()); // test for full not builtin functions with where condition String where = "test_for_create_function%"; sf = new ShowFunctionsCommand("test", true, where); - List func5 = sf.getFunctions(connectContext); + List func5 = sf.getFunctions(connectContext); List> re5 = sf.getResultRowSetByFunctions(func5); Assertions.assertEquals(5, re5.get(0).size()); - Assertions.assertEquals("test_for_create_function", re5.get(0).get(0)); - Assertions.assertEquals("", re5.get(0).get(1)); - Assertions.assertEquals("", re5.get(0).get(2)); - Assertions.assertEquals("", re5.get(0).get(3)); - Assertions.assertEquals("", re5.get(0).get(4)); + Assertions.assertTrue(re5.get(0).get(0).startsWith("test_for_create_function")); + Assertions.assertFalse(re5.get(0).get(1).isEmpty()); + Assertions.assertFalse(re5.get(0).get(2).isEmpty()); + Assertions.assertFalse(re5.get(0).get(4).isEmpty()); } @Test diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ShowGlobalFunctionsCommandTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ShowGlobalFunctionsCommandTest.java index fefa2e02578158..46d84957d5a63a 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ShowGlobalFunctionsCommandTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/plans/commands/ShowGlobalFunctionsCommandTest.java @@ -17,6 +17,7 @@ package org.apache.doris.nereids.trees.plans.commands; +import org.apache.doris.catalog.Function; import org.apache.doris.common.AnalysisException; import org.apache.doris.utframe.TestWithFeService; @@ -39,27 +40,27 @@ protected void runBeforeAll() throws Exception { void testGetFunctions() throws AnalysisException { // test for not global ShowFunctionsCommand sf = new ShowFunctionsCommand(false, null, false); - ShowFunctionsCommand finalSf = sf; - Assertions.assertThrows(AnalysisException.class, () -> finalSf.getFunctions(connectContext)); + List nonGlobal = sf.getFunctions(connectContext); + Assertions.assertTrue(nonGlobal.isEmpty()); // test for verbose connectContext.setDatabase("test"); sf = new ShowFunctionsCommand(true, null, true); - List re1 = sf.getFunctions(connectContext); + List re1 = sf.getFunctions(connectContext); Assertions.assertEquals(1, re1.size()); - Assertions.assertEquals("test_for_create_function", re1.get(0)); + Assertions.assertEquals("test_for_create_function", re1.get(0).functionName()); // test for no verbose sf = new ShowFunctionsCommand(false, null, true); - List re2 = sf.getFunctions(connectContext); + List re2 = sf.getFunctions(connectContext); Assertions.assertEquals(1, re2.size()); - Assertions.assertEquals("test_for_create_function", re2.get(0)); + Assertions.assertEquals("test_for_create_function", re2.get(0).functionName()); // test for like condition sf = new ShowFunctionsCommand(false, "test_for_create%", true); - List re3 = sf.getFunctions(connectContext); + List re3 = sf.getFunctions(connectContext); Assertions.assertEquals(1, re3.size()); - Assertions.assertEquals("test_for_create_function", re3.get(0)); + Assertions.assertEquals("test_for_create_function", re3.get(0).functionName()); } @Test @@ -67,17 +68,18 @@ void testGetResultRowSetByFunctions() throws AnalysisException { connectContext.setDatabase("test"); // test for verbose ShowFunctionsCommand sf = new ShowFunctionsCommand(true, null, true); - List func3 = sf.getFunctions(connectContext); + List func3 = sf.getFunctions(connectContext); List> re3 = sf.getResultRowSetByFunctions(func3); Assertions.assertEquals(1, re3.size()); - Assertions.assertEquals("", re3.get(0).get(1)); - Assertions.assertEquals("", re3.get(0).get(2)); - Assertions.assertEquals("", re3.get(0).get(3)); - Assertions.assertEquals("", re3.get(0).get(4)); + Assertions.assertEquals(5, re3.get(0).size()); + Assertions.assertTrue(re3.get(0).get(0).startsWith("test_for_create_function")); + Assertions.assertFalse(re3.get(0).get(1).isEmpty()); + Assertions.assertFalse(re3.get(0).get(2).isEmpty()); + Assertions.assertFalse(re3.get(0).get(4).isEmpty()); // test for not verbose sf = new ShowFunctionsCommand(false, null, true); - List func4 = sf.getFunctions(connectContext); + List func4 = sf.getFunctions(connectContext); List> re4 = sf.getResultRowSetByFunctions(func4); Assertions.assertEquals(1, re4.get(0).size()); Assertions.assertEquals("test_for_create_function", re4.get(0).get(0)); @@ -85,13 +87,12 @@ void testGetResultRowSetByFunctions() throws AnalysisException { // test for like condition String where = "test_for_create_function%"; sf = new ShowFunctionsCommand(true, where, true); - List func5 = sf.getFunctions(connectContext); + List func5 = sf.getFunctions(connectContext); List> re5 = sf.getResultRowSetByFunctions(func5); Assertions.assertEquals(5, re5.get(0).size()); - Assertions.assertEquals("test_for_create_function", re5.get(0).get(0)); - Assertions.assertEquals("", re5.get(0).get(1)); - Assertions.assertEquals("", re5.get(0).get(2)); - Assertions.assertEquals("", re5.get(0).get(3)); - Assertions.assertEquals("", re5.get(0).get(4)); + Assertions.assertTrue(re5.get(0).get(0).startsWith("test_for_create_function")); + Assertions.assertFalse(re5.get(0).get(1).isEmpty()); + Assertions.assertFalse(re5.get(0).get(2).isEmpty()); + Assertions.assertFalse(re5.get(0).get(4).isEmpty()); } } diff --git a/regression-test/suites/nereids_p0/show/test_nereids_show_functions.groovy b/regression-test/suites/nereids_p0/show/test_nereids_show_functions.groovy index 725d712bc3df5c..c4d39b849a069a 100644 --- a/regression-test/suites/nereids_p0/show/test_nereids_show_functions.groovy +++ b/regression-test/suites/nereids_p0/show/test_nereids_show_functions.groovy @@ -33,17 +33,19 @@ suite("test_nereids_show_functions") { def res = sql """show builtin functions like '%yow%';""" assertTrue(res.size() == 1) def res1 = sql """use ${dbName}; show functions;""" - assertTrue(res1.size() == 1) + assertTrue(res1.size() >= 1) def res2 = sql """use ${dbName}; show functions like '${functionName}%';""" assertTrue(res2.size() == 1) // in nereids, each column of 'show full functions' is empty string, except Signature. def res3 = sql """use ${dbName}; show full functions like '${functionName}%';""" assertTrue(res3.size() == 1) - assertEquals(res3.get(0).get(0), functionName) - assertEquals(res3.get(0).get(1), "") - assertEquals(res3.get(0).get(2), "") + assertEquals(res3.get(0).get(0), "zzzyyyxxx(int)") + assertEquals(res3.get(0).get(1), "varchar(65533)") + assertEquals(res3.get(0).get(2), "ALIAS/JAVA_UDF") assertEquals(res3.get(0).get(3), "") - assertEquals(res3.get(0).get(4), "") + assertTrue(res3[0][4].contains("ID=")) + assertTrue(res3[0][4].contains("NULLABLE_MODE=")) + assertTrue(res3[0][4].contains("ALIAS_OF=")) checkNereidsExecute("show builtin functions;") checkNereidsExecute("show builtin functions like 'ye%';") @@ -56,17 +58,19 @@ suite("test_nereids_show_functions") { def res4 = sql """show builtin functions like '%yow%';""" assertTrue(res4.size() == 1) def res5 = sql """show functions from ${dbName}""" - assertTrue(res5.size() == 1) + assertTrue(res5.size() >= 1) def res6 = sql """show functions from ${dbName} like '${functionName}%';""" assertTrue(res6.size() == 1) // in nereids, each column of 'show full functions' is empty string, except Signature. def res7 = sql """show full functions like '${functionName}%';""" assertTrue(res7.size() == 1) - assertEquals(res7.get(0).get(0), functionName) - assertEquals(res7.get(0).get(1), "") - assertEquals(res7.get(0).get(2), "") + assertEquals(res7.get(0).get(0), "zzzyyyxxx(int)") + assertEquals(res7.get(0).get(1), "varchar(65533)") + assertEquals(res7.get(0).get(2), "ALIAS/JAVA_UDF") assertEquals(res7.get(0).get(3), "") - assertEquals(res7.get(0).get(4), "") + assertTrue(res7[0][4].contains("ID=")) + assertTrue(res7[0][4].contains("NULLABLE_MODE=")) + assertTrue(res7[0][4].contains("ALIAS_OF=")) checkNereidsExecute("show builtin functions;") checkNereidsExecute("show builtin functions like 'ye%';") @@ -79,15 +83,114 @@ suite("test_nereids_show_functions") { def res8 = sql """show builtin functions like '%yow%';""" assertTrue(res8.size() == 1) def res9 = sql """show functions in ${dbName}""" - assertTrue(res9.size() == 1) + assertTrue(res9.size() >= 1) def res10 = sql """show functions in ${dbName} like '${functionName}%';""" assertTrue(res10.size() == 1) // in nereids, each column of 'show full functions' is empty string, except Signature. def res11 = sql """show full functions in ${dbName} like '${functionName}%';""" assertTrue(res11.size() == 1) - assertEquals(res11.get(0).get(0), functionName) - assertEquals(res11.get(0).get(1), "") - assertEquals(res11.get(0).get(2), "") + assertEquals(res11.get(0).get(0), "zzzyyyxxx(int)") + assertEquals(res11.get(0).get(1), "varchar(65533)") + assertEquals(res11.get(0).get(2), "ALIAS/JAVA_UDF") assertEquals(res11.get(0).get(3), "") - assertEquals(res11.get(0).get(4), "") + assertTrue(res11[0][4].contains("ID=")) + assertTrue(res11[0][4].contains("NULLABLE_MODE=")) + assertTrue(res11[0][4].contains("ALIAS_OF=")) + + def runtime_version = "3.8.10" + def suitePath = context.file.parent + "/../.." + + sql """ DROP FUNCTION IF EXISTS py_add(int, int) """ + sql """ CREATE FUNCTION py_add(INT, INT) + RETURNS INT + PROPERTIES ( + "type" = "PYTHON_UDF", + "symbol" = "evaluate", + "runtime_version" = "${runtime_version}" + ) + AS \$\$ + def evaluate(a, b): + return a + b + \$\$; + """ + def pyinline_res = sql """show full functions like 'py_add';""" + assertTrue(pyinline_res.size() == 1) + assertEquals("py_add(int, int)", pyinline_res[0][0]) + assertEquals("int", pyinline_res[0][1]) + assertEquals("SCALAR/PYTHON_UDF", pyinline_res[0][2]) + assertEquals("", pyinline_res[0][3]) + assertTrue(pyinline_res[0][4].contains("ID=")) + assertTrue(pyinline_res[0][4].contains("NULLABLE_MODE=ALWAYS_NULLABLE")) + assertTrue(pyinline_res[0][4].contains("RUNTIME_VERSION=${runtime_version}")) + assertTrue(pyinline_res[0][4].contains("SYMBOL=evaluate")) + assertTrue(pyinline_res[0][4].contains("INLINE_CODE=")) + + sql """ DROP FUNCTION IF EXISTS python_udf_int_test(int) """ + sql """ CREATE FUNCTION python_udf_int_test(int) RETURNS int PROPERTIES ( + "file"="file://${suitePath}/pythonudf_p0/udf_scripts/pyudf.zip", + "symbol"="int_test.evaluate", + "type"="PYTHON_UDF", + "always_nullable" = "true", + "runtime_version" = "${runtime_version}" + ); + """ + def pyudf_res = sql """show full functions like 'python_udf_int_test';""" + assertTrue(pyudf_res.size() == 1) + assertEquals("python_udf_int_test(int)", pyudf_res[0][0]) + assertEquals("int", pyudf_res[0][1]) + assertEquals("SCALAR/PYTHON_UDF", pyudf_res[0][2]) + assertEquals("", pyudf_res[0][3]) + assertTrue(pyudf_res[0][4].contains("ID=")) + assertTrue(pyudf_res[0][4].contains("CHECKSUM=")) + assertTrue(pyudf_res[0][4].contains("OBJECT_FILE=")) + assertTrue(pyudf_res[0][4].contains("pythonudf_p0/udf_scripts/pyudf.zip")) + assertTrue(pyudf_res[0][4].contains("NULLABLE_MODE=ALWAYS_NULLABLE")) + assertTrue(pyudf_res[0][4].contains("RUNTIME_VERSION=${runtime_version}")) + assertTrue(pyudf_res[0][4].contains("SYMBOL=int_test.evaluate")) + + sql """ DROP FUNCTION IF EXISTS python_udaf_sum_int(int) """ + sql """ CREATE AGGREGATE FUNCTION python_udaf_sum_int(int) RETURNS bigint PROPERTIES ( + "file"="file://${suitePath}/pythonudf_p0/udf_scripts/pyudf.zip", + "symbol"="sum_int.SumInt", + "type"="PYTHON_UDF", + "always_nullable" = "true", + "runtime_version" = "${runtime_version}" + ); + """ + def pyudaf_res = sql """show full functions like 'python_udaf_sum_int';""" + assertTrue(pyudaf_res.size() == 1) + assertEquals("python_udaf_sum_int(int)", pyudaf_res[0][0]) + assertEquals("bigint", pyudaf_res[0][1]) + assertEquals("AGGREGATE/PYTHON_UDF", pyudaf_res[0][2]) + assertTrue(pyudaf_res[0][4].contains("ID=")) + assertTrue(pyudaf_res[0][4].contains("CHECKSUM=")) + assertTrue(pyudaf_res[0][4].contains("OBJECT_FILE=")) + assertTrue(pyudaf_res[0][4].contains("pythonudf_p0/udf_scripts/pyudf.zip")) + assertTrue(pyudaf_res[0][4].contains("NULLABLE_MODE=ALWAYS_NULLABLE")) + assertTrue(pyudaf_res[0][4].contains("RUNTIME_VERSION=${runtime_version}")) + assertTrue(pyudaf_res[0][4].contains("SYMBOL=sum_int.SumInt")) + + sql """ DROP FUNCTION IF EXISTS py_split_string_module(STRING) """ + sql """CREATE TABLES FUNCTION py_split_string_module(STRING) + RETURNS ARRAY PROPERTIES ( + "file" = "file://${suitePath}/pythonudtf_p0/udtf_scripts/pyudtf.zip", + "symbol" = "pyudtf_module.basic_udtf.split_string_udtf", + "type" = "PYTHON_UDF", + "runtime_version" = "${runtime_version}" + ); + """ + def pyudtf_res = sql """show full functions like 'py_split_string_module';""" + assertTrue(pyudtf_res.size() == 1) + assertEquals("py_split_string_module(text)", pyudtf_res[0][0]) + assertEquals("text", pyudtf_res[0][1]) + assertEquals("UDTF/PYTHON_UDF", pyudtf_res[0][2]) + assertEquals("", pyudtf_res[0][3]) + assertTrue(pyudtf_res[0][4].contains("ID=")) + assertTrue(pyudtf_res[0][4].contains("CHECKSUM=")) + assertTrue(pyudtf_res[0][4].contains("OBJECT_FILE=")) + assertTrue(pyudtf_res[0][4].contains("pythonudtf_p0/udtf_scripts/pyudtf.zip")) + assertTrue(pyudtf_res[0][4].contains("NULLABLE_MODE=ALWAYS_NULLABLE")) + assertTrue(pyudtf_res[0][4].contains("RUNTIME_VERSION=${runtime_version}")) + assertTrue(pyudtf_res[0][4].contains("SYMBOL=pyudtf_module.basic_udtf.split_string_udtf")) + } diff --git a/regression-test/suites/nereids_p0/show/test_nereids_show_global_functions.groovy b/regression-test/suites/nereids_p0/show/test_nereids_show_global_functions.groovy index 4f14bcfc5cf8ba..6c58b379d6c649 100644 --- a/regression-test/suites/nereids_p0/show/test_nereids_show_global_functions.groovy +++ b/regression-test/suites/nereids_p0/show/test_nereids_show_global_functions.groovy @@ -19,6 +19,7 @@ suite("test_nereids_show_global_functions") { String dbName = "show_functions_db" String functionName = "global_xyz" + sql """DROP GLOBAL FUNCTION IF EXISTS ${functionName}(INT);""" sql "CREATE DATABASE IF NOT EXISTS ${dbName}" sql """CREATE global ALIAS FUNCTION ${functionName}(INT) WITH PARAMETER(id) AS CONCAT(LEFT(id, 3), '****', RIGHT(id, 4));""" @@ -34,10 +35,11 @@ suite("test_nereids_show_global_functions") { // in nereids, each column of 'show full functions' is empty string, except Signature. def res3 = sql """use ${dbName}; show global full functions like '${functionName}%';""" assertTrue(res3.size() == 1) - assertEquals(res3.get(0).get(0), functionName) - assertEquals(res3.get(0).get(1), "") - assertEquals(res3.get(0).get(2), "") + assertEquals(res3.get(0).get(0), "global_xyz(int)") + assertEquals(res3.get(0).get(1), "varchar(65533)") + assertEquals(res3.get(0).get(2), "ALIAS/JAVA_UDF") assertEquals(res3.get(0).get(3), "") - assertEquals(res3.get(0).get(4), "") + assertTrue(res3[0][4].contains("NULLABLE_MODE=")) + assertTrue(res3[0][4].contains("ALIAS_OF=")) sql """DROP GLOBAL FUNCTION ${functionName}(INT)""" }