You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by xu...@apache.org on 2020/02/27 03:30:18 UTC
[incubator-iotdb] branch new_series_reader updated: [IOTDB-476]
Improve the ExpressionOptimizer (#841)
This is an automated email from the ASF dual-hosted git repository.
xuekaifeng pushed a commit to branch new_series_reader
in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git
The following commit(s) were added to refs/heads/new_series_reader by this push:
new 9bc8ec5 [IOTDB-476] Improve the ExpressionOptimizer (#841)
9bc8ec5 is described below
commit 9bc8ec562e9e9241d7e4e847e850295c0364c0a9
Author: Ring-k <36...@users.noreply.github.com>
AuthorDate: Thu Feb 27 11:30:08 2020 +0800
[IOTDB-476] Improve the ExpressionOptimizer (#841)
* optimize expression
* google code style
* remove temp test
* change if else statement
* update test
---
.../read/expression/util/ExpressionOptimizer.java | 59 ++++++++++++++++++++--
.../read/filter/IExpressionOptimizerTest.java | 16 +++---
2 files changed, 65 insertions(+), 10 deletions(-)
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/expression/util/ExpressionOptimizer.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/expression/util/ExpressionOptimizer.java
index da83d1b..e8b0eb8 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/expression/util/ExpressionOptimizer.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/expression/util/ExpressionOptimizer.java
@@ -45,7 +45,7 @@ public class ExpressionOptimizer {
/**
* try to remove GlobalTimeExpression.
*
- * @param expression IExpression to be transferred
+ * @param expression IExpression to be transferred
* @param selectedSeries selected series
* @return an executable query filter, whether a GlobalTimeExpression or All leaf nodes are
* SingleSeriesExpression
@@ -108,14 +108,65 @@ public class ExpressionOptimizer {
addTimeFilterToQueryFilter((globalTimeExpression).getFilter(), regularRightIExpression);
return regularRightIExpression;
} else if (relation == ExpressionType.OR) {
- return BinaryExpression
- .or(pushGlobalTimeFilterToAllSeries(globalTimeExpression, selectedSeries),
- regularRightIExpression);
+ IExpression afterTransform = pushGlobalTimeFilterToAllSeries(globalTimeExpression,
+ selectedSeries);
+ return mergeSecondTreeToFirstTree(afterTransform, regularRightIExpression);
}
throw new QueryFilterOptimizationException("unknown relation in IExpression:" + relation);
}
/**
+ * This method merge the second input, which is of tree structure, to the first parameter. It
+ * visits all leaf nodes, which are SingleSeriesExpressions, or AndExpression in right Expression,
+ * merge them to the right position in leftExpression.
+ *
+ * @param leftExpression The IExpression transformed from GlobalTimeExpression, which might have
+ * already be updated and merged.
+ * @param rightExpression The IExpression to be merged into the first IExpression
+ * @return a merged IExpression, which is initially based on the input leftExpression
+ */
+ private IExpression mergeSecondTreeToFirstTree(IExpression leftExpression,
+ IExpression rightExpression) {
+ if (rightExpression.getType() == ExpressionType.SERIES) {
+ SingleSeriesExpression leaf = (SingleSeriesExpression) rightExpression;
+ updateFilterWithOr(leftExpression, leaf.getFilter(), leaf.getSeriesPath());
+ return leftExpression;
+ } else if (rightExpression.getType() == ExpressionType.OR) {
+ IExpression leftChild = ((BinaryExpression) rightExpression).getLeft();
+ IExpression rightChild = ((BinaryExpression) rightExpression).getRight();
+ leftExpression = mergeSecondTreeToFirstTree(leftExpression, leftChild);
+ leftExpression = mergeSecondTreeToFirstTree(leftExpression, rightChild);
+ return leftExpression;
+ } else {
+ return BinaryExpression.or(leftExpression, rightExpression);
+ }
+ }
+
+ /**
+ * This method search the node in the input expression, whose path is identical to the input
+ * path, then merges its filter and the input filter with relation OR.
+ *
+ * @return true if the input filter is merged.
+ */
+ private boolean updateFilterWithOr(IExpression expression, Filter filter, Path path) {
+ if (expression.getType() == ExpressionType.SERIES && ((SingleSeriesExpression) expression)
+ .getSeriesPath().equals(path)) {
+ Filter nodeFilter = ((SingleSeriesExpression) expression).getFilter();
+ nodeFilter = FilterFactory.or(nodeFilter, filter);
+ ((SingleSeriesExpression) expression).setFilter(nodeFilter);
+ return true;
+ } else if (expression.getType() == ExpressionType.OR) {
+ assert expression instanceof BinaryExpression;
+ IExpression left = ((BinaryExpression) expression).getLeft();
+ IExpression right = ((BinaryExpression) expression).getRight();
+ return updateFilterWithOr(left, filter, path) || updateFilterWithOr(right, filter, path);
+ } else {
+ return false;
+ }
+ }
+
+
+ /**
* Combine GlobalTimeExpression with all selected series. example: input:
* GlobalTimeExpression(timeFilter) Selected Series: path1, path2, path3 output: QueryFilterOR(
* QueryFilterOR( SingleSeriesExpression(path1, timeFilter), SingleSeriesExpression(path2,
diff --git a/tsfile/src/test/java/org/apache/iotdb/tsfile/read/filter/IExpressionOptimizerTest.java b/tsfile/src/test/java/org/apache/iotdb/tsfile/read/filter/IExpressionOptimizerTest.java
index 8bf416d..c64afe2 100644
--- a/tsfile/src/test/java/org/apache/iotdb/tsfile/read/filter/IExpressionOptimizerTest.java
+++ b/tsfile/src/test/java/org/apache/iotdb/tsfile/read/filter/IExpressionOptimizerTest.java
@@ -20,6 +20,7 @@ package org.apache.iotdb.tsfile.read.filter;
import java.util.ArrayList;
import java.util.List;
+
import org.apache.iotdb.tsfile.exception.filter.QueryFilterOptimizationException;
import org.apache.iotdb.tsfile.read.common.Path;
import org.apache.iotdb.tsfile.read.expression.IExpression;
@@ -143,7 +144,7 @@ public class IExpressionOptimizerTest {
.or(BinaryExpression.and(singleSeriesExp1, globalTimeFilter),
globalTimeFilter2);
try {
- String rightRet = "[[[[[d1.s1:time > 1] || [d2.s1:time > 1]] || [d1.s2:time > 1]] || [d2.s2:time > 1]] || [d2.s1:((value > 100 || value < 50) && time < 14001234)]]";
+ String rightRet = "[[[[d1.s1:time > 1] || [d2.s1:(time > 1 || ((value > 100 || value < 50) && time < 14001234))]] || [d1.s2:time > 1]] || [d2.s2:time > 1]]";
IExpression regularFilter = expressionOptimizer.optimize(expression, selectedSeries);
Assert.assertEquals(rightRet, regularFilter.toString());
} catch (QueryFilterOptimizationException e) {
@@ -189,8 +190,10 @@ public class IExpressionOptimizerTest {
try {
String rightRet =
- "[[[[[d1.s1:time < 14001234] || [d2.s1:time < 14001234]] || [d1.s2:time < 14001234]] "
- + "|| [d2.s2:time < 14001234]] || [[d2.s1:(value > 100 || value < 50)] || [d1.s2:(value > 100.5 || value < 50.6)]]]";
+ "[[[[d1.s1:time < 14001234] "
+ + "|| [d2.s1:(time < 14001234 || (value > 100 || value < 50))]] "
+ + "|| [d1.s2:(time < 14001234 || (value > 100.5 || value < 50.6))]] "
+ + "|| [d2.s2:time < 14001234]]";
IExpression regularFilter = expressionOptimizer.optimize(expression, selectedSeries);
Assert.assertEquals(rightRet, regularFilter.toString());
} catch (QueryFilterOptimizationException e) {
@@ -216,9 +219,10 @@ public class IExpressionOptimizerTest {
try {
String rightRet =
- "[[[[[d1.s1:(time < 14001234 && time > 14001000)] || [d2.s1:(time < 14001234 "
- + "&& time > 14001000)]] || [d1.s2:(time < 14001234 && time > 14001000)]] || [d2.s2:(time < 14001234 "
- + "&& time > 14001000)]] || [[d2.s1:(value > 100 || value < 50)] || [d1.s2:(value > 100.5 || value < 50.6)]]]";
+ "[[[[d1.s1:(time < 14001234 && time > 14001000)] "
+ + "|| [d2.s1:((time < 14001234 && time > 14001000) || (value > 100 || value < 50))]] "
+ + "|| [d1.s2:((time < 14001234 && time > 14001000) || (value > 100.5 || value < 50.6))]] "
+ + "|| [d2.s2:(time < 14001234 && time > 14001000)]]";
IExpression regularFilter = expressionOptimizer.optimize(expression, selectedSeries);
Assert.assertEquals(rightRet, regularFilter.toString());
} catch (QueryFilterOptimizationException e) {