This is an automated email from the ASF dual-hosted git repository.

chenyz pushed a commit to branch udsf
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 499ae65fc08a64d296b00c7b9ef4f0182184f132
Author: Chen YZ <[email protected]>
AuthorDate: Tue Nov 19 16:06:07 2024 +0800

    save
---
 iotdb-api/udf-api/pom.xml                          |   6 +
 .../config/ScalarFunctionConfig.java}              |  12 +-
 .../customizer/parameter/FunctionParameters.java   |  56 +++++++++
 ...egationFunction.java => AggregateFunction.java} |   2 +-
 .../iotdb/udf/api/relational/ScalarFunction.java   |  30 ++++-
 .../execution/aggregation/UDAFAccumulator.java     |   3 +-
 .../relational/metadata/TableMetadataImpl.java     |  21 +++-
 .../udf/UserDefineScalarFunctionTransformer.java   | 125 +++++++++++++++++++++
 .../transformation/dag/udf/UDTFExecutor.java       |   3 +-
 .../udf/builtin/UDTFEqualSizeBucketSample.java     |   3 +-
 .../apache/iotdb/commons/udf/builtin/UDTFJexl.java |   3 +-
 .../apache/iotdb/commons/udf/builtin/UDTFM4.java   |   6 +-
 .../iotdb/commons/udf/utils/TableUDFUtils.java     |  54 +++++++++
 .../commons/udf/utils/UDFDataTypeTransformer.java  |  62 ++++++++++
 14 files changed, 373 insertions(+), 13 deletions(-)

diff --git a/iotdb-api/udf-api/pom.xml b/iotdb-api/udf-api/pom.xml
index 8a66274237f..734b7a5fb0c 100644
--- a/iotdb-api/udf-api/pom.xml
+++ b/iotdb-api/udf-api/pom.xml
@@ -34,6 +34,12 @@
             <artifactId>common</artifactId>
             <version>${tsfile.version}</version>
         </dependency>
+        <dependency>
+            <groupId>net.bytebuddy</groupId>
+            <artifactId>byte-buddy</artifactId>
+            <version>1.15.10</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
     <profiles>
         <profile>
diff --git 
a/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/AggregationFunction.java
 
b/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/customizer/config/ScalarFunctionConfig.java
similarity index 73%
copy from 
iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/AggregationFunction.java
copy to 
iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/customizer/config/ScalarFunctionConfig.java
index e831d5b5292..adacabed085 100644
--- 
a/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/AggregationFunction.java
+++ 
b/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/customizer/config/ScalarFunctionConfig.java
@@ -17,6 +17,14 @@
  * under the License.
  */
 
-package org.apache.iotdb.udf.api.relational;
+package org.apache.iotdb.udf.api.customizer.config;
 
-public interface AggregationFunction extends SQLFunction {}
+import org.apache.iotdb.udf.api.type.Type;
+
+public class ScalarFunctionConfig extends UDFConfigurations {
+
+  public ScalarFunctionConfig setOutputDataType(Type outputDataType) {
+    this.outputDataType = outputDataType;
+    return this;
+  }
+}
diff --git 
a/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/customizer/parameter/FunctionParameters.java
 
b/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/customizer/parameter/FunctionParameters.java
new file mode 100644
index 00000000000..5af832cbaa7
--- /dev/null
+++ 
b/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;
+  }
+}
diff --git 
a/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/AggregationFunction.java
 
b/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/AggregateFunction.java
similarity index 93%
rename from 
iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/AggregationFunction.java
rename to 
iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/AggregateFunction.java
index e831d5b5292..24942afd010 100644
--- 
a/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/AggregationFunction.java
+++ 
b/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/AggregateFunction.java
@@ -19,4 +19,4 @@
 
 package org.apache.iotdb.udf.api.relational;
 
-public interface AggregationFunction extends SQLFunction {}
+public interface AggregateFunction extends SQLFunction {}
diff --git 
a/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/ScalarFunction.java
 
