JackieTien97 commented on code in PR #14223: URL: https://github.com/apache/iotdb/pull/14223#discussion_r1863192481
########## iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/customizer/config/ScalarFunctionConfig.java: ########## @@ -0,0 +1,30 @@ +/* + * 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.iotdb.udf.api.customizer.config; + +import org.apache.iotdb.udf.api.type.Type; + +public class ScalarFunctionConfig extends UDFConfigurations { + + public ScalarFunctionConfig setOutputDataType(Type outputDataType) { Review Comment: all public methods are visible to users, so we need to add java doc to explain the functionality. ########## iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/customizer/parameter/FunctionParameters.java: ########## @@ -0,0 +1,56 @@ +/* + * 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.iotdb.udf.api.customizer.parameter; + +import org.apache.iotdb.udf.api.type.Type; + +import java.util.List; +import java.util.Map; + +public class FunctionParameters { + private final List<Type> childExpressionDataTypes; + private final Map<String, String> systemAttributes; + + public FunctionParameters( + List<Type> childExpressionDataTypes, Map<String, String> systemAttributes) { + this.childExpressionDataTypes = childExpressionDataTypes; + this.systemAttributes = systemAttributes; + } + + public List<Type> getChildExpressionDataTypes() { + return childExpressionDataTypes; + } + + public int getChildExpressionsSize() { + return childExpressionDataTypes.size(); + } + + public Type getDataType(int index) { + return childExpressionDataTypes.get(index); + } + + public boolean hasSystemAttribute(String attributeKey) { + return systemAttributes.containsKey(attributeKey); + } + + public Map<String, String> getSystemAttributes() { + return systemAttributes; + } Review Comment: all public methods are visible to users, so we need to add java doc to explain the functionality. ########## iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/access/Record.java: ########## @@ -78,31 +75,48 @@ public interface Record { * * @param columnIndex index of the specified column * @return the boolean value at the specified column in this row - * @throws IOException if an I/O error occurs */ - boolean getBoolean(int columnIndex) throws IOException; + boolean getBoolean(int columnIndex); /** * Returns the Binary value at the specified column in this row. * - * <p>Users need to ensure that the data type of the specified column is {@code TSDataType.TEXT}. + * <p>Users need to ensure that the data type of the specified column is {@code TSDataType.TEXT}, + * {@code TSDataType.STRING} or {@code TSDataType.BLOB}. * * @param columnIndex index of the specified column * @return the Binary value at the specified column in this row - * @throws IOException if an I/O error occurs */ - Binary getBinary(int columnIndex) throws IOException; + Binary getBinary(int columnIndex); /** * Returns the String value at the specified column in this row. * - * <p>Users need to ensure that the data type of the specified column is {@code TSDataType.TEXT}. + * <p>Users need to ensure that the data type of the specified column is {@code TSDataType.TEXT} + * or {@code TSDataType.STRING}. * * @param columnIndex index of the specified column * @return the String value at the specified column in this row - * @throws IOException if an I/O error occurs */ - String getString(int columnIndex) throws IOException; + String getString(int columnIndex); + + /** + * Returns the String value at the specified column in this row. + * + * <p>Users need to ensure that the data type of the specified column is {@code TSDataType.DATE}. + * + * @param columnIndex index of the specified column + * @return the String value at the specified column in this row + */ + LocalDate getLocalDate(int columnIndex); + + /** + * Returns the object value at the specified column in this row. + * + * @param columnIndex index of the specified column + * @return the object value at the specified column in this row + */ + Object getObject(int columnIndex); Review Comment: ```suggestion ``` ########## iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/ScalarFunction.java: ########## @@ -19,4 +19,50 @@ package org.apache.iotdb.udf.api.relational; -public interface ScalarFunction extends SQLFunction {} +import org.apache.iotdb.udf.api.customizer.config.ScalarFunctionConfig; +import org.apache.iotdb.udf.api.customizer.parameter.FunctionParameters; +import org.apache.iotdb.udf.api.relational.access.Record; + +public interface ScalarFunction extends SQLFunction { + + /** + * This method is used to validate {@link FunctionParameters}. + * + * @param parameters parameters used to validate + * @throws Exception if any parameter is not valid + */ + void validate(FunctionParameters parameters) throws Exception; + + /** + * This method is mainly used to initialize {@link ScalarFunction}. In this method, the user can Review Comment: ```suggestion * This method is mainly used to initialize {@link ScalarFunction} and set the output data type. In this method, the user can ``` ########## iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/utils/TableUDFUtils.java: ########## @@ -0,0 +1,51 @@ +/* + * 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.iotdb.commons.udf.utils; + +import org.apache.iotdb.commons.udf.service.UDFManagementService; +import org.apache.iotdb.udf.api.relational.AggregateFunction; +import org.apache.iotdb.udf.api.relational.ScalarFunction; +import org.apache.iotdb.udf.api.relational.TableFunction; + +public class TableUDFUtils { + public static ScalarFunction tryGetScalarFunction(String functionName) { + try { + return UDFManagementService.getInstance().reflect(functionName, ScalarFunction.class); Review Comment: may also need to add a method in `UDFManagementService`, like `tryReflect` to avoid print warn logs ########## iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/TableBuiltinScalarFunction.java: ########## @@ -70,4 +75,14 @@ public enum TableBuiltinScalarFunction { public String getFunctionName() { return functionName; } + + private static final Set<String> NATIVE_FUNCTION_NAMES = + new HashSet<>( + Arrays.stream(TableBuiltinScalarFunction.values()) + .map(TableBuiltinScalarFunction::getFunctionName) + .collect(Collectors.toList())); + + public static Set<String> getNativeFunctionNames() { Review Comment: ```suggestion public static Set<String> getBuiltInScalarFunctionNames() { ``` ########## iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java: ########## @@ -627,7 +630,26 @@ && isIntegerNumber(argumentTypes.get(2)))) { // ignore } - // TODO scalar UDF function + // User-defined scalar function + ScalarFunction scalarFunction = TableUDFUtils.tryGetScalarFunction(functionName); Review Comment: we may add new method instead of calling `UDFManagementService.reflect` which will print warn log in that. ########## iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/relational/TableBuiltinScalarFunction.java: ########## @@ -70,4 +75,14 @@ public enum TableBuiltinScalarFunction { public String getFunctionName() { return functionName; } + + private static final Set<String> NATIVE_FUNCTION_NAMES = Review Comment: ```suggestion private static final Set<String> BUILT_IN_SCALAR_FUNCTION_NAMES = ``` ########## iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java: ########## @@ -996,6 +1003,25 @@ private ColumnTransformer getFunctionColumnTransformer( source, ((LongLiteral) children.get(3)).getParsedValue(), context.sessionInfo.getZoneId()); + } else { + // user defined function + ScalarFunction scalarFunction = TableUDFUtils.tryGetScalarFunction(functionName); + if (scalarFunction != null) { + List<ColumnTransformer> childrenColumnTransformer = + children.stream().map(child -> process(child, context)).collect(Collectors.toList()); + FunctionParameters parameters = + new FunctionParameters( + childrenColumnTransformer.stream() + .map(i -> UDFDataTypeTransformer.transformReadTypeToUDFDataType(i.getType())) + .collect(Collectors.toList()), + Collections.emptyMap()); + ScalarFunctionConfig config = new ScalarFunctionConfig(); + scalarFunction.beforeStart(parameters, config); + Type returnType = + UDFDataTypeTransformer.transformUDFDataTypeToReadType(config.getOutputDataType()); + return new UserDefineScalarFunctionTransformer( + returnType, scalarFunction, childrenColumnTransformer); + } } throw new IllegalArgumentException(String.format("Unknown function: %s", functionName)); Review Comment: add current DatanodeId in error msg. You can get that from `IoTDBDescriptor.getInstance().getConfig().getDataNodeId()` ########## iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/ShowFunctionsTask.java: ########## @@ -175,6 +260,15 @@ private static Binary getFunctionType(UDFInformation udfInformation) { } else if (TreeUDFUtils.isUDAF(udfInformation.getFunctionName())) { return BINARY_MAP.get(FUNCTION_TYPE_EXTERNAL_UDAF); } + } else { + if (TableUDFUtils.tryGetScalarFunction(udfInformation.getFunctionName()) != null) { + return BINARY_MAP.get(FUNCTION_TYPE_USER_DEFINED_SCALAR_FUNC); + } else if (TableUDFUtils.tryGetAggregateFunction(udfInformation.getFunctionName()) + != null) { + return BINARY_MAP.get(FUNCTION_TYPE_USER_DEFINED_AGG_FUNC); + } else if (TableUDFUtils.tryGetTableFunction(udfInformation.getFunctionName()) != null) { + return BINARY_MAP.get(FUNCTION_TYPE_USER_DEFINED_TABLE_FUNC); + } Review Comment: Each show functions, we need to reflect a UDF class to judge what type it's.... Why not store that in UDFInformation -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
