This is an automated email from the ASF dual-hosted git repository. rong pushed a commit to branch iotdb-3145 in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 79bf5434ef40c792e921b2544f4b8894ebef1fee Author: Steve Yurong Su <[email protected]> AuthorDate: Fri May 13 16:38:09 2022 +0800 support type inferring --- .../iotdb/db/mpp/plan/analyze/TypeProvider.java | 4 + .../iotdb/db/query/expression/Expression.java | 21 ++++++ .../expression/binary/AdditionExpression.java | 2 +- .../binary/ArithmeticBinaryExpression.java | 60 +++++++++++++++ .../expression/binary/CompareBinaryExpression.java | 85 ++++++++++++++++++++++ .../expression/binary/DivisionExpression.java | 2 +- .../query/expression/binary/EqualToExpression.java | 2 +- .../expression/binary/GreaterEqualExpression.java | 2 +- .../expression/binary/GreaterThanExpression.java | 2 +- .../expression/binary/LessEqualExpression.java | 2 +- .../expression/binary/LessThanExpression.java | 2 +- .../expression/binary/LogicAndExpression.java | 2 +- ...rExpression.java => LogicBinaryExpression.java} | 35 ++++----- .../query/expression/binary/LogicOrExpression.java | 2 +- .../query/expression/binary/ModuloExpression.java | 2 +- .../binary/MultiplicationExpression.java | 2 +- .../expression/binary/NonEqualExpression.java | 2 +- .../expression/binary/SubtractionExpression.java | 2 +- .../db/query/expression/leaf/ConstantOperand.java | 7 ++ .../query/expression/leaf/TimeSeriesOperand.java | 7 ++ .../db/query/expression/leaf/TimestampOperand.java | 7 ++ .../query/expression/multi/FunctionExpression.java | 18 +++++ .../db/query/expression/unary/InExpression.java | 11 +++ .../db/query/expression/unary/LikeExpression.java | 14 ++++ .../query/expression/unary/LogicNotExpression.java | 14 ++++ .../query/expression/unary/NegationExpression.java | 20 +++++ .../query/expression/unary/RegularExpression.java | 14 ++++ .../api/customizer/parameter/UDFParameters.java | 12 +++ .../query/udf/core/executor/UDTFTypeInferrer.java | 68 +++++++++++++++++ 29 files changed, 390 insertions(+), 33 deletions(-) diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/TypeProvider.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/TypeProvider.java index 34d8acfc9a..6c70c44e2d 100644 --- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/TypeProvider.java +++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/TypeProvider.java @@ -55,6 +55,10 @@ public class TypeProvider { this.typeMap.put(path, dataType); } + public boolean containsTypeInfoOf(String path) { + return typeMap.containsKey(path); + } + public void serialize(ByteBuffer byteBuffer) { ReadWriteIOUtils.write(typeMap.size(), byteBuffer); for (Map.Entry<String, TSDataType> entry : typeMap.entrySet()) { diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/Expression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/Expression.java index 14d5007739..b666e70fc9 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/Expression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/Expression.java @@ -22,6 +22,8 @@ package org.apache.iotdb.db.query.expression; import org.apache.iotdb.commons.path.PartialPath; import org.apache.iotdb.db.exception.query.LogicalOptimizeException; import org.apache.iotdb.db.exception.query.QueryProcessException; +import org.apache.iotdb.db.exception.sql.SemanticException; +import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider; import org.apache.iotdb.db.qp.physical.crud.UDTFPlan; import org.apache.iotdb.db.query.expression.binary.AdditionExpression; import org.apache.iotdb.db.query.expression.binary.DivisionExpression; @@ -56,6 +58,7 @@ import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils; import java.io.IOException; import java.nio.ByteBuffer; import java.time.ZoneId; +import java.util.Arrays; import java.util.Deque; import java.util.Iterator; import java.util.LinkedList; @@ -108,6 +111,24 @@ public abstract class Expression { public abstract void constructUdfExecutors( Map<String, UDTFExecutor> expressionName2Executor, ZoneId zoneId); + ///////////////////////////////////////////////////////////////////////////////////////////////// + // type inference + ///////////////////////////////////////////////////////////////////////////////////////////////// + public abstract TSDataType inferTypes(TypeProvider typeProvider); + + protected static void checkInputExpressionDataType( + String expressionString, TSDataType actual, TSDataType... expected) { + for (TSDataType type : expected) { + if (actual.equals(type)) { + return; + } + } + throw new SemanticException( + String.format( + "Invalid input expression data type. expression: %s, actual data type: %s, expected data type(s): %s.", + expressionString, actual.name(), Arrays.toString(expected))); + } + ///////////////////////////////////////////////////////////////////////////////////////////////// // For expression evaluation DAG building ///////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/AdditionExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/AdditionExpression.java index 6ec5ce8399..6fd5e698fc 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/AdditionExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/AdditionExpression.java @@ -27,7 +27,7 @@ import org.apache.iotdb.db.query.udf.core.transformer.binary.ArithmeticBinaryTra import java.nio.ByteBuffer; -public class AdditionExpression extends BinaryExpression { +public class AdditionExpression extends ArithmeticBinaryExpression { public AdditionExpression(Expression leftExpression, Expression rightExpression) { super(leftExpression, rightExpression); diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/ArithmeticBinaryExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/ArithmeticBinaryExpression.java new file mode 100644 index 0000000000..185a8ce617 --- /dev/null +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/ArithmeticBinaryExpression.java @@ -0,0 +1,60 @@ +/* + * 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.expression.binary; + +import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider; +import org.apache.iotdb.db.query.expression.Expression; +import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; + +import java.nio.ByteBuffer; + +public abstract class ArithmeticBinaryExpression extends BinaryExpression { + + protected ArithmeticBinaryExpression(Expression leftExpression, Expression rightExpression) { + super(leftExpression, rightExpression); + } + + protected ArithmeticBinaryExpression(ByteBuffer byteBuffer) { + super(byteBuffer); + } + + @Override + public final TSDataType inferTypes(TypeProvider typeProvider) { + final String expressionString = toString(); + if (!typeProvider.containsTypeInfoOf(expressionString)) { + checkInputExpressionDataType( + leftExpression.toString(), + leftExpression.inferTypes(typeProvider), + TSDataType.INT32, + TSDataType.INT64, + TSDataType.FLOAT, + TSDataType.DOUBLE); + checkInputExpressionDataType( + rightExpression.toString(), + rightExpression.inferTypes(typeProvider), + TSDataType.INT32, + TSDataType.INT64, + TSDataType.FLOAT, + TSDataType.DOUBLE); + typeProvider.setType(expressionString, TSDataType.DOUBLE); + } + return TSDataType.DOUBLE; + } +} diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/CompareBinaryExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/CompareBinaryExpression.java new file mode 100644 index 0000000000..66f795faa1 --- /dev/null +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/CompareBinaryExpression.java @@ -0,0 +1,85 @@ +/* + * 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.expression.binary; + +import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider; +import org.apache.iotdb.db.query.expression.Expression; +import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; + +import java.nio.ByteBuffer; + +public abstract class CompareBinaryExpression extends BinaryExpression { + + protected CompareBinaryExpression(Expression leftExpression, Expression rightExpression) { + super(leftExpression, rightExpression); + } + + protected CompareBinaryExpression(ByteBuffer byteBuffer) { + super(byteBuffer); + } + + @Override + public TSDataType inferTypes(TypeProvider typeProvider) { + final String expressionString = toString(); + + if (!typeProvider.containsTypeInfoOf(expressionString)) { + final TSDataType leftExpressionDataType = leftExpression.inferTypes(typeProvider); + final TSDataType rightExpressionDataType = rightExpression.inferTypes(typeProvider); + + if (!leftExpressionDataType.equals(rightExpressionDataType)) { + final String leftExpressionString = leftExpression.toString(); + final String rightExpressionString = rightExpression.toString(); + + if (TSDataType.BOOLEAN.equals(leftExpressionDataType) + || TSDataType.BOOLEAN.equals(rightExpressionDataType)) { + checkInputExpressionDataType( + leftExpressionString, leftExpressionDataType, TSDataType.BOOLEAN); + checkInputExpressionDataType( + rightExpressionString, rightExpressionDataType, TSDataType.BOOLEAN); + } else if (TSDataType.TEXT.equals(leftExpressionDataType) + || TSDataType.TEXT.equals(rightExpressionDataType)) { + checkInputExpressionDataType( + leftExpressionString, leftExpressionDataType, TSDataType.TEXT); + checkInputExpressionDataType( + rightExpressionString, rightExpressionDataType, TSDataType.TEXT); + } else { + checkInputExpressionDataType( + leftExpressionString, + leftExpressionDataType, + TSDataType.INT32, + TSDataType.INT64, + TSDataType.FLOAT, + TSDataType.DOUBLE); + checkInputExpressionDataType( + rightExpressionString, + rightExpressionDataType, + TSDataType.INT32, + TSDataType.INT64, + TSDataType.FLOAT, + TSDataType.DOUBLE); + } + } + + typeProvider.setType(expressionString, TSDataType.BOOLEAN); + } + + return TSDataType.BOOLEAN; + } +} diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/DivisionExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/DivisionExpression.java index 5ba106f459..8eb9308d91 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/DivisionExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/DivisionExpression.java @@ -27,7 +27,7 @@ import org.apache.iotdb.db.query.udf.core.transformer.binary.ArithmeticDivisionT import java.nio.ByteBuffer; -public class DivisionExpression extends BinaryExpression { +public class DivisionExpression extends ArithmeticBinaryExpression { public DivisionExpression(Expression leftExpression, Expression rightExpression) { super(leftExpression, rightExpression); diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/EqualToExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/EqualToExpression.java index aa85becd07..d966284402 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/EqualToExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/EqualToExpression.java @@ -27,7 +27,7 @@ import org.apache.iotdb.db.query.udf.core.transformer.binary.CompareEqualToTrans import java.nio.ByteBuffer; -public class EqualToExpression extends BinaryExpression { +public class EqualToExpression extends CompareBinaryExpression { public EqualToExpression(Expression leftExpression, Expression rightExpression) { super(leftExpression, rightExpression); diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/GreaterEqualExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/GreaterEqualExpression.java index 0364212ac8..6d06a29284 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/GreaterEqualExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/GreaterEqualExpression.java @@ -27,7 +27,7 @@ import org.apache.iotdb.db.query.udf.core.transformer.binary.CompareGreaterEqual import java.nio.ByteBuffer; -public class GreaterEqualExpression extends BinaryExpression { +public class GreaterEqualExpression extends CompareBinaryExpression { public GreaterEqualExpression(Expression leftExpression, Expression rightExpression) { super(leftExpression, rightExpression); diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/GreaterThanExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/GreaterThanExpression.java index 56589b5e10..6a574f68e9 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/GreaterThanExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/GreaterThanExpression.java @@ -27,7 +27,7 @@ import org.apache.iotdb.db.query.udf.core.transformer.binary.CompareGreaterThanT import java.nio.ByteBuffer; -public class GreaterThanExpression extends BinaryExpression { +public class GreaterThanExpression extends CompareBinaryExpression { public GreaterThanExpression(Expression leftExpression, Expression rightExpression) { super(leftExpression, rightExpression); diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LessEqualExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LessEqualExpression.java index 599a05f67b..a0fff83b49 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LessEqualExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LessEqualExpression.java @@ -27,7 +27,7 @@ import org.apache.iotdb.db.query.udf.core.transformer.binary.CompareLessEqualTra import java.nio.ByteBuffer; -public class LessEqualExpression extends BinaryExpression { +public class LessEqualExpression extends CompareBinaryExpression { public LessEqualExpression(Expression leftExpression, Expression rightExpression) { super(leftExpression, rightExpression); diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LessThanExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LessThanExpression.java index 1852771e8e..8f49780392 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LessThanExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LessThanExpression.java @@ -27,7 +27,7 @@ import org.apache.iotdb.db.query.udf.core.transformer.binary.CompareLessThanTran import java.nio.ByteBuffer; -public class LessThanExpression extends BinaryExpression { +public class LessThanExpression extends CompareBinaryExpression { public LessThanExpression(Expression leftExpression, Expression rightExpression) { super(leftExpression, rightExpression); diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicAndExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicAndExpression.java index 35f19c258b..26ac76b3c2 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicAndExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicAndExpression.java @@ -27,7 +27,7 @@ import org.apache.iotdb.db.query.udf.core.transformer.binary.LogicBinaryTransfor import java.nio.ByteBuffer; -public class LogicAndExpression extends BinaryExpression { +public class LogicAndExpression extends LogicBinaryExpression { public LogicAndExpression(Expression leftExpression, Expression rightExpression) { super(leftExpression, rightExpression); diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicOrExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicBinaryExpression.java similarity index 53% copy from server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicOrExpression.java copy to server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicBinaryExpression.java index ee0609ae16..9ad7e20bfa 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicOrExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicBinaryExpression.java @@ -19,37 +19,32 @@ package org.apache.iotdb.db.query.expression.binary; +import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider; import org.apache.iotdb.db.query.expression.Expression; -import org.apache.iotdb.db.query.expression.ExpressionType; -import org.apache.iotdb.db.query.udf.core.reader.LayerPointReader; -import org.apache.iotdb.db.query.udf.core.transformer.binary.LogicBinaryTransformer; -import org.apache.iotdb.db.query.udf.core.transformer.binary.LogicOrTransformer; +import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; import java.nio.ByteBuffer; -public class LogicOrExpression extends BinaryExpression { +public abstract class LogicBinaryExpression extends BinaryExpression { - public LogicOrExpression(Expression leftExpression, Expression rightExpression) { + protected LogicBinaryExpression(Expression leftExpression, Expression rightExpression) { super(leftExpression, rightExpression); } - public LogicOrExpression(ByteBuffer byteBuffer) { + protected LogicBinaryExpression(ByteBuffer byteBuffer) { super(byteBuffer); } @Override - protected LogicBinaryTransformer constructTransformer( - LayerPointReader leftParentLayerPointReader, LayerPointReader rightParentLayerPointReader) { - return new LogicOrTransformer(leftParentLayerPointReader, rightParentLayerPointReader); - } - - @Override - protected String operator() { - return "|"; - } - - @Override - public ExpressionType getExpressionType() { - return ExpressionType.LOGIC_OR; + public final TSDataType inferTypes(TypeProvider typeProvider) { + final String expressionString = toString(); + if (!typeProvider.containsTypeInfoOf(expressionString)) { + checkInputExpressionDataType( + leftExpression.toString(), leftExpression.inferTypes(typeProvider), TSDataType.BOOLEAN); + checkInputExpressionDataType( + rightExpression.toString(), rightExpression.inferTypes(typeProvider), TSDataType.BOOLEAN); + typeProvider.setType(expressionString, TSDataType.BOOLEAN); + } + return TSDataType.BOOLEAN; } } diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicOrExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicOrExpression.java index ee0609ae16..eff1d56357 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicOrExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/LogicOrExpression.java @@ -27,7 +27,7 @@ import org.apache.iotdb.db.query.udf.core.transformer.binary.LogicOrTransformer; import java.nio.ByteBuffer; -public class LogicOrExpression extends BinaryExpression { +public class LogicOrExpression extends LogicBinaryExpression { public LogicOrExpression(Expression leftExpression, Expression rightExpression) { super(leftExpression, rightExpression); diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/ModuloExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/ModuloExpression.java index e43f23f3c5..39f4738aca 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/ModuloExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/ModuloExpression.java @@ -27,7 +27,7 @@ import org.apache.iotdb.db.query.udf.core.transformer.binary.ArithmeticModuloTra import java.nio.ByteBuffer; -public class ModuloExpression extends BinaryExpression { +public class ModuloExpression extends ArithmeticBinaryExpression { public ModuloExpression(Expression leftExpression, Expression rightExpression) { super(leftExpression, rightExpression); diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/MultiplicationExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/MultiplicationExpression.java index d5b15dc55d..6b72d5a2d2 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/MultiplicationExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/MultiplicationExpression.java @@ -27,7 +27,7 @@ import org.apache.iotdb.db.query.udf.core.transformer.binary.ArithmeticMultiplic import java.nio.ByteBuffer; -public class MultiplicationExpression extends BinaryExpression { +public class MultiplicationExpression extends ArithmeticBinaryExpression { public MultiplicationExpression(Expression leftExpression, Expression rightExpression) { super(leftExpression, rightExpression); diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/NonEqualExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/NonEqualExpression.java index 6c9337fa57..542d4a7c25 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/NonEqualExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/NonEqualExpression.java @@ -27,7 +27,7 @@ import org.apache.iotdb.db.query.udf.core.transformer.binary.CompareNonEqualTran import java.nio.ByteBuffer; -public class NonEqualExpression extends BinaryExpression { +public class NonEqualExpression extends CompareBinaryExpression { public NonEqualExpression(Expression leftExpression, Expression rightExpression) { super(leftExpression, rightExpression); diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/SubtractionExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/SubtractionExpression.java index 3e31ad9039..372d56cc73 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/binary/SubtractionExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/binary/SubtractionExpression.java @@ -27,7 +27,7 @@ import org.apache.iotdb.db.query.udf.core.transformer.binary.ArithmeticSubtracti import java.nio.ByteBuffer; -public class SubtractionExpression extends BinaryExpression { +public class SubtractionExpression extends ArithmeticBinaryExpression { public SubtractionExpression(Expression leftExpression, Expression rightExpression) { super(leftExpression, rightExpression); diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/ConstantOperand.java b/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/ConstantOperand.java index d92c8021c3..7acd877fc0 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/ConstantOperand.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/ConstantOperand.java @@ -21,6 +21,7 @@ package org.apache.iotdb.db.query.expression.leaf; import org.apache.iotdb.commons.path.PartialPath; import org.apache.iotdb.db.exception.query.QueryProcessException; +import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider; import org.apache.iotdb.db.qp.physical.crud.UDTFPlan; import org.apache.iotdb.db.query.expression.Expression; import org.apache.iotdb.db.query.expression.ExpressionType; @@ -91,6 +92,12 @@ public class ConstantOperand extends LeafOperand { // Do nothing } + @Override + public TSDataType inferTypes(TypeProvider typeProvider) { + typeProvider.setType(toString(), dataType); + return dataType; + } + @Override public void bindInputLayerColumnIndexWithExpression(UDTFPlan udtfPlan) { // Do nothing diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/TimeSeriesOperand.java b/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/TimeSeriesOperand.java index 11a6b72912..5d896a932f 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/TimeSeriesOperand.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/TimeSeriesOperand.java @@ -23,6 +23,7 @@ import org.apache.iotdb.commons.path.PartialPath; import org.apache.iotdb.db.exception.query.LogicalOptimizeException; import org.apache.iotdb.db.exception.query.QueryProcessException; import org.apache.iotdb.db.metadata.path.PathDeserializeUtil; +import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider; import org.apache.iotdb.db.qp.physical.crud.UDTFPlan; import org.apache.iotdb.db.query.expression.Expression; import org.apache.iotdb.db.query.expression.ExpressionType; @@ -87,6 +88,11 @@ public class TimeSeriesOperand extends LeafOperand { pathSet.add(path); } + @Override + public TSDataType inferTypes(TypeProvider typeProvider) { + return typeProvider.getType(toString()); + } + @Override public void bindInputLayerColumnIndexWithExpression(UDTFPlan udtfPlan) { inputColumnIndex = udtfPlan.getReaderIndexByExpressionName(toString()); @@ -125,6 +131,7 @@ public class TimeSeriesOperand extends LeafOperand { return expressionIntermediateLayerMap.get(this); } + @Override public String getExpressionStringInternal() { return path.isMeasurementAliasExists() ? path.getFullPathWithAlias() : path.getFullPath(); } diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/TimestampOperand.java b/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/TimestampOperand.java index 73c77a2b37..bb473451b7 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/TimestampOperand.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/leaf/TimestampOperand.java @@ -22,6 +22,7 @@ package org.apache.iotdb.db.query.expression.leaf; import org.apache.iotdb.commons.path.PartialPath; import org.apache.iotdb.db.exception.query.LogicalOptimizeException; import org.apache.iotdb.db.exception.query.QueryProcessException; +import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider; import org.apache.iotdb.db.qp.physical.crud.UDTFPlan; import org.apache.iotdb.db.query.expression.Expression; import org.apache.iotdb.db.query.expression.ExpressionType; @@ -75,6 +76,12 @@ public class TimestampOperand extends LeafOperand { pathSet.add(TIMESTAMP_PARTIAL_PATH); } + @Override + public TSDataType inferTypes(TypeProvider typeProvider) { + typeProvider.setType(toString(), TSDataType.INT64); + return TSDataType.INT64; + } + @Override public void bindInputLayerColumnIndexWithExpression(UDTFPlan udtfPlan) { // do nothing diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/multi/FunctionExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/multi/FunctionExpression.java index b2bd93b05c..7fe3f1e14e 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/multi/FunctionExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/multi/FunctionExpression.java @@ -23,6 +23,7 @@ import org.apache.iotdb.commons.conf.IoTDBConstant; import org.apache.iotdb.commons.path.PartialPath; import org.apache.iotdb.db.exception.query.LogicalOptimizeException; import org.apache.iotdb.db.exception.query.QueryProcessException; +import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider; import org.apache.iotdb.db.qp.constant.SQLConstant; import org.apache.iotdb.db.qp.physical.crud.UDTFPlan; import org.apache.iotdb.db.qp.strategy.optimizer.ConcatPathOptimizer; @@ -32,6 +33,7 @@ import org.apache.iotdb.db.query.expression.leaf.TimeSeriesOperand; import org.apache.iotdb.db.query.udf.api.customizer.strategy.AccessStrategy; import org.apache.iotdb.db.query.udf.core.executor.UDTFContext; import org.apache.iotdb.db.query.udf.core.executor.UDTFExecutor; +import org.apache.iotdb.db.query.udf.core.executor.UDTFTypeInferrer; import org.apache.iotdb.db.query.udf.core.layer.IntermediateLayer; import org.apache.iotdb.db.query.udf.core.layer.LayerMemoryAssigner; import org.apache.iotdb.db.query.udf.core.layer.MultiInputColumnIntermediateLayer; @@ -238,6 +240,22 @@ public class FunctionExpression extends Expression { expressionName2Executor.put(expressionString, new UDTFExecutor(this, zoneId)); } + @Override + public TSDataType inferTypes(TypeProvider typeProvider) { + final String expressionString = toString(); + + if (!typeProvider.containsTypeInfoOf(expressionString)) { + for (Expression expression : expressions) { + expression.inferTypes(typeProvider); + } + + typeProvider.setType( + expressionString, new UDTFTypeInferrer(this).inferOutputType(typeProvider)); + } + + return typeProvider.getType(expressionString); + } + @Override public void bindInputLayerColumnIndexWithExpression(UDTFPlan udtfPlan) { for (Expression expression : expressions) { diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/InExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/InExpression.java index 9f329b3728..979d4c2bbc 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/InExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/InExpression.java @@ -19,11 +19,13 @@ package org.apache.iotdb.db.query.expression.unary; +import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider; import org.apache.iotdb.db.query.expression.Expression; import org.apache.iotdb.db.query.expression.ExpressionType; import org.apache.iotdb.db.query.udf.core.reader.LayerPointReader; import org.apache.iotdb.db.query.udf.core.transformer.Transformer; import org.apache.iotdb.db.query.udf.core.transformer.unary.InTransformer; +import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils; import java.nio.ByteBuffer; @@ -59,6 +61,15 @@ public class InExpression extends UnaryExpression { return values; } + @Override + public TSDataType inferTypes(TypeProvider typeProvider) { + final String expressionString = toString(); + if (!typeProvider.containsTypeInfoOf(expressionString)) { + typeProvider.setType(expressionString, expression.inferTypes(typeProvider)); + } + return typeProvider.getType(expressionString); + } + @Override protected String getExpressionStringInternal() { StringBuilder valuesStringBuilder = new StringBuilder(); diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/LikeExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/LikeExpression.java index 2d91ac0720..0e94037e72 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/LikeExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/LikeExpression.java @@ -19,11 +19,14 @@ package org.apache.iotdb.db.query.expression.unary; +import org.apache.iotdb.db.exception.sql.SemanticException; +import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider; import org.apache.iotdb.db.query.expression.Expression; import org.apache.iotdb.db.query.expression.ExpressionType; import org.apache.iotdb.db.query.udf.core.reader.LayerPointReader; import org.apache.iotdb.db.query.udf.core.transformer.Transformer; import org.apache.iotdb.db.query.udf.core.transformer.unary.RegularTransformer; +import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils; import java.nio.ByteBuffer; @@ -115,6 +118,17 @@ public class LikeExpression extends UnaryExpression { return stringBuilder.toString(); } + @Override + public TSDataType inferTypes(TypeProvider typeProvider) throws SemanticException { + final String expressionString = toString(); + if (!typeProvider.containsTypeInfoOf(expressionString)) { + checkInputExpressionDataType( + expression.toString(), expression.inferTypes(typeProvider), TSDataType.TEXT); + typeProvider.setType(expressionString, TSDataType.TEXT); + } + return TSDataType.TEXT; + } + @Override protected String getExpressionStringInternal() { return expression + " LIKE '" + pattern + "'"; diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/LogicNotExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/LogicNotExpression.java index 2c22a52841..a538e4a028 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/LogicNotExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/LogicNotExpression.java @@ -19,6 +19,8 @@ package org.apache.iotdb.db.query.expression.unary; +import org.apache.iotdb.db.exception.sql.SemanticException; +import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider; import org.apache.iotdb.db.query.expression.Expression; import org.apache.iotdb.db.query.expression.ExpressionType; import org.apache.iotdb.db.query.expression.leaf.ConstantOperand; @@ -27,6 +29,7 @@ import org.apache.iotdb.db.query.expression.multi.FunctionExpression; import org.apache.iotdb.db.query.udf.core.reader.LayerPointReader; import org.apache.iotdb.db.query.udf.core.transformer.Transformer; import org.apache.iotdb.db.query.udf.core.transformer.unary.LogicNotTransformer; +import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; import java.nio.ByteBuffer; @@ -50,6 +53,17 @@ public class LogicNotExpression extends UnaryExpression { return new LogicNotExpression(childExpression); } + @Override + public TSDataType inferTypes(TypeProvider typeProvider) throws SemanticException { + final String expressionString = toString(); + if (!typeProvider.containsTypeInfoOf(expressionString)) { + checkInputExpressionDataType( + expression.toString(), expression.inferTypes(typeProvider), TSDataType.BOOLEAN); + typeProvider.setType(expressionString, TSDataType.BOOLEAN); + } + return TSDataType.BOOLEAN; + } + @Override public String getExpressionStringInternal() { return expression instanceof FunctionExpression diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/NegationExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/NegationExpression.java index 8e12a85a57..6d8c111078 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/NegationExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/NegationExpression.java @@ -19,6 +19,8 @@ package org.apache.iotdb.db.query.expression.unary; +import org.apache.iotdb.db.exception.sql.SemanticException; +import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider; import org.apache.iotdb.db.query.expression.Expression; import org.apache.iotdb.db.query.expression.ExpressionType; import org.apache.iotdb.db.query.expression.leaf.ConstantOperand; @@ -27,6 +29,7 @@ import org.apache.iotdb.db.query.expression.multi.FunctionExpression; import org.apache.iotdb.db.query.udf.core.reader.LayerPointReader; import org.apache.iotdb.db.query.udf.core.transformer.Transformer; import org.apache.iotdb.db.query.udf.core.transformer.unary.ArithmeticNegationTransformer; +import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; import java.nio.ByteBuffer; @@ -50,6 +53,23 @@ public class NegationExpression extends UnaryExpression { return new NegationExpression(childExpression); } + @Override + public TSDataType inferTypes(TypeProvider typeProvider) throws SemanticException { + final String expressionString = toString(); + if (!typeProvider.containsTypeInfoOf(expressionString)) { + TSDataType inputExpressionType = expression.inferTypes(typeProvider); + checkInputExpressionDataType( + expression.toString(), + inputExpressionType, + TSDataType.INT32, + TSDataType.INT64, + TSDataType.FLOAT, + TSDataType.DOUBLE); + typeProvider.setType(expressionString, inputExpressionType); + } + return typeProvider.getType(expressionString); + } + @Override public String getExpressionStringInternal() { return expression instanceof TimeSeriesOperand diff --git a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/RegularExpression.java b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/RegularExpression.java index f6027a9c8e..a8b30f0d5a 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/expression/unary/RegularExpression.java +++ b/server/src/main/java/org/apache/iotdb/db/query/expression/unary/RegularExpression.java @@ -19,11 +19,14 @@ package org.apache.iotdb.db.query.expression.unary; +import org.apache.iotdb.db.exception.sql.SemanticException; +import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider; import org.apache.iotdb.db.query.expression.Expression; import org.apache.iotdb.db.query.expression.ExpressionType; import org.apache.iotdb.db.query.udf.core.reader.LayerPointReader; import org.apache.iotdb.db.query.udf.core.transformer.Transformer; import org.apache.iotdb.db.query.udf.core.transformer.unary.RegularTransformer; +import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils; import org.apache.commons.lang3.Validate; @@ -72,6 +75,17 @@ public class RegularExpression extends UnaryExpression { return new RegularExpression(childExpression, patternString, pattern); } + @Override + public TSDataType inferTypes(TypeProvider typeProvider) throws SemanticException { + final String expressionString = toString(); + if (!typeProvider.containsTypeInfoOf(expressionString)) { + checkInputExpressionDataType( + expression.toString(), expression.inferTypes(typeProvider), TSDataType.TEXT); + typeProvider.setType(expressionString, TSDataType.TEXT); + } + return TSDataType.TEXT; + } + @Override protected String getExpressionStringInternal() { return expression + " REGEXP '" + patternString + "'"; diff --git a/server/src/main/java/org/apache/iotdb/db/query/udf/api/customizer/parameter/UDFParameters.java b/server/src/main/java/org/apache/iotdb/db/query/udf/api/customizer/parameter/UDFParameters.java index 5f057ccf8d..9b9b6640f0 100644 --- a/server/src/main/java/org/apache/iotdb/db/query/udf/api/customizer/parameter/UDFParameters.java +++ b/server/src/main/java/org/apache/iotdb/db/query/udf/api/customizer/parameter/UDFParameters.java @@ -22,6 +22,7 @@ package org.apache.iotdb.db.query.udf.api.customizer.parameter; import org.apache.iotdb.commons.exception.MetadataException; import org.apache.iotdb.commons.path.PartialPath; import org.apache.iotdb.db.exception.query.QueryProcessException; +import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider; import org.apache.iotdb.db.query.expression.Expression; import org.apache.iotdb.db.query.expression.multi.FunctionExpression; import org.apache.iotdb.db.query.udf.api.UDTF; @@ -63,6 +64,17 @@ public class UDFParameters { } } + public UDFParameters(FunctionExpression functionExpression, TypeProvider typeProvider) + throws QueryProcessException { + expressions = functionExpression.getExpressions(); + paths = functionExpression.getPaths(); + attributes = functionExpression.getFunctionAttributes(); + dataTypes = new ArrayList<>(); + for (Expression expression : expressions) { + dataTypes.add(typeProvider.getType(expression.toString())); + } + } + public List<Expression> getExpressions() { return expressions; } diff --git a/server/src/main/java/org/apache/iotdb/db/query/udf/core/executor/UDTFTypeInferrer.java b/server/src/main/java/org/apache/iotdb/db/query/udf/core/executor/UDTFTypeInferrer.java new file mode 100644 index 0000000000..ca7233906a --- /dev/null +++ b/server/src/main/java/org/apache/iotdb/db/query/udf/core/executor/UDTFTypeInferrer.java @@ -0,0 +1,68 @@ +/* + * 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.core.executor; + +import org.apache.iotdb.db.exception.sql.SemanticException; +import org.apache.iotdb.db.mpp.plan.analyze.TypeProvider; +import org.apache.iotdb.db.query.expression.multi.FunctionExpression; +import org.apache.iotdb.db.query.udf.api.UDTF; +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.service.UDFRegistrationService; +import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.ZoneId; + +public class UDTFTypeInferrer { + + private static final Logger LOGGER = LoggerFactory.getLogger(UDTFTypeInferrer.class); + + protected final FunctionExpression expression; + + public UDTFTypeInferrer(FunctionExpression expression) { + this.expression = expression; + } + + public TSDataType inferOutputType(TypeProvider typeProvider) { + try { + UDTF udtf = (UDTF) UDFRegistrationService.getInstance().reflect(expression); + + UDFParameters parameters = new UDFParameters(expression, typeProvider); + udtf.validate(new UDFParameterValidator(parameters)); + + // use ZoneId.systemDefault() because UDF's data type is ZoneId independent + UDTFConfigurations configurations = new UDTFConfigurations(ZoneId.systemDefault()); + udtf.beforeStart(parameters, configurations); + + udtf.beforeDestroy(); + + return configurations.getOutputDataType(); + } catch (Exception e) { + LOGGER.warn("Error occurred during inferring UDF data type", e); + throw new SemanticException( + String.format("Error occurred during inferring UDF data type: %s", System.lineSeparator()) + + e); + } + } +}
