This is an automated email from the ASF dual-hosted git repository.
caogaofei 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 c74f552733b add bewteen and, is null, is not null, substring, like,
round
new 4392c97a181 Merge branch 'ty/TableModelGrammar' of
github.com:apache/iotdb into ty/TableModelGrammar
c74f552733b is described below
commit c74f552733b4007e235a678a610d57c9e6ee3262
Author: Beyyes <[email protected]>
AuthorDate: Sat Apr 27 10:27:44 2024 +0800
add bewteen and, is null, is not null, substring, like, round
---
.../plan/relational/planner/PlanBuilder.java | 2 +-
.../plan/relational/planner/QueryPlanner.java | 8 +-
.../relational/planner/ir/ExpressionRewriter.java | 14 +-
.../planner/ir/ExpressionTranslateVisitor.java | 94 +++++---
.../planner/ir/ExpressionTreeRewriter.java | 84 +------
.../ExtractCommonPredicatesExpressionRewriter.java | 22 +-
.../ir/GlobalTimePredicateExtractVisitor.java | 247 +++++++++++++++++++++
.../plan/relational/planner/ir/IrVisitor.java | 25 ---
.../planner/ir/NormalizeOrExpressionRewriter.java | 10 +-
.../relational/planner/ir/RewritingVisitor.java | 221 ++++++++++++++++++
10 files changed, 552 insertions(+), 175 deletions(-)
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlanBuilder.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlanBuilder.java
index 38af83ec7f8..4e0d3982949 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlanBuilder.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/PlanBuilder.java
@@ -82,7 +82,7 @@ public class PlanBuilder {
}
private Expression translate(Expression expression) {
- return new ExpressionTranslateVisitor().process(expression, this);
+ return ExpressionTranslateVisitor.translateToSymbolReference(expression,
this);
}
public Optional<Symbol> getSymbolForColumn(Expression expression) {
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/QueryPlanner.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/QueryPlanner.java
index 5f1f193e2e6..a99e0f473e1 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/QueryPlanner.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/QueryPlanner.java
@@ -19,6 +19,7 @@ import org.apache.iotdb.db.queryengine.common.SessionInfo;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
import org.apache.iotdb.db.queryengine.plan.relational.analyzer.Analysis;
import org.apache.iotdb.db.queryengine.plan.relational.analyzer.NodeRef;
+import
org.apache.iotdb.db.queryengine.plan.relational.planner.ir.ExpressionTranslateVisitor;
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.FilterNode;
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.LimitNode;
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.OffsetNode;
@@ -50,7 +51,7 @@ import static
com.google.common.collect.ImmutableList.toImmutableList;
import static java.util.Objects.requireNonNull;
import static
org.apache.iotdb.db.queryengine.plan.relational.planner.OrderingTranslator.sortItemToSortOrder;
import static
org.apache.iotdb.db.queryengine.plan.relational.planner.PlanBuilder.newPlanBuilder;
-import static
org.apache.iotdb.db.queryengine.plan.relational.planner.PredicateUtils.extractGlobalTimePredicate;
+import static
org.apache.iotdb.db.queryengine.plan.relational.planner.ir.GlobalTimePredicateExtractVisitor.extractGlobalTimeFilter;
public class QueryPlanner {
private final Analysis analysis;
@@ -244,8 +245,9 @@ public class QueryPlanner {
return planBuilder;
}
- Pair<Expression, Boolean> resultPair =
extractGlobalTimePredicate(predicate, true, true);
- Expression globalTimePredicate = resultPair.left;
+ Pair<Expression, Boolean> resultPair = extractGlobalTimeFilter(predicate);
+ Expression globalTimePredicate =
+ ExpressionTranslateVisitor.translateToSymbolReference(resultPair.left,
planBuilder);
analysis.setGlobalTableModelTimePredicate(globalTimePredicate);
boolean hasValueFilter = resultPair.right;
if (!hasValueFilter) {
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionRewriter.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionRewriter.java
index e0d72f48928..13b8daf01da 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionRewriter.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionRewriter.java
@@ -37,9 +37,13 @@ import
org.apache.iotdb.db.relational.sql.tree.SimpleCaseExpression;
import org.apache.iotdb.db.relational.sql.tree.SymbolReference;
public class ExpressionRewriter<C> {
+
protected Expression rewriteExpression(
Expression node, C context, ExpressionTreeRewriter<C> treeRewriter) {
return null;
+ // throw new IllegalStateException(
+ // String.format("%s is not supported in ExpressionRewriter yet",
+ // node.getClass().getName()));
}
public Expression rewriteRow(Row node, C context, ExpressionTreeRewriter<C>
treeRewriter) {
@@ -106,11 +110,6 @@ public class ExpressionRewriter<C> {
return rewriteExpression(node, context, treeRewriter);
}
- // public Expression rewriteLambdaExpression(LambdaExpression node, C
context,
- // ExpressionTreeRewriter<C> treeRewriter) {
- // return rewriteExpression(node, context, treeRewriter);
- // }
-
// public Expression rewriteBindExpression(BindExpression node, C context,
// ExpressionTreeRewriter<C> treeRewriter) {
// return rewriteExpression(node, context, treeRewriter);
@@ -126,11 +125,6 @@ public class ExpressionRewriter<C> {
// return rewriteExpression(node, context, treeRewriter);
// }
- // public Expression rewriteSubscriptExpression(SubscriptExpression node,
C context,
- // ExpressionTreeRewriter<C> treeRewriter) {
- // return rewriteExpression(node, context, treeRewriter);
- // }
-
public Expression rewriteCast(Cast node, C context,
ExpressionTreeRewriter<C> treeRewriter) {
return rewriteExpression(node, context, treeRewriter);
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionTranslateVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionTranslateVisitor.java
index 400184f91b0..c7a05609bde 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionTranslateVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionTranslateVisitor.java
@@ -16,14 +16,12 @@ package
org.apache.iotdb.db.queryengine.plan.relational.planner.ir;
import org.apache.iotdb.db.queryengine.plan.relational.planner.PlanBuilder;
import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol;
import org.apache.iotdb.db.relational.sql.tree.ArithmeticBinaryExpression;
-import org.apache.iotdb.db.relational.sql.tree.AstVisitor;
-import org.apache.iotdb.db.relational.sql.tree.BetweenPredicate;
import org.apache.iotdb.db.relational.sql.tree.ComparisonExpression;
import org.apache.iotdb.db.relational.sql.tree.Expression;
+import org.apache.iotdb.db.relational.sql.tree.FunctionCall;
import org.apache.iotdb.db.relational.sql.tree.Identifier;
import org.apache.iotdb.db.relational.sql.tree.IfExpression;
import org.apache.iotdb.db.relational.sql.tree.InPredicate;
-import org.apache.iotdb.db.relational.sql.tree.IsNotNullPredicate;
import org.apache.iotdb.db.relational.sql.tree.IsNullPredicate;
import org.apache.iotdb.db.relational.sql.tree.LikePredicate;
import org.apache.iotdb.db.relational.sql.tree.Literal;
@@ -34,39 +32,42 @@ import
org.apache.iotdb.db.relational.sql.tree.SearchedCaseExpression;
import org.apache.iotdb.db.relational.sql.tree.SimpleCaseExpression;
import org.apache.iotdb.db.relational.sql.tree.SymbolReference;
+import java.util.List;
+import java.util.stream.Collectors;
+
import static com.google.common.collect.ImmutableList.toImmutableList;
/** Change Identifier to SymbolReference */
-public class ExpressionTranslateVisitor extends AstVisitor<Expression,
PlanBuilder> {
+public class ExpressionTranslateVisitor extends RewritingVisitor<PlanBuilder> {
- @Override
- protected Expression visitSymbolReference(SymbolReference node, PlanBuilder
context) {
- return new
SymbolReference(context.getSymbolForColumn(node).get().getName());
- }
+ private ExpressionTranslateVisitor() {}
- @Override
- protected Expression visitIdentifier(Identifier node, PlanBuilder context) {
- return
context.getSymbolForColumn(node).map(Symbol::toSymbolReference).get();
+ private static final String NOT_SUPPORTED = "%s is not supported expression
translate yet.";
+
+ public static Expression translateToSymbolReference(
+ Expression expression, PlanBuilder planBuilder) {
+ return new ExpressionTranslateVisitor().process(expression, planBuilder);
}
@Override
- protected Expression visitInPredicate(InPredicate node, PlanBuilder context)
{
- return null;
+ protected Expression visitExpression(Expression node, PlanBuilder context) {
+ throw new IllegalStateException(String.format(NOT_SUPPORTED,
node.getClass().getName()));
}
@Override
- protected Expression visitIsNullPredicate(IsNullPredicate node, PlanBuilder
context) {
- return null;
+ protected Expression visitSymbolReference(SymbolReference node, PlanBuilder
context) {
+ return new
SymbolReference(context.getSymbolForColumn(node).get().getName());
}
@Override
- protected Expression visitIsNotNullPredicate(IsNotNullPredicate node,
PlanBuilder context) {
- return null;
+ protected Expression visitIdentifier(Identifier node, PlanBuilder context) {
+ return
context.getSymbolForColumn(node).map(Symbol::toSymbolReference).get();
}
@Override
- protected Expression visitLikePredicate(LikePredicate node, PlanBuilder
context) {
- return null;
+ protected Expression visitArithmeticBinary(ArithmeticBinaryExpression node,
PlanBuilder context) {
+ return new ArithmeticBinaryExpression(
+ node.getOperator(), process(node.getLeft(), context),
process(node.getRight(), context));
}
@Override
@@ -77,8 +78,8 @@ public class ExpressionTranslateVisitor extends
AstVisitor<Expression, PlanBuild
}
@Override
- protected Expression visitNotExpression(NotExpression node, PlanBuilder
context) {
- return null;
+ protected Expression visitLiteral(Literal node, PlanBuilder context) {
+ return node;
}
@Override
@@ -89,39 +90,58 @@ public class ExpressionTranslateVisitor extends
AstVisitor<Expression, PlanBuild
}
@Override
- protected Expression visitSimpleCaseExpression(SimpleCaseExpression node,
PlanBuilder context) {
- return null;
+ protected Expression visitFunctionCall(FunctionCall node, PlanBuilder
context) {
+ List<Expression> newArguments =
+ node.getArguments().stream()
+ .map(argument -> process(argument, context))
+ .collect(Collectors.toList());
+ return new FunctionCall(node.getName(), newArguments);
}
@Override
- protected Expression visitSearchedCaseExpression(
- SearchedCaseExpression node, PlanBuilder context) {
- return null;
+ protected Expression visitIsNullPredicate(IsNullPredicate node, PlanBuilder
context) {
+ return new IsNullPredicate(process(node.getValue(), context));
}
@Override
- protected Expression visitIfExpression(IfExpression node, PlanBuilder
context) {
- return null;
+ protected Expression visitInPredicate(InPredicate node, PlanBuilder context)
{
+ return new InPredicate(
+ process(node.getValue(), context), process(node.getValueList(),
context));
}
@Override
- protected Expression visitNullIfExpression(NullIfExpression node,
PlanBuilder context) {
- return null;
+ protected Expression visitLikePredicate(LikePredicate node, PlanBuilder
context) {
+ return new LikePredicate(
+ process(node.getValue(), context),
+ process(node.getPattern(), context),
+ process(node.getPattern(), context));
}
+ // ============================ not implemented
=======================================
+
@Override
- protected Expression visitBetweenPredicate(BetweenPredicate node,
PlanBuilder context) {
- return null;
+ protected Expression visitNotExpression(NotExpression node, PlanBuilder
context) {
+ throw new IllegalStateException(String.format(NOT_SUPPORTED,
node.getClass().getName()));
}
@Override
- protected Expression visitArithmeticBinary(ArithmeticBinaryExpression node,
PlanBuilder context) {
- return new ArithmeticBinaryExpression(
- node.getOperator(), process(node.getLeft(), context),
process(node.getRight(), context));
+ protected Expression visitSimpleCaseExpression(SimpleCaseExpression node,
PlanBuilder context) {
+ throw new IllegalStateException(String.format(NOT_SUPPORTED,
node.getClass().getName()));
}
@Override
- protected Expression visitLiteral(Literal node, PlanBuilder context) {
- return node;
+ protected Expression visitSearchedCaseExpression(
+ SearchedCaseExpression node, PlanBuilder context) {
+ throw new IllegalStateException(String.format(NOT_SUPPORTED,
node.getClass().getName()));
+ }
+
+ @Override
+ protected Expression visitIfExpression(IfExpression node, PlanBuilder
context) {
+ throw new IllegalStateException(String.format(NOT_SUPPORTED,
node.getClass().getName()));
+ }
+
+ @Override
+ protected Expression visitNullIfExpression(NullIfExpression node,
PlanBuilder context) {
+ throw new IllegalStateException(String.format(NOT_SUPPORTED,
node.getClass().getName()));
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionTreeRewriter.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionTreeRewriter.java
index e2367eb8602..fb9cc31cecc 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionTreeRewriter.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExpressionTreeRewriter.java
@@ -49,6 +49,11 @@ public final class ExpressionTreeRewriter<C> {
private final ExpressionRewriter<C> rewriter;
private final IrVisitor<Expression, Context<C>> visitor;
+ public ExpressionTreeRewriter(ExpressionRewriter<C> rewriter) {
+ this.rewriter = rewriter;
+ this.visitor = new RewritingVisitor();
+ }
+
public static <T extends Expression> T rewriteWith(ExpressionRewriter<Void>
rewriter, T node) {
return new ExpressionTreeRewriter<>(rewriter).rewrite(node, null);
}
@@ -58,11 +63,6 @@ public final class ExpressionTreeRewriter<C> {
return new ExpressionTreeRewriter<>(rewriter).rewrite(node, context);
}
- public ExpressionTreeRewriter(ExpressionRewriter<C> rewriter) {
- this.rewriter = rewriter;
- this.visitor = new RewritingVisitor();
- }
-
private List<Expression> rewrite(List<Expression> items, Context<C> context)
{
ImmutableList.Builder<Expression> builder = ImmutableList.builder();
for (Expression expression : items) {
@@ -86,6 +86,7 @@ public final class ExpressionTreeRewriter<C> {
}
private class RewritingVisitor extends IrVisitor<Expression, Context<C>> {
+
@Override
protected Expression visitExpression(Expression node, Context<C> context) {
// RewritingVisitor must have explicit support for each expression type,
with a dedicated
@@ -155,28 +156,6 @@ public final class ExpressionTreeRewriter<C> {
return node;
}
- // @Override
- // protected Expression
visitSubscriptExpression(SubscriptExpression node, Context<C>
- // context)
- // {
- // if (!context.isDefaultRewrite()) {
- // Expression result =
rewriter.rewriteSubscriptExpression(node, context.get(),
- // ExpressionTreeRewriter.this);
- // if (result != null) {
- // return result;
- // }
- // }
- //
- // Expression base = rewrite(node.getBase(), context.get());
- // Expression index = rewrite(node.getIndex(), context.get());
- //
- // if (base != node.getBase() || index != node.getIndex()) {
- // return new SubscriptExpression(base, index);
- // }
- //
- // return node;
- // }
-
@Override
public Expression visitComparisonExpression(ComparisonExpression node,
Context<C> context) {
if (!context.isDefaultRewrite()) {
@@ -400,53 +379,6 @@ public final class ExpressionTreeRewriter<C> {
return node;
}
- // @Override
- // protected Expression visitLambdaExpression(LambdaExpression
node, Context<C> context)
- // {
- // if (!context.isDefaultRewrite()) {
- // Expression result =
rewriter.rewriteLambdaExpression(node, context.get(),
- // ExpressionTreeRewriter.this);
- // if (result != null) {
- // return result;
- // }
- // }
- //
- // List<String> arguments = node.getArguments().stream()
- // .map(SymbolReference::new)
- // .map(expression -> rewrite(expression,
context.get()))
- // .map(SymbolReference::getName)
- // .collect(toImmutableList());
- //
- // Expression body = rewrite(node.getBody(), context.get());
- // if (body != node.getBody()) {
- // return new LambdaExpression(arguments, body);
- // }
- //
- // return node;
- // }
-
- // @Override
- // protected Expression visitBindExpression(BindExpression node,
Context<C> context)
- // {
- // if (!context.isDefaultRewrite()) {
- // Expression result = rewriter.rewriteBindExpression(node,
context.get(),
- // ExpressionTreeRewriter.this);
- // if (result != null) {
- // return result;
- // }
- // }
- //
- // List<Expression> values = node.getValues().stream()
- // .map(value -> rewrite(value, context.get()))
- // .collect(toImmutableList());
- // Expression function = rewrite(node.getFunction(),
context.get());
- //
- // if (!sameElements(values, node.getValues()) || (function !=
node.getFunction())) {
- // return new BindExpression(values, function);
- // }
- // return node;
- // }
-
@Override
public Expression visitInPredicate(InPredicate node, Context<C> context) {
if (!context.isDefaultRewrite()) {
@@ -544,7 +476,7 @@ public final class ExpressionTreeRewriter<C> {
}
}
- private static <T> boolean sameElements(Optional<T> a, Optional<T> b) {
+ public static <T> boolean sameElements(Optional<T> a, Optional<T> b) {
if (!a.isPresent() && !b.isPresent()) {
return true;
}
@@ -556,7 +488,7 @@ public final class ExpressionTreeRewriter<C> {
}
@SuppressWarnings("ObjectEquality")
- private static <T> boolean sameElements(Iterable<? extends T> a, Iterable<?
extends T> b) {
+ public static <T> boolean sameElements(Iterable<? extends T> a, Iterable<?
extends T> b) {
if (Iterables.size(a) != Iterables.size(b)) {
return false;
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExtractCommonPredicatesExpressionRewriter.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExtractCommonPredicatesExpressionRewriter.java
index 154eff8c547..96ced66c660 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExtractCommonPredicatesExpressionRewriter.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/ExtractCommonPredicatesExpressionRewriter.java
@@ -42,34 +42,20 @@ import static
org.apache.iotdb.db.relational.sql.tree.LogicalExpression.Operator
public final class ExtractCommonPredicatesExpressionRewriter {
public static Expression extractCommonPredicates(Expression expression) {
- return ExpressionTreeRewriter.rewriteWith(new Visitor(), expression,
NodeContext.ROOT_NODE);
+ return new Visitor().process(expression, NodeContext.ROOT_NODE);
}
private ExtractCommonPredicatesExpressionRewriter() {}
- private static class Visitor extends ExpressionRewriter<NodeContext> {
- @Override
- protected Expression rewriteExpression(
- Expression node, NodeContext context,
ExpressionTreeRewriter<NodeContext> treeRewriter) {
- if (context.isRootNode()) {
- return treeRewriter.rewrite(node, NodeContext.NOT_ROOT_NODE);
- }
-
- return null;
- }
+ private static class Visitor extends RewritingVisitor<NodeContext> {
@Override
- public Expression rewriteLogicalExpression(
- LogicalExpression node,
- NodeContext context,
- ExpressionTreeRewriter<NodeContext> treeRewriter) {
+ public Expression visitLogicalExpression(LogicalExpression node,
NodeContext context) {
Expression expression =
combinePredicates(
node.getOperator(),
extractPredicates(node.getOperator(), node).stream()
- .map(
- subExpression ->
- treeRewriter.rewrite(subExpression,
NodeContext.NOT_ROOT_NODE))
+ .map(subExpression -> process(subExpression,
NodeContext.NOT_ROOT_NODE))
.collect(toImmutableList()));
if (!(expression instanceof LogicalExpression)) {
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/GlobalTimePredicateExtractVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/GlobalTimePredicateExtractVisitor.java
new file mode 100644
index 00000000000..2d0b185f617
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/GlobalTimePredicateExtractVisitor.java
@@ -0,0 +1,247 @@
+/*
+ * 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.plan.relational.planner.ir;
+
+import org.apache.iotdb.db.relational.sql.tree.ArithmeticBinaryExpression;
+import org.apache.iotdb.db.relational.sql.tree.BetweenPredicate;
+import org.apache.iotdb.db.relational.sql.tree.ComparisonExpression;
+import org.apache.iotdb.db.relational.sql.tree.Expression;
+import org.apache.iotdb.db.relational.sql.tree.FunctionCall;
+import org.apache.iotdb.db.relational.sql.tree.Identifier;
+import org.apache.iotdb.db.relational.sql.tree.IfExpression;
+import org.apache.iotdb.db.relational.sql.tree.InPredicate;
+import org.apache.iotdb.db.relational.sql.tree.IsNotNullPredicate;
+import org.apache.iotdb.db.relational.sql.tree.IsNullPredicate;
+import org.apache.iotdb.db.relational.sql.tree.LikePredicate;
+import org.apache.iotdb.db.relational.sql.tree.LogicalExpression;
+import org.apache.iotdb.db.relational.sql.tree.LongLiteral;
+import org.apache.iotdb.db.relational.sql.tree.NotExpression;
+import org.apache.iotdb.db.relational.sql.tree.NullIfExpression;
+import org.apache.iotdb.db.relational.sql.tree.SearchedCaseExpression;
+import org.apache.iotdb.db.relational.sql.tree.SimpleCaseExpression;
+
+import org.apache.tsfile.utils.Pair;
+
+import java.util.Arrays;
+
+import static org.apache.iotdb.commons.conf.IoTDBConstant.TIME;
+import static
org.apache.iotdb.db.relational.sql.tree.BooleanLiteral.TRUE_LITERAL;
+import static
org.apache.iotdb.db.relational.sql.tree.LogicalExpression.Operator.AND;
+import static
org.apache.iotdb.db.relational.sql.tree.LogicalExpression.Operator.OR;
+import static org.apache.iotdb.db.relational.sql.tree.LogicalExpression.and;
+import static org.apache.iotdb.db.relational.sql.tree.LogicalExpression.or;
+
+public class GlobalTimePredicateExtractVisitor
+ extends IrVisitor<Pair<Expression, Boolean>,
GlobalTimePredicateExtractVisitor.Context> {
+
+ private static final String NOT_SUPPORTED =
+ "visit() not implemented for %s in GlobalTimePredicateExtract.";
+
+ public static Pair<Expression, Boolean> extractGlobalTimeFilter(Expression
predicate) {
+ return new GlobalTimePredicateExtractVisitor()
+ .process(predicate, new
GlobalTimePredicateExtractVisitor.Context(true, true));
+ }
+
+ protected Pair<Expression, Boolean> visitExpression(
+ Pair<Expression, Boolean> node, Context context) {
+ throw new IllegalStateException(String.format(NOT_SUPPORTED,
node.getClass()));
+ }
+
+ @Override
+ protected Pair<Expression, Boolean> visitLogicalExpression(
+ LogicalExpression node, Context context) {
+ if (node.getOperator() == AND) {
+ Pair<Expression, Boolean> leftResultPair =
process(node.getTerms().get(0), context);
+ Pair<Expression, Boolean> rightResultPair =
process(node.getTerms().get(1), context);
+
+ // rewrite predicate to avoid duplicate calculation on time filter
+ // If Left-child or Right-child does not contain value filter
+ // We can set it to true in Predicate Tree
+ if (context.canRewrite) {
+ Expression newLeftExpression = null, newRightExpression = null;
+ if (leftResultPair.left != null && !leftResultPair.right) {
+ newLeftExpression = TRUE_LITERAL;
+ }
+ if (rightResultPair.left != null && !rightResultPair.right) {
+ newRightExpression = TRUE_LITERAL;
+ }
+ if (newLeftExpression != null || newRightExpression != null) {
+ node.setTerms(
+ Arrays.asList(
+ newLeftExpression != null ? newLeftExpression :
node.getTerms().get(0),
+ newRightExpression != null ? newRightExpression :
node.getTerms().get(1)));
+ }
+ }
+
+ if (leftResultPair.left != null && rightResultPair.left != null) {
+ return new Pair<>(
+ and(leftResultPair.left, rightResultPair.left),
+ leftResultPair.right || rightResultPair.right);
+ } else if (leftResultPair.left != null) {
+ return new Pair<>(leftResultPair.left, true);
+ } else if (rightResultPair.left != null) {
+ return new Pair<>(rightResultPair.left, true);
+ }
+
+ return new Pair<>(null, true);
+ } else if (node.getOperator() == OR) {
+ Pair<Expression, Boolean> leftResultPair =
+ process(node.getTerms().get(0), new Context(false, false));
+ Pair<Expression, Boolean> rightResultPair =
+ process(node.getTerms().get(1), new Context(false, false));
+
+ if (leftResultPair.left != null && rightResultPair.left != null) {
+ if (Boolean.TRUE.equals(
+ context.isFirstOr && !leftResultPair.right &&
!rightResultPair.right)) {
+ node.getTerms().set(0, TRUE_LITERAL);
+ node.getTerms().set(0, TRUE_LITERAL);
+ }
+ return new Pair<>(
+ or(leftResultPair.left, rightResultPair.left),
+ leftResultPair.right || rightResultPair.right);
+ }
+ return new Pair<>(null, true);
+ } else {
+ throw new IllegalStateException("Illegal state in
visitLogicalExpression");
+ }
+ }
+
+ @Override
+ protected Pair<Expression, Boolean> visitComparisonExpression(
+ ComparisonExpression node, Context context) {
+ Expression leftExpression = node.getLeft();
+ Expression rightExpression = node.getRight();
+ if (checkIsTimeFilter(leftExpression, rightExpression)
+ || checkIsTimeFilter(rightExpression, leftExpression)) {
+ return new Pair<>(node, false);
+ }
+ return new Pair<>(null, true);
+ }
+
+ @Override
+ protected Pair<Expression, Boolean> visitIsNullPredicate(IsNullPredicate
node, Context context) {
+ // time filter don't support IS_NULL
+ return new Pair<>(null, true);
+ }
+
+ @Override
+ protected Pair<Expression, Boolean> visitIsNotNullPredicate(
+ IsNotNullPredicate node, Context context) {
+ return new Pair<>(null, true);
+ }
+
+ @Override
+ protected Pair<Expression, Boolean> visitFunctionCall(FunctionCall node,
Context context) {
+ return new Pair<>(null, true);
+ }
+
+ @Override
+ protected Pair<Expression, Boolean> visitLikePredicate(LikePredicate node,
Context context) {
+ return new Pair<>(null, true);
+ }
+
+ @Override
+ protected Pair<Expression, Boolean> visitBetweenPredicate(
+ BetweenPredicate node, Context context) {
+ Expression firstExpression = node.getValue();
+ Expression secondExpression = node.getMin();
+ Expression thirdExpression = node.getMax();
+
+ boolean isTimeFilter = false;
+ if (isTimeIdentifier(firstExpression)) {
+ isTimeFilter = checkBetweenConstantSatisfy(secondExpression,
thirdExpression);
+ } else if (isTimeIdentifier(secondExpression)) {
+ isTimeFilter = checkBetweenConstantSatisfy(firstExpression,
thirdExpression);
+ } else if (isTimeIdentifier(thirdExpression)) {
+ isTimeFilter = checkBetweenConstantSatisfy(secondExpression,
firstExpression);
+ }
+ if (isTimeFilter) {
+ return new Pair<>(node, false);
+ }
+ return new Pair<>(null, true);
+ }
+
+ // ============================ not implemented
=======================================
+
+ @Override
+ protected Pair<Expression, Boolean> visitArithmeticBinary(
+ ArithmeticBinaryExpression node, Context context) {
+ throw new IllegalStateException(String.format(NOT_SUPPORTED,
node.getClass()));
+ }
+
+ @Override
+ protected Pair<Expression, Boolean> visitInPredicate(InPredicate node,
Context context) {
+ throw new IllegalStateException(String.format(NOT_SUPPORTED,
node.getClass()));
+ }
+
+ @Override
+ protected Pair<Expression, Boolean> visitNotExpression(NotExpression node,
Context context) {
+ throw new IllegalStateException(String.format(NOT_SUPPORTED,
node.getClass()));
+ }
+
+ @Override
+ protected Pair<Expression, Boolean> visitSimpleCaseExpression(
+ SimpleCaseExpression node, Context context) {
+ throw new IllegalStateException(String.format(NOT_SUPPORTED,
node.getClass()));
+ }
+
+ @Override
+ protected Pair<Expression, Boolean> visitSearchedCaseExpression(
+ SearchedCaseExpression node, Context context) {
+ throw new IllegalStateException(String.format(NOT_SUPPORTED,
node.getClass()));
+ }
+
+ @Override
+ protected Pair<Expression, Boolean> visitIfExpression(IfExpression node,
Context context) {
+ throw new IllegalStateException(String.format(NOT_SUPPORTED,
node.getClass()));
+ }
+
+ @Override
+ protected Pair<Expression, Boolean> visitNullIfExpression(
+ NullIfExpression node, Context context) {
+ throw new IllegalStateException(String.format(NOT_SUPPORTED,
node.getClass()));
+ }
+
+ private static boolean isTimeIdentifier(Expression e) {
+ return e instanceof Identifier && TIME.equalsIgnoreCase(((Identifier)
e).getValue());
+ }
+
+ private static boolean checkIsTimeFilter(Expression timeExpression,
Expression valueExpression) {
+ return timeExpression instanceof Identifier
+ && ((Identifier) timeExpression).getValue().equalsIgnoreCase(TIME)
+ && valueExpression instanceof LongLiteral;
+ }
+
+ private static boolean checkBetweenConstantSatisfy(Expression e1, Expression
e2) {
+ return e1 instanceof LongLiteral
+ && e2 instanceof LongLiteral
+ && ((LongLiteral) e1).getParsedValue() <= ((LongLiteral)
e2).getParsedValue();
+ }
+
+ public static class Context {
+ boolean canRewrite;
+ boolean isFirstOr;
+
+ public Context(boolean canRewrite, boolean isFirstOr) {
+ this.canRewrite = canRewrite;
+ this.isFirstOr = isFirstOr;
+ }
+ }
+}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/IrVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/IrVisitor.java
index 96bc02b17e0..bc7a2ff6681 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/IrVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/IrVisitor.java
@@ -65,11 +65,6 @@ public abstract class IrVisitor<R, C> extends AstVisitor<R,
C> {
return visitExpression(node, context);
}
- // protected R visitConstant(Constant node, C context)
- // {
- // return visitExpression(node, context);
- // }
-
protected R visitInPredicate(InPredicate node, C context) {
return visitExpression(node, context);
}
@@ -78,11 +73,6 @@ public abstract class IrVisitor<R, C> extends AstVisitor<R,
C> {
return visitExpression(node, context);
}
- // protected R visitLambdaExpression(LambdaExpression node, C context)
- // {
- // return visitExpression(node, context);
- // }
-
protected R visitSimpleCaseExpression(SimpleCaseExpression node, C context) {
return visitExpression(node, context);
}
@@ -91,11 +81,6 @@ public abstract class IrVisitor<R, C> extends AstVisitor<R,
C> {
return visitExpression(node, context);
}
- // protected R visitArithmeticNegation(ArithmeticNegation node, C context)
- // {
- // return visitExpression(node, context);
- // }
-
protected R visitNotExpression(NotExpression node, C context) {
return visitExpression(node, context);
}
@@ -108,11 +93,6 @@ public abstract class IrVisitor<R, C> extends AstVisitor<R,
C> {
return visitExpression(node, context);
}
- // protected R visitSubscriptExpression(SubscriptExpression node, C
context)
- // {
- // return visitExpression(node, context);
- // }
-
protected R visitLogicalExpression(LogicalExpression node, C context) {
return visitExpression(node, context);
}
@@ -128,9 +108,4 @@ public abstract class IrVisitor<R, C> extends AstVisitor<R,
C> {
protected R visitSymbolReference(SymbolReference node, C context) {
return visitExpression(node, context);
}
-
- // protected R visitBindExpression(BindExpression node, C context)
- // {
- // return visitExpression(node, context);
- // }
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/NormalizeOrExpressionRewriter.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/NormalizeOrExpressionRewriter.java
index 6d00d1b72eb..ddd05f34ee5 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/NormalizeOrExpressionRewriter.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/NormalizeOrExpressionRewriter.java
@@ -43,18 +43,18 @@ import static
org.apache.iotdb.db.relational.sql.tree.LogicalExpression.Operator
public final class NormalizeOrExpressionRewriter {
public static Expression normalizeOrExpression(Expression expression) {
- return ExpressionTreeRewriter.rewriteWith(new Visitor(), expression);
+ return new Visitor().process(expression, null);
}
private NormalizeOrExpressionRewriter() {}
- private static class Visitor extends ExpressionRewriter<Void> {
+ private static class Visitor extends RewritingVisitor<Void> {
+
@Override
- public Expression rewriteLogicalExpression(
- LogicalExpression node, Void context, ExpressionTreeRewriter<Void>
treeRewriter) {
+ public Expression visitLogicalExpression(LogicalExpression node, Void
context) {
List<Expression> terms =
node.getTerms().stream()
- .map(expression -> treeRewriter.rewrite(expression, context))
+ .map(expression -> process(expression, context))
.collect(toImmutableList());
if (node.getOperator() == AND) {
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/RewritingVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/RewritingVisitor.java
new file mode 100644
index 00000000000..64a87fa7bf7
--- /dev/null
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/RewritingVisitor.java
@@ -0,0 +1,221 @@
+package org.apache.iotdb.db.queryengine.plan.relational.planner.ir;
+
+import org.apache.iotdb.db.relational.sql.tree.ArithmeticBinaryExpression;
+import org.apache.iotdb.db.relational.sql.tree.BetweenPredicate;
+import org.apache.iotdb.db.relational.sql.tree.Cast;
+import org.apache.iotdb.db.relational.sql.tree.ComparisonExpression;
+import org.apache.iotdb.db.relational.sql.tree.Expression;
+import org.apache.iotdb.db.relational.sql.tree.FunctionCall;
+import org.apache.iotdb.db.relational.sql.tree.Identifier;
+import org.apache.iotdb.db.relational.sql.tree.InPredicate;
+import org.apache.iotdb.db.relational.sql.tree.IsNotNullPredicate;
+import org.apache.iotdb.db.relational.sql.tree.IsNullPredicate;
+import org.apache.iotdb.db.relational.sql.tree.LikePredicate;
+import org.apache.iotdb.db.relational.sql.tree.Literal;
+import org.apache.iotdb.db.relational.sql.tree.LogicalExpression;
+import org.apache.iotdb.db.relational.sql.tree.NotExpression;
+import org.apache.iotdb.db.relational.sql.tree.NullIfExpression;
+import org.apache.iotdb.db.relational.sql.tree.SymbolReference;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import static
org.apache.iotdb.db.queryengine.plan.relational.planner.ir.ExpressionTreeRewriter.sameElements;
+
+public class RewritingVisitor<C> extends IrVisitor<Expression, C> {
+
+ @Override
+ protected Expression visitExpression(Expression node, C context) {
+ // RewritingVisitor must have explicit support for each expression type,
with a dedicated
+ // visit method,
+ // so visitExpression() should never be called.
+ throw new UnsupportedOperationException(
+ "visit() not implemented for " + node.getClass().getName());
+ }
+
+ @Override
+ protected Expression visitArithmeticBinary(ArithmeticBinaryExpression node,
C context) {
+ Expression left = process(node.getLeft(), context);
+ Expression right = process(node.getRight(), context);
+
+ if (left != node.getLeft() || right != node.getRight()) {
+ // node.getLocation().get() may be null
+ return new ArithmeticBinaryExpression(
+ node.getLocation().get(), node.getOperator(), left, right);
+ }
+
+ return node;
+ }
+
+ @Override
+ protected Expression visitComparisonExpression(ComparisonExpression node, C
context) {
+ Expression left = process(node.getLeft(), context);
+ Expression right = process(node.getRight(), context);
+
+ if (left != node.getLeft() || right != node.getRight()) {
+ return new ComparisonExpression(node.getOperator(), left, right);
+ }
+
+ return node;
+ }
+
+ @Override
+ protected Expression visitBetweenPredicate(BetweenPredicate node, C context)
{
+ Expression value = process(node.getValue(), context);
+ Expression min = process(node.getMin(), context);
+ Expression max = process(node.getMax(), context);
+
+ if (value != node.getValue() || min != node.getMin() || max !=
node.getMax()) {
+ return new BetweenPredicate(value, min, max);
+ }
+
+ return node;
+ }
+
+ @Override
+ protected Expression visitLogicalExpression(LogicalExpression node, C
context) {
+ List<Expression> terms =
+ node.getTerms().stream().map(term -> process(term,
context)).collect(Collectors.toList());
+ if (!sameElements(node.getTerms(), terms)) {
+ return new LogicalExpression(node.getOperator(), terms);
+ }
+
+ return node;
+ }
+
+ @Override
+ protected Expression visitNotExpression(NotExpression node, C context) {
+ Expression value = process(node.getValue(), context);
+
+ if (value != node.getValue()) {
+ return new NotExpression(value);
+ }
+
+ return node;
+ }
+
+ @Override
+ protected Expression visitLikePredicate(LikePredicate node, C context) {
+ Expression value = process(node.getValue(), context);
+ Expression pattern = process(node.getPattern(), context);
+ Expression escape =
+ node.getEscape().isPresent() ? process(node.getEscape().get(),
context) : null;
+
+ if (value != node.getValue()
+ || pattern != node.getPattern()
+ || (escape != null && escape != node.getEscape().get())) {
+ return new LikePredicate(value, pattern, escape);
+ }
+
+ return node;
+ }
+
+ @Override
+ protected Expression visitIsNullPredicate(IsNullPredicate node, C context) {
+ Expression value = process(node.getValue(), context);
+
+ if (value != node.getValue()) {
+ return new IsNullPredicate(value);
+ }
+
+ return node;
+ }
+
+ @Override
+ protected Expression visitIsNotNullPredicate(IsNotNullPredicate node, C
context) {
+ Expression value = process(node.getValue(), context);
+
+ if (value != node.getValue()) {
+ return new IsNotNullPredicate(value);
+ }
+
+ return node;
+ }
+
+ @Override
+ protected Expression visitNullIfExpression(NullIfExpression node, C context)
{
+ Expression first = process(node.getFirst(), context);
+ Expression second = process(node.getSecond(), context);
+
+ if (first != node.getFirst() || second != node.getSecond()) {
+ return new NullIfExpression(first, second);
+ }
+
+ return node;
+ }
+
+ // @Override
+ // protected Expression visitSearchedCaseExpression(
+ // SearchedCaseExpression node, C context) {
+ // ImmutableList.Builder<WhenClause> builder =
ImmutableList.builder();
+ // for (WhenClause expression : node.getWhenClauses()) {
+ // builder.add(process(expression, context));
+ // }
+ //
+ // Optional<Expression> defaultValue =
+ // node.getDefaultValue().map(value -> rewrite(value,
context.get()));
+ //
+ // if (!sameElements(node.getDefaultValue(), defaultValue)
+ // || !sameElements(node.getWhenClauses(), builder.build())) {
+ // // defaultValue.get() may be null
+ // return new SearchedCaseExpression(builder.build(),
defaultValue.get());
+ // }
+ //
+ // return node;
+ // }
+
+ @Override
+ protected Expression visitFunctionCall(FunctionCall node, C context) {
+ List<Expression> arguments =
+ node.getArguments().stream()
+ .map(argument -> process(argument, context))
+ .collect(Collectors.toList());
+
+ if (!sameElements(node.getArguments(), arguments)) {
+ return new FunctionCall(node.getName(), arguments);
+ }
+ return node;
+ }
+
+ @Override
+ protected Expression visitInPredicate(InPredicate node, C context) {
+ Expression value = process(node.getValue(), context);
+ // List<Expression> values = node.getValueList().stream()
+ // .map(entry -> rewrite(entry, context.get()))
+ // .collect(toImmutableList());
+
+ if (node.getValue() != value
+ || !sameElements(Optional.of(value), Optional.of(node.getValue()))) {
+ return new InPredicate(value, value);
+ }
+
+ return node;
+ }
+
+ @Override
+ protected Expression visitCast(Cast node, C context) {
+ Expression expression = process(node.getExpression(), context);
+
+ if (expression != node.getExpression()) {
+ return new Cast(expression, node.getType(), node.isSafe(),
node.isTypeOnly());
+ }
+
+ return node;
+ }
+
+ @Override
+ protected Expression visitSymbolReference(SymbolReference node, C context) {
+ return node;
+ }
+
+ @Override
+ protected Expression visitIdentifier(Identifier node, C context) {
+ return node;
+ }
+
+ @Override
+ protected Expression visitLiteral(Literal node, C context) {
+ return node;
+ }
+}