This is an automated email from the ASF dual-hosted git repository.
jackietien pushed a commit to branch ty/TableModelGrammar
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/ty/TableModelGrammar by this
push:
new e31904b5c7b add support for diff, cast, substring and round
e31904b5c7b is described below
commit e31904b5c7b26f588b20576728184a71b3f275e3
Author: JackieTien97 <[email protected]>
AuthorDate: Tue Apr 23 16:37:28 2024 +0800
add support for diff, cast, substring and round
---
.../protocol/thrift/impl/ClientRPCServiceImpl.java | 4 +-
.../relational/ColumnTransformerBuilder.java | 512 ++++++++++++++-------
.../plan/planner/LocalExecutionPlanner.java | 6 +-
.../plan/planner/TableOperatorGenerator.java | 13 +-
.../ConvertPredicateToTimeFilterVisitor.java | 3 +-
.../relational/metadata/TableMetadataImpl.java | 51 +-
.../ternary/CompareTernaryColumnTransformer.java | 24 -
.../column/ternary/TernaryColumnTransformer.java | 23 +
.../column/unary/scalar/DiffColumnTransformer.java | 73 +++
.../unary/scalar/Replace2ColumnTransformer.java | 66 +++
.../scalar/Replace3ColumnTransformer.java} | 71 +--
.../unary/scalar/RoundColumnTransformer.java | 78 ++++
.../unary/scalar/SubString2ColumnTransformer.java | 63 +++
.../unary/scalar/SubString3ColumnTransformer.java | 78 ++++
14 files changed, 830 insertions(+), 235 deletions(-)
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
index 4e8d16ba9bb..aaf2fa1a514 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
@@ -76,13 +76,13 @@ import
org.apache.iotdb.db.queryengine.plan.execution.ExecutionResult;
import org.apache.iotdb.db.queryengine.plan.execution.IQueryExecution;
import org.apache.iotdb.db.queryengine.plan.parser.ASTVisitor;
import org.apache.iotdb.db.queryengine.plan.parser.StatementGenerator;
+import org.apache.iotdb.db.queryengine.plan.planner.LocalExecutionPlanner;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNodeId;
import
org.apache.iotdb.db.queryengine.plan.planner.plan.parameter.AggregationStep;
import
org.apache.iotdb.db.queryengine.plan.planner.plan.parameter.GroupByTimeParameter;
import
org.apache.iotdb.db.queryengine.plan.planner.plan.parameter.InputLocation;
import
org.apache.iotdb.db.queryengine.plan.planner.plan.parameter.SeriesScanOptions;
import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
-import
org.apache.iotdb.db.queryengine.plan.relational.metadata.TableMetadataImpl;
import org.apache.iotdb.db.queryengine.plan.statement.Statement;
import org.apache.iotdb.db.queryengine.plan.statement.StatementType;
import org.apache.iotdb.db.queryengine.plan.statement.component.Ordering;
@@ -269,7 +269,7 @@ public class ClientRPCServiceImpl implements
IClientRPCServiceWithHandler {
public ClientRPCServiceImpl() {
partitionFetcher = ClusterPartitionFetcher.getInstance();
schemaFetcher = ClusterSchemaFetcher.getInstance();
- metadata = new TableMetadataImpl();
+ metadata = LocalExecutionPlanner.getInstance().metadata;
relationSqlParser = new SqlParser();
}
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 577ef24121c..2d4ce5ac0e6 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
@@ -19,10 +19,14 @@
package org.apache.iotdb.db.queryengine.execution.relational;
+import org.apache.iotdb.commons.udf.builtin.BuiltinScalarFunction;
+import org.apache.iotdb.db.exception.sql.SemanticException;
import org.apache.iotdb.db.queryengine.common.SessionInfo;
import org.apache.iotdb.db.queryengine.plan.analyze.TypeProvider;
import
org.apache.iotdb.db.queryengine.plan.planner.plan.parameter.InputLocation;
+import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol;
+import
org.apache.iotdb.db.queryengine.plan.relational.type.TypeNotFoundException;
import
org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
import
org.apache.iotdb.db.queryengine.transformation.dag.column.binary.ArithmeticAdditionColumnTransformer;
import
org.apache.iotdb.db.queryengine.transformation.dag.column.binary.ArithmeticDivisionColumnTransformer;
@@ -42,11 +46,23 @@ import
org.apache.iotdb.db.queryengine.transformation.dag.column.leaf.NullColumn
import
org.apache.iotdb.db.queryengine.transformation.dag.column.leaf.TimeColumnTransformer;
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;
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.CastFunctionColumnTransformer;
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.DiffColumnTransformer;
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.DiffFunctionColumnTransformer;
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.Replace2ColumnTransformer;
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.Replace3ColumnTransformer;
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.ReplaceFunctionColumnTransformer;
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.RoundColumnTransformer;
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.RoundFunctionColumnTransformer;
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.SubString2ColumnTransformer;
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.SubString3ColumnTransformer;
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.SubStringFunctionColumnTransformer;
import org.apache.iotdb.db.relational.sql.tree.ArithmeticBinaryExpression;
import org.apache.iotdb.db.relational.sql.tree.ArithmeticUnaryExpression;
import org.apache.iotdb.db.relational.sql.tree.AstVisitor;
@@ -97,6 +113,9 @@ import java.util.Optional;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkArgument;
+import static
org.apache.iotdb.db.queryengine.plan.relational.analyzer.predicate.PredicatePushIntoIndexScanChecker.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;
import static org.apache.tsfile.read.common.type.BinaryType.TEXT;
import static org.apache.tsfile.read.common.type.BooleanType.BOOLEAN;
import static org.apache.tsfile.read.common.type.DoubleType.DOUBLE;
@@ -118,40 +137,45 @@ public class ColumnTransformerBuilder
@Override
protected ColumnTransformer visitArithmeticBinary(
ArithmeticBinaryExpression node, Context context) {
- ColumnTransformer res =
- context.cache.computeIfAbsent(
- node,
- n -> {
- if (context.hasSeen.containsKey(node)) {
- IdentityColumnTransformer identity =
- new IdentityColumnTransformer(
- DOUBLE, context.originSize +
context.commonTransformerList.size());
- ColumnTransformer columnTransformer =
context.hasSeen.get(node);
- columnTransformer.addReferenceCount();
- context.commonTransformerList.add(columnTransformer);
- context.leafList.add(identity);
- context.inputDataTypes.add(TSDataType.DOUBLE);
- return identity;
- } else {
- ColumnTransformer left = process(node.getLeft(), context);
- ColumnTransformer right = process(node.getRight(), context);
- switch (node.getOperator()) {
- case ADD:
- return new ArithmeticAdditionColumnTransformer(DOUBLE,
left, right);
- case SUBTRACT:
- return new ArithmeticSubtractionColumnTransformer(DOUBLE,
left, right);
- case MULTIPLY:
- return new
ArithmeticMultiplicationColumnTransformer(DOUBLE, left, right);
- case DIVIDE:
- return new ArithmeticDivisionColumnTransformer(DOUBLE,
left, right);
- case MODULUS:
- return new ArithmeticModuloColumnTransformer(DOUBLE, left,
right);
- default:
- throw new UnsupportedOperationException(
- String.format(UNSUPPORTED_EXPRESSION,
node.getOperator()));
- }
- }
- });
+ if (!context.cache.containsKey(node)) {
+ if (context.hasSeen.containsKey(node)) {
+ IdentityColumnTransformer identity =
+ new IdentityColumnTransformer(
+ DOUBLE, context.originSize +
context.commonTransformerList.size());
+ ColumnTransformer columnTransformer = context.hasSeen.get(node);
+ columnTransformer.addReferenceCount();
+ context.commonTransformerList.add(columnTransformer);
+ context.leafList.add(identity);
+ context.inputDataTypes.add(TSDataType.DOUBLE);
+ context.cache.put(node, identity);
+ } else {
+ ColumnTransformer left = process(node.getLeft(), context);
+ ColumnTransformer right = process(node.getRight(), context);
+ ColumnTransformer child;
+ switch (node.getOperator()) {
+ case ADD:
+ child = new ArithmeticAdditionColumnTransformer(DOUBLE, left,
right);
+ break;
+ case SUBTRACT:
+ child = new ArithmeticSubtractionColumnTransformer(DOUBLE, left,
right);
+ break;
+ case MULTIPLY:
+ child = new ArithmeticMultiplicationColumnTransformer(DOUBLE,
left, right);
+ break;
+ case DIVIDE:
+ child = new ArithmeticDivisionColumnTransformer(DOUBLE, left,
right);
+ break;
+ case MODULUS:
+ child = new ArithmeticModuloColumnTransformer(DOUBLE, left, right);
+ break;
+ default:
+ throw new UnsupportedOperationException(
+ String.format(UNSUPPORTED_EXPRESSION, node.getOperator()));
+ }
+ context.cache.put(node, child);
+ }
+ }
+ ColumnTransformer res = context.cache.get(node);
res.addReferenceCount();
return res;
}
@@ -163,25 +187,24 @@ public class ColumnTransformerBuilder
case PLUS:
return process(node.getValue(), context);
case MINUS:
- ColumnTransformer res =
- context.cache.computeIfAbsent(
- node,
- n -> {
- if (context.hasSeen.containsKey(node)) {
- IdentityColumnTransformer identity =
- new IdentityColumnTransformer(
- DOUBLE, context.originSize +
context.commonTransformerList.size());
- ColumnTransformer columnTransformer =
context.hasSeen.get(node);
- columnTransformer.addReferenceCount();
- context.commonTransformerList.add(columnTransformer);
- context.leafList.add(identity);
- context.inputDataTypes.add(TSDataType.DOUBLE);
- return identity;
- } else {
- ColumnTransformer childColumnTransformer =
process(node.getValue(), context);
- return new ArithmeticNegationColumnTransformer(DOUBLE,
childColumnTransformer);
- }
- });
+ if (!context.cache.containsKey(node)) {
+ if (context.hasSeen.containsKey(node)) {
+ IdentityColumnTransformer identity =
+ new IdentityColumnTransformer(
+ DOUBLE, context.originSize +
context.commonTransformerList.size());
+ ColumnTransformer columnTransformer = context.hasSeen.get(node);
+ columnTransformer.addReferenceCount();
+ context.commonTransformerList.add(columnTransformer);
+ context.leafList.add(identity);
+ context.inputDataTypes.add(TSDataType.DOUBLE);
+ context.cache.put(node, identity);
+ } else {
+ ColumnTransformer childColumnTransformer =
process(node.getValue(), context);
+ context.cache.put(
+ node, new ArithmeticNegationColumnTransformer(DOUBLE,
childColumnTransformer));
+ }
+ }
+ ColumnTransformer res = context.cache.get(node);
res.addReferenceCount();
return res;
default:
@@ -191,12 +214,58 @@ public class ColumnTransformerBuilder
@Override
protected ColumnTransformer visitBetweenPredicate(BetweenPredicate node,
Context context) {
- throw new
UnsupportedOperationException(String.format(UNSUPPORTED_EXPRESSION, node));
+ if (!context.cache.containsKey(node)) {
+ if (context.hasSeen.containsKey(node)) {
+ IdentityColumnTransformer identity =
+ new IdentityColumnTransformer(
+ BOOLEAN, context.originSize +
context.commonTransformerList.size());
+ ColumnTransformer columnTransformer = context.hasSeen.get(node);
+ columnTransformer.addReferenceCount();
+ context.commonTransformerList.add(columnTransformer);
+ context.leafList.add(identity);
+ context.inputDataTypes.add(TSDataType.BOOLEAN);
+ context.cache.put(node, identity);
+ } else {
+ ColumnTransformer value = this.process(node.getValue(), context);
+ ColumnTransformer min = this.process(node.getMin(), context);
+ ColumnTransformer max = this.process(node.getMax(), context);
+ context.cache.put(node, new BetweenColumnTransformer(BOOLEAN, value,
min, max, false));
+ }
+ }
+ ColumnTransformer res = context.cache.get(node);
+ res.addReferenceCount();
+ return res;
}
@Override
protected ColumnTransformer visitCast(Cast node, Context context) {
- throw new
UnsupportedOperationException(String.format(UNSUPPORTED_EXPRESSION, node));
+
+ if (!context.cache.containsKey(node)) {
+ if (context.hasSeen.containsKey(node)) {
+ ColumnTransformer columnTransformer = context.hasSeen.get(node);
+ IdentityColumnTransformer identity =
+ new IdentityColumnTransformer(
+ columnTransformer.getType(),
+ context.originSize + context.commonTransformerList.size());
+ columnTransformer.addReferenceCount();
+ context.commonTransformerList.add(columnTransformer);
+ context.leafList.add(identity);
+ context.inputDataTypes.add(getTSDataType(columnTransformer.getType()));
+ context.cache.put(node, identity);
+ } else {
+ ColumnTransformer child = this.process(node.getExpression(), context);
+ Type type;
+ try {
+ type = context.metadata.getType(toTypeSignature(node.getType()));
+ } catch (TypeNotFoundException e) {
+ throw new SemanticException(String.format("Unknown type: %s",
node.getType()));
+ }
+ context.cache.put(node, new CastFunctionColumnTransformer(type,
child));
+ }
+ }
+ ColumnTransformer res = context.cache.get(node);
+ res.addReferenceCount();
+ return res;
}
@Override
@@ -297,7 +366,6 @@ public class ColumnTransformerBuilder
@Override
protected ColumnTransformer visitComparisonExpression(
ComparisonExpression node, Context context) {
- // fixme why using computeIfAbsent throw npe
ColumnTransformer comparisonTransformer;
if (context.cache.containsKey(node)) {
comparisonTransformer = context.cache.get(node);
@@ -405,141 +473,247 @@ public class ColumnTransformerBuilder
@Override
protected ColumnTransformer visitFunctionCall(FunctionCall node, Context
context) {
- throw new
UnsupportedOperationException(String.format(UNSUPPORTED_EXPRESSION, node));
+ if (!context.cache.containsKey(node)) {
+ if (context.hasSeen.containsKey(node)) {
+ ColumnTransformer columnTransformer = context.hasSeen.get(node);
+ IdentityColumnTransformer identity =
+ new IdentityColumnTransformer(
+ columnTransformer.getType(),
+ context.originSize + context.commonTransformerList.size());
+ columnTransformer.addReferenceCount();
+ context.commonTransformerList.add(columnTransformer);
+ context.leafList.add(identity);
+ context.inputDataTypes.add(getTSDataType(columnTransformer.getType()));
+ context.cache.put(node, identity);
+ } else {
+ context.cache.put(
+ node,
+ getFunctionColumnTransformer(node.getName().getSuffix(),
node.getArguments(), context));
+ }
+ }
+ ColumnTransformer res = context.cache.get(node);
+ res.addReferenceCount();
+ return res;
+ }
+
+ private ColumnTransformer getFunctionColumnTransformer(
+ String functionName, List<Expression> children, Context context) {
+ // builtin scalar function
+ if
(BuiltinScalarFunction.DIFF.getFunctionName().equalsIgnoreCase(functionName)) {
+ boolean ignoreNull = true;
+ if (children.size() > 1) {
+ if (isBooleanLiteral(children.get(1))) {
+ ignoreNull = ((BooleanLiteral) children.get(1)).getValue();
+ } else {
+ return new DiffColumnTransformer(
+ DOUBLE,
+ this.process(children.get(0), context),
+ this.process(children.get(1), context));
+ }
+ }
+ return new DiffFunctionColumnTransformer(
+ DOUBLE, this.process(children.get(0), context), ignoreNull);
+ } else if
(BuiltinScalarFunction.ROUND.getFunctionName().equalsIgnoreCase(functionName)) {
+ int places = 0;
+ if (children.size() > 1) {
+ if (isLongLiteral(children.get(1))) {
+ places = (int) ((LongLiteral) children.get(1)).getParsedValue();
+ } else {
+ return new RoundColumnTransformer(
+ DOUBLE,
+ this.process(children.get(0), context),
+ this.process(children.get(1), context));
+ }
+ }
+ return new RoundFunctionColumnTransformer(
+ DOUBLE, this.process(children.get(0), context), places);
+ } else if
(BuiltinScalarFunction.REPLACE.getFunctionName().equalsIgnoreCase(functionName))
{
+ if (children.size() == 2) {
+ if (isStringLiteral(children.get(1))) {
+ return new ReplaceFunctionColumnTransformer(
+ TEXT,
+ this.process(children.get(0), context),
+ ((StringLiteral) children.get(1)).getValue(),
+ "");
+ } else {
+ return new Replace2ColumnTransformer(
+ TEXT, this.process(children.get(0), context),
this.process(children.get(1), context));
+ }
+ } else {
+ // size == 3
+ if (isStringLiteral(children.get(1)) &&
isStringLiteral(children.get(2))) {
+ return new ReplaceFunctionColumnTransformer(
+ TEXT,
+ this.process(children.get(0), context),
+ ((StringLiteral) children.get(1)).getValue(),
+ ((StringLiteral) children.get(2)).getValue());
+ } else {
+ return new Replace3ColumnTransformer(
+ TEXT,
+ this.process(children.get(0), context),
+ this.process(children.get(1), context),
+ this.process(children.get(2), context));
+ }
+ }
+ } else if
(BuiltinScalarFunction.SUBSTRING.getFunctionName().equalsIgnoreCase(functionName))
{
+ if (children.size() == 2) {
+ if (isLongLiteral(children.get(1))) {
+ return new SubStringFunctionColumnTransformer(
+ TEXT,
+ this.process(children.get(0), context),
+ (int) ((LongLiteral) children.get(1)).getParsedValue(),
+ Integer.MAX_VALUE);
+ } else {
+ return new SubString2ColumnTransformer(
+ TEXT, this.process(children.get(0), context),
this.process(children.get(1), context));
+ }
+ } else {
+ // size == 3
+ if (isLongLiteral(children.get(1)) && isLongLiteral(children.get(2))) {
+ return new SubStringFunctionColumnTransformer(
+ TEXT,
+ this.process(children.get(0), context),
+ (int) ((LongLiteral) children.get(1)).getParsedValue(),
+ (int) ((LongLiteral) children.get(2)).getParsedValue());
+ } else {
+ return new SubString3ColumnTransformer(
+ TEXT,
+ this.process(children.get(0), context),
+ this.process(children.get(1), context),
+ this.process(children.get(2), context));
+ }
+ }
+ }
+
+ throw new IllegalArgumentException(String.format("Unknown function: %s",
functionName));
}
@Override
protected ColumnTransformer visitInPredicate(InPredicate node, Context
context) {
- ColumnTransformer res =
- context.cache.computeIfAbsent(
- node,
- n -> {
- if (context.hasSeen.containsKey(node)) {
- IdentityColumnTransformer identity =
- new IdentityColumnTransformer(
- BOOLEAN, context.originSize +
context.commonTransformerList.size());
- ColumnTransformer columnTransformer =
context.hasSeen.get(node);
- columnTransformer.addReferenceCount();
- context.commonTransformerList.add(columnTransformer);
- context.leafList.add(identity);
- context.inputDataTypes.add(TSDataType.BOOLEAN);
- return identity;
- } else {
- ColumnTransformer childColumnTransformer =
process(node.getValue(), context);
- InListExpression inListExpression = (InListExpression)
node.getValueList();
- List<Expression> expressionList = inListExpression.getValues();
- List<Literal> values = new ArrayList<>();
- for (Expression expression : expressionList) {
- checkArgument(expression instanceof Literal);
- values.add((Literal) expression);
- }
- return new InColumnTransformer(BOOLEAN,
childColumnTransformer, values);
- }
- });
+ if (!context.cache.containsKey(node)) {
+ if (context.hasSeen.containsKey(node)) {
+ IdentityColumnTransformer identity =
+ new IdentityColumnTransformer(
+ BOOLEAN, context.originSize +
context.commonTransformerList.size());
+ ColumnTransformer columnTransformer = context.hasSeen.get(node);
+ columnTransformer.addReferenceCount();
+ context.commonTransformerList.add(columnTransformer);
+ context.leafList.add(identity);
+ context.inputDataTypes.add(TSDataType.BOOLEAN);
+ context.cache.put(node, identity);
+ } else {
+ ColumnTransformer childColumnTransformer = process(node.getValue(),
context);
+ InListExpression inListExpression = (InListExpression)
node.getValueList();
+ List<Expression> expressionList = inListExpression.getValues();
+ List<Literal> values = new ArrayList<>();
+ for (Expression expression : expressionList) {
+ checkArgument(expression instanceof Literal);
+ values.add((Literal) expression);
+ }
+ context.cache.put(node, new InColumnTransformer(BOOLEAN,
childColumnTransformer, values));
+ }
+ }
+
+ ColumnTransformer res = context.cache.get(node);
res.addReferenceCount();
return res;
}
@Override
protected ColumnTransformer visitNotExpression(NotExpression node, Context
context) {
- ColumnTransformer res =
- context.cache.computeIfAbsent(
- node,
- n -> {
- if (context.hasSeen.containsKey(node)) {
- IdentityColumnTransformer identity =
- new IdentityColumnTransformer(
- BOOLEAN, context.originSize +
context.commonTransformerList.size());
- ColumnTransformer columnTransformer =
context.hasSeen.get(node);
- columnTransformer.addReferenceCount();
- context.commonTransformerList.add(columnTransformer);
- context.leafList.add(identity);
- context.inputDataTypes.add(TSDataType.BOOLEAN);
- return identity;
- } else {
- ColumnTransformer childColumnTransformer =
process(node.getValue(), context);
- return new LogicNotColumnTransformer(BOOLEAN,
childColumnTransformer);
- }
- });
+ if (!context.cache.containsKey(node)) {
+ if (context.hasSeen.containsKey(node)) {
+ IdentityColumnTransformer identity =
+ new IdentityColumnTransformer(
+ BOOLEAN, context.originSize +
context.commonTransformerList.size());
+ ColumnTransformer columnTransformer = context.hasSeen.get(node);
+ columnTransformer.addReferenceCount();
+ context.commonTransformerList.add(columnTransformer);
+ context.leafList.add(identity);
+ context.inputDataTypes.add(TSDataType.BOOLEAN);
+ context.cache.put(node, identity);
+ } else {
+ ColumnTransformer childColumnTransformer = process(node.getValue(),
context);
+ context.cache.put(node, new LogicNotColumnTransformer(BOOLEAN,
childColumnTransformer));
+ }
+ }
+ ColumnTransformer res = context.cache.get(node);
res.addReferenceCount();
return res;
}
@Override
protected ColumnTransformer visitLikePredicate(LikePredicate node, Context
context) {
- ColumnTransformer res =
- context.cache.computeIfAbsent(
+ if (!context.cache.containsKey(node)) {
+ if (context.hasSeen.containsKey(node)) {
+ IdentityColumnTransformer identity =
+ new IdentityColumnTransformer(
+ BOOLEAN, context.originSize +
context.commonTransformerList.size());
+ ColumnTransformer columnTransformer = context.hasSeen.get(node);
+ columnTransformer.addReferenceCount();
+ context.commonTransformerList.add(columnTransformer);
+ context.leafList.add(identity);
+ context.inputDataTypes.add(TSDataType.BOOLEAN);
+ context.cache.put(node, identity);
+ } else {
+ ColumnTransformer childColumnTransformer = process(node.getValue(),
context);
+ context.cache.put(
node,
- n -> {
- if (context.hasSeen.containsKey(node)) {
- IdentityColumnTransformer identity =
- new IdentityColumnTransformer(
- BOOLEAN, context.originSize +
context.commonTransformerList.size());
- ColumnTransformer columnTransformer =
context.hasSeen.get(node);
- columnTransformer.addReferenceCount();
- context.commonTransformerList.add(columnTransformer);
- context.leafList.add(identity);
- context.inputDataTypes.add(TSDataType.BOOLEAN);
- return identity;
- } else {
- ColumnTransformer childColumnTransformer =
process(node.getValue(), context);
- return new RegularColumnTransformer(
- BOOLEAN,
- childColumnTransformer,
- compileRegex(
- parseLikePatternToRegex(((StringLiteral)
node.getPattern()).getValue())));
- }
- });
+ new RegularColumnTransformer(
+ BOOLEAN,
+ childColumnTransformer,
+ compileRegex(
+ parseLikePatternToRegex(((StringLiteral)
node.getPattern()).getValue()))));
+ }
+ }
+ ColumnTransformer res = context.cache.get(node);
res.addReferenceCount();
return res;
}
@Override
protected ColumnTransformer visitIsNotNullPredicate(IsNotNullPredicate node,
Context context) {
- ColumnTransformer res =
- context.cache.computeIfAbsent(
- node,
- n -> {
- if (context.hasSeen.containsKey(node)) {
- IdentityColumnTransformer identity =
- new IdentityColumnTransformer(
- BOOLEAN, context.originSize +
context.commonTransformerList.size());
- ColumnTransformer columnTransformer =
context.hasSeen.get(node);
- columnTransformer.addReferenceCount();
- context.commonTransformerList.add(columnTransformer);
- context.leafList.add(identity);
- context.inputDataTypes.add(TSDataType.BOOLEAN);
- return identity;
- } else {
- ColumnTransformer childColumnTransformer =
process(node.getValue(), context);
- return new IsNullColumnTransformer(BOOLEAN,
childColumnTransformer, true);
- }
- });
+ if (!context.cache.containsKey(node)) {
+ if (context.hasSeen.containsKey(node)) {
+ IdentityColumnTransformer identity =
+ new IdentityColumnTransformer(
+ BOOLEAN, context.originSize +
context.commonTransformerList.size());
+ ColumnTransformer columnTransformer = context.hasSeen.get(node);
+ columnTransformer.addReferenceCount();
+ context.commonTransformerList.add(columnTransformer);
+ context.leafList.add(identity);
+ context.inputDataTypes.add(TSDataType.BOOLEAN);
+ context.cache.put(node, identity);
+ } else {
+ ColumnTransformer childColumnTransformer = process(node.getValue(),
context);
+ context.cache.put(node, new IsNullColumnTransformer(BOOLEAN,
childColumnTransformer, true));
+ }
+ }
+ ColumnTransformer res = context.cache.get(node);
res.addReferenceCount();
return res;
}
@Override
protected ColumnTransformer visitIsNullPredicate(IsNullPredicate node,
Context context) {
- ColumnTransformer res =
- context.cache.computeIfAbsent(
- node,
- n -> {
- if (context.hasSeen.containsKey(node)) {
- IdentityColumnTransformer identity =
- new IdentityColumnTransformer(
- BOOLEAN, context.originSize +
context.commonTransformerList.size());
- ColumnTransformer columnTransformer =
context.hasSeen.get(node);
- columnTransformer.addReferenceCount();
- context.commonTransformerList.add(columnTransformer);
- context.leafList.add(identity);
- context.inputDataTypes.add(TSDataType.BOOLEAN);
- return identity;
- } else {
- ColumnTransformer childColumnTransformer =
process(node.getValue(), context);
- return new IsNullColumnTransformer(BOOLEAN,
childColumnTransformer, false);
- }
- });
+ if (!context.cache.containsKey(node)) {
+ if (context.hasSeen.containsKey(node)) {
+ IdentityColumnTransformer identity =
+ new IdentityColumnTransformer(
+ BOOLEAN, context.originSize +
context.commonTransformerList.size());
+ ColumnTransformer columnTransformer = context.hasSeen.get(node);
+ columnTransformer.addReferenceCount();
+ context.commonTransformerList.add(columnTransformer);
+ context.leafList.add(identity);
+ context.inputDataTypes.add(TSDataType.BOOLEAN);
+ context.cache.put(node, identity);
+ } else {
+ ColumnTransformer childColumnTransformer = process(node.getValue(),
context);
+ context.cache.put(
+ node, new IsNullColumnTransformer(BOOLEAN, childColumnTransformer,
false));
+ }
+ }
+ ColumnTransformer res = context.cache.get(node);
res.addReferenceCount();
return res;
}
@@ -638,6 +812,14 @@ public class ColumnTransformerBuilder
throw new
UnsupportedOperationException(String.format(UNSUPPORTED_EXPRESSION, node));
}
+ public static boolean isLongLiteral(Expression expression) {
+ return expression instanceof LongLiteral;
+ }
+
+ public static boolean isBooleanLiteral(Expression expression) {
+ return expression instanceof BooleanLiteral;
+ }
+
public static class Context {
private final SessionInfo sessionInfo;
@@ -663,6 +845,8 @@ public class ColumnTransformerBuilder
private final TypeProvider typeProvider;
+ private final Metadata metadata;
+
public Context(
SessionInfo sessionInfo,
List<LeafColumnTransformer> leafList,
@@ -672,7 +856,8 @@ public class ColumnTransformerBuilder
List<ColumnTransformer> commonTransformerList,
List<TSDataType> inputDataTypes,
int originSize,
- TypeProvider typeProvider) {
+ TypeProvider typeProvider,
+ Metadata metadata) {
this.sessionInfo = sessionInfo;
this.leafList = leafList;
this.inputLocations = inputLocations;
@@ -682,6 +867,7 @@ public class ColumnTransformerBuilder
this.inputDataTypes = inputDataTypes;
this.originSize = originSize;
this.typeProvider = typeProvider;
+ this.metadata = metadata;
}
public Type getType(SymbolReference symbolReference) {
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LocalExecutionPlanner.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LocalExecutionPlanner.java
index 2894ac2b432..5fa313e747b 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LocalExecutionPlanner.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/LocalExecutionPlanner.java
@@ -31,6 +31,8 @@ import
org.apache.iotdb.db.queryengine.execution.operator.Operator;
import org.apache.iotdb.db.queryengine.metric.QueryRelatedResourceMetricSet;
import org.apache.iotdb.db.queryengine.plan.analyze.TypeProvider;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
+import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
+import
org.apache.iotdb.db.queryengine.plan.relational.metadata.TableMetadataImpl;
import org.apache.iotdb.db.schemaengine.schemaregion.ISchemaRegion;
import org.apache.iotdb.db.utils.SetThreadName;
@@ -51,6 +53,8 @@ public class LocalExecutionPlanner {
private static final long ALLOCATE_MEMORY_FOR_OPERATORS;
private static final long MAX_REST_MEMORY_FOR_LOAD;
+ public final Metadata metadata = new TableMetadataImpl();
+
static {
IoTDBConfig CONFIG = IoTDBDescriptor.getInstance().getConfig();
ALLOCATE_MEMORY_FOR_OPERATORS = CONFIG.getAllocateMemoryForOperators();
@@ -88,7 +92,7 @@ public class LocalExecutionPlanner {
root = plan.accept(new OperatorTreeGenerator(), context);
break;
case TABLE:
- root = plan.accept(new TableOperatorGenerator(), context);
+ root = plan.accept(new TableOperatorGenerator(metadata), context);
break;
default:
throw new IllegalArgumentException(String.format("Unknown sql dialect:
%s", sqlDialect));
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
index bd17059f141..e9d17b2d21d 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
@@ -45,6 +45,7 @@ import
org.apache.iotdb.db.queryengine.plan.planner.plan.node.sink.IdentitySinkN
import
org.apache.iotdb.db.queryengine.plan.planner.plan.parameter.InputLocation;
import
org.apache.iotdb.db.queryengine.plan.planner.plan.parameter.SeriesScanOptions;
import org.apache.iotdb.db.queryengine.plan.relational.metadata.ColumnSchema;
+import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol;
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.FilterNode;
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.LimitNode;
@@ -87,6 +88,12 @@ import static
org.apache.iotdb.db.queryengine.plan.relational.type.InternalTypeM
/** This Visitor is responsible for transferring Table PlanNode Tree to Table
Operator Tree. */
public class TableOperatorGenerator extends PlanVisitor<Operator,
LocalExecutionPlanContext> {
+ private final Metadata metadata;
+
+ public TableOperatorGenerator(Metadata metadata) {
+ this.metadata = metadata;
+ }
+
@Override
public Operator visitPlan(PlanNode node, LocalExecutionPlanContext context) {
throw new UnsupportedOperationException("should call the concrete
visitXX() method");
@@ -336,7 +343,8 @@ public class TableOperatorGenerator extends
PlanVisitor<Operator, LocalExecution
ImmutableList.of(),
ImmutableList.of(),
0,
- context.getTypeProvider());
+ context.getTypeProvider(),
+ metadata);
return visitor.process(p, filterColumnTransformerContext);
})
@@ -362,7 +370,8 @@ public class TableOperatorGenerator extends
PlanVisitor<Operator, LocalExecution
commonTransformerList,
filterOutputDataTypes,
inputLocations.size() - 1,
- context.getTypeProvider());
+ context.getTypeProvider(),
+ metadata);
for (Expression expression : projectExpressions) {
projectOutputTransformerList.add(
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/ConvertPredicateToTimeFilterVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/ConvertPredicateToTimeFilterVisitor.java
index bac96ac74f5..0ea15d2f79a 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/ConvertPredicateToTimeFilterVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/predicate/ConvertPredicateToTimeFilterVisitor.java
@@ -47,6 +47,7 @@ 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.expression.leaf.TimestampOperand.TIMESTAMP_EXPRESSION_STRING;
public class ConvertPredicateToTimeFilterVisitor extends
PredicateVisitor<Filter, Void> {
@@ -210,7 +211,7 @@ public class ConvertPredicateToTimeFilterVisitor extends
PredicateVisitor<Filter
public static boolean isTimeColumn(Expression expression) {
return expression instanceof SymbolReference
- && "time".equalsIgnoreCase(((SymbolReference) expression).getName());
+ && TIMESTAMP_EXPRESSION_STRING.equalsIgnoreCase(((SymbolReference)
expression).getName());
}
public static long getLongValue(Expression expression) {
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 af519b94a23..4b4dfcad85f 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
@@ -108,18 +108,42 @@ public class TableMetadataImpl implements Metadata {
public Type getFunctionReturnType(String functionName, List<? extends Type>
argumentTypes) {
// builtin scalar function
- if
(BuiltinScalarFunction.DIFF.getFunctionName().equalsIgnoreCase(functionName)
- ||
BuiltinScalarFunction.ROUND.getFunctionName().equalsIgnoreCase(functionName)) {
- if (!isOneNumericType(argumentTypes)) {
+ if
(BuiltinScalarFunction.DIFF.getFunctionName().equalsIgnoreCase(functionName)) {
+ if (!isOneNumericType(argumentTypes)
+ && !(argumentTypes.size() == 2
+ && isNumericType(argumentTypes.get(0))
+ && BOOLEAN.equals(argumentTypes.get(0)))) {
throw new SemanticException(
"Scalar function"
+ functionName.toLowerCase(Locale.ENGLISH)
- + " only supports numeric data types [INT32, INT64, FLOAT,
DOUBLE]");
+ + " only supports one numeric data types [INT32, INT64, FLOAT,
DOUBLE] and one boolean");
+ }
+
+ } else if
(BuiltinScalarFunction.ROUND.getFunctionName().equalsIgnoreCase(functionName)) {
+ if (!isOneNumericType(argumentTypes) &&
!isTwoNumericType(argumentTypes)) {
+ throw new SemanticException(
+ "Scalar function"
+ + functionName.toLowerCase(Locale.ENGLISH)
+ + " only supports two numeric data types [INT32, INT64, FLOAT,
DOUBLE]");
}
return DOUBLE;
- } else if
(BuiltinScalarFunction.REPLACE.getFunctionName().equalsIgnoreCase(functionName)
- ||
BuiltinScalarFunction.SUBSTRING.getFunctionName().equalsIgnoreCase(functionName))
{
- if (!isOneTextType(argumentTypes)) {
+ } else if
(BuiltinScalarFunction.REPLACE.getFunctionName().equalsIgnoreCase(functionName))
{
+
+ if (!isTwoTextType(argumentTypes) && isThreeTextType(argumentTypes)) {
+ throw new SemanticException(
+ "Scalar function"
+ + functionName.toLowerCase(Locale.ENGLISH)
+ + " only supports text data type.");
+ }
+ return TEXT;
+ } else if
(BuiltinScalarFunction.SUBSTRING.getFunctionName().equalsIgnoreCase(functionName))
{
+ if (!(argumentTypes.size() == 2
+ && TEXT.equals(argumentTypes.get(0))
+ && isNumericType(argumentTypes.get(1)))
+ && !(argumentTypes.size() == 3
+ && TEXT.equals(argumentTypes.get(0))
+ && isNumericType(argumentTypes.get(1))
+ && isNumericType(argumentTypes.get(2)))) {
throw new SemanticException(
"Scalar function"
+ functionName.toLowerCase(Locale.ENGLISH)
@@ -265,6 +289,19 @@ public class TableMetadataImpl implements Metadata {
return argumentTypes.size() == 1 && TEXT.equals(argumentTypes.get(0));
}
+ public static boolean isTwoTextType(List<? extends Type> argumentTypes) {
+ return argumentTypes.size() == 2
+ && TEXT.equals(argumentTypes.get(0))
+ && TEXT.equals(argumentTypes.get(1));
+ }
+
+ public static boolean isThreeTextType(List<? extends Type> argumentTypes) {
+ return argumentTypes.size() == 3
+ && TEXT.equals(argumentTypes.get(0))
+ && TEXT.equals(argumentTypes.get(1))
+ && TEXT.equals(argumentTypes.get(2));
+ }
+
public static boolean isNumericType(Type type) {
return DOUBLE.equals(type) || FLOAT.equals(type) || INT32.equals(type) ||
INT64.equals(type);
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/CompareTernaryColumnTransformer.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/CompareTernaryColumnTransformer.java
index de83b409e8a..f4401c37a2a 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/CompareTernaryColumnTransformer.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/CompareTernaryColumnTransformer.java
@@ -21,8 +21,6 @@ package
org.apache.iotdb.db.queryengine.transformation.dag.column.ternary;
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.Type;
import org.apache.tsfile.read.common.type.TypeEnum;
@@ -35,21 +33,6 @@ public abstract class CompareTernaryColumnTransformer
extends TernaryColumnTrans
super(returnType, firstColumnTransformer, secondColumnTransformer,
thirdColumnTransformer);
}
- @Override
- public void evaluate() {
- firstColumnTransformer.tryEvaluate();
- secondColumnTransformer.tryEvaluate();
- thirdColumnTransformer.tryEvaluate();
- // attention: get positionCount before calling getColumn
- int positionCount = firstColumnTransformer.getColumnCachePositionCount();
- Column firstColumn = firstColumnTransformer.getColumn();
- Column secondColumn = secondColumnTransformer.getColumn();
- Column thirdColumn = thirdColumnTransformer.getColumn();
- ColumnBuilder columnBuilder =
returnType.createColumnBuilder(positionCount);
- doTransform(firstColumn, secondColumn, thirdColumn, columnBuilder,
positionCount);
- initializeColumnCache(columnBuilder.build());
- }
-
@Override
protected final void checkType() {
if (firstColumnTransformer.isReturnTypeNumeric()
@@ -64,11 +47,4 @@ public abstract class CompareTernaryColumnTransformer
extends TernaryColumnTrans
throw new UnsupportedOperationException(
"The Type of three subExpression should be all Numeric or Text");
}
-
- protected abstract void doTransform(
- Column firstColumn,
- Column secondColumn,
- Column thirdColumn,
- ColumnBuilder builder,
- int positionCount);
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/TernaryColumnTransformer.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/TernaryColumnTransformer.java
index 6d747d3dae8..5359e50cbb5 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/TernaryColumnTransformer.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/TernaryColumnTransformer.java
@@ -21,6 +21,8 @@ package
org.apache.iotdb.db.queryengine.transformation.dag.column.ternary;
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.Type;
public abstract class TernaryColumnTransformer extends ColumnTransformer {
@@ -43,6 +45,27 @@ public abstract class TernaryColumnTransformer extends
ColumnTransformer {
checkType();
}
+ @Override
+ protected void evaluate() {
+ firstColumnTransformer.tryEvaluate();
+ secondColumnTransformer.tryEvaluate();
+ thirdColumnTransformer.tryEvaluate();
+ int positionCount = firstColumnTransformer.getColumnCachePositionCount();
+ Column firstColumn = firstColumnTransformer.getColumn();
+ Column secondColumn = secondColumnTransformer.getColumn();
+ Column thirdColumn = thirdColumnTransformer.getColumn();
+ ColumnBuilder columnBuilder =
returnType.createColumnBuilder(positionCount);
+ doTransform(firstColumn, secondColumn, thirdColumn, columnBuilder,
positionCount);
+ initializeColumnCache(columnBuilder.build());
+ }
+
+ protected abstract void doTransform(
+ Column firstColumn,
+ Column secondColumn,
+ Column thirdColumn,
+ ColumnBuilder builder,
+ int positionCount);
+
public ColumnTransformer getFirstColumnTransformer() {
return firstColumnTransformer;
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/DiffColumnTransformer.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/DiffColumnTransformer.java
new file mode 100644
index 00000000000..dca73590f7c
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/DiffColumnTransformer.java
@@ -0,0 +1,73 @@
+/*
+ * 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.unary.scalar;
+
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.binary.BinaryColumnTransformer;
+
+import org.apache.tsfile.block.column.Column;
+import org.apache.tsfile.block.column.ColumnBuilder;
+import org.apache.tsfile.read.common.type.Type;
+
+public class DiffColumnTransformer extends BinaryColumnTransformer {
+
+ // cache the last non-null value
+ private double lastValue;
+
+ // indicate whether lastValue is null
+ private boolean lastValueIsNull = true;
+
+ public DiffColumnTransformer(
+ Type returnType, ColumnTransformer leftTransformer, ColumnTransformer
rightTransformer) {
+ super(returnType, leftTransformer, rightTransformer);
+ }
+
+ @Override
+ protected void checkType() {
+ // do nothing
+ }
+
+ @Override
+ protected void doTransform(
+ Column leftColumn, Column rightColumn, ColumnBuilder builder, int
positionCount) {
+ Type leftType = leftTransformer.getType();
+ Type rightType = rightTransformer.getType();
+ for (int i = 0; i < positionCount; i++) {
+ if (leftColumn.isNull(i)) {
+ builder.appendNull(); // currValue is null, append null
+
+ // When currValue is null:
+ // ignoreNull = true, keep lastValueIsNull as before
+ // ignoreNull = false or ignoreNull is null, update lastValueIsNull to
true
+ lastValueIsNull |= (rightColumn.isNull(i) ||
!rightType.getBoolean(rightColumn, i));
+ } else {
+ double currValue = leftType.getDouble(leftColumn, i);
+ if (lastValueIsNull) {
+ builder.appendNull(); // lastValue is null, append null
+ } else {
+ returnType.writeDouble(builder, currValue - lastValue);
+ }
+
+ lastValue = currValue; // currValue is not null, update lastValue
+ lastValueIsNull = false;
+ }
+ }
+ }
+}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/Replace2ColumnTransformer.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/Replace2ColumnTransformer.java
new file mode 100644
index 00000000000..defcbfaf2fd
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/Replace2ColumnTransformer.java
@@ -0,0 +1,66 @@
+/*
+ * 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.unary.scalar;
+
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.binary.BinaryColumnTransformer;
+
+import org.apache.tsfile.block.column.Column;
+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.utils.BytesUtils;
+
+public class Replace2ColumnTransformer extends BinaryColumnTransformer {
+
+ public Replace2ColumnTransformer(
+ Type returnType, ColumnTransformer leftTransformer, ColumnTransformer
rightTransformer) {
+ super(returnType, leftTransformer, rightTransformer);
+ }
+
+ @Override
+ protected void checkType() {
+ // do nothing
+ }
+
+ @Override
+ protected void doTransform(
+ Column leftColumn, Column rightColumn, ColumnBuilder builder, int
positionCount) {
+ Type leftType = leftTransformer.getType();
+ Type rightType = rightTransformer.getType();
+ for (int i = 0, n = leftColumn.getPositionCount(); i < n; i++) {
+ if (!leftColumn.isNull(i) && !rightColumn.isNull(i)) {
+ returnType.writeBinary(
+ builder,
+ BytesUtils.valueOf(
+ leftType
+ .getBinary(leftColumn, i)
+ .getStringValue(TSFileConfig.STRING_CHARSET)
+ .replace(
+ rightType
+ .getBinary(rightColumn, i)
+ .getStringValue(TSFileConfig.STRING_CHARSET),
+ "")));
+ } else {
+ builder.appendNull();
+ }
+ }
+ }
+}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/CompareTernaryColumnTransformer.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/Replace3ColumnTransformer.java
similarity index 50%
copy from
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/CompareTernaryColumnTransformer.java
copy to
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/Replace3ColumnTransformer.java
index de83b409e8a..d8cddbe5124 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/ternary/CompareTernaryColumnTransformer.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/Replace3ColumnTransformer.java
@@ -17,17 +17,19 @@
* under the License.
*/
-package org.apache.iotdb.db.queryengine.transformation.dag.column.ternary;
+package org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar;
import
org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.ternary.TernaryColumnTransformer;
import org.apache.tsfile.block.column.Column;
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.BytesUtils;
-public abstract class CompareTernaryColumnTransformer extends
TernaryColumnTransformer {
- protected CompareTernaryColumnTransformer(
+public class Replace3ColumnTransformer extends TernaryColumnTransformer {
+ public Replace3ColumnTransformer(
Type returnType,
ColumnTransformer firstColumnTransformer,
ColumnTransformer secondColumnTransformer,
@@ -36,39 +38,38 @@ public abstract class CompareTernaryColumnTransformer
extends TernaryColumnTrans
}
@Override
- public void evaluate() {
- firstColumnTransformer.tryEvaluate();
- secondColumnTransformer.tryEvaluate();
- thirdColumnTransformer.tryEvaluate();
- // attention: get positionCount before calling getColumn
- int positionCount = firstColumnTransformer.getColumnCachePositionCount();
- Column firstColumn = firstColumnTransformer.getColumn();
- Column secondColumn = secondColumnTransformer.getColumn();
- Column thirdColumn = thirdColumnTransformer.getColumn();
- ColumnBuilder columnBuilder =
returnType.createColumnBuilder(positionCount);
- doTransform(firstColumn, secondColumn, thirdColumn, columnBuilder,
positionCount);
- initializeColumnCache(columnBuilder.build());
- }
-
- @Override
- protected final void checkType() {
- if (firstColumnTransformer.isReturnTypeNumeric()
- && secondColumnTransformer.isReturnTypeNumeric()
- && thirdColumnTransformer.isReturnTypeNumeric()
- || firstColumnTransformer.typeEquals(TypeEnum.TEXT)
- && secondColumnTransformer.typeEquals(TypeEnum.TEXT)
- && thirdColumnTransformer.typeEquals(TypeEnum.TEXT)) {
- return;
- }
-
- throw new UnsupportedOperationException(
- "The Type of three subExpression should be all Numeric or Text");
- }
-
- protected abstract void doTransform(
+ protected void doTransform(
Column firstColumn,
Column secondColumn,
Column thirdColumn,
ColumnBuilder builder,
- int positionCount);
+ int positionCount) {
+ Type firstType = firstColumnTransformer.getType();
+ Type secondType = secondColumnTransformer.getType();
+ Type thirdType = thirdColumnTransformer.getType();
+ for (int i = 0, n = firstColumn.getPositionCount(); i < n; i++) {
+ if (!firstColumn.isNull(i) && !secondColumn.isNull(i) &&
!thirdColumn.isNull(i)) {
+ returnType.writeBinary(
+ builder,
+ BytesUtils.valueOf(
+ firstType
+ .getBinary(firstColumn, i)
+ .getStringValue(TSFileConfig.STRING_CHARSET)
+ .replace(
+ secondType
+ .getBinary(secondColumn, i)
+ .getStringValue(TSFileConfig.STRING_CHARSET),
+ thirdType
+ .getBinary(thirdColumn, i)
+ .getStringValue(TSFileConfig.STRING_CHARSET))));
+ } else {
+ builder.appendNull();
+ }
+ }
+ }
+
+ @Override
+ protected void checkType() {
+ // do nothing
+ }
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/RoundColumnTransformer.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/RoundColumnTransformer.java
new file mode 100644
index 00000000000..ebd250cc86c
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/RoundColumnTransformer.java
@@ -0,0 +1,78 @@
+/*
+ * 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.unary.scalar;
+
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.binary.BinaryColumnTransformer;
+
+import org.apache.tsfile.block.column.Column;
+import org.apache.tsfile.block.column.ColumnBuilder;
+import org.apache.tsfile.read.common.type.Type;
+import org.apache.tsfile.read.common.type.TypeEnum;
+
+public class RoundColumnTransformer extends BinaryColumnTransformer {
+
+ public RoundColumnTransformer(
+ Type returnType, ColumnTransformer leftTransformer, ColumnTransformer
rightTransformer) {
+ super(returnType, leftTransformer, rightTransformer);
+ }
+
+ @Override
+ protected void doTransform(
+ Column leftColumn, Column rightColumn, ColumnBuilder builder, int
positionCount) {
+ TypeEnum sourceType = leftTransformer.getType().getTypeEnum();
+ Type rightType = rightTransformer.getType();
+ for (int i = 0; i < positionCount; i++) {
+ if (!leftColumn.isNull(i) && !rightColumn.isNull(i)) {
+ int places = rightType.getInt(rightColumn, i);
+ switch (sourceType) {
+ case INT32:
+ builder.writeDouble(
+ Math.rint(leftColumn.getInt(i) * Math.pow(10, places)) /
Math.pow(10, places));
+ break;
+ case INT64:
+ builder.writeDouble(
+ Math.rint(leftColumn.getLong(i) * Math.pow(10, places)) /
Math.pow(10, places));
+ break;
+ case FLOAT:
+ builder.writeDouble(
+ Math.rint(leftColumn.getFloat(i) * Math.pow(10, places)) /
Math.pow(10, places));
+ break;
+ case DOUBLE:
+ builder.writeDouble(
+ Math.rint(leftColumn.getDouble(i) * Math.pow(10, places)) /
Math.pow(10, places));
+ break;
+ default:
+ throw new UnsupportedOperationException(
+ String.format("Unsupported source dataType: %s", sourceType));
+ }
+ } else {
+ builder.appendNull();
+ }
+ }
+ }
+
+ @Override
+ protected void checkType() {
+ if (!leftTransformer.isReturnTypeNumeric() ||
!rightTransformer.isReturnTypeNumeric()) {
+ throw new UnsupportedOperationException("Unsupported Type");
+ }
+ }
+}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubString2ColumnTransformer.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubString2ColumnTransformer.java
new file mode 100644
index 00000000000..fc85b6f54a9
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubString2ColumnTransformer.java
@@ -0,0 +1,63 @@
+/*
+ * 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.unary.scalar;
+
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.binary.BinaryColumnTransformer;
+
+import org.apache.tsfile.block.column.Column;
+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.utils.BytesUtils;
+
+import static
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.SubStringFunctionColumnTransformer.EMPTY_STRING;
+
+public class SubString2ColumnTransformer extends BinaryColumnTransformer {
+ public SubString2ColumnTransformer(
+ Type returnType, ColumnTransformer leftTransformer, ColumnTransformer
rightTransformer) {
+ super(returnType, leftTransformer, rightTransformer);
+ }
+
+ @Override
+ protected void checkType() {
+ // do nothing
+ }
+
+ @Override
+ protected void doTransform(
+ Column leftColumn, Column rightColumn, ColumnBuilder builder, int
positionCount) {
+ Type rightType = rightTransformer.getType();
+ for (int i = 0; i < positionCount; i++) {
+ if (!leftColumn.isNull(i) && !rightColumn.isNull(i)) {
+ String currentValue =
leftColumn.getBinary(i).getStringValue(TSFileConfig.STRING_CHARSET);
+ int beginPosition = rightType.getInt(rightColumn, i);
+ if (beginPosition >= currentValue.length()) {
+ currentValue = EMPTY_STRING;
+ } else {
+ currentValue = currentValue.substring(beginPosition);
+ }
+ builder.writeBinary(BytesUtils.valueOf(currentValue));
+ } else {
+ builder.appendNull();
+ }
+ }
+ }
+}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubString3ColumnTransformer.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubString3ColumnTransformer.java
new file mode 100644
index 00000000000..c9a3ae1a3fe
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/SubString3ColumnTransformer.java
@@ -0,0 +1,78 @@
+/*
+ * 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.unary.scalar;
+
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer;
+import
org.apache.iotdb.db.queryengine.transformation.dag.column.ternary.TernaryColumnTransformer;
+
+import org.apache.tsfile.block.column.Column;
+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.utils.BytesUtils;
+
+import static
org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar.SubStringFunctionColumnTransformer.EMPTY_STRING;
+
+public class SubString3ColumnTransformer extends TernaryColumnTransformer {
+ public SubString3ColumnTransformer(
+ Type returnType,
+ ColumnTransformer firstColumnTransformer,
+ ColumnTransformer secondColumnTransformer,
+ ColumnTransformer thirdColumnTransformer) {
+ super(returnType, firstColumnTransformer, secondColumnTransformer,
thirdColumnTransformer);
+ }
+
+ @Override
+ protected void checkType() {
+ // do nothing
+ }
+
+ @Override
+ protected void doTransform(
+ Column firstColumn,
+ Column secondColumn,
+ Column thirdColumn,
+ ColumnBuilder builder,
+ int positionCount) {
+ Type firstType = firstColumnTransformer.getType();
+ Type secondType = secondColumnTransformer.getType();
+ Type thirdType = thirdColumnTransformer.getType();
+ for (int i = 0; i < positionCount; i++) {
+ if (!firstColumn.isNull(i) && !secondColumn.isNull(i) &&
!thirdColumn.isNull(i)) {
+ String currentValue =
+ firstType.getBinary(firstColumn,
i).getStringValue(TSFileConfig.STRING_CHARSET);
+ int beginPosition = secondType.getInt(secondColumn, i);
+ int endPosition = thirdType.getInt(thirdColumn, i);
+ if (beginPosition >= currentValue.length() || endPosition < 0) {
+ currentValue = EMPTY_STRING;
+ } else {
+ if (endPosition >= currentValue.length()) {
+ currentValue = currentValue.substring(beginPosition);
+ } else {
+ currentValue = currentValue.substring(beginPosition, endPosition);
+ }
+ }
+ builder.writeBinary(BytesUtils.valueOf(currentValue));
+ } else {
+ builder.appendNull();
+ }
+ }
+ }
+}