You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ro...@apache.org on 2022/05/08 15:41:42 UTC
[iotdb] branch master updated: [IOTDB-2992] JEXL UDF: support multi input columns (#5810)
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 c446c692f0 [IOTDB-2992] JEXL UDF: support multi input columns (#5810)
c446c692f0 is described below
commit c446c692f062aac854f49532ca44b9aa1ee86614
Author: AACEPT <34...@users.noreply.github.com>
AuthorDate: Sun May 8 23:41:37 2022 +0800
[IOTDB-2992] JEXL UDF: support multi input columns (#5810)
---
docs/UserGuide/Query-Data/Select-Expression.md | 74 +++----
docs/zh/UserGuide/Query-Data/Select-Expression.md | 72 +++----
.../db/integration/IoTDBUDTFBuiltinFunctionIT.java | 39 +++-
.../iotdb/db/query/udf/builtin/UDTFJexl.java | 224 +++++++++++++--------
4 files changed, 252 insertions(+), 157 deletions(-)
diff --git a/docs/UserGuide/Query-Data/Select-Expression.md b/docs/UserGuide/Query-Data/Select-Expression.md
index 7d9170750b..d97fc85622 100644
--- a/docs/UserGuide/Query-Data/Select-Expression.md
+++ b/docs/UserGuide/Query-Data/Select-Expression.md
@@ -752,53 +752,53 @@ Java Expression Language (JEXL) is an expression language engine. We use JEXL to
| 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 |
+| JEXL | INT32 / INT64 / FLOAT / DOUBLE / TEXT / BOOLEAN | `expr` is a lambda expression that supports standard one or multi arguments in the form `x -> {...}` or `(x, y, z) -> {...}`, e.g. ` x -> {x * 2}`, `(x, y, z) -> {x + y * z}` | 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|
-+-----------------------------+-----------------------------+
+Example data: `root.ln.wf01.wt01.temperature`, `root.ln.wf01.wt01.st`, `root.ln.wf01.wt01.str` a total of `11` data.
+
+```
+IoTDB> select * from root.ln.wf01.wt01;
++-----------------------------+---------------------+--------------------+-----------------------------+
+| Time|root.ln.wf01.wt01.str|root.ln.wf01.wt01.st|root.ln.wf01.wt01.temperature|
++-----------------------------+---------------------+--------------------+-----------------------------+
+|1970-01-01T08:00:00.000+08:00| str| 10.0| 0.0|
+|1970-01-01T08:00:00.001+08:00| str| 20.0| 1.0|
+|1970-01-01T08:00:00.002+08:00| str| 30.0| 2.0|
+|1970-01-01T08:00:00.003+08:00| str| 40.0| 3.0|
+|1970-01-01T08:00:00.004+08:00| str| 50.0| 4.0|
+|1970-01-01T08:00:00.005+08:00| str| 60.0| 5.0|
+|1970-01-01T08:00:00.006+08:00| str| 70.0| 6.0|
+|1970-01-01T08:00:00.007+08:00| str| 80.0| 7.0|
+|1970-01-01T08:00:00.008+08:00| str| 90.0| 8.0|
+|1970-01-01T08:00:00.009+08:00| str| 100.0| 9.0|
+|1970-01-01T08:00:00.010+08:00| str| 110.0| 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;```
+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, jexl(temperature, st, 'expr'='(x, y) -> {x + y}') as jexl5, jexl(temperature, st, str, 'expr'='(x, y, z) -> {x + y + z}') as jexl6 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|
-+-----------------------------+-----+-----+-----+------+
++-----------------------------+-----+-----+-----+------+-----+--------+
+| Time|jexl1|jexl2|jexl3| jexl4|jexl5| jexl6|
++-----------------------------+-----+-----+-----+------+-----+--------+
+|1970-01-01T08:00:00.000+08:00| 0.0| 0.0| 0.0| 0.0| 10.0| 10.0str|
+|1970-01-01T08:00:00.001+08:00| 2.0| 3.0| 1.0| 100.0| 21.0| 21.0str|
+|1970-01-01T08:00:00.002+08:00| 4.0| 6.0| 4.0| 200.0| 32.0| 32.0str|
+|1970-01-01T08:00:00.003+08:00| 6.0| 9.0| 9.0| 300.0| 43.0| 43.0str|
+|1970-01-01T08:00:00.004+08:00| 8.0| 12.0| 16.0| 400.0| 54.0| 54.0str|
+|1970-01-01T08:00:00.005+08:00| 10.0| 15.0| 25.0| 500.0| 65.0| 65.0str|
+|1970-01-01T08:00:00.006+08:00| 12.0| 18.0| 36.0| 600.0| 76.0| 76.0str|
+|1970-01-01T08:00:00.007+08:00| 14.0| 21.0| 49.0| 700.0| 87.0| 87.0str|
+|1970-01-01T08:00:00.008+08:00| 16.0| 24.0| 64.0| 800.0| 98.0| 98.0str|
+|1970-01-01T08:00:00.009+08:00| 18.0| 27.0| 81.0| 900.0|109.0|109.0str|
+|1970-01-01T08:00:00.010+08:00| 20.0| 30.0|100.0|1000.0|120.0|120.0str|
++-----------------------------+-----+-----+-----+------+-----+--------+
Total line number = 11
-It costs 0.055s
+It costs 0.118s
```
### User Defined Timeseries Generating Functions
diff --git a/docs/zh/UserGuide/Query-Data/Select-Expression.md b/docs/zh/UserGuide/Query-Data/Select-Expression.md
index fe6374d347..5758f601fc 100644
--- a/docs/zh/UserGuide/Query-Data/Select-Expression.md
+++ b/docs/zh/UserGuide/Query-Data/Select-Expression.md
@@ -756,51 +756,51 @@ Java Expression Language (JEXL) 是一个表达式语言引擎。我们使用JEX
| 函数名 | 可接收的输入序列类型 | 必要的属性参数 | 输出序列类型 | 功能类型 |
|----------|--------------------------------|---------------------------------------|------------|--------------------------------------------------|
-| JEXL | INT32 / INT64 / FLOAT / DOUBLE / TEXT / BOOLEAN | `expr`是一个标准的只有一个参数的lambda表达式,符合`x -> {...}`的格式,例如`x -> {x * 2}`| INT32 / INT64 / FLOAT / DOUBLE / TEXT / BOOLEAN | 返回将输入的时间序列通过lambda表达式变换的序列 |
+| JEXL | INT32 / INT64 / FLOAT / DOUBLE / TEXT / BOOLEAN | `expr`是一个支持标准的一元或多元参数的lambda表达式,符合`x -> {...}`或`(x, y, z) -> {...}`的格式,例如`x -> {x * 2}`, `(x, y, z) -> {x + y * z}`| 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|
-+-----------------------------+-----------------------------+
+测试数据:`root.ln.wf01.wt01.temperature`, `root.ln.wf01.wt01.st`, `root.ln.wf01.wt01.str`共`11`条数据。
+```
+IoTDB> select * from root.ln.wf01.wt01;
++-----------------------------+---------------------+--------------------+-----------------------------+
+| Time|root.ln.wf01.wt01.str|root.ln.wf01.wt01.st|root.ln.wf01.wt01.temperature|
++-----------------------------+---------------------+--------------------+-----------------------------+
+|1970-01-01T08:00:00.000+08:00| str| 10.0| 0.0|
+|1970-01-01T08:00:00.001+08:00| str| 20.0| 1.0|
+|1970-01-01T08:00:00.002+08:00| str| 30.0| 2.0|
+|1970-01-01T08:00:00.003+08:00| str| 40.0| 3.0|
+|1970-01-01T08:00:00.004+08:00| str| 50.0| 4.0|
+|1970-01-01T08:00:00.005+08:00| str| 60.0| 5.0|
+|1970-01-01T08:00:00.006+08:00| str| 70.0| 6.0|
+|1970-01-01T08:00:00.007+08:00| str| 80.0| 7.0|
+|1970-01-01T08:00:00.008+08:00| str| 90.0| 8.0|
+|1970-01-01T08:00:00.009+08:00| str| 100.0| 9.0|
+|1970-01-01T08:00:00.010+08:00| str| 110.0| 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;```
+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, jexl(temperature, st, 'expr'='(x, y) -> {x + y}') as jexl5, jexl(temperature, st, str, 'expr'='(x, y, z) -> {x + y + z}') as jexl6 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|
-+-----------------------------+-----+-----+-----+------+
++-----------------------------+-----+-----+-----+------+-----+--------+
+| Time|jexl1|jexl2|jexl3| jexl4|jexl5| jexl6|
++-----------------------------+-----+-----+-----+------+-----+--------+
+|1970-01-01T08:00:00.000+08:00| 0.0| 0.0| 0.0| 0.0| 10.0| 10.0str|
+|1970-01-01T08:00:00.001+08:00| 2.0| 3.0| 1.0| 100.0| 21.0| 21.0str|
+|1970-01-01T08:00:00.002+08:00| 4.0| 6.0| 4.0| 200.0| 32.0| 32.0str|
+|1970-01-01T08:00:00.003+08:00| 6.0| 9.0| 9.0| 300.0| 43.0| 43.0str|
+|1970-01-01T08:00:00.004+08:00| 8.0| 12.0| 16.0| 400.0| 54.0| 54.0str|
+|1970-01-01T08:00:00.005+08:00| 10.0| 15.0| 25.0| 500.0| 65.0| 65.0str|
+|1970-01-01T08:00:00.006+08:00| 12.0| 18.0| 36.0| 600.0| 76.0| 76.0str|
+|1970-01-01T08:00:00.007+08:00| 14.0| 21.0| 49.0| 700.0| 87.0| 87.0str|
+|1970-01-01T08:00:00.008+08:00| 16.0| 24.0| 64.0| 800.0| 98.0| 98.0str|
+|1970-01-01T08:00:00.009+08:00| 18.0| 27.0| 81.0| 900.0|109.0|109.0str|
+|1970-01-01T08:00:00.010+08:00| 20.0| 30.0|100.0|1000.0|120.0|120.0str|
++-----------------------------+-----+-----+-----+------+-----+--------+
Total line number = 11
-It costs 0.055s
+It costs 0.118s
```
### 自定义时间序列生成函数
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 7b1d66f395..e2bab16409 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
@@ -916,6 +916,9 @@ public class IoTDBUDTFBuiltinFunctionIT {
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");
+ statement.execute("CREATE TIMESERIES root.sg.d7.s7 with datatype=INT64,encoding=PLAIN");
+ statement.execute("CREATE TIMESERIES root.sg.d7.s8 with datatype=FLOAT,encoding=PLAIN");
+ statement.execute("CREATE TIMESERIES root.sg.d7.s9 with datatype=TEXT,encoding=PLAIN");
} catch (SQLException throwable) {
fail(throwable.getMessage());
}
@@ -925,6 +928,9 @@ public class IoTDBUDTFBuiltinFunctionIT {
String[] SQL_FOR_SAMPLE_4 = new String[5];
String[] SQL_FOR_SAMPLE_5 = new String[5];
String[] SQL_FOR_SAMPLE_6 = new String[5];
+ String[] SQL_FOR_SAMPLE_7 = new String[5];
+ String[] SQL_FOR_SAMPLE_8 = new String[5];
+ String[] SQL_FOR_SAMPLE_9 = 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);
@@ -937,11 +943,20 @@ public class IoTDBUDTFBuiltinFunctionIT {
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);
+ SQL_FOR_SAMPLE_7[i] =
+ String.format("insert into root.sg.d7(time, s7) values (%d, %d)", i, i + 1);
+ SQL_FOR_SAMPLE_8[i] =
+ String.format("insert into root.sg.d7(time, s8) values (%d, %f)", i, i + 1.0);
+ SQL_FOR_SAMPLE_9[i] =
+ String.format("insert into root.sg.d7(time, s9) values (%d, '%s')", i, "string");
}
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"};
+ double[] ANSWER7 = new double[] {1, 4, 9, 16, 25};
+ String[] ANSWER8 = new String[] {"string1", "string4", "string9", "string16", "string25"};
+ double[] ANSWER9 = new double[] {2, 9, 28, 65, 126};
try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {
for (int i = 0; i < 5; i++) {
@@ -951,6 +966,9 @@ public class IoTDBUDTFBuiltinFunctionIT {
statement.execute(SQL_FOR_SAMPLE_4[i]);
statement.execute(SQL_FOR_SAMPLE_5[i]);
statement.execute(SQL_FOR_SAMPLE_6[i]);
+ statement.execute(SQL_FOR_SAMPLE_7[i]);
+ statement.execute(SQL_FOR_SAMPLE_8[i]);
+ statement.execute(SQL_FOR_SAMPLE_9[i]);
}
} catch (SQLException throwable) {
fail(throwable.getMessage());
@@ -965,6 +983,9 @@ public class IoTDBUDTFBuiltinFunctionIT {
String expr4 = "x -> {x + 2}";
String expr5 = "x -> {x == true}";
String expr6 = "x -> {x == x}";
+ String expr7 = "(x, y) -> {x * y}";
+ String expr8 = "(x, y, z) -> {x + y * z}";
+ String expr9 = "(x, y, z, a) -> {x * y * z + (a ? 1 : -1)}";
ResultSet resultSet =
statement.executeQuery(
String.format(
@@ -973,7 +994,10 @@ public class IoTDBUDTFBuiltinFunctionIT {
+ "%s(s3, 'expr'='%s'), "
+ "%s(s4, 'expr'='%s'), "
+ "%s(s5, 'expr'='%s'), "
- + "%s(s6, 'expr'='%s') "
+ + "%s(s6, 'expr'='%s'), "
+ + "%s(s7, s8, 'expr'='%s'), "
+ + "%s(s4, s7, s1, 'expr'='%s'), "
+ + "%s(s1, s7, s8, s5, 'expr'='%s') "
+ "from root.sg.d7",
functionName,
expr1,
@@ -986,9 +1010,15 @@ public class IoTDBUDTFBuiltinFunctionIT {
functionName,
expr5,
functionName,
- expr6));
+ expr6,
+ functionName,
+ expr7,
+ functionName,
+ expr8,
+ functionName,
+ expr9));
int columnCount = resultSet.getMetaData().getColumnCount();
- assertEquals(1 + 6, columnCount);
+ assertEquals(1 + 9, columnCount);
for (int i = 0; i < 5; i++) {
resultSet.next();
assertEquals(ANSWER1[i], resultSet.getDouble(2), 0.01);
@@ -997,6 +1027,9 @@ public class IoTDBUDTFBuiltinFunctionIT {
assertEquals(ANSWER4[i], resultSet.getString(5));
assertTrue(resultSet.getBoolean(6));
assertTrue(resultSet.getBoolean(7));
+ assertEquals(ANSWER7[i], resultSet.getDouble(8), 0.01);
+ assertEquals(ANSWER8[i], resultSet.getString(9));
+ assertEquals(ANSWER9[i], resultSet.getDouble(10), 0.01);
}
} catch (Exception e) {
e.printStackTrace();
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
index af05530ec0..20a529e31d 100644
--- 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
@@ -38,26 +38,30 @@ import org.apache.commons.jexl3.JexlEngine;
import org.apache.commons.jexl3.JexlScript;
import java.io.IOException;
+import java.util.HashMap;
public class UDTFJexl implements UDTF {
+ private int inputSeriesNumber;
+ private TSDataType[] inputDataType;
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");
+ inputSeriesNumber = validator.getParameters().getPaths().size();
+ for (int i = 0; i < inputSeriesNumber; i++) {
+ validator.validateInputSeriesDataType(
+ i,
+ TSDataType.INT32,
+ TSDataType.INT64,
+ TSDataType.FLOAT,
+ TSDataType.DOUBLE,
+ TSDataType.TEXT,
+ TSDataType.BOOLEAN);
+ }
+ validator.validateRequiredAttribute("expr");
}
@Override
@@ -68,38 +72,45 @@ public class UDTFJexl implements UDTF {
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);
+ inputDataType = new TSDataType[inputSeriesNumber];
+ for (int i = 0; i < inputSeriesNumber; i++) {
+ inputDataType[i] = parameters.getDataType(i);
+ }
+ outputDataType = probeOutputDataType();
+
+ if (inputSeriesNumber == 1) {
+ switch (inputDataType[0]) {
+ 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[0],
+ TSDataType.INT32,
+ TSDataType.INT64,
+ TSDataType.FLOAT,
+ TSDataType.DOUBLE,
+ TSDataType.TEXT,
+ TSDataType.BOOLEAN);
+ }
+ } else {
+ evaluator = new EvaluatorMulInput();
}
configurations
@@ -107,42 +118,28 @@ public class UDTFJexl implements UDTF {
.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);
+ // 23, 23L, 23f, 23d, "string", true are hard codes for probing
+ private HashMap<TSDataType, Object> initialMap() {
+ HashMap<TSDataType, Object> map = new HashMap<TSDataType, Object>();
+ map.put(TSDataType.INT32, 23);
+ map.put(TSDataType.INT64, 23L);
+ map.put(TSDataType.FLOAT, 23f);
+ map.put(TSDataType.DOUBLE, 23d);
+ map.put(TSDataType.TEXT, "string");
+ map.put(TSDataType.BOOLEAN, true);
+ return map;
+ }
+
+ private TSDataType probeOutputDataType() throws UDFOutputSeriesDataTypeNotValidException {
+ // initial inputHardCodes to probe OutputDataType
+ HashMap<TSDataType, Object> map = initialMap();
+ Object[] inputHardCodes = new Object[inputSeriesNumber];
+ for (int i = 0; i < inputSeriesNumber; i++) {
+ inputHardCodes[i] = map.get(inputDataType[i]);
}
+ Object o = script.execute(null, inputHardCodes);
+
if (o instanceof Number) {
return TSDataType.DOUBLE;
} else if (o instanceof String) {
@@ -156,7 +153,8 @@ public class UDTFJexl implements UDTF {
@Override
public void transform(Row row, PointCollector collector)
- throws IOException, UDFOutputSeriesDataTypeNotValidException, QueryProcessException {
+ throws IOException, UDFOutputSeriesDataTypeNotValidException, QueryProcessException,
+ UDFInputSeriesDataTypeNotValidException {
switch (outputDataType) {
case DOUBLE:
evaluator.evaluateDouble(row, collector);
@@ -174,11 +172,14 @@ public class UDTFJexl implements UDTF {
}
private interface Evaluator {
- void evaluateDouble(Row row, PointCollector collector) throws IOException;
+ void evaluateDouble(Row row, PointCollector collector)
+ throws IOException, UDFInputSeriesDataTypeNotValidException;
- void evaluateText(Row row, PointCollector collector) throws IOException, QueryProcessException;
+ void evaluateText(Row row, PointCollector collector)
+ throws IOException, QueryProcessException, UDFInputSeriesDataTypeNotValidException;
- void evaluateBoolean(Row row, PointCollector collector) throws IOException;
+ void evaluateBoolean(Row row, PointCollector collector)
+ throws IOException, UDFInputSeriesDataTypeNotValidException;
}
private class EvaluatorIntInput implements Evaluator {
@@ -294,4 +295,65 @@ public class UDTFJexl implements UDTF {
collector.putBoolean(row.getTime(), (Boolean) script.execute(null, row.getBoolean(0)));
}
}
+
+ private class EvaluatorMulInput implements Evaluator {
+
+ Object[] values = new Object[inputSeriesNumber];
+
+ @Override
+ public void evaluateDouble(Row row, PointCollector collector)
+ throws IOException, UDFInputSeriesDataTypeNotValidException {
+ getValues(row);
+ collector.putDouble(row.getTime(), ((Number) script.execute(null, values)).doubleValue());
+ }
+
+ @Override
+ public void evaluateText(Row row, PointCollector collector)
+ throws IOException, QueryProcessException, UDFInputSeriesDataTypeNotValidException {
+ getValues(row);
+ collector.putString(row.getTime(), (String) script.execute(null, values));
+ }
+
+ @Override
+ public void evaluateBoolean(Row row, PointCollector collector)
+ throws IOException, UDFInputSeriesDataTypeNotValidException {
+ getValues(row);
+ collector.putBoolean(row.getTime(), (Boolean) script.execute(null, values));
+ }
+
+ public void getValues(Row row) throws IOException, UDFInputSeriesDataTypeNotValidException {
+ for (int i = 0; i < inputSeriesNumber; i++) {
+ switch (inputDataType[i]) {
+ case INT32:
+ values[i] = row.getInt(i);
+ break;
+ case INT64:
+ values[i] = row.getLong(i);
+ break;
+ case FLOAT:
+ values[i] = row.getFloat(i);
+ break;
+ case DOUBLE:
+ values[i] = row.getDouble(i);
+ break;
+ case TEXT:
+ values[i] = row.getString(i);
+ break;
+ case BOOLEAN:
+ values[i] = row.getBoolean(i);
+ break;
+ default:
+ throw new UDFInputSeriesDataTypeNotValidException(
+ i,
+ inputDataType[i],
+ TSDataType.INT32,
+ TSDataType.INT64,
+ TSDataType.FLOAT,
+ TSDataType.DOUBLE,
+ TSDataType.TEXT,
+ TSDataType.BOOLEAN);
+ }
+ }
+ }
+ }
}