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 1e1a223a11c [fix](multi-catalog)put java udf to custom lib (#34990) 1e1a223a11c is described below commit 1e1a223a11cd7992533ed9ba4d07583a4d7fb92c Author: slothever <18522955+w...@users.noreply.github.com> AuthorDate: Sun May 26 14:23:47 2024 +0800 [fix](multi-catalog)put java udf to custom lib (#34990) when use java udf , we can put its jars in custom_lib of FE and BE in advance, and then we can create function without file property: ``` CREATE FUNCTION java_udf_add_one(int) RETURNS int PROPERTIES ( "symbol"="org.apache.doris.udf.AddOne", "always_nullable"="true", "type"="JAVA_UDF" ); ``` and we can use file property for custom jar: ``` CREATE FUNCTION java_udf_add_one(int) RETURNS int PROPERTIES ( "file"="file:///path/to/java-udf-demo.jar", "symbol"="org.apache.doris.udf.AddOne", "always_nullable"="true", "type"="JAVA_UDF" ); ``` on FE, we use null location if the 'file' property is not set on BE, we get jar path if both file path location and checksum are null --- .../aggregate_function_java_udaf.h | 13 +- .../exprs/table_function/udf_table_function.cpp | 9 +- be/src/vec/functions/function_java_udf.cpp | 10 +- bin/start_fe.sh | 2 +- .../apache/doris/analysis/CreateFunctionStmt.java | 336 +++++----- .../trees/expressions/functions/udf/JavaUdaf.java | 4 +- .../trees/expressions/functions/udf/JavaUdf.java | 4 +- .../trees/expressions/functions/udf/JavaUdtf.java | 4 +- .../test_javaudaf_custom_lib_mysum_int.out | 20 + .../test_javaudf_custom_lib_all_types.out | 12 + .../test_javaudtf_custom_lib_all_types.out | 692 +++++++++++++++++++++ .../test_javaudaf_custom_lib_mysum_int.groovy | 64 ++ .../test_javaudf_custom_lib_all_types.groovy | 63 ++ .../test_javaudtf_custom_lib_all_types.groovy | 181 ++++++ run-regression-test.sh | 32 +- 15 files changed, 1272 insertions(+), 174 deletions(-) diff --git a/be/src/vec/aggregate_functions/aggregate_function_java_udaf.h b/be/src/vec/aggregate_functions/aggregate_function_java_udaf.h index 59711d513dd..d314cba7a65 100644 --- a/be/src/vec/aggregate_functions/aggregate_function_java_udaf.h +++ b/be/src/vec/aggregate_functions/aggregate_function_java_udaf.h @@ -95,8 +95,9 @@ public: { TJavaUdfExecutorCtorParams ctor_params; ctor_params.__set_fn(fn); - ctor_params.__set_location(local_location); - + if (!fn.hdfs_location.empty() && !fn.checksum.empty()) { + ctor_params.__set_location(local_location); + } jbyteArray ctor_params_bytes; // Pushed frame will be popped when jni_frame goes out-of-scope. @@ -274,7 +275,13 @@ public: //So need to check as soon as possible, before call Data function Status check_udaf(const TFunction& fn) { auto function_cache = UserFunctionCache::instance(); - return function_cache->get_jarpath(fn.id, fn.hdfs_location, fn.checksum, &_local_location); + // get jar path if both file path location and checksum are null + if (!fn.hdfs_location.empty() && !fn.checksum.empty()) { + return function_cache->get_jarpath(fn.id, fn.hdfs_location, fn.checksum, + &_local_location); + } else { + return Status::OK(); + } } void create(AggregateDataPtr __restrict place) const override { diff --git a/be/src/vec/exprs/table_function/udf_table_function.cpp b/be/src/vec/exprs/table_function/udf_table_function.cpp index 59111c8e88e..82e727b3f5d 100644 --- a/be/src/vec/exprs/table_function/udf_table_function.cpp +++ b/be/src/vec/exprs/table_function/udf_table_function.cpp @@ -57,11 +57,14 @@ Status UDFTableFunction::open() { { std::string local_location; auto* function_cache = UserFunctionCache::instance(); - RETURN_IF_ERROR(function_cache->get_jarpath(_t_fn.id, _t_fn.hdfs_location, _t_fn.checksum, - &local_location)); TJavaUdfExecutorCtorParams ctor_params; ctor_params.__set_fn(_t_fn); - ctor_params.__set_location(local_location); + if (!_t_fn.hdfs_location.empty() && !_t_fn.checksum.empty()) { + // get jar path if both file path location and checksum are null + RETURN_IF_ERROR(function_cache->get_jarpath(_t_fn.id, _t_fn.hdfs_location, + _t_fn.checksum, &local_location)); + ctor_params.__set_location(local_location); + } jbyteArray ctor_params_bytes; // Pushed frame will be popped when jni_frame goes out-of-scope. RETURN_IF_ERROR(jni_frame.push(env)); diff --git a/be/src/vec/functions/function_java_udf.cpp b/be/src/vec/functions/function_java_udf.cpp index dc367486dfc..c7e82bf96dc 100644 --- a/be/src/vec/functions/function_java_udf.cpp +++ b/be/src/vec/functions/function_java_udf.cpp @@ -55,11 +55,15 @@ Status JavaFunctionCall::open(FunctionContext* context, FunctionContext::Functio { std::string local_location; auto function_cache = UserFunctionCache::instance(); - RETURN_IF_ERROR(function_cache->get_jarpath(fn_.id, fn_.hdfs_location, fn_.checksum, - &local_location)); TJavaUdfExecutorCtorParams ctor_params; ctor_params.__set_fn(fn_); - ctor_params.__set_location(local_location); + // get jar path if both file path location and checksum are null + if (!fn_.hdfs_location.empty() && !fn_.checksum.empty()) { + RETURN_IF_ERROR(function_cache->get_jarpath(fn_.id, fn_.hdfs_location, fn_.checksum, + &local_location)); + ctor_params.__set_location(local_location); + } + jbyteArray ctor_params_bytes; // Pushed frame will be popped when jni_frame goes out-of-scope. diff --git a/bin/start_fe.sh b/bin/start_fe.sh index 733ad458c8d..9d51648ff4f 100755 --- a/bin/start_fe.sh +++ b/bin/start_fe.sh @@ -207,7 +207,7 @@ done # add custom_libs to CLASSPATH if [[ -d "${DORIS_HOME}/custom_lib" ]]; then for f in "${DORIS_HOME}/custom_lib"/*.jar; do - CLASSPATH="${f}:${CLASSPATH}" + CLASSPATH="${CLASSPATH}:${f}" done fi diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java index d5ce0d80424..ac00037c42c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateFunctionStmt.java @@ -263,10 +263,10 @@ public class CreateFunctionStmt extends DdlStmt { } userFile = properties.getOrDefault(FILE_KEY, properties.get(OBJECT_FILE_KEY)); - if (Strings.isNullOrEmpty(userFile)) { - throw new AnalysisException("No 'file' or 'object_file' in properties"); - } - if (binaryType != TFunctionBinaryType.RPC) { + // if (Strings.isNullOrEmpty(userFile)) { + // throw new AnalysisException("No 'file' or 'object_file' in properties"); + // } + if (!Strings.isNullOrEmpty(userFile) && binaryType != TFunctionBinaryType.RPC) { try { computeObjectChecksum(); } catch (IOException | NoSuchAlgorithmException e) { @@ -325,7 +325,12 @@ public class CreateFunctionStmt extends DdlStmt { throw new AnalysisException("JAVA_UDF OF UDTF return type must be array type"); } analyzeJavaUdf(symbol); - URI location = URI.create(userFile); + URI location; + if (!Strings.isNullOrEmpty(userFile)) { + location = URI.create(userFile); + } else { + location = null; + } function = ScalarFunction.createUdf(binaryType, functionName, argsDef.getArgTypes(), ((ArrayType) (returnType.getType())).getItemType(), argsDef.isVariadic(), @@ -340,10 +345,15 @@ public class CreateFunctionStmt extends DdlStmt { private void analyzeUda() throws AnalysisException { AggregateFunction.AggregateFunctionBuilder builder = AggregateFunction.AggregateFunctionBuilder.createUdfBuilder(); - + URI location; + if (!Strings.isNullOrEmpty(userFile)) { + location = URI.create(userFile); + } else { + location = null; + } builder.name(functionName).argsType(argsDef.getArgTypes()).retType(returnType.getType()) .hasVarArgs(argsDef.isVariadic()).intermediateType(intermediateType.getType()) - .location(URI.create(userFile)); + .location(location); String initFnSymbol = properties.get(INIT_KEY); if (initFnSymbol == null && !(binaryType == TFunctionBinaryType.JAVA_UDF || binaryType == TFunctionBinaryType.RPC)) { @@ -389,8 +399,6 @@ public class CreateFunctionStmt extends DdlStmt { function = builder.initFnSymbol(initFnSymbol).updateFnSymbol(updateFnSymbol).mergeFnSymbol(mergeFnSymbol) .serializeFnSymbol(serializeFnSymbol).finalizeFnSymbol(finalizeFnSymbol) .getValueFnSymbol(getValueFnSymbol).removeFnSymbol(removeFnSymbol).symbolName(symbol).build(); - - URI location = URI.create(userFile); function.setLocation(location); function.setBinaryType(binaryType); function.setChecksum(checksum); @@ -414,7 +422,12 @@ public class CreateFunctionStmt extends DdlStmt { } else if (binaryType == TFunctionBinaryType.JAVA_UDF) { analyzeJavaUdf(symbol); } - URI location = URI.create(userFile); + URI location; + if (!Strings.isNullOrEmpty(userFile)) { + location = URI.create(userFile); + } else { + location = null; + } function = ScalarFunction.createUdf(binaryType, functionName, argsDef.getArgTypes(), returnType.getType(), argsDef.isVariadic(), @@ -427,94 +440,18 @@ public class CreateFunctionStmt extends DdlStmt { HashMap<String, Method> allMethods = new HashMap<>(); try { + if (Strings.isNullOrEmpty(userFile)) { + try { + ClassLoader cl = this.getClass().getClassLoader(); + checkUdafClass(clazz, cl, allMethods); + return; + } catch (ClassNotFoundException e) { + throw new AnalysisException("Class [" + clazz + "] not found in classpath"); + } + } URL[] urls = {new URL("jar:" + userFile + "!/")}; try (URLClassLoader cl = URLClassLoader.newInstance(urls)) { - Class udfClass = cl.loadClass(clazz); - String udfClassName = udfClass.getCanonicalName(); - String stateClassName = udfClassName + "$" + STATE_CLASS_NAME; - Class stateClass = cl.loadClass(stateClassName); - - for (Method m : udfClass.getMethods()) { - if (!m.getDeclaringClass().equals(udfClass)) { - continue; - } - String name = m.getName(); - if (allMethods.containsKey(name)) { - throw new AnalysisException( - String.format("UDF class '%s' has multiple methods with name '%s' ", udfClassName, - name)); - } - allMethods.put(name, m); - } - - if (allMethods.get(CREATE_METHOD_NAME) == null) { - throw new AnalysisException( - String.format("No method '%s' in class '%s'!", CREATE_METHOD_NAME, udfClassName)); - } else { - checkMethodNonStaticAndPublic(CREATE_METHOD_NAME, allMethods.get(CREATE_METHOD_NAME), udfClassName); - checkArgumentCount(allMethods.get(CREATE_METHOD_NAME), 0, udfClassName); - checkReturnJavaType(udfClassName, allMethods.get(CREATE_METHOD_NAME), stateClass); - } - - if (allMethods.get(DESTROY_METHOD_NAME) == null) { - throw new AnalysisException( - String.format("No method '%s' in class '%s'!", DESTROY_METHOD_NAME, udfClassName)); - } else { - checkMethodNonStaticAndPublic(DESTROY_METHOD_NAME, allMethods.get(DESTROY_METHOD_NAME), - udfClassName); - checkArgumentCount(allMethods.get(DESTROY_METHOD_NAME), 1, udfClassName); - checkReturnJavaType(udfClassName, allMethods.get(DESTROY_METHOD_NAME), void.class); - } - - if (allMethods.get(ADD_METHOD_NAME) == null) { - throw new AnalysisException( - String.format("No method '%s' in class '%s'!", ADD_METHOD_NAME, udfClassName)); - } else { - checkMethodNonStaticAndPublic(ADD_METHOD_NAME, allMethods.get(ADD_METHOD_NAME), udfClassName); - checkArgumentCount(allMethods.get(ADD_METHOD_NAME), argsDef.getArgTypes().length + 1, udfClassName); - checkReturnJavaType(udfClassName, allMethods.get(ADD_METHOD_NAME), void.class); - for (int i = 0; i < argsDef.getArgTypes().length; i++) { - Parameter p = allMethods.get(ADD_METHOD_NAME).getParameters()[i + 1]; - checkUdfType(udfClass, allMethods.get(ADD_METHOD_NAME), argsDef.getArgTypes()[i], p.getType(), - p.getName()); - } - } - - if (allMethods.get(SERIALIZE_METHOD_NAME) == null) { - throw new AnalysisException( - String.format("No method '%s' in class '%s'!", SERIALIZE_METHOD_NAME, udfClassName)); - } else { - checkMethodNonStaticAndPublic(SERIALIZE_METHOD_NAME, allMethods.get(SERIALIZE_METHOD_NAME), - udfClassName); - checkArgumentCount(allMethods.get(SERIALIZE_METHOD_NAME), 2, udfClassName); - checkReturnJavaType(udfClassName, allMethods.get(SERIALIZE_METHOD_NAME), void.class); - } - - if (allMethods.get(MERGE_METHOD_NAME) == null) { - throw new AnalysisException( - String.format("No method '%s' in class '%s'!", MERGE_METHOD_NAME, udfClassName)); - } else { - checkMethodNonStaticAndPublic(MERGE_METHOD_NAME, allMethods.get(MERGE_METHOD_NAME), udfClassName); - checkArgumentCount(allMethods.get(MERGE_METHOD_NAME), 2, udfClassName); - checkReturnJavaType(udfClassName, allMethods.get(MERGE_METHOD_NAME), void.class); - } - - if (allMethods.get(GETVALUE_METHOD_NAME) == null) { - throw new AnalysisException( - String.format("No method '%s' in class '%s'!", GETVALUE_METHOD_NAME, udfClassName)); - } else { - checkMethodNonStaticAndPublic(GETVALUE_METHOD_NAME, allMethods.get(GETVALUE_METHOD_NAME), - udfClassName); - checkArgumentCount(allMethods.get(GETVALUE_METHOD_NAME), 1, udfClassName); - checkReturnUdfType(udfClass, allMethods.get(GETVALUE_METHOD_NAME), returnType.getType()); - } - - if (!Modifier.isPublic(stateClass.getModifiers()) || !Modifier.isStatic(stateClass.getModifiers())) { - throw new AnalysisException( - String.format( - "UDAF '%s' should have one public & static 'State' class to Construction data ", - udfClassName)); - } + checkUdafClass(clazz, cl, allMethods); } catch (ClassNotFoundException e) { throw new AnalysisException( "Class [" + clazz + "] or inner class [State] not found in file :" + userFile); @@ -526,6 +463,96 @@ public class CreateFunctionStmt extends DdlStmt { } } + private void checkUdafClass(String clazz, ClassLoader cl, HashMap<String, Method> allMethods) + throws ClassNotFoundException, AnalysisException { + Class udfClass = cl.loadClass(clazz); + String udfClassName = udfClass.getCanonicalName(); + String stateClassName = udfClassName + "$" + STATE_CLASS_NAME; + Class stateClass = cl.loadClass(stateClassName); + + for (Method m : udfClass.getMethods()) { + if (!m.getDeclaringClass().equals(udfClass)) { + continue; + } + String name = m.getName(); + if (allMethods.containsKey(name)) { + throw new AnalysisException( + String.format("UDF class '%s' has multiple methods with name '%s' ", udfClassName, + name)); + } + allMethods.put(name, m); + } + + if (allMethods.get(CREATE_METHOD_NAME) == null) { + throw new AnalysisException( + String.format("No method '%s' in class '%s'!", CREATE_METHOD_NAME, udfClassName)); + } else { + checkMethodNonStaticAndPublic(CREATE_METHOD_NAME, allMethods.get(CREATE_METHOD_NAME), udfClassName); + checkArgumentCount(allMethods.get(CREATE_METHOD_NAME), 0, udfClassName); + checkReturnJavaType(udfClassName, allMethods.get(CREATE_METHOD_NAME), stateClass); + } + + if (allMethods.get(DESTROY_METHOD_NAME) == null) { + throw new AnalysisException( + String.format("No method '%s' in class '%s'!", DESTROY_METHOD_NAME, udfClassName)); + } else { + checkMethodNonStaticAndPublic(DESTROY_METHOD_NAME, allMethods.get(DESTROY_METHOD_NAME), + udfClassName); + checkArgumentCount(allMethods.get(DESTROY_METHOD_NAME), 1, udfClassName); + checkReturnJavaType(udfClassName, allMethods.get(DESTROY_METHOD_NAME), void.class); + } + + if (allMethods.get(ADD_METHOD_NAME) == null) { + throw new AnalysisException( + String.format("No method '%s' in class '%s'!", ADD_METHOD_NAME, udfClassName)); + } else { + checkMethodNonStaticAndPublic(ADD_METHOD_NAME, allMethods.get(ADD_METHOD_NAME), udfClassName); + checkArgumentCount(allMethods.get(ADD_METHOD_NAME), argsDef.getArgTypes().length + 1, udfClassName); + checkReturnJavaType(udfClassName, allMethods.get(ADD_METHOD_NAME), void.class); + for (int i = 0; i < argsDef.getArgTypes().length; i++) { + Parameter p = allMethods.get(ADD_METHOD_NAME).getParameters()[i + 1]; + checkUdfType(udfClass, allMethods.get(ADD_METHOD_NAME), argsDef.getArgTypes()[i], p.getType(), + p.getName()); + } + } + + if (allMethods.get(SERIALIZE_METHOD_NAME) == null) { + throw new AnalysisException( + String.format("No method '%s' in class '%s'!", SERIALIZE_METHOD_NAME, udfClassName)); + } else { + checkMethodNonStaticAndPublic(SERIALIZE_METHOD_NAME, allMethods.get(SERIALIZE_METHOD_NAME), + udfClassName); + checkArgumentCount(allMethods.get(SERIALIZE_METHOD_NAME), 2, udfClassName); + checkReturnJavaType(udfClassName, allMethods.get(SERIALIZE_METHOD_NAME), void.class); + } + + if (allMethods.get(MERGE_METHOD_NAME) == null) { + throw new AnalysisException( + String.format("No method '%s' in class '%s'!", MERGE_METHOD_NAME, udfClassName)); + } else { + checkMethodNonStaticAndPublic(MERGE_METHOD_NAME, allMethods.get(MERGE_METHOD_NAME), udfClassName); + checkArgumentCount(allMethods.get(MERGE_METHOD_NAME), 2, udfClassName); + checkReturnJavaType(udfClassName, allMethods.get(MERGE_METHOD_NAME), void.class); + } + + if (allMethods.get(GETVALUE_METHOD_NAME) == null) { + throw new AnalysisException( + String.format("No method '%s' in class '%s'!", GETVALUE_METHOD_NAME, udfClassName)); + } else { + checkMethodNonStaticAndPublic(GETVALUE_METHOD_NAME, allMethods.get(GETVALUE_METHOD_NAME), + udfClassName); + checkArgumentCount(allMethods.get(GETVALUE_METHOD_NAME), 1, udfClassName); + checkReturnUdfType(udfClass, allMethods.get(GETVALUE_METHOD_NAME), returnType.getType()); + } + + if (!Modifier.isPublic(stateClass.getModifiers()) || !Modifier.isStatic(stateClass.getModifiers())) { + throw new AnalysisException( + String.format( + "UDAF '%s' should have one public & static 'State' class to Construction data ", + udfClassName)); + } + } + private void checkMethodNonStaticAndPublic(String methoName, Method method, String udfClassName) throws AnalysisException { if (Modifier.isStatic(method.getModifiers())) { @@ -565,60 +592,18 @@ public class CreateFunctionStmt extends DdlStmt { private void analyzeJavaUdf(String clazz) throws AnalysisException { try { + if (Strings.isNullOrEmpty(userFile)) { + try { + ClassLoader cl = this.getClass().getClassLoader(); + checkUdfClass(clazz, cl); + return; + } catch (ClassNotFoundException e) { + throw new AnalysisException("Class [" + clazz + "] not found in classpath"); + } + } URL[] urls = {new URL("jar:" + userFile + "!/")}; try (URLClassLoader cl = URLClassLoader.newInstance(urls)) { - Class udfClass = cl.loadClass(clazz); - List<Method> evalList = Arrays.stream(udfClass.getMethods()) - .filter(m -> m.getDeclaringClass().equals(udfClass) && EVAL_METHOD_KEY.equals(m.getName())) - .collect(Collectors.toList()); - if (evalList.size() == 0) { - throw new AnalysisException(String.format( - "No method '%s' in class '%s'!", EVAL_METHOD_KEY, udfClass.getCanonicalName())); - } - List<Method> evalNonStaticAndPublicList = evalList.stream() - .filter(m -> !Modifier.isStatic(m.getModifiers()) && Modifier.isPublic(m.getModifiers())) - .collect(Collectors.toList()); - if (evalNonStaticAndPublicList.size() == 0) { - throw new AnalysisException( - String.format("Method '%s' in class '%s' should be non-static and public", EVAL_METHOD_KEY, - udfClass.getCanonicalName())); - } - List<Method> evalArgLengthMatchList = evalNonStaticAndPublicList.stream().filter( - m -> m.getParameters().length == argsDef.getArgTypes().length).collect(Collectors.toList()); - if (evalArgLengthMatchList.size() == 0) { - throw new AnalysisException( - String.format("The number of parameters for method '%s' in class '%s' should be %d", - EVAL_METHOD_KEY, udfClass.getCanonicalName(), argsDef.getArgTypes().length)); - } else if (evalArgLengthMatchList.size() == 1) { - Method method = evalArgLengthMatchList.get(0); - checkUdfType(udfClass, method, returnType.getType(), method.getReturnType(), "return"); - for (int i = 0; i < method.getParameters().length; i++) { - Parameter p = method.getParameters()[i]; - checkUdfType(udfClass, method, argsDef.getArgTypes()[i], p.getType(), p.getName()); - } - } else { - // If multiple methods have the same parameters, - // the error message returned cannot be as specific as a single method - boolean hasError = false; - for (Method method : evalArgLengthMatchList) { - try { - checkUdfType(udfClass, method, returnType.getType(), method.getReturnType(), "return"); - for (int i = 0; i < method.getParameters().length; i++) { - Parameter p = method.getParameters()[i]; - checkUdfType(udfClass, method, argsDef.getArgTypes()[i], p.getType(), p.getName()); - } - hasError = false; - break; - } catch (AnalysisException e) { - hasError = true; - } - } - if (hasError) { - throw new AnalysisException(String.format( - "Multi methods '%s' in class '%s' and no one passed parameter matching verification", - EVAL_METHOD_KEY, udfClass.getCanonicalName())); - } - } + checkUdfClass(clazz, cl); } catch (ClassNotFoundException e) { throw new AnalysisException("Class [" + clazz + "] not found in file :" + userFile); } catch (IOException e) { @@ -629,6 +614,61 @@ public class CreateFunctionStmt extends DdlStmt { } } + private void checkUdfClass(String clazz, ClassLoader cl) throws ClassNotFoundException, AnalysisException { + Class udfClass = cl.loadClass(clazz); + List<Method> evalList = Arrays.stream(udfClass.getMethods()) + .filter(m -> m.getDeclaringClass().equals(udfClass) && EVAL_METHOD_KEY.equals(m.getName())) + .collect(Collectors.toList()); + if (evalList.size() == 0) { + throw new AnalysisException(String.format( + "No method '%s' in class '%s'!", EVAL_METHOD_KEY, udfClass.getCanonicalName())); + } + List<Method> evalNonStaticAndPublicList = evalList.stream() + .filter(m -> !Modifier.isStatic(m.getModifiers()) && Modifier.isPublic(m.getModifiers())) + .collect(Collectors.toList()); + if (evalNonStaticAndPublicList.size() == 0) { + throw new AnalysisException( + String.format("Method '%s' in class '%s' should be non-static and public", EVAL_METHOD_KEY, + udfClass.getCanonicalName())); + } + List<Method> evalArgLengthMatchList = evalNonStaticAndPublicList.stream().filter( + m -> m.getParameters().length == argsDef.getArgTypes().length).collect(Collectors.toList()); + if (evalArgLengthMatchList.size() == 0) { + throw new AnalysisException( + String.format("The number of parameters for method '%s' in class '%s' should be %d", + EVAL_METHOD_KEY, udfClass.getCanonicalName(), argsDef.getArgTypes().length)); + } else if (evalArgLengthMatchList.size() == 1) { + Method method = evalArgLengthMatchList.get(0); + checkUdfType(udfClass, method, returnType.getType(), method.getReturnType(), "return"); + for (int i = 0; i < method.getParameters().length; i++) { + Parameter p = method.getParameters()[i]; + checkUdfType(udfClass, method, argsDef.getArgTypes()[i], p.getType(), p.getName()); + } + } else { + // If multiple methods have the same parameters, + // the error message returned cannot be as specific as a single method + boolean hasError = false; + for (Method method : evalArgLengthMatchList) { + try { + checkUdfType(udfClass, method, returnType.getType(), method.getReturnType(), "return"); + for (int i = 0; i < method.getParameters().length; i++) { + Parameter p = method.getParameters()[i]; + checkUdfType(udfClass, method, argsDef.getArgTypes()[i], p.getType(), p.getName()); + } + hasError = false; + break; + } catch (AnalysisException e) { + hasError = true; + } + } + if (hasError) { + throw new AnalysisException(String.format( + "Multi methods '%s' in class '%s' and no one passed parameter matching verification", + EVAL_METHOD_KEY, udfClass.getCanonicalName())); + } + } + } + private void checkUdfType(Class clazz, Method method, Type expType, Class pType, String pname) throws AnalysisException { Set<Class> javaTypes; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdaf.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdaf.java index 4fbce8b94a3..27cf22b73b2 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdaf.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdaf.java @@ -151,7 +151,7 @@ public class JavaUdaf extends AggregateFunction implements ExplicitlyCastableSig JavaUdaf udaf = new JavaUdaf(fnName, aggregate.getId(), dbName, aggregate.getBinaryType(), sig, intermediateType, aggregate.getNullableMode(), - aggregate.getLocation().getLocation(), + aggregate.getLocation() == null ? null : aggregate.getLocation().getLocation(), aggregate.getSymbolName(), aggregate.getInitFnSymbol(), aggregate.getUpdateFnSymbol(), @@ -182,7 +182,7 @@ public class JavaUdaf extends AggregateFunction implements ExplicitlyCastableSig signature.returnType.toCatalogDataType(), signature.hasVarArgs, intermediateType.toCatalogDataType(), - URI.create(objectFile), + objectFile == null ? null : URI.create(objectFile), initFn, updateFn, mergeFn, diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdf.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdf.java index 90d27481cf4..3ed770e12ed 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdf.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdf.java @@ -129,7 +129,7 @@ public class JavaUdf extends ScalarFunction implements ExplicitlyCastableSignatu JavaUdf udf = new JavaUdf(fnName, scalar.getId(), dbName, scalar.getBinaryType(), sig, scalar.getNullableMode(), - scalar.getLocation().getLocation(), + scalar.getLocation() == null ? null : scalar.getLocation().getLocation(), scalar.getSymbolName(), scalar.getPrepareFnSymbol(), scalar.getCloseFnSymbol(), @@ -154,7 +154,7 @@ public class JavaUdf extends ScalarFunction implements ExplicitlyCastableSignatu signature.argumentsTypes.stream().map(DataType::toCatalogDataType).toArray(Type[]::new), signature.returnType.toCatalogDataType(), signature.hasVarArgs, - URI.create(objectFile), + objectFile == null ? null : URI.create(objectFile), symbol, prepareFn, closeFn diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdtf.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdtf.java index 48bf65edc57..96ea02bf2b7 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdtf.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/JavaUdtf.java @@ -111,7 +111,7 @@ public class JavaUdtf extends TableGeneratingFunction implements ExplicitlyCasta signature.argumentsTypes.stream().map(DataType::toCatalogDataType).toArray(Type[]::new), signature.returnType.toCatalogDataType(), signature.hasVarArgs, - URI.create(objectFile), + objectFile == null ? null : URI.create(objectFile), symbol, prepareFn, closeFn @@ -148,7 +148,7 @@ public class JavaUdtf extends TableGeneratingFunction implements ExplicitlyCasta JavaUdtf udf = new JavaUdtf(fnName, scalar.getId(), dbName, scalar.getBinaryType(), sig, scalar.getNullableMode(), - scalar.getLocation().getLocation(), + scalar.getLocation() == null ? null : scalar.getLocation().getLocation(), scalar.getSymbolName(), scalar.getPrepareFnSymbol(), scalar.getCloseFnSymbol(), diff --git a/regression-test/data/javaudf_p0/test_javaudaf_custom_lib_mysum_int.out b/regression-test/data/javaudf_p0/test_javaudaf_custom_lib_mysum_int.out new file mode 100644 index 00000000000..f2404c94be5 --- /dev/null +++ b/regression-test/data/javaudf_p0/test_javaudaf_custom_lib_mysum_int.out @@ -0,0 +1,20 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !select_default -- +1 1 abcdefg1 poiuytre1abcdefg +2 2 abcdefg2 poiuytre2abcdefg +0 3 abcdefg3 poiuytre3abcdefg +1 4 abcdefg4 poiuytre4abcdefg +2 5 abcdefg5 poiuytre5abcdefg +0 6 abcdefg6 poiuytre6abcdefg +1 7 abcdefg7 poiuytre7abcdefg +2 8 abcdefg8 poiuytre8abcdefg +9 9 abcdefg9 poiuytre9abcdefg + +-- !select1 -- +18 + +-- !select2 -- +0 0 +1 3 +2 6 +9 9 diff --git a/regression-test/data/javaudf_p0/test_javaudf_custom_lib_all_types.out b/regression-test/data/javaudf_p0/test_javaudf_custom_lib_all_types.out new file mode 100644 index 00000000000..46f207a5bca --- /dev/null +++ b/regression-test/data/javaudf_p0/test_javaudf_custom_lib_all_types.out @@ -0,0 +1,12 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !java_udf_all_types -- +1 1 +2 2 +3 3 +4 4 +5 5 +6 6 +7 7 +8 8 +9 9 +10 10 diff --git a/regression-test/data/javaudf_p0/test_javaudtf_custom_lib_all_types.out b/regression-test/data/javaudf_p0/test_javaudtf_custom_lib_all_types.out new file mode 100644 index 00000000000..e59b67adcc5 --- /dev/null +++ b/regression-test/data/javaudf_p0/test_javaudtf_custom_lib_all_types.out @@ -0,0 +1,692 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !select -- +\N \N \N \N \N \N \N \N \N \N \N \N \N \N +1 true 1 2 3 4 3.3300 7.77 3.1415 2023-10-18 2023-10-11T10:11:11.234 row1 [null, "nested1"] {"k1":null, "k2":"value1"} +2 false 2 4 6 8 1.6650 3.885 1.57075 2023-10-19 2023-10-12T10:12:11.234 row2 [null, "nested2"] {"k2":null, "k3":"value2"} +3 true 3 6 9 12 1.1100 2.59 1.04717 2023-10-20 2023-10-13T10:13:11.234 row3 [null, "nested3"] {"k3":null, "k4":"value3"} +4 false 4 8 12 16 0.8325 1.943 0.78538 2023-10-21 2023-10-14T10:14:11.234 row4 [null, "nested4"] {"k4":null, "k5":"value4"} +5 true 5 10 15 20 0.6660 1.554 0.6283 2023-10-22 2023-10-15T10:15:11.234 row5 [null, "nested5"] {"k5":null, "k6":"value5"} +6 false 6 12 18 24 0.5550 1.295 0.52358 2023-10-23 2023-10-16T10:16:11.234 row6 [null, "nested6"] {"k6":null, "k7":"value6"} +7 true 7 14 21 28 0.4757 1.11 0.44879 2023-10-24 2023-10-17T10:17:11.234 row7 [null, "nested7"] {"k7":null, "k8":"value7"} +8 false 8 16 24 32 0.4163 0.971 0.39269 2023-10-25 2023-10-18T10:18:11.234 row8 [null, "nested8"] {"k8":null, "k9":"value8"} +9 true 9 18 27 36 0.3700 0.863 0.34906 2023-10-26 2023-10-19T10:19:11.234 row9 [null, "nested9"] {"k9":null, "k10":"value9"} +10 false \N 20 30 40 \N 0.777 0.31415 \N 2023-10-20T10:10:11.234 \N [null, "nested10"] {"k10":null, "k11":"value10"} + +-- !select_boolean_col -- +1 true true +2 false false +2 false true +3 true false +3 true true +3 true true +4 false false +4 false false +4 false true +4 false true +5 true false +5 true false +5 true true +5 true true +5 true true +6 false false +6 false false +6 false false +6 false true +6 false true +6 false true +7 true false +7 true false +7 true false +7 true true +7 true true +7 true true +7 true true +8 false false +8 false false +8 false false +8 false false +8 false true +8 false true +8 false true +8 false true +9 true false +9 true false +9 true false +9 true false +9 true true +9 true true +9 true true +9 true true +9 true true +10 false false +10 false false +10 false false +10 false false +10 false false +10 false true +10 false true +10 false true +10 false true +10 false true + +-- !select_tinyint_col -- +1 1 1 +2 2 2 +2 2 3 +3 3 3 +3 3 4 +3 3 5 +4 4 4 +4 4 5 +4 4 6 +4 4 7 +5 5 5 +5 5 6 +5 5 7 +5 5 8 +5 5 9 +6 6 6 +6 6 7 +6 6 8 +6 6 9 +6 6 10 +6 6 11 +7 7 7 +7 7 8 +7 7 9 +7 7 10 +7 7 11 +7 7 12 +7 7 13 +8 8 8 +8 8 9 +8 8 10 +8 8 11 +8 8 12 +8 8 13 +8 8 14 +8 8 15 +9 9 9 +9 9 10 +9 9 11 +9 9 12 +9 9 13 +9 9 14 +9 9 15 +9 9 16 +9 9 17 + +-- !select_smallint_col -- +1 2 2 +2 4 4 +2 4 6 +3 6 6 +3 6 8 +3 6 10 +4 8 8 +4 8 10 +4 8 12 +4 8 14 +5 10 10 +5 10 12 +5 10 14 +5 10 16 +5 10 18 +6 12 12 +6 12 14 +6 12 16 +6 12 18 +6 12 20 +6 12 22 +7 14 14 +7 14 16 +7 14 18 +7 14 20 +7 14 22 +7 14 24 +7 14 26 +8 16 16 +8 16 18 +8 16 20 +8 16 22 +8 16 24 +8 16 26 +8 16 28 +8 16 30 +9 18 18 +9 18 20 +9 18 22 +9 18 24 +9 18 26 +9 18 28 +9 18 30 +9 18 32 +9 18 34 +10 20 20 +10 20 22 +10 20 24 +10 20 26 +10 20 28 +10 20 30 +10 20 32 +10 20 34 +10 20 36 +10 20 38 + +-- !select_int_col -- +1 1 1 +2 2 2 +2 2 5 +3 3 3 +3 3 6 +3 3 9 +4 4 4 +4 4 7 +4 4 10 +4 4 13 +5 5 5 +5 5 8 +5 5 11 +5 5 14 +5 5 17 +6 6 6 +6 6 9 +6 6 12 +6 6 15 +6 6 18 +6 6 21 +7 7 7 +7 7 10 +7 7 13 +7 7 16 +7 7 19 +7 7 22 +7 7 25 +8 8 8 +8 8 11 +8 8 14 +8 8 17 +8 8 20 +8 8 23 +8 8 26 +8 8 29 +9 9 9 +9 9 12 +9 9 15 +9 9 18 +9 9 21 +9 9 24 +9 9 27 +9 9 30 +9 9 33 +10 10 10 +10 10 13 +10 10 16 +10 10 19 +10 10 22 +10 10 25 +10 10 28 +10 10 31 +10 10 34 +10 10 37 + +-- !select_bigint_col -- +1 3 3 +2 6 6 +2 6 10 +3 9 9 +3 9 13 +3 9 17 +4 12 12 +4 12 16 +4 12 20 +4 12 24 +5 15 15 +5 15 19 +5 15 23 +5 15 27 +5 15 31 +6 18 18 +6 18 22 +6 18 26 +6 18 30 +6 18 34 +6 18 38 +7 21 21 +7 21 25 +7 21 29 +7 21 33 +7 21 37 +7 21 41 +7 21 45 +8 24 24 +8 24 28 +8 24 32 +8 24 36 +8 24 40 +8 24 44 +8 24 48 +8 24 52 +9 27 27 +9 27 31 +9 27 35 +9 27 39 +9 27 43 +9 27 47 +9 27 51 +9 27 55 +9 27 59 +10 30 30 +10 30 34 +10 30 38 +10 30 42 +10 30 46 +10 30 50 +10 30 54 +10 30 58 +10 30 62 +10 30 66 + +-- !select_largeint_col -- +1 4 4 +2 8 8 +2 8 13 +3 12 12 +3 12 17 +3 12 22 +4 16 16 +4 16 21 +4 16 26 +4 16 31 +5 20 20 +5 20 25 +5 20 30 +5 20 35 +5 20 40 +6 24 24 +6 24 29 +6 24 34 +6 24 39 +6 24 44 +6 24 49 +7 28 28 +7 28 33 +7 28 38 +7 28 43 +7 28 48 +7 28 53 +7 28 58 +8 32 32 +8 32 37 +8 32 42 +8 32 47 +8 32 52 +8 32 57 +8 32 62 +8 32 67 +9 36 36 +9 36 41 +9 36 46 +9 36 51 +9 36 56 +9 36 61 +9 36 66 +9 36 71 +9 36 76 +10 40 40 +10 40 45 +10 40 50 +10 40 55 +10 40 60 +10 40 65 +10 40 70 +10 40 75 +10 40 80 +10 40 85 + +-- !select_decimal_col -- +1 3.3300 3.3300 +2 1.6650 1.6650 +2 1.6650 1.6660 +3 1.1100 1.1100 +3 1.1100 1.1110 +3 1.1100 1.1120 +4 0.8325 0.8325 +4 0.8325 0.8335 +4 0.8325 0.8345 +4 0.8325 0.8355 +5 0.6660 0.6660 +5 0.6660 0.6670 +5 0.6660 0.6680 +5 0.6660 0.6690 +5 0.6660 0.6700 +6 0.5550 0.5550 +6 0.5550 0.5560 +6 0.5550 0.5570 +6 0.5550 0.5580 +6 0.5550 0.5590 +6 0.5550 0.5600 +7 0.4757 0.4757 +7 0.4757 0.4767 +7 0.4757 0.4777 +7 0.4757 0.4787 +7 0.4757 0.4797 +7 0.4757 0.4807 +7 0.4757 0.4817 +8 0.4163 0.4163 +8 0.4163 0.4173 +8 0.4163 0.4183 +8 0.4163 0.4193 +8 0.4163 0.4203 +8 0.4163 0.4213 +8 0.4163 0.4223 +8 0.4163 0.4233 +9 0.3700 0.3700 +9 0.3700 0.3710 +9 0.3700 0.3720 +9 0.3700 0.3730 +9 0.3700 0.3740 +9 0.3700 0.3750 +9 0.3700 0.3760 +9 0.3700 0.3770 +9 0.3700 0.3780 + +-- !select_float_col -- +1 7.77 7.77 +2 3.885 3.885 +2 3.885 3.985 +3 2.59 2.59 +3 2.59 2.6899998 +3 2.59 2.79 +4 1.943 1.943 +4 1.943 2.043 +4 1.943 2.143 +4 1.943 2.243 +5 1.554 1.554 +5 1.554 1.654 +5 1.554 1.7540001 +5 1.554 1.854 +5 1.554 1.954 +6 1.295 1.295 +6 1.295 1.395 +6 1.295 1.495 +6 1.295 1.5949999 +6 1.295 1.6949999 +6 1.295 1.795 +7 1.11 1.11 +7 1.11 1.21 +7 1.11 1.3100001 +7 1.11 1.41 +7 1.11 1.51 +7 1.11 1.61 +7 1.11 1.71 +8 0.971 0.971 +8 0.971 1.071 +8 0.971 1.171 +8 0.971 1.271 +8 0.971 1.371 +8 0.971 1.471 +8 0.971 1.571 +8 0.971 1.671 +9 0.863 0.863 +9 0.863 0.963 +9 0.863 1.063 +9 0.863 1.163 +9 0.863 1.263 +9 0.863 1.3629999 +9 0.863 1.4629999 +9 0.863 1.563 +9 0.863 1.663 +10 0.777 0.777 +10 0.777 0.87700003 +10 0.777 0.977 +10 0.777 1.077 +10 0.777 1.177 +10 0.777 1.277 +10 0.777 1.377 +10 0.777 1.477 +10 0.777 1.577 +10 0.777 1.677 + +-- !select_double_col -- +1 3.1415 3.1415 +2 1.57075 1.57075 +2 1.57075 1.58075 +3 1.04717 1.04717 +3 1.04717 1.05717 +3 1.04717 1.06717 +4 0.78538 0.78538 +4 0.78538 0.79538 +4 0.78538 0.80538 +4 0.78538 0.81538 +5 0.6283 0.6283 +5 0.6283 0.6383 +5 0.6283 0.6483 +5 0.6283 0.6583 +5 0.6283 0.6683 +6 0.52358 0.52358 +6 0.52358 0.53358 +6 0.52358 0.5435800000000001 +6 0.52358 0.5535800000000001 +6 0.52358 0.5635800000000001 +6 0.52358 0.5735800000000001 +7 0.44879 0.44879 +7 0.44879 0.45879000000000003 +7 0.44879 0.46879000000000004 +7 0.44879 0.47879000000000005 +7 0.44879 0.48879 +7 0.44879 0.49879 +7 0.44879 0.5087900000000001 +8 0.39269 0.39269 +8 0.39269 0.40269 +8 0.39269 0.41269 +8 0.39269 0.42269 +8 0.39269 0.43268999999999996 +8 0.39269 0.44269 +8 0.39269 0.45269 +8 0.39269 0.46269 +9 0.34906 0.34906 +9 0.34906 0.35906 +9 0.34906 0.36906 +9 0.34906 0.37905999999999995 +9 0.34906 0.38905999999999996 +9 0.34906 0.39905999999999997 +9 0.34906 0.40906 +9 0.34906 0.41906 +9 0.34906 0.42906 +10 0.31415 0.31415 +10 0.31415 0.32415 +10 0.31415 0.33415 +10 0.31415 0.34414999999999996 +10 0.31415 0.35414999999999996 +10 0.31415 0.36415 +10 0.31415 0.37415 +10 0.31415 0.38415 +10 0.31415 0.39415 +10 0.31415 0.40415 + +-- !select_date_col -- +1 2023-10-18 2023-10-18 +2 2023-10-19 2023-10-19 +2 2023-10-19 2023-11-19 +3 2023-10-20 2023-10-20 +3 2023-10-20 2023-11-20 +3 2023-10-20 2023-12-20 +4 2023-10-21 2023-10-21 +4 2023-10-21 2023-11-21 +4 2023-10-21 2023-12-21 +4 2023-10-21 2024-01-21 +5 2023-10-22 2023-10-22 +5 2023-10-22 2023-11-22 +5 2023-10-22 2023-12-22 +5 2023-10-22 2024-01-22 +5 2023-10-22 2024-02-22 +6 2023-10-23 2023-10-23 +6 2023-10-23 2023-11-23 +6 2023-10-23 2023-12-23 +6 2023-10-23 2024-01-23 +6 2023-10-23 2024-02-23 +6 2023-10-23 2024-03-23 +7 2023-10-24 2023-10-24 +7 2023-10-24 2023-11-24 +7 2023-10-24 2023-12-24 +7 2023-10-24 2024-01-24 +7 2023-10-24 2024-02-24 +7 2023-10-24 2024-03-24 +7 2023-10-24 2024-04-24 +8 2023-10-25 2023-10-25 +8 2023-10-25 2023-11-25 +8 2023-10-25 2023-12-25 +8 2023-10-25 2024-01-25 +8 2023-10-25 2024-02-25 +8 2023-10-25 2024-03-25 +8 2023-10-25 2024-04-25 +8 2023-10-25 2024-05-25 +9 2023-10-26 2023-10-26 +9 2023-10-26 2023-11-26 +9 2023-10-26 2023-12-26 +9 2023-10-26 2024-01-26 +9 2023-10-26 2024-02-26 +9 2023-10-26 2024-03-26 +9 2023-10-26 2024-04-26 +9 2023-10-26 2024-05-26 +9 2023-10-26 2024-06-26 + +-- !select_datetime_col -- +1 2023-10-11T10:11:11.234 2023-10-11T10:11:11.234 +2 2023-10-12T10:12:11.234 2023-10-12T10:12:11.234 +2 2023-10-12T10:12:11.234 2023-10-13T10:12:11.234 +3 2023-10-13T10:13:11.234 2023-10-13T10:13:11.234 +3 2023-10-13T10:13:11.234 2023-10-14T10:13:11.234 +3 2023-10-13T10:13:11.234 2023-10-15T10:13:11.234 +4 2023-10-14T10:14:11.234 2023-10-14T10:14:11.234 +4 2023-10-14T10:14:11.234 2023-10-15T10:14:11.234 +4 2023-10-14T10:14:11.234 2023-10-16T10:14:11.234 +4 2023-10-14T10:14:11.234 2023-10-17T10:14:11.234 +5 2023-10-15T10:15:11.234 2023-10-15T10:15:11.234 +5 2023-10-15T10:15:11.234 2023-10-16T10:15:11.234 +5 2023-10-15T10:15:11.234 2023-10-17T10:15:11.234 +5 2023-10-15T10:15:11.234 2023-10-18T10:15:11.234 +5 2023-10-15T10:15:11.234 2023-10-19T10:15:11.234 +6 2023-10-16T10:16:11.234 2023-10-16T10:16:11.234 +6 2023-10-16T10:16:11.234 2023-10-17T10:16:11.234 +6 2023-10-16T10:16:11.234 2023-10-18T10:16:11.234 +6 2023-10-16T10:16:11.234 2023-10-19T10:16:11.234 +6 2023-10-16T10:16:11.234 2023-10-20T10:16:11.234 +6 2023-10-16T10:16:11.234 2023-10-21T10:16:11.234 +7 2023-10-17T10:17:11.234 2023-10-17T10:17:11.234 +7 2023-10-17T10:17:11.234 2023-10-18T10:17:11.234 +7 2023-10-17T10:17:11.234 2023-10-19T10:17:11.234 +7 2023-10-17T10:17:11.234 2023-10-20T10:17:11.234 +7 2023-10-17T10:17:11.234 2023-10-21T10:17:11.234 +7 2023-10-17T10:17:11.234 2023-10-22T10:17:11.234 +7 2023-10-17T10:17:11.234 2023-10-23T10:17:11.234 +8 2023-10-18T10:18:11.234 2023-10-18T10:18:11.234 +8 2023-10-18T10:18:11.234 2023-10-19T10:18:11.234 +8 2023-10-18T10:18:11.234 2023-10-20T10:18:11.234 +8 2023-10-18T10:18:11.234 2023-10-21T10:18:11.234 +8 2023-10-18T10:18:11.234 2023-10-22T10:18:11.234 +8 2023-10-18T10:18:11.234 2023-10-23T10:18:11.234 +8 2023-10-18T10:18:11.234 2023-10-24T10:18:11.234 +8 2023-10-18T10:18:11.234 2023-10-25T10:18:11.234 +9 2023-10-19T10:19:11.234 2023-10-19T10:19:11.234 +9 2023-10-19T10:19:11.234 2023-10-20T10:19:11.234 +9 2023-10-19T10:19:11.234 2023-10-21T10:19:11.234 +9 2023-10-19T10:19:11.234 2023-10-22T10:19:11.234 +9 2023-10-19T10:19:11.234 2023-10-23T10:19:11.234 +9 2023-10-19T10:19:11.234 2023-10-24T10:19:11.234 +9 2023-10-19T10:19:11.234 2023-10-25T10:19:11.234 +9 2023-10-19T10:19:11.234 2023-10-26T10:19:11.234 +9 2023-10-19T10:19:11.234 2023-10-27T10:19:11.234 +10 2023-10-20T10:10:11.234 2023-10-20T10:10:11.234 +10 2023-10-20T10:10:11.234 2023-10-21T10:10:11.234 +10 2023-10-20T10:10:11.234 2023-10-22T10:10:11.234 +10 2023-10-20T10:10:11.234 2023-10-23T10:10:11.234 +10 2023-10-20T10:10:11.234 2023-10-24T10:10:11.234 +10 2023-10-20T10:10:11.234 2023-10-25T10:10:11.234 +10 2023-10-20T10:10:11.234 2023-10-26T10:10:11.234 +10 2023-10-20T10:10:11.234 2023-10-27T10:10:11.234 +10 2023-10-20T10:10:11.234 2023-10-28T10:10:11.234 +10 2023-10-20T10:10:11.234 2023-10-29T10:10:11.234 + +-- !select_string_col -- +1 row1 1 +1 row1 o +1 row1 r +1 row1 w +2 row2 2 +2 row2 o +2 row2 r +2 row2 w +3 row3 3 +3 row3 o +3 row3 r +3 row3 w +4 row4 4 +4 row4 o +4 row4 r +4 row4 w +5 row5 5 +5 row5 o +5 row5 r +5 row5 w +6 row6 6 +6 row6 o +6 row6 r +6 row6 w +7 row7 7 +7 row7 o +7 row7 r +7 row7 w +8 row8 8 +8 row8 o +8 row8 r +8 row8 w +9 row9 9 +9 row9 o +9 row9 r +9 row9 w + +-- !select_array_col -- +1 [null, "nested1"] \N +1 [null, "nested1"] nested1 +2 [null, "nested2"] \N +2 [null, "nested2"] nested2 +3 [null, "nested3"] \N +3 [null, "nested3"] nested3 +4 [null, "nested4"] \N +4 [null, "nested4"] nested4 +5 [null, "nested5"] \N +5 [null, "nested5"] nested5 +6 [null, "nested6"] \N +6 [null, "nested6"] nested6 +7 [null, "nested7"] \N +7 [null, "nested7"] nested7 +8 [null, "nested8"] \N +8 [null, "nested8"] nested8 +9 [null, "nested9"] \N +9 [null, "nested9"] nested9 +10 [null, "nested10"] \N +10 [null, "nested10"] nested10 + +-- !select_map_col -- +1 {"k1":null, "k2":"value1"} k1 +1 {"k1":null, "k2":"value1"} k2 +2 {"k2":null, "k3":"value2"} \N +2 {"k2":null, "k3":"value2"} value2 +3 {"k3":null, "k4":"value3"} k3 +3 {"k3":null, "k4":"value3"} k4 +4 {"k4":null, "k5":"value4"} \N +4 {"k4":null, "k5":"value4"} value4 +5 {"k5":null, "k6":"value5"} k5 +5 {"k5":null, "k6":"value5"} k6 +6 {"k6":null, "k7":"value6"} \N +6 {"k6":null, "k7":"value6"} value6 +7 {"k7":null, "k8":"value7"} k7 +7 {"k7":null, "k8":"value7"} k8 +8 {"k8":null, "k9":"value8"} \N +8 {"k8":null, "k9":"value8"} value8 +9 {"k9":null, "k10":"value9"} k10 +9 {"k9":null, "k10":"value9"} k9 +10 {"k10":null, "k11":"value10"} \N +10 {"k10":null, "k11":"value10"} value10 diff --git a/regression-test/suites/javaudf_p0/test_javaudaf_custom_lib_mysum_int.groovy b/regression-test/suites/javaudf_p0/test_javaudaf_custom_lib_mysum_int.groovy new file mode 100644 index 00000000000..e28245933cc --- /dev/null +++ b/regression-test/suites/javaudf_p0/test_javaudaf_custom_lib_mysum_int.groovy @@ -0,0 +1,64 @@ +// 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. + +import org.codehaus.groovy.runtime.IOGroovyMethods + +import java.nio.charset.StandardCharsets +import java.nio.file.Files +import java.nio.file.Paths + +suite("test_javaudaf_custom_lib_mysum_int") { + def tableName = "test_javaudaf_custom_lib_mysum_int" + try { + sql """ DROP TABLE IF EXISTS ${tableName} """ + sql """ + CREATE TABLE IF NOT EXISTS ${tableName} ( + `user_id` INT NOT NULL COMMENT "用户id", + `char_col` CHAR NOT NULL COMMENT "", + `varchar_col` VARCHAR(10) NOT NULL COMMENT "", + `string_col` STRING NOT NULL COMMENT "" + ) + DISTRIBUTED BY HASH(user_id) PROPERTIES("replication_num" = "1"); + """ + StringBuilder sb = new StringBuilder() + int i = 1 + for (; i < 9; i ++) { + sb.append(""" + (${i % 3}, '${i}','abcdefg${i}','poiuytre${i}abcdefg'), + """) + } + sb.append(""" + (${i}, '${i}','abcdefg${i}','poiuytre${i}abcdefg') + """) + sql """ INSERT INTO ${tableName} VALUES + ${sb.toString()} + """ + qt_select_default """ SELECT * FROM ${tableName} t ORDER BY char_col; """ + + sql """ CREATE AGGREGATE FUNCTION c_udaf_my_sum_int(int) RETURNS BigInt PROPERTIES ( + "symbol"="org.apache.doris.udf.MySumInt", + "always_nullable"="false", + "type"="JAVA_UDF" + ); """ + + qt_select1 """ SELECT c_udaf_my_sum_int(user_id) result FROM ${tableName}; """ + qt_select2 """ select user_id, c_udaf_my_sum_int(user_id) from ${tableName} group by user_id order by user_id; """ + } finally { + try_sql("DROP FUNCTION IF EXISTS c_udaf_my_sum_int(int);") + try_sql("DROP TABLE IF EXISTS ${tableName}") + } +} diff --git a/regression-test/suites/javaudf_p0/test_javaudf_custom_lib_all_types.groovy b/regression-test/suites/javaudf_p0/test_javaudf_custom_lib_all_types.groovy new file mode 100644 index 00000000000..0223d84bcdd --- /dev/null +++ b/regression-test/suites/javaudf_p0/test_javaudf_custom_lib_all_types.groovy @@ -0,0 +1,63 @@ +// 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. + +import org.codehaus.groovy.runtime.IOGroovyMethods + +import java.nio.charset.StandardCharsets +import java.nio.file.Files +import java.nio.file.Paths + +suite("test_javaudf_custom_lib_all_types") { + def tableName = "test_javaudf_custom_lib_all_types" + try { + sql """ DROP TABLE IF EXISTS ${tableName} """ + sql """ + CREATE TABLE IF NOT EXISTS ${tableName} ( + int_col int, + string_col string + ) + DISTRIBUTED BY HASH(int_col) PROPERTIES("replication_num" = "1"); + """ + StringBuilder sb = new StringBuilder() + int i = 1 + for (; i < 10; i++) { + sb.append(""" + (${i},${i%2}), + """) + } + sb.append(""" + (${i},null) + """) + sql """ INSERT INTO ${tableName} VALUES + ${sb.toString()} + """ + + sql """DROP FUNCTION IF EXISTS c_echo_int(int);""" + sql """CREATE FUNCTION c_echo_int(int) RETURNS int PROPERTIES ( + "symbol"="org.apache.doris.udf.Echo\$EchoInt", + "type"="JAVA_UDF" + );""" + + qt_java_udf_all_types """select + int_col, + c_echo_int(int_col) + from ${tableName} order by int_col;""" + } finally { + try_sql """DROP FUNCTION IF EXISTS c_echo_int(int);""" + try_sql("""DROP TABLE IF EXISTS ${tableName};""") + } +} diff --git a/regression-test/suites/javaudf_p0/test_javaudtf_custom_lib_all_types.groovy b/regression-test/suites/javaudf_p0/test_javaudtf_custom_lib_all_types.groovy new file mode 100644 index 00000000000..b1e2323fdce --- /dev/null +++ b/regression-test/suites/javaudf_p0/test_javaudtf_custom_lib_all_types.groovy @@ -0,0 +1,181 @@ +// 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. + +import org.codehaus.groovy.runtime.IOGroovyMethods + +import java.nio.charset.StandardCharsets +import java.nio.file.Files +import java.nio.file.Paths + +suite("test_javaudtf_custom_lib_all_types") { + def tableName = "test_javaudtf_custom_lib_all_types" + + try { + sql """ DROP TABLE IF EXISTS ${tableName} """ + sql """ + CREATE TABLE IF NOT EXISTS ${tableName} ( + int_col int, + boolean_col boolean, + tinyint_col tinyint, + smallint_col smallint, + bigint_col bigint, + largeint_col largeint, + decimal_col decimal(15, 4), + float_col float, + double_col double, + date_col date, + datetime_col datetime(6), + string_col string, + array_col array<string>, + map_col map<string, string> + ) + DISTRIBUTED BY HASH(int_col) PROPERTIES("replication_num" = "1"); + """ + StringBuilder sb = new StringBuilder() + int i = 1 + for (; i < 10; i++) { + sb.append(""" + (${i},${i%2},${i},${i}*2,${i}*3,${i}*4,${3.33/i},${(7.77/i).round(3)},${(3.1415/i).round(5)},"2023-10-${i+17}","2023-10-${i+10} 10:1${i}:11.234","row${i}",array(null, "nested${i}"),{"k${i}":null,"k${i+1}":"value${i}"}), + """) + } + sb.append(""" + (${i},${i%2},null,${i}*2,${i}*3,${i}*4,null,${(7.77/i).round(3)},${(3.1415/i).round(5)},null,"2023-10-${i+10} 10:${i}:11.234",null,array(null, "nested${i}"),{"k${i}":null,"k${i+1}":"value${i}"}), + """) + sb.append(""" + (null,null,null,null,null,null,null,null,null,null,null,null,null,null) + """) + sql """ INSERT INTO ${tableName} VALUES + ${sb.toString()} + """ + qt_select """select * from ${tableName} order by 1,2,3;""" + + + sql """DROP FUNCTION IF EXISTS c_udtf_boolean(boolean, int);""" + sql """CREATE TABLES FUNCTION c_udtf_boolean(boolean, int) RETURNS array<boolean> PROPERTIES ( + "symbol"="org.apache.doris.udf.UDTFAllTypeTest\$UdtfBoolean", + "type"="JAVA_UDF" + );""" + + sql """DROP FUNCTION IF EXISTS c_udtf_tinyint(tinyint, int);""" + sql """CREATE TABLES FUNCTION c_udtf_tinyint(tinyint, int) RETURNS array<tinyint> PROPERTIES ( + "symbol"="org.apache.doris.udf.UDTFAllTypeTest\$UdtfByte", + "type"="JAVA_UDF" + );""" + + sql """DROP FUNCTION IF EXISTS c_udtf_short(smallint, int);""" + sql """CREATE TABLES FUNCTION c_udtf_short(smallint, int) RETURNS array<smallint> PROPERTIES ( + "symbol"="org.apache.doris.udf.UDTFAllTypeTest\$UdtfShort", + "type"="JAVA_UDF" + );""" + + sql """DROP FUNCTION IF EXISTS c_udtf_int(int, int);""" + sql """CREATE TABLES FUNCTION c_udtf_int(int, int) RETURNS array<int> PROPERTIES ( + "symbol"="org.apache.doris.udf.UDTFAllTypeTest\$UdtfInt", + "type"="JAVA_UDF" + );""" + + sql """DROP FUNCTION IF EXISTS c_udtf_long(bigint, int);""" + sql """CREATE TABLES FUNCTION c_udtf_long(bigint, int) RETURNS array<bigint> PROPERTIES ( + "symbol"="org.apache.doris.udf.UDTFAllTypeTest\$UdtfLong", + "type"="JAVA_UDF" + );""" + + sql """DROP FUNCTION IF EXISTS c_udtf_largeint(largeint, int);""" + sql """CREATE TABLES FUNCTION c_udtf_largeint(largeint, int) RETURNS array<largeint> PROPERTIES ( + "symbol"="org.apache.doris.udf.UDTFAllTypeTest\$UdtfLargeInt", + "type"="JAVA_UDF" + );""" + + sql """DROP FUNCTION IF EXISTS c_udtf_decimal(decimal(15, 4), int);""" + sql """CREATE TABLES FUNCTION c_udtf_decimal(decimal(15, 4), int) RETURNS array<decimal(15, 4)> PROPERTIES ( + "symbol"="org.apache.doris.udf.UDTFAllTypeTest\$UdtfDecimal", + "type"="JAVA_UDF" + );""" + + sql """DROP FUNCTION IF EXISTS c_udtf_float(float, int);""" + sql """CREATE TABLES FUNCTION c_udtf_float(float, int) RETURNS array<float> PROPERTIES ( + "symbol"="org.apache.doris.udf.UDTFAllTypeTest\$UdtfFloat", + "type"="JAVA_UDF" + );""" + + sql """DROP FUNCTION IF EXISTS c_udtf_double(double, int);""" + sql """CREATE TABLES FUNCTION c_udtf_double(double, int) RETURNS array<double> PROPERTIES ( + "symbol"="org.apache.doris.udf.UDTFAllTypeTest\$UdtfDouble", + "type"="JAVA_UDF" + );""" + + sql """DROP FUNCTION IF EXISTS c_udtf_date(date, int);""" + sql """CREATE TABLES FUNCTION c_udtf_date(date, int) RETURNS array<date> PROPERTIES ( + "symbol"="org.apache.doris.udf.UDTFAllTypeTest\$UdtfDate", + "type"="JAVA_UDF" + );""" + + sql """DROP FUNCTION IF EXISTS c_udtf_datetime(datetime(6), int);""" + sql """CREATE TABLES FUNCTION c_udtf_datetime(datetime(6), int) RETURNS array<datetime(6)> PROPERTIES ( + "symbol"="org.apache.doris.udf.UDTFAllTypeTest\$UdtfDateTime", + "type"="JAVA_UDF" + );""" + + sql """DROP FUNCTION IF EXISTS c_udtf_string(string, string);""" + sql """CREATE TABLES FUNCTION c_udtf_string(string,string) RETURNS array<string> PROPERTIES ( + "symbol"="org.apache.doris.udf.UDTFAllTypeTest\$UdtfString", + "type"="JAVA_UDF" + );""" + + sql """DROP FUNCTION IF EXISTS c_udtf_list(array<string>, int);""" + sql """CREATE TABLES FUNCTION c_udtf_list(array<string>, int) RETURNS array<string> PROPERTIES ( + "symbol"="org.apache.doris.udf.UDTFAllTypeTest\$UdtfList", + "type"="JAVA_UDF" + );""" + + sql """DROP FUNCTION IF EXISTS c_udtf_map(map<string,string>, int);""" + sql """CREATE TABLES FUNCTION c_udtf_map(map<string,string>, int) RETURNS array<string> PROPERTIES ( + "symbol"="org.apache.doris.udf.UDTFAllTypeTest\$UdtfMap", + "type"="JAVA_UDF" + );""" + + qt_select_boolean_col """select int_col, boolean_col, e1 from ${tableName} lateral view c_udtf_boolean(boolean_col, int_col) tmp1 as e1 order by int_col,2,3;""" + qt_select_tinyint_col """select int_col, tinyint_col, e1 from ${tableName} lateral view c_udtf_tinyint(tinyint_col, int_col) tmp1 as e1 order by int_col,2,3;""" + qt_select_smallint_col """select int_col, smallint_col, e1 from ${tableName} lateral view c_udtf_short(smallint_col, int_col) tmp1 as e1 order by int_col,2,3;""" + qt_select_int_col """select int_col, int_col, e1 from ${tableName} lateral view c_udtf_int(int_col, int_col) tmp1 as e1 order by int_col,2,3;""" + qt_select_bigint_col """select int_col, bigint_col, e1 from ${tableName} lateral view c_udtf_long(bigint_col, int_col) tmp1 as e1 order by int_col,2,3;""" + qt_select_largeint_col """select int_col, largeint_col,e1 from ${tableName} lateral view c_udtf_largeint(largeint_col, int_col) tmp1 as e1 order by int_col,2,3;""" + qt_select_decimal_col """select int_col, decimal_col,e1 from ${tableName} lateral view c_udtf_decimal(decimal_col, int_col) tmp1 as e1 order by int_col,2,3;""" + qt_select_float_col """select int_col, float_col,e1 from ${tableName} lateral view c_udtf_float(float_col, int_col) tmp1 as e1 order by int_col,2,3;""" + qt_select_double_col """select int_col, double_col,e1 from ${tableName} lateral view c_udtf_double(double_col, int_col) tmp1 as e1 order by int_col,2,3;""" + qt_select_date_col """select int_col, date_col,e1 from ${tableName} lateral view c_udtf_date(date_col, int_col) tmp1 as e1 order by int_col,2,3;""" + qt_select_datetime_col """select int_col, datetime_col,e1 from ${tableName} lateral view c_udtf_datetime(datetime_col, int_col) tmp1 as e1 order by int_col,2,3;""" + qt_select_string_col """select int_col, string_col,e1 from ${tableName} lateral view c_udtf_string(string_col, "") tmp1 as e1 order by int_col,2,3;""" + qt_select_array_col """select int_col, array_col,e1 from ${tableName} lateral view c_udtf_list(array_col, int_col) tmp1 as e1 order by int_col,3;""" + qt_select_map_col """select int_col, map_col,e1 from ${tableName} lateral view c_udtf_map(map_col, int_col) tmp1 as e1 order by int_col,3;""" + } finally { + try_sql """DROP FUNCTION IF EXISTS c_udtf_boolean (boolean, int);""" + try_sql """DROP FUNCTION IF EXISTS c_udtf_tinyint (tinyint, int);""" + try_sql """DROP FUNCTION IF EXISTS c_udtf_short (smallint, int);""" + try_sql """DROP FUNCTION IF EXISTS c_udtf_int (int, int);""" + try_sql """DROP FUNCTION IF EXISTS c_udtf_long (bigint, int);""" + try_sql """DROP FUNCTION IF EXISTS c_udtf_largeint (largeint, int);""" + try_sql """DROP FUNCTION IF EXISTS c_udtf_decimal (decimal(15, 4), int);""" + try_sql """DROP FUNCTION IF EXISTS c_udtf_float (float, int);""" + try_sql """DROP FUNCTION IF EXISTS c_udtf_double (double, int);""" + try_sql """DROP FUNCTION IF EXISTS c_udtf_date (date, int);""" + try_sql """DROP FUNCTION IF EXISTS c_udtf_datetime (datetime(6), int);""" + try_sql """DROP FUNCTION IF EXISTS c_udtf_string (string, string);""" + try_sql """DROP FUNCTION IF EXISTS c_udtf_list (array<string>, int);""" + try_sql """DROP FUNCTION IF EXISTS c_udtf_map (map<string,string>, int);""" + } +} diff --git a/run-regression-test.sh b/run-regression-test.sh index e04d1d7cefb..f38d99cef29 100755 --- a/run-regression-test.sh +++ b/run-regression-test.sh @@ -50,7 +50,7 @@ Usage: $0 <shell_options> <framework_options> Eg. $0 build regression test framework and run all suite which in default group $0 --run test_select run a suite which named as test_select - $0 --run 'test*' run all suite which named start with 'test', note that you must quota with '' + $0 --compile only compile regression framework $0 --run -s test_select run a suite which named as test_select $0 --run test_select -genOut generate output file for test_select if not exist $0 --run -g default run all suite in the group which named as default @@ -65,7 +65,7 @@ Default config file: \${DORIS_HOME}/regression-test/conf/regression-conf.groovy " exit 1 } - +ONLY_COMPILE=0 CLEAN=0 WRONG_CMD=0 TEAMCITY=0 @@ -96,6 +96,11 @@ else shift shift ;; + --compile) + RUN=1 + ONLY_COMPILE=1 + shift + ;; --run) RUN=1 shift @@ -178,6 +183,11 @@ if ! test -f ${RUN_JAR:+${RUN_JAR}}; then cd "${DORIS_HOME}"/regression-test/java-udf-src "${MVN_CMD}" package cp target/java-udf-case-jar-with-dependencies.jar "${DORIS_HOME}"/regression-test/suites/javaudf_p0/jars/ + # be and fe dir is compiled output + mkdir -p "${DORIS_HOME}"/output/fe/custom_lib/ + mkdir -p "${DORIS_HOME}"/output/be/custom_lib/ + cp target/java-udf-case-jar-with-dependencies.jar "${DORIS_HOME}"/output/fe/custom_lib/ + cp target/java-udf-case-jar-with-dependencies.jar "${DORIS_HOME}"/output/be/custom_lib/ cd "${DORIS_HOME}" fi @@ -206,11 +216,13 @@ if [[ "${TEAMCITY}" -eq 1 ]]; then JAVA_OPTS="${JAVA_OPTS} -DstdoutAppenderType=teamcity -Xmx2048m" fi -"${JAVA}" -DDORIS_HOME="${DORIS_HOME}" \ - -DLOG_PATH="${LOG_OUTPUT_FILE}" \ - -Dfile.encoding="UTF-8" \ - -Dlogback.configurationFile="${LOG_CONFIG_FILE}" \ - ${JAVA_OPTS:+${JAVA_OPTS}} \ - -jar ${RUN_JAR:+${RUN_JAR}} \ - -cf "${CONFIG_FILE}" \ - ${REGRESSION_OPTIONS_PREFIX:+${REGRESSION_OPTIONS_PREFIX}} "$@" +if [[ "${ONLY_COMPILE}" -eq 0 ]]; then + "${JAVA}" -DDORIS_HOME="${DORIS_HOME}" \ + -DLOG_PATH="${LOG_OUTPUT_FILE}" \ + -Dfile.encoding="UTF-8" \ + -Dlogback.configurationFile="${LOG_CONFIG_FILE}" \ + ${JAVA_OPTS:+${JAVA_OPTS}} \ + -jar ${RUN_JAR:+${RUN_JAR}} \ + -cf "${CONFIG_FILE}" \ + ${REGRESSION_OPTIONS_PREFIX:+${REGRESSION_OPTIONS_PREFIX}} "$@" +fi --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org