You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ja...@apache.org on 2024/08/27 02:48:52 UTC
(iotdb) branch ty/EnhanceInPredicate created (now b5bb63ef1f8)
This is an automated email from the ASF dual-hosted git repository.
jackietien pushed a change to branch ty/EnhanceInPredicate
in repository https://gitbox.apache.org/repos/asf/iotdb.git
at b5bb63ef1f8 Support expression in InPredicate
This branch includes the following new commits:
new b5bb63ef1f8 Support expression in InPredicate
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(iotdb) 01/01: Support expression in InPredicate
Posted by ja...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
jackietien pushed a commit to branch ty/EnhanceInPredicate
in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit b5bb63ef1f83087f40377ec3a3023638aef6510d
Author: JackieTien97 <ja...@gmail.com>
AuthorDate: Tue Aug 27 10:48:39 2024 +0800
Support expression in InPredicate
---
.../scalar/IoTDBRoundFunctionTableIT.java | 6 ++
.../it/query/old/query/IoTDBInTableIT.java | 79 ++++++++++++---
.../relational/ColumnTransformerBuilder.java | 107 ++++++++++++++++++++-
.../PredicateCombineIntoTableScanChecker.java | 18 +++-
.../PredicatePushIntoMetadataChecker.java | 3 +-
.../relational/metadata/TableMetadataImpl.java | 15 ++-
.../multi/InBinaryMultiColumnTransformer.java | 59 ++++++++++++
.../multi/InBooleanMultiColumnTransformer.java | 58 +++++++++++
.../multi/InDoubleMultiColumnTransformer.java | 58 +++++++++++
.../multi/InFloatMultiColumnTransformer.java | 58 +++++++++++
.../multi/InInt32MultiColumnTransformer.java | 58 +++++++++++
.../multi/InInt64MultiColumnTransformer.java | 58 +++++++++++
.../dag/column/multi/InMultiColumnTransformer.java | 54 +++++++++++
.../dag/column/unary/InColumnTransformer.java | 41 ++++----
14 files changed, 629 insertions(+), 43 deletions(-)
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBRoundFunctionTableIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBRoundFunctionTableIT.java
index c90e2659d63..25baece8d53 100644
--- a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBRoundFunctionTableIT.java
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/builtinfunction/scalar/IoTDBRoundFunctionTableIT.java
@@ -309,5 +309,11 @@ public class IoTDBRoundFunctionTableIT {
TSStatusCode.SEMANTIC_ERROR.getStatusCode()
+ ": Scalar function round only supports two numeric data types [INT32, INT64, FLOAT, DOUBLE]",
DATABASE_NAME);
+
+ tableAssertTestFail(
+ "select round(time) from table1",
+ TSStatusCode.SEMANTIC_ERROR.getStatusCode()
+ + ": Scalar function round only supports two numeric data types [INT32, INT64, FLOAT, DOUBLE]",
+ DATABASE_NAME);
}
}
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/query/IoTDBInTableIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/query/IoTDBInTableIT.java
index 9a4a5a144f5..cb5bb58fe53 100644
--- a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/query/IoTDBInTableIT.java
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/old/query/IoTDBInTableIT.java
@@ -57,19 +57,19 @@ public class IoTDBInTableIT {
new String[] {
"CREATE DATABASE " + DATABASE_NAME,
"USE " + DATABASE_NAME,
- "CREATE TABLE sg(device1 STRING ID, device2 STRING ID, qrcode TEXT MEASUREMENT)",
- "insert into sg(time,device1,device2,qrcode) values(1509465600000,'d1','s1','qrcode001')",
- "insert into sg(time,device1,device2,qrcode) values(1509465660000,'d1','s1','qrcode002')",
- "insert into sg(time,device1,device2,qrcode) values(1509465720000,'d1','s1','qrcode003')",
- "insert into sg(time,device1,device2,qrcode) values(1509465780000,'d1','s1','qrcode004')",
- "insert into sg(time,device1,device2,qrcode) values(1509465720000,'d1','s2','qrcode002')",
- "insert into sg(time,device1,device2,qrcode) values(1509465780000,'d1','s2','qrcode003')",
- "insert into sg(time,device1,device2,qrcode) values(1509465840000,'d1','s2','qrcode004')",
- "insert into sg(time,device1,device2,qrcode) values(1509465900000,'d1','s2','qrcode005')",
- "insert into sg(time,device1,device2,qrcode) values(1509465780000,'d2','s1','qrcode002')",
- "insert into sg(time,device1,device2,qrcode) values(1509465840000,'d2','s1','qrcode003')",
- "insert into sg(time,device1,device2,qrcode) values(1509465900000,'d2','s1','qrcode004')",
- "insert into sg(time,device1,device2,qrcode) values(1509465960000,'d2','s1','qrcode005')",
+ "CREATE TABLE sg(device1 STRING ID, device2 STRING ID, qrcode TEXT MEASUREMENT, date_v DATE MEASUREMENT, blob_v BLOB MEASUREMENT)",
+ "insert into sg(time,device1,device2,qrcode,date_v,blob_v) values(1509465600000,'d1','s1','qrcode001', '2024-08-01', X'abc0')",
+ "insert into sg(time,device1,device2,qrcode,date_v,blob_v) values(1509465660000,'d1','s1','qrcode002', '2024-08-02', X'abc1')",
+ "insert into sg(time,device1,device2,qrcode,date_v,blob_v) values(1509465720000,'d1','s1','qrcode003', '2024-08-03', X'abc2')",
+ "insert into sg(time,device1,device2,qrcode,date_v,blob_v) values(1509465780000,'d1','s1','qrcode004', '2024-08-04', X'abc3')",
+ "insert into sg(time,device1,device2,qrcode,date_v,blob_v) values(1509465720000,'d1','s2','qrcode002', '2024-08-05', X'abc4')",
+ "insert into sg(time,device1,device2,qrcode,date_v,blob_v) values(1509465780000,'d1','s2','qrcode003', '2024-08-06', X'abc5')",
+ "insert into sg(time,device1,device2,qrcode,date_v,blob_v) values(1509465840000,'d1','s2','qrcode004', '2024-08-07', X'abc6')",
+ "insert into sg(time,device1,device2,qrcode,date_v,blob_v) values(1509465900000,'d1','s2','qrcode005', '2024-08-08', X'abc7')",
+ "insert into sg(time,device1,device2,qrcode,date_v,blob_v) values(1509465780000,'d2','s1','qrcode002', '2024-08-09', X'abc8')",
+ "insert into sg(time,device1,device2,qrcode,date_v,blob_v) values(1509465840000,'d2','s1','qrcode003', '2024-08-10', X'abc9')",
+ "insert into sg(time,device1,device2,qrcode,date_v,blob_v) values(1509465900000,'d2','s1','qrcode004', '2024-08-11', X'abca')",
+ "insert into sg(time,device1,device2,qrcode,date_v,blob_v) values(1509465960000,'d2','s1','qrcode005', '2024-08-12', X'abcb')",
"CREATE TABLE table1(device STRING ID, s1 INT32 MEASUREMENT, s2 INT64 MEASUREMENT, s3 FLOAT MEASUREMENT, s4 DOUBLE MEASUREMENT, s5 BOOLEAN MEASUREMENT)",
};
@@ -132,7 +132,7 @@ public class IoTDBInTableIT {
statement.execute("USE " + DATABASE_NAME);
try (ResultSet resultSet =
statement.executeQuery(
- "select * from sg where qrcode in ('d1','s1','qrcode002','qrcode004') order by device1,device2")) {
+ "select time,device1,device2,qrcode from sg where qrcode in ('d1','s1','qrcode002','qrcode004') order by device1,device2")) {
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
List<Integer> actualIndexToExpectedIndexList =
checkHeader(
@@ -158,6 +158,57 @@ public class IoTDBInTableIT {
}
Assert.assertEquals(6, cnt);
}
+
+ // DATE IN
+ try (ResultSet resultSet =
+ statement.executeQuery(
+ "select date_v from sg where date_v in (CAST('2024-08-05' AS DATE), CAST('2024-08-12' AS DATE), CAST('2024-08-22' AS DATE)) order by date_v")) {
+ ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+ checkHeader(
+ resultSetMetaData,
+ "date_v,",
+ new int[] {
+ Types.DATE,
+ });
+
+ int cnt = 0;
+ while (resultSet.next()) {
+ String expectedString = "2024-08-05,2024-08-12,";
+ StringBuilder actualBuilder = new StringBuilder();
+ for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
+ actualBuilder.append(resultSet.getString(i)).append(",");
+ }
+ Assert.assertEquals(expectedString, actualBuilder.toString());
+ cnt++;
+ }
+ Assert.assertEquals(2, cnt);
+ }
+
+ // BLOB IN
+ try (ResultSet resultSet =
+ statement.executeQuery(
+ "select blob_v from sg where blob_v in (X'abc3', X'abca', X'bbbb') order by blob_v")) {
+ ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+ checkHeader(
+ resultSetMetaData,
+ "blob_v,",
+ new int[] {
+ Types.BLOB,
+ });
+
+ int cnt = 0;
+ while (resultSet.next()) {
+ String expectedString = "0xabc3,0xabca,";
+ StringBuilder actualBuilder = new StringBuilder();
+ for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
+ actualBuilder.append(resultSet.getString(i)).append(",");
+ }
+ Assert.assertEquals(expectedString, actualBuilder.toString());
+ cnt++;
+ }
+ Assert.assertEquals(2, cnt);
+ }
+
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
index 19fe9b2edb3..bdaa1f2ea1c 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/relational/ColumnTransformerBuilder.java
@@ -76,11 +76,17 @@ import org.apache.iotdb.db.queryengine.transformation.dag.column.leaf.IdentityCo
import org.apache.iotdb.db.queryengine.transformation.dag.column.leaf.LeafColumnTransformer;
import org.apache.iotdb.db.queryengine.transformation.dag.column.leaf.NullColumnTransformer;
import org.apache.iotdb.db.queryengine.transformation.dag.column.leaf.TimeColumnTransformer;
+import org.apache.iotdb.db.queryengine.transformation.dag.column.multi.InBinaryMultiColumnTransformer;
+import org.apache.iotdb.db.queryengine.transformation.dag.column.multi.InBooleanMultiColumnTransformer;
+import org.apache.iotdb.db.queryengine.transformation.dag.column.multi.InDoubleMultiColumnTransformer;
+import org.apache.iotdb.db.queryengine.transformation.dag.column.multi.InFloatMultiColumnTransformer;
+import org.apache.iotdb.db.queryengine.transformation.dag.column.multi.InInt32MultiColumnTransformer;
+import org.apache.iotdb.db.queryengine.transformation.dag.column.multi.InInt64MultiColumnTransformer;
+import org.apache.iotdb.db.queryengine.transformation.dag.column.multi.InMultiColumnTransformer;
import org.apache.iotdb.db.queryengine.transformation.dag.column.multi.LogicalAndMultiColumnTransformer;
import org.apache.iotdb.db.queryengine.transformation.dag.column.multi.LogicalOrMultiColumnTransformer;
import org.apache.iotdb.db.queryengine.transformation.dag.column.ternary.BetweenColumnTransformer;
import org.apache.iotdb.db.queryengine.transformation.dag.column.unary.ArithmeticNegationColumnTransformer;
-import org.apache.iotdb.db.queryengine.transformation.dag.column.unary.InColumnTransformer;
import org.apache.iotdb.db.queryengine.transformation.dag.column.unary.IsNullColumnTransformer;
import org.apache.iotdb.db.queryengine.transformation.dag.column.unary.LogicNotColumnTransformer;
import org.apache.iotdb.db.queryengine.transformation.dag.column.unary.RegularColumnTransformer;
@@ -147,15 +153,18 @@ import org.apache.tsfile.read.common.block.column.DoubleColumn;
import org.apache.tsfile.read.common.block.column.IntColumn;
import org.apache.tsfile.read.common.block.column.LongColumn;
import org.apache.tsfile.read.common.type.Type;
+import org.apache.tsfile.read.common.type.TypeEnum;
import org.apache.tsfile.utils.Binary;
+import org.apache.tsfile.utils.DateUtils;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.Set;
import java.util.stream.Collectors;
-import static com.google.common.base.Preconditions.checkArgument;
import static org.apache.iotdb.db.queryengine.plan.relational.analyzer.predicate.PredicatePushIntoMetadataChecker.isStringLiteral;
import static org.apache.iotdb.db.queryengine.plan.relational.type.InternalTypeManager.getTSDataType;
import static org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignatureTranslator.toTypeSignature;
@@ -928,14 +937,21 @@ public class ColumnTransformerBuilder
context.cache.put(node, identity);
} else {
ColumnTransformer childColumnTransformer = process(node.getValue(), context);
+ TypeEnum childTypeEnum = childColumnTransformer.getType().getTypeEnum();
InListExpression inListExpression = (InListExpression) node.getValueList();
List<Expression> expressionList = inListExpression.getValues();
List<Literal> values = new ArrayList<>();
+ List<ColumnTransformer> valueColumnTransformerList = new ArrayList<>();
+ valueColumnTransformerList.add(childColumnTransformer);
for (Expression expression : expressionList) {
- checkArgument(expression instanceof Literal);
- values.add((Literal) expression);
+ if (expression instanceof Literal) {
+ values.add((Literal) expression);
+ } else {
+ valueColumnTransformerList.add(process(expression, context));
+ }
}
- context.cache.put(node, new InColumnTransformer(BOOLEAN, childColumnTransformer, values));
+ context.cache.put(
+ node, constructInColumnTransformer(childTypeEnum, valueColumnTransformerList, values));
}
}
@@ -944,6 +960,87 @@ public class ColumnTransformerBuilder
return res;
}
+ private InMultiColumnTransformer constructInColumnTransformer(
+ TypeEnum childType,
+ List<ColumnTransformer> valueColumnTransformerList,
+ List<Literal> values) {
+ String errorMsg = "\"%s\" cannot be cast to [%s]";
+ switch (childType) {
+ case INT32:
+ Set<Integer> intSet = new HashSet<>();
+ for (Literal value : values) {
+ try {
+ long v = ((LongLiteral) value).getParsedValue();
+ if (v <= Integer.MAX_VALUE && v >= Integer.MIN_VALUE) {
+ intSet.add((int) v);
+ }
+ } catch (IllegalArgumentException e) {
+ throw new SemanticException(String.format(errorMsg, value, childType));
+ }
+ }
+ return new InInt32MultiColumnTransformer(intSet, valueColumnTransformerList);
+ case DATE:
+ Set<Integer> dateSet = new HashSet<>();
+ for (Literal value : values) {
+ dateSet.add(DateUtils.parseDateExpressionToInt(((StringLiteral) value).getValue()));
+ }
+ return new InInt32MultiColumnTransformer(dateSet, valueColumnTransformerList);
+ case INT64:
+ case TIMESTAMP:
+ Set<Long> longSet = new HashSet<>();
+ for (Literal value : values) {
+ try {
+ longSet.add((((LongLiteral) value).getParsedValue()));
+ } catch (IllegalArgumentException e) {
+ throw new SemanticException(String.format(errorMsg, value, childType));
+ }
+ }
+ return new InInt64MultiColumnTransformer(longSet, valueColumnTransformerList);
+ case FLOAT:
+ Set<Float> floatSet = new HashSet<>();
+ for (Literal value : values) {
+ try {
+ floatSet.add((float) ((DoubleLiteral) value).getValue());
+ } catch (IllegalArgumentException e) {
+ throw new SemanticException(String.format(errorMsg, value, childType));
+ }
+ }
+ return new InFloatMultiColumnTransformer(floatSet, valueColumnTransformerList);
+ case DOUBLE:
+ Set<Double> doubleSet = new HashSet<>();
+ for (Literal value : values) {
+ try {
+ doubleSet.add(((DoubleLiteral) value).getValue());
+ } catch (IllegalArgumentException e) {
+ throw new SemanticException(String.format(errorMsg, value, childType));
+ }
+ }
+ return new InDoubleMultiColumnTransformer(doubleSet, valueColumnTransformerList);
+ case BOOLEAN:
+ Set<Boolean> booleanSet = new HashSet<>();
+ for (Literal value : values) {
+ booleanSet.add(((BooleanLiteral) value).getValue());
+ }
+ return new InBooleanMultiColumnTransformer(booleanSet, valueColumnTransformerList);
+ case TEXT:
+ case STRING:
+ Set<Binary> stringSet = new HashSet<>();
+ for (Literal value : values) {
+ stringSet.add(
+ new Binary(((StringLiteral) value).getValue(), TSFileConfig.STRING_CHARSET));
+ }
+ return new InBinaryMultiColumnTransformer(stringSet, valueColumnTransformerList);
+ case BLOB:
+ Set<Binary> binarySet = new HashSet<>();
+ for (Literal value : values) {
+ binarySet.add(new Binary(((BinaryLiteral) value).getValue()));
+ }
+ return new InBinaryMultiColumnTransformer(binarySet, valueColumnTransformerList);
+ default:
+ throw new UnsupportedOperationException("unsupported data type: " + childType);
+ }
+ }
+
@Override
protected ColumnTransformer visitNotExpression(NotExpression node, Context context) {
if (!context.cache.containsKey(node)) {
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/PredicateCombineIntoTableScanChecker.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/PredicateCombineIntoTableScanChecker.java
index 1d7f74330c2..f80aa3ac691 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/PredicateCombineIntoTableScanChecker.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/PredicateCombineIntoTableScanChecker.java
@@ -23,10 +23,12 @@ import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BetweenPredicate;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ComparisonExpression;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.IfExpression;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InListExpression;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.InPredicate;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.IsNotNullPredicate;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.IsNullPredicate;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LikePredicate;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Literal;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LogicalExpression;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NotExpression;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NullIfExpression;
@@ -69,7 +71,21 @@ public class PredicateCombineIntoTableScanChecker extends PredicateVisitor<Boole
@Override
protected Boolean visitInPredicate(InPredicate node, Void context) {
- return isMeasurementColumn(node.getValue());
+ return isMeasurementColumn(node.getValue()) && isInListAllLiteral(node);
+ }
+
+ public static Boolean isInListAllLiteral(InPredicate node) {
+ if (node.getValue() instanceof InListExpression) {
+ List<Expression> values = ((InListExpression) node.getValue()).getValues();
+ for (Expression value : values) {
+ if (!(value instanceof Literal)) {
+ return Boolean.FALSE;
+ }
+ }
+ return Boolean.TRUE;
+ } else {
+ return Boolean.FALSE;
+ }
}
@Override
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/PredicatePushIntoMetadataChecker.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/PredicatePushIntoMetadataChecker.java
index 331b3e9db16..c01ba634bfd 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/PredicatePushIntoMetadataChecker.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/PredicatePushIntoMetadataChecker.java
@@ -38,6 +38,7 @@ import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SymbolReference;
import java.util.List;
import java.util.Set;
+import static org.apache.iotdb.db.queryengine.plan.relational.analyzer.predicate.PredicateCombineIntoTableScanChecker.isInListAllLiteral;
import static org.apache.iotdb.db.queryengine.plan.relational.analyzer.predicate.PredicatePushIntoScanChecker.isSymbolReference;
/**
@@ -65,7 +66,7 @@ public class PredicatePushIntoMetadataChecker extends PredicateVisitor<Boolean,
@Override
protected Boolean visitInPredicate(final InPredicate node, final Void context) {
- return isIdOrAttributeColumn(node.getValue());
+ return isIdOrAttributeColumn(node.getValue()) && isInListAllLiteral(node);
}
@Override
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 1fe3773aee5..1f7cadb111e 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
@@ -159,7 +159,8 @@ public class TableMetadataImpl implements Metadata {
}
return DOUBLE;
} else if (TableBuiltinScalarFunction.ROUND.getFunctionName().equalsIgnoreCase(functionName)) {
- if (!isOneNumericType(argumentTypes) && !isTwoNumericType(argumentTypes)) {
+ if (!isOneSupportedMathNumericType(argumentTypes)
+ && !isTwoSupportedMathNumericType(argumentTypes)) {
throw new SemanticException(
"Scalar function "
+ functionName.toLowerCase(Locale.ENGLISH)
@@ -481,7 +482,7 @@ public class TableMetadataImpl implements Metadata {
case SqlConstant.VARIANCE:
case SqlConstant.VAR_POP:
case SqlConstant.VAR_SAMP:
- if (!isOneNumericType(argumentTypes)) {
+ if (!isOneSupportedMathNumericType(argumentTypes)) {
throw new SemanticException(
String.format(
"Aggregate functions [%s] only support numeric data types [INT32, INT64, FLOAT, DOUBLE]",
@@ -652,6 +653,16 @@ public class TableMetadataImpl implements Metadata {
return argumentTypes.size() == 1 && isNumericType(argumentTypes.get(0));
}
+ public static boolean isTwoSupportedMathNumericType(List<? extends Type> argumentTypes) {
+ return argumentTypes.size() == 2
+ && isSupportedMathNumericType(argumentTypes.get(0))
+ && isSupportedMathNumericType(argumentTypes.get(1));
+ }
+
+ public static boolean isOneSupportedMathNumericType(List<? extends Type> argumentTypes) {
+ return argumentTypes.size() == 1 && isSupportedMathNumericType(argumentTypes.get(0));
+ }
+
public static boolean isOneBooleanType(List<? extends Type> argumentTypes) {
return argumentTypes.size() == 1 && BOOLEAN.equals(argumentTypes.get(0));
}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InBinaryMultiColumnTransformer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InBinaryMultiColumnTransformer.java
new file mode 100644
index 00000000000..9491a201ed1
--- /dev/null
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InBinaryMultiColumnTransformer.java
@@ -0,0 +1,59 @@
+/*
+ * 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.multi;
+
+import org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
+
+import org.apache.tsfile.block.column.Column;
+import org.apache.tsfile.read.common.type.Type;
+import org.apache.tsfile.utils.Binary;
+
+import java.util.List;
+import java.util.Set;
+
+public class InBinaryMultiColumnTransformer extends InMultiColumnTransformer {
+
+ private final Set<Binary> constantSet;
+
+ public InBinaryMultiColumnTransformer(
+ Set<Binary> constantSet, List<ColumnTransformer> columnTransformerList) {
+ super(columnTransformerList);
+ this.constantSet = constantSet;
+ }
+
+ @Override
+ protected boolean satisfy(List<Column> childrenColumns, int index) {
+ Binary value = childrenColumns.get(0).getBinary(index);
+ if (constantSet.contains(value)) {
+ return true;
+ } else {
+ for (int i = 1, size = childrenColumns.size(); i < size; i++) {
+ Column valueColumn = childrenColumns.get(i);
+ if (!valueColumn.isNull(i)) {
+ Type valueType = columnTransformerList.get(i).getType();
+ if (value.equals(valueType.getBinary(valueColumn, index))) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InBooleanMultiColumnTransformer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InBooleanMultiColumnTransformer.java
new file mode 100644
index 00000000000..f99bc791b39
--- /dev/null
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InBooleanMultiColumnTransformer.java
@@ -0,0 +1,58 @@
+/*
+ * 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.multi;
+
+import org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
+
+import org.apache.tsfile.block.column.Column;
+import org.apache.tsfile.read.common.type.Type;
+
+import java.util.List;
+import java.util.Set;
+
+public class InBooleanMultiColumnTransformer extends InMultiColumnTransformer {
+
+ private final Set<Boolean> constantSet;
+
+ public InBooleanMultiColumnTransformer(
+ Set<Boolean> constantSet, List<ColumnTransformer> columnTransformerList) {
+ super(columnTransformerList);
+ this.constantSet = constantSet;
+ }
+
+ @Override
+ protected boolean satisfy(List<Column> childrenColumns, int index) {
+ boolean value = childrenColumns.get(0).getBoolean(index);
+ if (constantSet.contains(value)) {
+ return true;
+ } else {
+ for (int i = 1, size = childrenColumns.size(); i < size; i++) {
+ Column valueColumn = childrenColumns.get(i);
+ if (!valueColumn.isNull(i)) {
+ Type valueType = columnTransformerList.get(i).getType();
+ if (valueType.getBoolean(valueColumn, index) == value) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InDoubleMultiColumnTransformer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InDoubleMultiColumnTransformer.java
new file mode 100644
index 00000000000..482214498b9
--- /dev/null
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InDoubleMultiColumnTransformer.java
@@ -0,0 +1,58 @@
+/*
+ * 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.multi;
+
+import org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
+
+import org.apache.tsfile.block.column.Column;
+import org.apache.tsfile.read.common.type.Type;
+
+import java.util.List;
+import java.util.Set;
+
+public class InDoubleMultiColumnTransformer extends InMultiColumnTransformer {
+
+ private final Set<Double> constantSet;
+
+ public InDoubleMultiColumnTransformer(
+ Set<Double> constantSet, List<ColumnTransformer> columnTransformerList) {
+ super(columnTransformerList);
+ this.constantSet = constantSet;
+ }
+
+ @Override
+ protected boolean satisfy(List<Column> childrenColumns, int index) {
+ double value = childrenColumns.get(0).getDouble(index);
+ if (constantSet.contains(value)) {
+ return true;
+ } else {
+ for (int i = 1, size = childrenColumns.size(); i < size; i++) {
+ Column valueColumn = childrenColumns.get(i);
+ if (!valueColumn.isNull(i)) {
+ Type valueType = columnTransformerList.get(i).getType();
+ if (valueType.getDouble(valueColumn, index) == value) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InFloatMultiColumnTransformer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InFloatMultiColumnTransformer.java
new file mode 100644
index 00000000000..310669c73cf
--- /dev/null
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InFloatMultiColumnTransformer.java
@@ -0,0 +1,58 @@
+/*
+ * 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.multi;
+
+import org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
+
+import org.apache.tsfile.block.column.Column;
+import org.apache.tsfile.read.common.type.Type;
+
+import java.util.List;
+import java.util.Set;
+
+public class InFloatMultiColumnTransformer extends InMultiColumnTransformer {
+
+ private final Set<Float> constantSet;
+
+ public InFloatMultiColumnTransformer(
+ Set<Float> constantSet, List<ColumnTransformer> columnTransformerList) {
+ super(columnTransformerList);
+ this.constantSet = constantSet;
+ }
+
+ @Override
+ protected boolean satisfy(List<Column> childrenColumns, int index) {
+ float value = childrenColumns.get(0).getFloat(index);
+ if (constantSet.contains(value)) {
+ return true;
+ } else {
+ for (int i = 1, size = childrenColumns.size(); i < size; i++) {
+ Column valueColumn = childrenColumns.get(i);
+ if (!valueColumn.isNull(i)) {
+ Type valueType = columnTransformerList.get(i).getType();
+ if (valueType.getFloat(valueColumn, index) == value) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InInt32MultiColumnTransformer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InInt32MultiColumnTransformer.java
new file mode 100644
index 00000000000..ad291426a1c
--- /dev/null
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InInt32MultiColumnTransformer.java
@@ -0,0 +1,58 @@
+/*
+ * 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.multi;
+
+import org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
+
+import org.apache.tsfile.block.column.Column;
+import org.apache.tsfile.read.common.type.Type;
+
+import java.util.List;
+import java.util.Set;
+
+public class InInt32MultiColumnTransformer extends InMultiColumnTransformer {
+
+ private final Set<Integer> constantSet;
+
+ public InInt32MultiColumnTransformer(
+ Set<Integer> constantSet, List<ColumnTransformer> columnTransformerList) {
+ super(columnTransformerList);
+ this.constantSet = constantSet;
+ }
+
+ @Override
+ protected boolean satisfy(List<Column> childrenColumns, int index) {
+ int value = childrenColumns.get(0).getInt(index);
+ if (constantSet.contains(value)) {
+ return true;
+ } else {
+ for (int i = 1, size = childrenColumns.size(); i < size; i++) {
+ Column valueColumn = childrenColumns.get(i);
+ if (!valueColumn.isNull(i)) {
+ Type valueType = columnTransformerList.get(i).getType();
+ if (valueType.getInt(valueColumn, index) == value) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InInt64MultiColumnTransformer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InInt64MultiColumnTransformer.java
new file mode 100644
index 00000000000..aa3ec1397fb
--- /dev/null
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InInt64MultiColumnTransformer.java
@@ -0,0 +1,58 @@
+/*
+ * 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.multi;
+
+import org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
+
+import org.apache.tsfile.block.column.Column;
+import org.apache.tsfile.read.common.type.Type;
+
+import java.util.List;
+import java.util.Set;
+
+public class InInt64MultiColumnTransformer extends InMultiColumnTransformer {
+
+ private final Set<Long> constantSet;
+
+ public InInt64MultiColumnTransformer(
+ Set<Long> constantSet, List<ColumnTransformer> columnTransformerList) {
+ super(columnTransformerList);
+ this.constantSet = constantSet;
+ }
+
+ @Override
+ protected boolean satisfy(List<Column> childrenColumns, int index) {
+ long value = childrenColumns.get(0).getLong(index);
+ if (constantSet.contains(value)) {
+ return true;
+ } else {
+ for (int i = 1, size = childrenColumns.size(); i < size; i++) {
+ Column valueColumn = childrenColumns.get(i);
+ if (!valueColumn.isNull(i)) {
+ Type valueType = columnTransformerList.get(i).getType();
+ if (valueType.getLong(valueColumn, index) == value) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InMultiColumnTransformer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InMultiColumnTransformer.java
new file mode 100644
index 00000000000..de59bc08bf6
--- /dev/null
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/multi/InMultiColumnTransformer.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.db.queryengine.transformation.dag.column.multi;
+
+import org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
+
+import org.apache.tsfile.block.column.Column;
+import org.apache.tsfile.block.column.ColumnBuilder;
+import org.apache.tsfile.read.common.type.BooleanType;
+
+import java.util.List;
+
+public abstract class InMultiColumnTransformer extends MultiColumnTransformer {
+
+ protected InMultiColumnTransformer(List<ColumnTransformer> columnTransformerList) {
+ super(BooleanType.BOOLEAN, columnTransformerList);
+ }
+
+ @Override
+ protected void checkType() {
+ // do nothing
+ }
+
+ @Override
+ protected void doTransform(
+ List<Column> childrenColumns, ColumnBuilder builder, int positionCount) {
+ for (int i = 0; i < positionCount; i++) {
+ if (!childrenColumns.get(0).isNull(i)) {
+ builder.writeBoolean(satisfy(childrenColumns, i));
+ } else {
+ builder.appendNull();
+ }
+ }
+ }
+
+ protected abstract boolean satisfy(List<Column> childrenColumns, int index);
+}
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/InColumnTransformer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/InColumnTransformer.java
index 884b5006f2b..29ef3d09403 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/InColumnTransformer.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/InColumnTransformer.java
@@ -20,6 +20,7 @@
package org.apache.iotdb.db.queryengine.transformation.dag.column.unary;
import org.apache.iotdb.db.exception.sql.SemanticException;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BinaryLiteral;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.BooleanLiteral;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DoubleLiteral;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Literal;
@@ -32,11 +33,13 @@ import org.apache.tsfile.block.column.ColumnBuilder;
import org.apache.tsfile.common.conf.TSFileConfig;
import org.apache.tsfile.read.common.type.Type;
import org.apache.tsfile.read.common.type.TypeEnum;
+import org.apache.tsfile.utils.Binary;
import org.apache.tsfile.utils.DateUtils;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.stream.Collectors;
public class InColumnTransformer extends UnaryColumnTransformer {
private final Satisfy satisfy;
@@ -48,7 +51,7 @@ public class InColumnTransformer extends UnaryColumnTransformer {
private Set<Float> floatSet;
private Set<Double> doubleSet;
private Set<Boolean> booleanSet;
- private Set<String> stringSet;
+ private Set<Binary> stringSet;
public InColumnTransformer(
Type returnType,
@@ -64,17 +67,6 @@ public class InColumnTransformer extends UnaryColumnTransformer {
initTypedSet(values);
}
- public InColumnTransformer(
- Type returnType, ColumnTransformer childColumnTransformer, List<Literal> values) {
- super(returnType, childColumnTransformer);
- satisfy = new InSatisfy();
- this.childType =
- childColumnTransformer.getType() == null
- ? null
- : childColumnTransformer.getType().getTypeEnum();
- initTypedSet(values);
- }
-
@Override
protected void doTransform(Column column, ColumnBuilder columnBuilder) {
for (int i = 0, n = column.getPositionCount(); i < n; i++) {
@@ -99,9 +91,8 @@ public class InColumnTransformer extends UnaryColumnTransformer {
break;
case STRING:
case TEXT:
- returnType.writeBoolean(
- columnBuilder,
- satisfy.of(column.getBinary(i).getStringValue(TSFileConfig.STRING_CHARSET)));
+ case BLOB:
+ returnType.writeBoolean(columnBuilder, satisfy.of(column.getBinary(i)));
break;
default:
throw new UnsupportedOperationException("unsupported data type: " + childType);
@@ -167,7 +158,10 @@ public class InColumnTransformer extends UnaryColumnTransformer {
break;
case TEXT:
case STRING:
- stringSet = values;
+ stringSet =
+ values.stream()
+ .map(v -> new Binary(v, TSFileConfig.STRING_CHARSET))
+ .collect(Collectors.toSet());
break;
default:
throw new UnsupportedOperationException("unsupported data type: " + childType);
@@ -237,7 +231,14 @@ public class InColumnTransformer extends UnaryColumnTransformer {
case STRING:
stringSet = new HashSet<>();
for (Literal value : values) {
- stringSet.add(((StringLiteral) value).getValue());
+ stringSet.add(
+ new Binary(((StringLiteral) value).getValue(), TSFileConfig.STRING_CHARSET));
+ }
+ break;
+ case BLOB:
+ stringSet = new HashSet<>();
+ for (Literal value : values) {
+ stringSet.add(new Binary(((BinaryLiteral) value).getValue()));
}
break;
default:
@@ -266,7 +267,7 @@ public class InColumnTransformer extends UnaryColumnTransformer {
boolean of(boolean booleanValue);
- boolean of(String stringValue);
+ boolean of(Binary stringValue);
}
private class InSatisfy implements Satisfy {
@@ -297,7 +298,7 @@ public class InColumnTransformer extends UnaryColumnTransformer {
}
@Override
- public boolean of(String stringValue) {
+ public boolean of(Binary stringValue) {
return stringSet.contains(stringValue);
}
}
@@ -330,7 +331,7 @@ public class InColumnTransformer extends UnaryColumnTransformer {
}
@Override
- public boolean of(String stringValue) {
+ public boolean of(Binary stringValue) {
return !stringSet.contains(stringValue);
}
}