b/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/ScalarFunction.java
index 996d6994138..bd0586d051c 100644
--- 
a/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/ScalarFunction.java
+++ 
b/iotdb-api/udf-api/src/main/java/org/apache/iotdb/udf/api/relational/ScalarFunction.java
@@ -19,4 +19,32 @@
 
 package org.apache.iotdb.udf.api.relational;
 
-public interface ScalarFunction extends SQLFunction {}
+import org.apache.iotdb.udf.api.customizer.parameter.FunctionParameters;
+import org.apache.iotdb.udf.api.relational.access.Record;
+import org.apache.iotdb.udf.api.type.Type;
+
+public interface ScalarFunction extends SQLFunction {
+
+  /**
+   * This method is mainly used to validate {@link FunctionParameters} and 
infer output data type.
+   *
+   * @param parameters parameters used to validate
+   * @throws Exception if any parameter is not valid
+   */
+  Type validateAndInferOutputType(FunctionParameters parameters) throws 
Exception;
+
+  /**
+   * This method will be called to process the transformation. In a single UDF 
query, this method
+   * may be called multiple times.
+   *
+   * @param input original input data row
+   * @throws Exception the user can throw errors if necessary
+   * @throws UnsupportedOperationException if the user does not override this 
method
+   */
+  Object evaluate(Record input) throws Exception;
+
+  /** This method is mainly used to release the resources used in the 
SQLFunction. */
+  default void beforeDestroy() {
+    // do nothing
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/aggregation/UDAFAccumulator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/aggregation/UDAFAccumulator.java
index a0b78cc8cd6..a56d6e9bd03 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/aggregation/UDAFAccumulator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/aggregation/UDAFAccumulator.java
@@ -199,7 +199,8 @@ public class UDAFAccumulator implements Accumulator {
 
   @Override
   public TSDataType getFinalType() {
-    return 
UDFDataTypeTransformer.transformToTsDataType(configurations.getOutputDataType());
+    return UDFDataTypeTransformer.transformToTsDataType(
+        configurations.getOutputDataType());
   }
 
   private void onError(String methodName, Exception e) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
index 89b053ac475..e127de7186d 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java
@@ -24,6 +24,8 @@ import 
org.apache.iotdb.commons.partition.DataPartitionQueryParam;
 import org.apache.iotdb.commons.partition.SchemaPartition;
 import org.apache.iotdb.commons.schema.table.TsTable;
 import org.apache.iotdb.commons.udf.service.UDFManagementService;
+import org.apache.iotdb.commons.udf.utils.TableUDFUtils;
+import org.apache.iotdb.commons.udf.utils.UDFDataTypeTransformer;
 import org.apache.iotdb.db.exception.sql.SemanticException;
 import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
 import org.apache.iotdb.db.queryengine.common.SessionInfo;
@@ -47,6 +49,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignature;
 import 
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.TableBuiltinScalarFunction;
 import org.apache.iotdb.db.schemaengine.table.DataNodeTableCache;
 import org.apache.iotdb.db.utils.constant.SqlConstant;
+import org.apache.iotdb.udf.api.customizer.parameter.FunctionParameters;
 import org.apache.iotdb.udf.api.relational.ScalarFunction;
 
 import org.apache.tsfile.file.metadata.IDeviceID;
@@ -619,10 +622,22 @@ public class TableMetadataImpl implements Metadata {
         // ignore
     }
 
-    // TODO scalar UDF function
     // 根据 argumentTypes 获取返回类型,这边暂时先 mock 一个 INT32
-    if (UDFManagementService.getInstance().isAssignableFrom(functionName, 
ScalarFunction.class)) {
-      return INT32;
+    if (TableUDFUtils.isScalarFunction(functionName)) {
+      ScalarFunction scalarFunction =
+          UDFManagementService.getInstance().reflect(functionName, 
ScalarFunction.class);
+      FunctionParameters functionParameters =
+          new FunctionParameters(
+              argumentTypes.stream()
+                  .map(UDFDataTypeTransformer::transformReadTypeToUDFDataType)
+                  .collect(Collectors.toList()),
+              Collections.emptyMap());
+      try {
+        return UDFDataTypeTransformer.transformUDFDataTypeToReadType(
+            scalarFunction.validateAndInferOutputType(functionParameters));
+      } catch (Exception e) {
+        throw new SemanticException("Invalid function parameters: " + 
e.getMessage());
+      }
     }
 
     // TODO UDAF
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/udf/UserDefineScalarFunctionTransformer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/udf/UserDefineScalarFunctionTransformer.java
new file mode 100644
index 00000000000..7689bbcca9d
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/udf/UserDefineScalarFunctionTransformer.java
@@ -0,0 +1,125 @@
+/*
+ * 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.db.queryengine.transformation.dag.column.udf;
+
+import org.apache.iotdb.commons.udf.service.UDFManagementService;
+import org.apache.iotdb.commons.udf.utils.UDFDataTypeTransformer;
+import org.apache.iotdb.db.exception.sql.SemanticException;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
+import 
org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
+import 
org.apache.iotdb.db.queryengine.transformation.dag.column.multi.MultiColumnTransformer;
+import 
org.apache.iotdb.db.queryengine.transformation.dag.udf.UDFParametersFactory;
+import org.apache.iotdb.udf.api.access.ColumnToRowIterator;
+import org.apache.iotdb.udf.api.customizer.parameter.UDFParameters;
+import org.apache.iotdb.udf.api.relational.ScalarFunction;
+
+import org.apache.tsfile.block.column.Column;
+import org.apache.tsfile.block.column.ColumnBuilder;
+import org.apache.tsfile.enums.TSDataType;
+import org.apache.tsfile.read.common.type.Type;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+// TODO(UDSF): encapsulate refect and validate logic
+public class UserDefineScalarFunctionTransformer extends 
MultiColumnTransformer {
+
+  private final ScalarFunction scalarFunction;
+  private final List<TSDataType> childrenTypes;
+
+  public UserDefineScalarFunctionTransformer(
+      Type returnType,
+      String functionName,
+      List<Expression> children,
+      List<ColumnTransformer> childrenTransformers) {
+    super(returnType, childrenTransformers);
+    ScalarFunction scalarFunction =
+        UDFManagementService.getInstance().reflect(functionName, 
ScalarFunction.class);
+    this.childrenTypes =
+        childrenTransformers.stream()
+            .map(ColumnTransformer::getType)
+            .map(UDFDataTypeTransformer::transformReadTypeToTSDataType)
+            .collect(Collectors.toList());
+    // TODO: 1、Table UDF 里不应该再用 String Expression 了
+    // TODO:2、想办法弄到 attributes
+    UDFParameters udfParameters =
+        UDFParametersFactory.buildUdfParameters(
+            
children.stream().map(Expression::toString).collect(Collectors.toList()),
+            childrenTypes,
+            Collections.emptyMap());
+    try {
+      //      scalarFunction.validate(new 
UDFParameterValidator(udfParameters));
+      //      scalarFunction.beforeStart(udfParameters, new 
ScalarFunctionConfig());
+    } catch (Exception e) {
+      throw new SemanticException(e.getMessage());
+    }
+
+    this.scalarFunction = scalarFunction;
+  }
+
+  @Override
+  protected void doTransform(
+      List<Column> childrenColumns, ColumnBuilder builder, int positionCount) {
+    ColumnToRowIterator iterator =
+        new ColumnToRowIterator(childrenTypes, childrenColumns, positionCount);
+    //    while (iterator.hasNextRow()) {
+    //      try {
+    //        Row row = iterator.next();
+    //        Object result = scalarFunction.evaluate(row);
+    //        if (result == null) {
+    //          builder.appendNull();
+    //        } else {
+    //          builder.writeObject(result);
+    //        }
+    //      } catch (Exception e) {
+    //        throw new RuntimeException(
+    //            "Error occurs when evaluating UDF " + 
scalarFunction.getClass().getName(), e);
+    //      }
+    //    }
+  }
+
+  @Override
+  protected void doTransform(
+      List<Column> childrenColumns, ColumnBuilder builder, int positionCount, 
boolean[] selection) {
+    ColumnToRowIterator iterator =
+        new ColumnToRowIterator(childrenTypes, childrenColumns, positionCount);
+    int i = 0;
+    //    while (iterator.hasNextRow()) {
+    //      try {
+    //        Row row = iterator.next();
+    //        Object result = scalarFunction.evaluate(row);
+    //        if (selection[i++] || result == null) {
+    //          builder.appendNull();
+    //        } else {
+    //          builder.writeObject(result);
+    //        }
+    //      } catch (Exception e) {
+    //        throw new RuntimeException(
+    //            "Error occurs when evaluating UDF " + 
scalarFunction.getClass().getName(), e);
+    //      }
+    //    }
+  }
+
+  @Override
+  protected void checkType() {
+    // TODO: implement this method
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/udf/UDTFExecutor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/udf/UDTFExecutor.java
index f93de5c1dc4..a9ab775360b 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/udf/UDTFExecutor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/udf/UDTFExecutor.java
@@ -80,7 +80,8 @@ public class UDTFExecutor {
         configurations.getAccessStrategy().getAccessStrategyType())) {
       outputStorage =
           ElasticSerializableTVList.construct(
-              
UDFDataTypeTransformer.transformToTsDataType(configurations.getOutputDataType()),
+              UDFDataTypeTransformer.transformToTsDataType(
+                  configurations.getOutputDataType()),
               queryId,
               collectorMemoryBudgetInMB,
               1);
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/UDTFEqualSizeBucketSample.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/UDTFEqualSizeBucketSample.java
index 306d35e110f..d3492ecbe2e 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/UDTFEqualSizeBucketSample.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/UDTFEqualSizeBucketSample.java
@@ -45,7 +45,8 @@ public abstract class UDTFEqualSizeBucketSample implements 
UDTF {
             "Illegal sample proportion. proportion > 0 and proportion <= 1",
             proportion);
     dataType =
-        
UDFDataTypeTransformer.transformToTsDataType(validator.getParameters().getDataType(0));
+        UDFDataTypeTransformer.transformToTsDataType(
+            validator.getParameters().getDataType(0));
     bucketSize = (int) (1 / proportion);
   }
 }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/UDTFJexl.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/UDTFJexl.java
index d554cfe2572..404ab2f26e7 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/UDTFJexl.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/UDTFJexl.java
@@ -70,7 +70,8 @@ public class UDTFJexl implements UDTF {
 
     inputDataType = new TSDataType[inputSeriesNumber];
     for (int i = 0; i < inputSeriesNumber; i++) {
-      inputDataType[i] = 
UDFDataTypeTransformer.transformToTsDataType(parameters.getDataType(i));
+      inputDataType[i] =
+          
UDFDataTypeTransformer.transformToTsDataType(parameters.getDataType(i));
     }
     outputDataType = probeOutputDataType();
 
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/UDTFM4.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/UDTFM4.java
index 824740b8c9b..ccbb2848a01 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/UDTFM4.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/UDTFM4.java
@@ -94,14 +94,16 @@ public class UDTFM4 implements UDTF {
     }
 
     dataType =
-        
UDFDataTypeTransformer.transformToTsDataType(validator.getParameters().getDataType(0));
+        UDFDataTypeTransformer.transformToTsDataType(
+            validator.getParameters().getDataType(0));
   }
 
   @Override
   public void beforeStart(UDFParameters parameters, UDTFConfigurations 
configurations)
       throws MetadataException {
     // set data type
-    
configurations.setOutputDataType(UDFDataTypeTransformer.transformToUDFDataType(dataType));
+    configurations.setOutputDataType(
+        UDFDataTypeTransformer.transformToUDFDataType(dataType));
 
     // set access strategy
     if (accessStrategy == AccessStrategy.SIZE_WINDOW) {
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/utils/TableUDFUtils.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/utils/TableUDFUtils.java
new file mode 100644
index 00000000000..bc2d42507a9
--- /dev/null
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/utils/TableUDFUtils.java
@@ -0,0 +1,54 @@
+/*
+ * 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 boolean isScalarFunction(String functionName) {
+    try {
+      UDFManagementService.getInstance().reflect(functionName, 
ScalarFunction.class);
+      return true;
+    } catch (Throwable e) {
+      return false;
+    }
+  }
+
+  public static boolean isTableFunction(String functionName) {
+    try {
+      UDFManagementService.getInstance().reflect(functionName, 
TableFunction.class);
+      return true;
+    } catch (Throwable e) {
+      return false;
+    }
+  }
+
+  public static boolean isAggregateFunction(String functionName) {
+    try {
+      UDFManagementService.getInstance().reflect(functionName, 
AggregateFunction.class);
+      return true;
+    } catch (Throwable e) {
+      return false;
+    }
+  }
+}
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/utils/UDFDataTypeTransformer.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/utils/UDFDataTypeTransformer.java
index f2af9d7ea9c..1cae52ea5b9 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/utils/UDFDataTypeTransformer.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/utils/UDFDataTypeTransformer.java
@@ -21,6 +21,12 @@ package org.apache.iotdb.commons.udf.utils;
 import org.apache.iotdb.udf.api.type.Type;
 
 import org.apache.tsfile.enums.TSDataType;
+import org.apache.tsfile.read.common.type.BinaryType;
+import org.apache.tsfile.read.common.type.BooleanType;
+import org.apache.tsfile.read.common.type.DoubleType;
+import org.apache.tsfile.read.common.type.FloatType;
+import org.apache.tsfile.read.common.type.IntType;
+import org.apache.tsfile.read.common.type.LongType;
 
 import java.util.List;
 import java.util.stream.Collectors;
@@ -77,6 +83,62 @@ public class UDFDataTypeTransformer {
     }
   }
 
+  public static Type 
transformReadTypeToUDFDataType(org.apache.tsfile.read.common.type.Type type) {
+    if (type == null) {
+      return null;
+    }
+    switch (type.getTypeEnum()) {
+      case BOOLEAN:
+        return Type.BOOLEAN;
+      case INT32:
+        return Type.INT32;
+      case INT64:
+        return Type.INT64;
+      case FLOAT:
+        return Type.FLOAT;
+      case DOUBLE:
+        return Type.DOUBLE;
+      case TEXT:
+        return Type.TEXT;
+      case TIMESTAMP:
+        return Type.TIMESTAMP;
+      case DATE:
+        return Type.DATE;
+      case BLOB:
+        return Type.BLOB;
+      case STRING:
+        return Type.STRING;
+      default:
+        throw new IllegalArgumentException("Invalid input: " + type);
+    }
+  }
+
+  public static org.apache.tsfile.read.common.type.Type 
transformUDFDataTypeToReadType(Type type) {
+    if (type == null) {
+      return null;
+    }
+    switch (type) {
+      case BOOLEAN:
+        return BooleanType.BOOLEAN;
+      case INT32:
+      case DATE:
+        return IntType.INT32;
+      case INT64:
+      case TIMESTAMP:
+        return LongType.INT64;
+      case FLOAT:
+        return FloatType.FLOAT;
+      case DOUBLE:
+        return DoubleType.DOUBLE;
+      case TEXT:
+      case BLOB:
+      case STRING:
+        return BinaryType.TEXT;
+      default:
+        throw new IllegalArgumentException("Invalid input: " + type);
+    }
+  }
+
   private static Type getUDFDataType(byte type) {
     switch (type) {
       case 0:

Reply via email to