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

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


The following commit(s) were added to refs/heads/master by this push:
     new 9db5ce48d6 [IOTDB-2992] JEXL UDF (#5787)
9db5ce48d6 is described below

commit 9db5ce48d66460aeef004a58016e8b750a2fc001
Author: AACEPT <[email protected]>
AuthorDate: Wed May 4 19:08:50 2022 +0800

    [IOTDB-2992] JEXL UDF (#5787)
    
    Co-authored-by: Steve Yurong Su <[email protected]>
---
 docs/UserGuide/Query-Data/Select-Expression.md     |  55 ++++
 docs/zh/UserGuide/Query-Data/Select-Expression.md  |  52 ++++
 .../db/integration/IoTDBUDTFBuiltinFunctionIT.java |  97 +++++++
 pom.xml                                            |   5 +
 .../UDFOutputSeriesDataTypeNotValidException.java  |  30 +++
 .../db/query/udf/builtin/BuiltinFunction.java      |   3 +-
 .../iotdb/db/query/udf/builtin/UDTFJexl.java       | 297 +++++++++++++++++++++
 7 files changed, 538 insertions(+), 1 deletion(-)

diff --git a/docs/UserGuide/Query-Data/Select-Expression.md 
b/docs/UserGuide/Query-Data/Select-Expression.md
index c8f9807617..7d9170750b 100644
--- a/docs/UserGuide/Query-Data/Select-Expression.md
+++ b/docs/UserGuide/Query-Data/Select-Expression.md
@@ -746,6 +746,61 @@ Total line number = 10
 It costs 0.041s
 ```
 
+### JEXL Function
+
+Java Expression Language (JEXL) is an expression language engine. We use JEXL 
to extend UDFs, which are implemented on the command line with simple lambda 
expressions. See the link for [operators supported in jexl lambda 
expressions](https://commons.apache.org/proper/commons-jexl/apidocs/org/apache/commons/jexl3/package-summary.html#customization).
+
+| Function Name | Allowed Input Series Data Types | Required Attributes        
                   | Output Series Data Type | Series Data Type  Description    
             |
+|----------|--------------------------------|---------------------------------------|------------|--------------------------------------------------|
+| JEXL   | INT32 / INT64 / FLOAT / DOUBLE / TEXT / BOOLEAN | `expr` is a 
standard lambda expression with only one argument, conforming to the format `x 
-> {...}`, for example `x -> {x * 2}` | INT32 / INT64 / FLOAT / DOUBLE / TEXT / 
BOOLEAN | Returns the input time series transformed by a lambda expression |
+
+#### Demonstrate
+Example data: `root.ln.wf01.wt01.temperature` has a total of `11` ordered data 
from `0.0-10.0`.
+
+```
+IoTDB> select temperature from root.ln.wf01.wt01;
++-----------------------------+-----------------------------+
+|                         Time|root.ln.wf01.wt01.temperature|
++-----------------------------+-----------------------------+
+|1970-01-01T08:00:00.000+08:00|                          0.0|
+|1970-01-01T08:00:00.001+08:00|                          1.0|
+|1970-01-01T08:00:00.002+08:00|                          2.0|
+|1970-01-01T08:00:00.003+08:00|                          3.0|
+|1970-01-01T08:00:00.004+08:00|                          4.0|
+|1970-01-01T08:00:00.005+08:00|                          5.0|
+|1970-01-01T08:00:00.006+08:00|                          6.0|
+|1970-01-01T08:00:00.007+08:00|                          7.0|
+|1970-01-01T08:00:00.008+08:00|                          8.0|
+|1970-01-01T08:00:00.009+08:00|                          9.0|
+|1970-01-01T08:00:00.010+08:00|                         10.0|
++-----------------------------+-----------------------------+
+```
+Sql:
+```sql
+select jexl(temperature, 'expr'='x -> {x + x}') as jexl1, jexl(temperature, 
'expr'='x -> {x * 3}') as jexl2, jexl(temperature, 'expr'='x -> {x * x}') as 
jexl3, jexl(temperature, 'expr'='x -> {multiply(x, 100)}') as jexl4 from 
root.ln.wf01.wt01;```
+```
+
+Result:
+```
++-----------------------------+-----+-----+-----+------+
+|                         Time|jexl1|jexl2|jexl3| jexl4|
++-----------------------------+-----+-----+-----+------+
+|1970-01-01T08:00:00.000+08:00|  0.0|  0.0|  0.0|   0.0|
+|1970-01-01T08:00:00.001+08:00|  2.0|  3.0|  1.0| 100.0|
+|1970-01-01T08:00:00.002+08:00|  4.0|  6.0|  4.0| 200.0|
+|1970-01-01T08:00:00.003+08:00|  6.0|  9.0|  9.0| 300.0|
+|1970-01-01T08:00:00.004+08:00|  8.0| 12.0| 16.0| 400.0|
+|1970-01-01T08:00:00.005+08:00| 10.0| 15.0| 25.0| 500.0|
+|1970-01-01T08:00:00.006+08:00| 12.0| 18.0| 36.0| 600.0|
+|1970-01-01T08:00:00.007+08:00| 14.0| 21.0| 49.0| 700.0|
+|1970-01-01T08:00:00.008+08:00| 16.0| 24.0| 64.0| 800.0|
+|1970-01-01T08:00:00.009+08:00| 18.0| 27.0| 81.0| 900.0|
+|1970-01-01T08:00:00.010+08:00| 20.0| 30.0|100.0|1000.0|
++-----------------------------+-----+-----+-----+------+
+Total line number = 11
+It costs 0.055s
+```
+
 ### User Defined Timeseries Generating Functions
 
 Please refer to [UDF (User Defined 
Function)](../Process-Data/UDF-User-Defined-Function.md).
diff --git a/docs/zh/UserGuide/Query-Data/Select-Expression.md 
b/docs/zh/UserGuide/Query-Data/Select-Expression.md
index d96589c761..fe6374d347 100644
--- a/docs/zh/UserGuide/Query-Data/Select-Expression.md
+++ b/docs/zh/UserGuide/Query-Data/Select-Expression.md
@@ -750,6 +750,58 @@ Total line number = 10
 It costs 0.041s
 ```
 
+### JEXL自定义函数
+Java Expression Language (JEXL) 
是一个表达式语言引擎。我们使用JEXL来扩展UDF,在命令行中,通过简易的lambda表达式来实现UDF。lambda表达式中支持的运算符详见链接 
[JEXL中lambda表达式支持的运算符](https://commons.apache.org/proper/commons-jexl/apidocs/org/apache/commons/jexl3/package-summary.html#customization)
 。
+
+
+| 函数名      | 可接收的输入序列类型                     | 必要的属性参数                          
     | 输出序列类型     | 功能类型                                             |
+|----------|--------------------------------|---------------------------------------|------------|--------------------------------------------------|
+| JEXL   | INT32 / INT64 / FLOAT / DOUBLE / TEXT / BOOLEAN | 
`expr`是一个标准的只有一个参数的lambda表达式,符合`x -> {...}`的格式,例如`x -> {x * 2}`| INT32 / INT64 
/ FLOAT / DOUBLE / TEXT / BOOLEAN | 返回将输入的时间序列通过lambda表达式变换的序列             |
+
+#### 演示
+测试数据:`root.ln.wf01.wt01.temperature`从`0.0-10.0`共`11`条数据。
+```
+IoTDB> select temperature from root.ln.wf01.wt01;
++-----------------------------+-----------------------------+
+|                         Time|root.ln.wf01.wt01.temperature|
++-----------------------------+-----------------------------+
+|1970-01-01T08:00:00.000+08:00|                          0.0|
+|1970-01-01T08:00:00.001+08:00|                          1.0|
+|1970-01-01T08:00:00.002+08:00|                          2.0|
+|1970-01-01T08:00:00.003+08:00|                          3.0|
+|1970-01-01T08:00:00.004+08:00|                          4.0|
+|1970-01-01T08:00:00.005+08:00|                          5.0|
+|1970-01-01T08:00:00.006+08:00|                          6.0|
+|1970-01-01T08:00:00.007+08:00|                          7.0|
+|1970-01-01T08:00:00.008+08:00|                          8.0|
+|1970-01-01T08:00:00.009+08:00|                          9.0|
+|1970-01-01T08:00:00.010+08:00|                         10.0|
++-----------------------------+-----------------------------+
+```
+sql:
+```sql
+select jexl(temperature, 'expr'='x -> {x + x}') as jexl1, jexl(temperature, 
'expr'='x -> {x * 3}') as jexl2, jexl(temperature, 'expr'='x -> {x * x}') as 
jexl3, jexl(temperature, 'expr'='x -> {multiply(x, 100)}') as jexl4 from 
root.ln.wf01.wt01;```
+```
+结果:
+```
++-----------------------------+-----+-----+-----+------+
+|                         Time|jexl1|jexl2|jexl3| jexl4|
++-----------------------------+-----+-----+-----+------+
+|1970-01-01T08:00:00.000+08:00|  0.0|  0.0|  0.0|   0.0|
+|1970-01-01T08:00:00.001+08:00|  2.0|  3.0|  1.0| 100.0|
+|1970-01-01T08:00:00.002+08:00|  4.0|  6.0|  4.0| 200.0|
+|1970-01-01T08:00:00.003+08:00|  6.0|  9.0|  9.0| 300.0|
+|1970-01-01T08:00:00.004+08:00|  8.0| 12.0| 16.0| 400.0|
+|1970-01-01T08:00:00.005+08:00| 10.0| 15.0| 25.0| 500.0|
+|1970-01-01T08:00:00.006+08:00| 12.0| 18.0| 36.0| 600.0|
+|1970-01-01T08:00:00.007+08:00| 14.0| 21.0| 49.0| 700.0|
+|1970-01-01T08:00:00.008+08:00| 16.0| 24.0| 64.0| 800.0|
+|1970-01-01T08:00:00.009+08:00| 18.0| 27.0| 81.0| 900.0|
+|1970-01-01T08:00:00.010+08:00| 20.0| 30.0|100.0|1000.0|
++-----------------------------+-----+-----+-----+------+
+Total line number = 11
+It costs 0.055s
+```
 
 ### 自定义时间序列生成函数
 
diff --git 
a/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBUDTFBuiltinFunctionIT.java
 
b/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBUDTFBuiltinFunctionIT.java
index b6349c914f..7b1d66f395 100644
--- 
a/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBUDTFBuiltinFunctionIT.java
+++ 
b/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBUDTFBuiltinFunctionIT.java
@@ -905,4 +905,101 @@ public class IoTDBUDTFBuiltinFunctionIT {
       e.printStackTrace();
     }
   }
+
+  @Test
+  public void testUDTFJexl() {
+    try (Connection connection = EnvFactory.getEnv().getConnection();
+        Statement statement = connection.createStatement()) {
+      statement.execute("CREATE TIMESERIES root.sg.d7.s1 with 
datatype=INT32,encoding=PLAIN");
+      statement.execute("CREATE TIMESERIES root.sg.d7.s2 with 
datatype=FLOAT,encoding=PLAIN");
+      statement.execute("CREATE TIMESERIES root.sg.d7.s3 with 
datatype=DOUBLE,encoding=PLAIN");
+      statement.execute("CREATE TIMESERIES root.sg.d7.s4 with 
datatype=TEXT,encoding=PLAIN");
+      statement.execute("CREATE TIMESERIES root.sg.d7.s5 with 
datatype=BOOLEAN,encoding=PLAIN");
+      statement.execute("CREATE TIMESERIES root.sg.d7.s6 with 
datatype=INT64,encoding=PLAIN");
+    } catch (SQLException throwable) {
+      fail(throwable.getMessage());
+    }
+    String[] SQL_FOR_SAMPLE_1 = new String[5];
+    String[] SQL_FOR_SAMPLE_2 = new String[5];
+    String[] SQL_FOR_SAMPLE_3 = new String[5];
+    String[] SQL_FOR_SAMPLE_4 = new String[5];
+    String[] SQL_FOR_SAMPLE_5 = new String[5];
+    String[] SQL_FOR_SAMPLE_6 = new String[5];
+    for (int i = 0; i < 5; i++) {
+      SQL_FOR_SAMPLE_1[i] =
+          String.format("insert into root.sg.d7(time, s1) values (%d, %d)", i, 
i + 1);
+      SQL_FOR_SAMPLE_2[i] =
+          String.format("insert into root.sg.d7(time, s2) values (%d, %f)", i, 
i + 1.0);
+      SQL_FOR_SAMPLE_3[i] =
+          String.format("insert into root.sg.d7(time, s3) values (%d, %f)", i, 
i + 1.0);
+      SQL_FOR_SAMPLE_4[i] =
+          String.format("insert into root.sg.d7(time, s4) values (%d, '%s')", 
i, "string");
+      SQL_FOR_SAMPLE_5[i] = String.format("insert into root.sg.d7(time, s5) 
values (%d, true)", i);
+      SQL_FOR_SAMPLE_6[i] =
+          String.format("insert into root.sg.d7(time, s6) values (%d, %d)", i, 
i + 8);
+    }
+    double[] ANSWER1 = new double[] {2, 4, 6, 8, 10};
+    double[] ANSWER2 = new double[] {2, 4, 6, 8, 10};
+    double[] ANSWER3 = new double[] {4, 7, 10, 13, 16};
+    String[] ANSWER4 = new String[] {"string2", "string2", "string2", 
"string2", "string2"};
+    try (Connection connection = EnvFactory.getEnv().getConnection();
+        Statement statement = connection.createStatement()) {
+      for (int i = 0; i < 5; i++) {
+        statement.execute(SQL_FOR_SAMPLE_1[i]);
+        statement.execute(SQL_FOR_SAMPLE_2[i]);
+        statement.execute(SQL_FOR_SAMPLE_3[i]);
+        statement.execute(SQL_FOR_SAMPLE_4[i]);
+        statement.execute(SQL_FOR_SAMPLE_5[i]);
+        statement.execute(SQL_FOR_SAMPLE_6[i]);
+      }
+    } catch (SQLException throwable) {
+      fail(throwable.getMessage());
+    }
+
+    try (Connection connection = EnvFactory.getEnv().getConnection();
+        Statement statement = connection.createStatement()) {
+      String functionName = "JEXL";
+      String expr1 = "x -> {2 * x}";
+      String expr2 = "x -> {x + x}";
+      String expr3 = "x -> {x * 3 + 1}";
+      String expr4 = "x -> {x + 2}";
+      String expr5 = "x -> {x == true}";
+      String expr6 = "x -> {x == x}";
+      ResultSet resultSet =
+          statement.executeQuery(
+              String.format(
+                  "select %s(s1, 'expr'='%s'), "
+                      + "%s(s2, 'expr'='%s'), "
+                      + "%s(s3, 'expr'='%s'), "
+                      + "%s(s4, 'expr'='%s'), "
+                      + "%s(s5, 'expr'='%s'), "
+                      + "%s(s6, 'expr'='%s') "
+                      + "from root.sg.d7",
+                  functionName,
+                  expr1,
+                  functionName,
+                  expr2,
+                  functionName,
+                  expr3,
+                  functionName,
+                  expr4,
+                  functionName,
+                  expr5,
+                  functionName,
+                  expr6));
+      int columnCount = resultSet.getMetaData().getColumnCount();
+      assertEquals(1 + 6, columnCount);
+      for (int i = 0; i < 5; i++) {
+        resultSet.next();
+        assertEquals(ANSWER1[i], resultSet.getDouble(2), 0.01);
+        assertEquals(ANSWER2[i], resultSet.getDouble(3), 0.01);
+        assertEquals(ANSWER3[i], resultSet.getDouble(4), 0.01);
+        assertEquals(ANSWER4[i], resultSet.getString(5));
+        assertTrue(resultSet.getBoolean(6));
+        assertTrue(resultSet.getBoolean(7));
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
 }
diff --git a/pom.xml b/pom.xml
index 47e150f4ae..289047b54c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -596,6 +596,11 @@
             <version>1.15.2</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-jexl3</artifactId>
+            <version>3.2.1</version>
+        </dependency>
     </dependencies>
     <build>
         <pluginManagement>
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/udf/api/exception/UDFOutputSeriesDataTypeNotValidException.java
 
b/server/src/main/java/org/apache/iotdb/db/query/udf/api/exception/UDFOutputSeriesDataTypeNotValidException.java
new file mode 100644
index 0000000000..f94591d97e
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/udf/api/exception/UDFOutputSeriesDataTypeNotValidException.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.db.query.udf.api.exception;
+
+public class UDFOutputSeriesDataTypeNotValidException extends 
UDFParameterNotValidException {
+
+  public UDFOutputSeriesDataTypeNotValidException(int index, String types) {
+    super(
+        String.format(
+            "the data type of the output series (index: %d) is not valid. 
expected: %s.",
+            index, types));
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/udf/builtin/BuiltinFunction.java
 
b/server/src/main/java/org/apache/iotdb/db/query/udf/builtin/BuiltinFunction.java
index 999e0ea923..bf1b7031e8 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/udf/builtin/BuiltinFunction.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/udf/builtin/BuiltinFunction.java
@@ -65,7 +65,8 @@ public enum BuiltinFunction {
   EQUAL_SIZE_BUCKET_AGG_SAMPLE("EQUAL_SIZE_BUCKET_AGG_SAMPLE", 
UDTFEqualSizeBucketAggSample.class),
   EQUAL_SIZE_BUCKET_M4_SAMPLE("EQUAL_SIZE_BUCKET_M4_SAMPLE", 
UDTFEqualSizeBucketM4Sample.class),
   EQUAL_SIZE_BUCKET_OUTLIER_SAMPLE(
-      "EQUAL_SIZE_BUCKET_OUTLIER_SAMPLE", 
UDTFEqualSizeBucketOutlierSample.class);
+      "EQUAL_SIZE_BUCKET_OUTLIER_SAMPLE", 
UDTFEqualSizeBucketOutlierSample.class),
+  JEXL("JEXL", UDTFJexl.class);
 
   private final String functionName;
   private final Class<?> functionClass;
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/udf/builtin/UDTFJexl.java 
b/server/src/main/java/org/apache/iotdb/db/query/udf/builtin/UDTFJexl.java
new file mode 100644
index 0000000000..af05530ec0
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/query/udf/builtin/UDTFJexl.java
@@ -0,0 +1,297 @@
+/*
+ * 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.query.udf.builtin;
+
+import org.apache.iotdb.commons.exception.MetadataException;
+import org.apache.iotdb.db.exception.query.QueryProcessException;
+import org.apache.iotdb.db.query.udf.api.UDTF;
+import org.apache.iotdb.db.query.udf.api.access.Row;
+import org.apache.iotdb.db.query.udf.api.collector.PointCollector;
+import org.apache.iotdb.db.query.udf.api.customizer.config.UDTFConfigurations;
+import 
org.apache.iotdb.db.query.udf.api.customizer.parameter.UDFParameterValidator;
+import org.apache.iotdb.db.query.udf.api.customizer.parameter.UDFParameters;
+import 
org.apache.iotdb.db.query.udf.api.customizer.strategy.RowByRowAccessStrategy;
+import org.apache.iotdb.db.query.udf.api.exception.UDFException;
+import 
org.apache.iotdb.db.query.udf.api.exception.UDFInputSeriesDataTypeNotValidException;
+import 
org.apache.iotdb.db.query.udf.api.exception.UDFOutputSeriesDataTypeNotValidException;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+
+import org.apache.commons.jexl3.JexlBuilder;
+import org.apache.commons.jexl3.JexlEngine;
+import org.apache.commons.jexl3.JexlScript;
+
+import java.io.IOException;
+
+public class UDTFJexl implements UDTF {
+
+  private TSDataType outputDataType;
+  private JexlScript script;
+  private Evaluator evaluator;
+
+  @Override
+  public void validate(UDFParameterValidator validator) throws UDFException {
+    validator
+        .validateInputSeriesNumber(1)
+        .validateInputSeriesDataType(
+            0,
+            TSDataType.INT32,
+            TSDataType.INT64,
+            TSDataType.FLOAT,
+            TSDataType.DOUBLE,
+            TSDataType.TEXT,
+            TSDataType.BOOLEAN)
+        .validateRequiredAttribute("expr");
+  }
+
+  @Override
+  public void beforeStart(UDFParameters parameters, UDTFConfigurations 
configurations)
+      throws UDFInputSeriesDataTypeNotValidException, 
UDFOutputSeriesDataTypeNotValidException,
+          MetadataException {
+    String expr = parameters.getString("expr");
+    JexlEngine jexl = new JexlBuilder().create();
+    script = jexl.createScript(expr);
+
+    TSDataType inputDataType = parameters.getDataType(0);
+    outputDataType = probeOutputDataType(inputDataType);
+
+    switch (inputDataType) {
+      case INT32:
+        evaluator = new EvaluatorIntInput();
+        break;
+      case INT64:
+        evaluator = new EvaluatorLongInput();
+        break;
+      case FLOAT:
+        evaluator = new EvaluatorFloatInput();
+        break;
+      case DOUBLE:
+        evaluator = new EvaluatorDoubleInput();
+        break;
+      case TEXT:
+        evaluator = new EvaluatorStringInput();
+        break;
+      case BOOLEAN:
+        evaluator = new EvaluatorBooleanInput();
+        break;
+      default:
+        throw new UDFInputSeriesDataTypeNotValidException(
+            0,
+            inputDataType,
+            TSDataType.INT32,
+            TSDataType.INT64,
+            TSDataType.FLOAT,
+            TSDataType.DOUBLE,
+            TSDataType.TEXT,
+            TSDataType.BOOLEAN);
+    }
+
+    configurations
+        .setAccessStrategy(new RowByRowAccessStrategy())
+        .setOutputDataType(outputDataType);
+  }
+
+  private TSDataType probeOutputDataType(TSDataType inputDataType)
+      throws UDFInputSeriesDataTypeNotValidException, 
UDFOutputSeriesDataTypeNotValidException {
+    Object o;
+    // 23, 23L, 23f, 23d, "string", true are hard codes for probing
+    switch (inputDataType) {
+      case INT32:
+        o = script.execute(null, 23);
+        break;
+      case INT64:
+        o = script.execute(null, 23L);
+        break;
+      case FLOAT:
+        o = script.execute(null, 23f);
+        break;
+      case DOUBLE:
+        o = script.execute(null, 23d);
+        break;
+      case TEXT:
+        o = script.execute(null, "string");
+        break;
+      case BOOLEAN:
+        o = script.execute(null, true);
+        break;
+      default:
+        // This will not happen.
+        throw new UDFInputSeriesDataTypeNotValidException(
+            0,
+            inputDataType,
+            TSDataType.INT32,
+            TSDataType.INT64,
+            TSDataType.FLOAT,
+            TSDataType.DOUBLE,
+            TSDataType.TEXT,
+            TSDataType.BOOLEAN);
+    }
+
+    if (o instanceof Number) {
+      return TSDataType.DOUBLE;
+    } else if (o instanceof String) {
+      return TSDataType.TEXT;
+    } else if (o instanceof Boolean) {
+      return TSDataType.BOOLEAN;
+    } else {
+      throw new UDFOutputSeriesDataTypeNotValidException(0, "[Number, String, 
Boolean]");
+    }
+  }
+
+  @Override
+  public void transform(Row row, PointCollector collector)
+      throws IOException, UDFOutputSeriesDataTypeNotValidException, 
QueryProcessException {
+    switch (outputDataType) {
+      case DOUBLE:
+        evaluator.evaluateDouble(row, collector);
+        break;
+      case TEXT:
+        evaluator.evaluateText(row, collector);
+        break;
+      case BOOLEAN:
+        evaluator.evaluateBoolean(row, collector);
+        break;
+      default:
+        // This will not happen.
+        throw new UDFOutputSeriesDataTypeNotValidException(0, "[Number, 
String, Boolean]");
+    }
+  }
+
+  private interface Evaluator {
+    void evaluateDouble(Row row, PointCollector collector) throws IOException;
+
+    void evaluateText(Row row, PointCollector collector) throws IOException, 
QueryProcessException;
+
+    void evaluateBoolean(Row row, PointCollector collector) throws IOException;
+  }
+
+  private class EvaluatorIntInput implements Evaluator {
+    @Override
+    public void evaluateDouble(Row row, PointCollector collector) throws 
IOException {
+      collector.putDouble(
+          row.getTime(), ((Number) script.execute(null, 
row.getInt(0))).doubleValue());
+    }
+
+    @Override
+    public void evaluateText(Row row, PointCollector collector)
+        throws IOException, QueryProcessException {
+      collector.putString(row.getTime(), (String) script.execute(null, 
row.getInt(0)));
+    }
+
+    @Override
+    public void evaluateBoolean(Row row, PointCollector collector) throws 
IOException {
+      collector.putBoolean(row.getTime(), (Boolean) script.execute(null, 
row.getInt(0)));
+    }
+  }
+
+  private class EvaluatorLongInput implements Evaluator {
+    @Override
+    public void evaluateDouble(Row row, PointCollector collector) throws 
IOException {
+      collector.putDouble(
+          row.getTime(), ((Number) script.execute(null, 
row.getLong(0))).doubleValue());
+    }
+
+    @Override
+    public void evaluateText(Row row, PointCollector collector)
+        throws IOException, QueryProcessException {
+      collector.putString(row.getTime(), (String) script.execute(null, 
row.getLong(0)));
+    }
+
+    @Override
+    public void evaluateBoolean(Row row, PointCollector collector) throws 
IOException {
+      collector.putBoolean(row.getTime(), (Boolean) script.execute(null, 
row.getLong(0)));
+    }
+  }
+
+  private class EvaluatorFloatInput implements Evaluator {
+    @Override
+    public void evaluateDouble(Row row, PointCollector collector) throws 
IOException {
+      collector.putDouble(
+          row.getTime(), ((Number) script.execute(null, 
row.getFloat(0))).doubleValue());
+    }
+
+    @Override
+    public void evaluateText(Row row, PointCollector collector)
+        throws IOException, QueryProcessException {
+      collector.putString(row.getTime(), (String) script.execute(null, 
row.getFloat(0)));
+    }
+
+    @Override
+    public void evaluateBoolean(Row row, PointCollector collector) throws 
IOException {
+      collector.putBoolean(row.getTime(), (Boolean) script.execute(null, 
row.getFloat(0)));
+    }
+  }
+
+  private class EvaluatorDoubleInput implements Evaluator {
+    @Override
+    public void evaluateDouble(Row row, PointCollector collector) throws 
IOException {
+      collector.putDouble(
+          row.getTime(), ((Number) script.execute(null, 
row.getDouble(0))).doubleValue());
+    }
+
+    @Override
+    public void evaluateText(Row row, PointCollector collector)
+        throws IOException, QueryProcessException {
+      collector.putString(row.getTime(), (String) script.execute(null, 
row.getDouble(0)));
+    }
+
+    @Override
+    public void evaluateBoolean(Row row, PointCollector collector) throws 
IOException {
+      collector.putBoolean(row.getTime(), (Boolean) script.execute(null, 
row.getDouble(0)));
+    }
+  }
+
+  private class EvaluatorStringInput implements Evaluator {
+    @Override
+    public void evaluateDouble(Row row, PointCollector collector) throws 
IOException {
+      collector.putDouble(
+          row.getTime(), ((Number) script.execute(null, 
row.getString(0))).doubleValue());
+    }
+
+    @Override
+    public void evaluateText(Row row, PointCollector collector)
+        throws IOException, QueryProcessException {
+      collector.putString(row.getTime(), (String) script.execute(null, 
row.getString(0)));
+    }
+
+    @Override
+    public void evaluateBoolean(Row row, PointCollector collector) throws 
IOException {
+      collector.putBoolean(row.getTime(), (Boolean) script.execute(null, 
row.getString(0)));
+    }
+  }
+
+  private class EvaluatorBooleanInput implements Evaluator {
+    @Override
+    public void evaluateDouble(Row row, PointCollector collector) throws 
IOException {
+      collector.putDouble(
+          row.getTime(), ((Number) script.execute(null, 
row.getBoolean(0))).doubleValue());
+    }
+
+    @Override
+    public void evaluateText(Row row, PointCollector collector)
+        throws IOException, QueryProcessException {
+      collector.putString(row.getTime(), (String) script.execute(null, 
row.getBoolean(0)));
+    }
+
+    @Override
+    public void evaluateBoolean(Row row, PointCollector collector) throws 
IOException {
+      collector.putBoolean(row.getTime(), (Boolean) script.execute(null, 
row.getBoolean(0)));
+    }
+  }
+}

Reply via email to