This is an automated email from the ASF dual-hosted git repository.
chaow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 6f67a81 [IOTDB-1453]Fix result set when the server query time
filtered is And (#3452)
6f67a81 is described below
commit 6f67a81cf418f18f87084fb869db1816ce6e92ec
Author: Hang Ji <[email protected]>
AuthorDate: Wed Jul 7 14:56:20 2021 +0800
[IOTDB-1453]Fix result set when the server query time filtered is And
(#3452)
---
.../cluster/query/fill/ClusterPreviousFill.java | 2 +-
.../cluster/server/member/MetaGroupMember.java | 5 +-
.../apache/iotdb/cluster/utils/PartitionUtils.java | 237 ---------------------
.../cluster/server/member/MetaGroupMemberTest.java | 6 +-
.../iotdb/db/query/executor/QueryRouter.java | 11 +
.../apache/iotdb/db/utils/TimeValuePairUtils.java | 232 ++++++++++++++++++++
.../db/integration/IoTDBSequenceDataQueryIT.java | 40 ++++
7 files changed, 290 insertions(+), 243 deletions(-)
diff --git
a/cluster/src/main/java/org/apache/iotdb/cluster/query/fill/ClusterPreviousFill.java
b/cluster/src/main/java/org/apache/iotdb/cluster/query/fill/ClusterPreviousFill.java
index 08689e7..e0f6053 100644
---
a/cluster/src/main/java/org/apache/iotdb/cluster/query/fill/ClusterPreviousFill.java
+++
b/cluster/src/main/java/org/apache/iotdb/cluster/query/fill/ClusterPreviousFill.java
@@ -32,12 +32,12 @@ import org.apache.iotdb.cluster.server.RaftServer;
import org.apache.iotdb.cluster.server.handlers.caller.PreviousFillHandler;
import org.apache.iotdb.cluster.server.member.DataGroupMember;
import org.apache.iotdb.cluster.server.member.MetaGroupMember;
-import org.apache.iotdb.cluster.utils.PartitionUtils.Intervals;
import org.apache.iotdb.db.exception.StorageEngineException;
import org.apache.iotdb.db.exception.query.QueryProcessException;
import org.apache.iotdb.db.metadata.PartialPath;
import org.apache.iotdb.db.query.context.QueryContext;
import org.apache.iotdb.db.query.executor.fill.PreviousFill;
+import org.apache.iotdb.db.utils.TimeValuePairUtils.Intervals;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.read.TimeValuePair;
diff --git
a/cluster/src/main/java/org/apache/iotdb/cluster/server/member/MetaGroupMember.java
b/cluster/src/main/java/org/apache/iotdb/cluster/server/member/MetaGroupMember.java
index be1fc7d..b78d388 100644
---
a/cluster/src/main/java/org/apache/iotdb/cluster/server/member/MetaGroupMember.java
+++
b/cluster/src/main/java/org/apache/iotdb/cluster/server/member/MetaGroupMember.java
@@ -83,7 +83,6 @@ import org.apache.iotdb.cluster.server.monitor.Timer;
import org.apache.iotdb.cluster.utils.ClientUtils;
import org.apache.iotdb.cluster.utils.ClusterUtils;
import org.apache.iotdb.cluster.utils.PartitionUtils;
-import org.apache.iotdb.cluster.utils.PartitionUtils.Intervals;
import org.apache.iotdb.cluster.utils.StatusUtils;
import org.apache.iotdb.cluster.utils.nodetool.function.Status;
import org.apache.iotdb.db.conf.IoTDBDescriptor;
@@ -96,6 +95,8 @@ import org.apache.iotdb.db.metadata.PartialPath;
import org.apache.iotdb.db.qp.physical.PhysicalPlan;
import org.apache.iotdb.db.service.IoTDB;
import org.apache.iotdb.db.utils.TestOnly;
+import org.apache.iotdb.db.utils.TimeValuePairUtils;
+import org.apache.iotdb.db.utils.TimeValuePairUtils.Intervals;
import org.apache.iotdb.service.rpc.thrift.EndPoint;
import org.apache.iotdb.service.rpc.thrift.TSStatus;
import org.apache.iotdb.tsfile.read.filter.basic.Filter;
@@ -1474,7 +1475,7 @@ public class MetaGroupMember extends RaftMember {
*/
public List<PartitionGroup> routeFilter(Filter filter, PartialPath path)
throws StorageEngineException, EmptyIntervalException {
- Intervals intervals = PartitionUtils.extractTimeInterval(filter);
+ Intervals intervals = TimeValuePairUtils.extractTimeInterval(filter);
if (intervals.isEmpty()) {
throw new EmptyIntervalException(filter);
}
diff --git
a/cluster/src/main/java/org/apache/iotdb/cluster/utils/PartitionUtils.java
b/cluster/src/main/java/org/apache/iotdb/cluster/utils/PartitionUtils.java
index 85cf424..6c4cf9d 100644
--- a/cluster/src/main/java/org/apache/iotdb/cluster/utils/PartitionUtils.java
+++ b/cluster/src/main/java/org/apache/iotdb/cluster/utils/PartitionUtils.java
@@ -41,21 +41,8 @@ import
org.apache.iotdb.db.qp.physical.sys.SetStorageGroupPlan;
import org.apache.iotdb.db.qp.physical.sys.SetTTLPlan;
import org.apache.iotdb.db.qp.physical.sys.ShowTTLPlan;
import org.apache.iotdb.service.rpc.thrift.TSStatus;
-import org.apache.iotdb.tsfile.read.filter.GroupByFilter;
-import org.apache.iotdb.tsfile.read.filter.TimeFilter.TimeEq;
-import org.apache.iotdb.tsfile.read.filter.TimeFilter.TimeGt;
-import org.apache.iotdb.tsfile.read.filter.TimeFilter.TimeGtEq;
-import org.apache.iotdb.tsfile.read.filter.TimeFilter.TimeIn;
-import org.apache.iotdb.tsfile.read.filter.TimeFilter.TimeLt;
-import org.apache.iotdb.tsfile.read.filter.TimeFilter.TimeLtEq;
-import org.apache.iotdb.tsfile.read.filter.TimeFilter.TimeNotEq;
-import org.apache.iotdb.tsfile.read.filter.basic.Filter;
-import org.apache.iotdb.tsfile.read.filter.operator.AndFilter;
-import org.apache.iotdb.tsfile.read.filter.operator.NotFilter;
-import org.apache.iotdb.tsfile.read.filter.operator.OrFilter;
import org.apache.iotdb.tsfile.utils.Murmur128Hash;
-import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -154,230 +141,6 @@ public class PartitionUtils {
}
}
- public static Intervals extractTimeInterval(Filter filter) {
- if (filter == null) {
- return Intervals.ALL_INTERVAL;
- }
- // and, or, not, value, time, group by
- // eq, neq, gt, gteq, lt, lteq, in
- if (filter instanceof AndFilter) {
- AndFilter andFilter = ((AndFilter) filter);
- Intervals leftIntervals = extractTimeInterval(andFilter.getLeft());
- Intervals rightIntervals = extractTimeInterval(andFilter.getRight());
- return leftIntervals.intersection(rightIntervals);
- } else if (filter instanceof OrFilter) {
- OrFilter orFilter = ((OrFilter) filter);
- Intervals leftIntervals = extractTimeInterval(orFilter.getLeft());
- Intervals rightIntervals = extractTimeInterval(orFilter.getRight());
- return leftIntervals.union(rightIntervals);
- } else if (filter instanceof NotFilter) {
- NotFilter notFilter = ((NotFilter) filter);
- return extractTimeInterval(notFilter.getFilter()).not();
- } else if (filter instanceof TimeGt) {
- TimeGt timeGt = ((TimeGt) filter);
- return new Intervals(((long) timeGt.getValue()) + 1, Long.MAX_VALUE);
- } else if (filter instanceof TimeGtEq) {
- TimeGtEq timeGtEq = ((TimeGtEq) filter);
- return new Intervals(((long) timeGtEq.getValue()), Long.MAX_VALUE);
- } else if (filter instanceof TimeEq) {
- TimeEq timeEq = ((TimeEq) filter);
- return new Intervals(((long) timeEq.getValue()), ((long)
timeEq.getValue()));
- } else if (filter instanceof TimeNotEq) {
- TimeNotEq timeNotEq = ((TimeNotEq) filter);
- Intervals intervals = new Intervals();
- intervals.addInterval(Long.MIN_VALUE, (long) timeNotEq.getValue() - 1);
- intervals.addInterval((long) timeNotEq.getValue() + 1, Long.MAX_VALUE);
- return intervals;
- } else if (filter instanceof TimeLt) {
- TimeLt timeLt = ((TimeLt) filter);
- return new Intervals(Long.MIN_VALUE, (long) timeLt.getValue() - 1);
- } else if (filter instanceof TimeLtEq) {
- TimeLtEq timeLtEq = ((TimeLtEq) filter);
- return new Intervals(Long.MIN_VALUE, (long) timeLtEq.getValue());
- } else if (filter instanceof TimeIn) {
- TimeIn timeIn = ((TimeIn) filter);
- Intervals intervals = new Intervals();
- for (Object value : timeIn.getValues()) {
- long time = ((long) value);
- intervals.addInterval(time, time);
- }
- return intervals;
- } else if (filter instanceof GroupByFilter) {
- GroupByFilter groupByFilter = ((GroupByFilter) filter);
- return new Intervals(groupByFilter.getStartTime(),
groupByFilter.getEndTime() + 1);
- }
- // value filter
- return Intervals.ALL_INTERVAL;
- }
-
- /** All intervals are closed. */
- public static class Intervals extends ArrayList<Long> {
-
- static final Intervals ALL_INTERVAL = new Intervals(Long.MIN_VALUE,
Long.MAX_VALUE);
-
- public Intervals() {
- super();
- }
-
- Intervals(long lowerBound, long upperBound) {
- super();
- addInterval(lowerBound, upperBound);
- }
-
- public int getIntervalSize() {
- return size() / 2;
- }
-
- public long getLowerBound(int index) {
- return get(index * 2);
- }
-
- public long getUpperBound(int index) {
- return get(index * 2 + 1);
- }
-
- void setLowerBound(int index, long lb) {
- set(index * 2, lb);
- }
-
- void setUpperBound(int index, long ub) {
- set(index * 2 + 1, ub);
- }
-
- public void addInterval(long lowerBound, long upperBound) {
- add(lowerBound);
- add(upperBound);
- }
-
- Intervals intersection(Intervals that) {
- Intervals result = new Intervals();
- int thisSize = this.getIntervalSize();
- int thatSize = that.getIntervalSize();
- for (int i = 0; i < thisSize; i++) {
- for (int j = 0; j < thatSize; j++) {
- long thisLB = this.getLowerBound(i);
- long thisUB = this.getUpperBound(i);
- long thatLB = that.getLowerBound(i);
- long thatUB = that.getUpperBound(i);
- if (thisUB >= thatLB) {
- if (thisUB <= thatUB) {
- result.addInterval(Math.max(thisLB, thatLB), thisUB);
- } else if (thisLB <= thatUB) {
- result.addInterval(Math.max(thisLB, thatLB), thatUB);
- }
- }
- }
- }
- return result;
- }
-
- /**
- * The union is implemented by merge, so the two intervals must be ordered.
- *
- * @param that
- * @return
- */
- Intervals union(Intervals that) {
- if (this.isEmpty()) {
- return that;
- } else if (that.isEmpty()) {
- return this;
- }
- Intervals result = new Intervals();
-
- int thisSize = this.getIntervalSize();
- int thatSize = that.getIntervalSize();
- int thisIndex = 0;
- int thatIndex = 0;
- // merge the heads of the two intervals
- while (thisIndex < thisSize && thatIndex < thatSize) {
- long thisLB = this.getLowerBound(thisIndex);
- long thisUB = this.getUpperBound(thisIndex);
- long thatLB = that.getLowerBound(thatIndex);
- long thatUB = that.getUpperBound(thatIndex);
- if (thisLB <= thatLB) {
- result.mergeLast(thisLB, thisUB);
- thisIndex++;
- } else {
- result.mergeLast(thatLB, thatUB);
- thatIndex++;
- }
- }
- // merge the remaining intervals
- Intervals remainingIntervals = thisIndex < thisSize ? this : that;
- int remainingIndex = thisIndex < thisSize ? thisIndex : thatIndex;
- mergeRemainingIntervals(remainingIndex, remainingIntervals, result);
-
- return result;
- }
-
- private void mergeRemainingIntervals(
- int remainingIndex, Intervals remainingIntervals, Intervals result) {
- for (int i = remainingIndex; i < remainingIntervals.getIntervalSize();
i++) {
- long lb = remainingIntervals.getLowerBound(i);
- long ub = remainingIntervals.getUpperBound(i);
- result.mergeLast(lb, ub);
- }
- }
-
- /**
- * Merge an interval of [lowerBound, upperBound] with the last interval if
they can be merged,
- * or just add it as the last interval if its lowerBound is larger than
the upperBound of the
- * last interval. If the upperBound of the new interval is less than the
lowerBound of the last
- * interval, nothing will be done.
- *
- * @param lowerBound
- * @param upperBound
- */
- private void mergeLast(long lowerBound, long upperBound) {
- if (getIntervalSize() == 0) {
- addInterval(lowerBound, upperBound);
- return;
- }
- int lastIndex = getIntervalSize() - 1;
- long lastLB = getLowerBound(lastIndex);
- long lastUB = getUpperBound(lastIndex);
- if (lowerBound > lastUB + 1) {
- // e.g., last [3, 5], new [7, 10], just add the new interval
- addInterval(lowerBound, upperBound);
- return;
- }
- if (upperBound < lastLB - 1) {
- // e.g., last [7, 10], new [3, 5], do nothing
- return;
- }
- // merge the new interval into the last one
- setLowerBound(lastIndex, Math.min(lastLB, lowerBound));
- setUpperBound(lastIndex, Math.max(lastUB, upperBound));
- }
-
- public Intervals not() {
- if (isEmpty()) {
- return ALL_INTERVAL;
- }
- Intervals result = new Intervals();
- long firstLB = getLowerBound(0);
- if (firstLB != Long.MIN_VALUE) {
- result.addInterval(Long.MIN_VALUE, firstLB - 1);
- }
-
- int intervalSize = getIntervalSize();
- for (int i = 0; i < intervalSize - 1; i++) {
- long currentUB = getUpperBound(i);
- long nextLB = getLowerBound(i + 1);
- if (currentUB + 1 <= nextLB - 1) {
- result.addInterval(currentUB + 1, nextLB - 1);
- }
- }
-
- long lastUB = getUpperBound(result.getIntervalSize() - 1);
- if (lastUB != Long.MAX_VALUE) {
- result.addInterval(lastUB + 1, Long.MAX_VALUE);
- }
- return result;
- }
- }
-
/**
* Calculate the headers of the groups that possibly store the data of a
timeseries over the given
* time range.
diff --git
a/cluster/src/test/java/org/apache/iotdb/cluster/server/member/MetaGroupMemberTest.java
b/cluster/src/test/java/org/apache/iotdb/cluster/server/member/MetaGroupMemberTest.java
index e0a28fe..88ada81 100644
---
a/cluster/src/test/java/org/apache/iotdb/cluster/server/member/MetaGroupMemberTest.java
+++
b/cluster/src/test/java/org/apache/iotdb/cluster/server/member/MetaGroupMemberTest.java
@@ -74,7 +74,6 @@ import
org.apache.iotdb.cluster.server.monitor.NodeStatusManager;
import org.apache.iotdb.cluster.server.service.MetaAsyncService;
import org.apache.iotdb.cluster.utils.ClusterUtils;
import org.apache.iotdb.cluster.utils.Constants;
-import org.apache.iotdb.cluster.utils.PartitionUtils;
import org.apache.iotdb.cluster.utils.StatusUtils;
import org.apache.iotdb.db.auth.AuthException;
import org.apache.iotdb.db.auth.authorizer.IAuthorizer;
@@ -100,6 +99,7 @@ import
org.apache.iotdb.db.query.control.QueryResourceManager;
import org.apache.iotdb.db.query.reader.series.IReaderByTimestamp;
import org.apache.iotdb.db.query.reader.series.ManagedSeriesReader;
import org.apache.iotdb.db.service.IoTDB;
+import org.apache.iotdb.db.utils.TimeValuePairUtils;
import org.apache.iotdb.rpc.TSStatusCode;
import org.apache.iotdb.service.rpc.thrift.TSStatus;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
@@ -1379,7 +1379,7 @@ public class MetaGroupMemberTest extends BaseMember {
StorageEngine.setEnablePartition(false);
testMetaMember.setCharacter(LEADER);
testMetaMember.setLeader(testMetaMember.getThisNode());
- PartitionUtils.Intervals intervals = new PartitionUtils.Intervals();
+ TimeValuePairUtils.Intervals intervals = new
TimeValuePairUtils.Intervals();
intervals.addInterval(Long.MIN_VALUE, Long.MAX_VALUE);
List<PartitionGroup> partitionGroups =
@@ -1395,7 +1395,7 @@ public class MetaGroupMemberTest extends BaseMember {
StorageEngine.setEnablePartition(true);
testMetaMember.setCharacter(LEADER);
testMetaMember.setLeader(testMetaMember.getThisNode());
- PartitionUtils.Intervals intervals = new PartitionUtils.Intervals();
+ TimeValuePairUtils.Intervals intervals = new
TimeValuePairUtils.Intervals();
intervals.addInterval(Long.MIN_VALUE, Long.MAX_VALUE);
List<PartitionGroup> partitionGroups =
diff --git
a/server/src/main/java/org/apache/iotdb/db/query/executor/QueryRouter.java
b/server/src/main/java/org/apache/iotdb/db/query/executor/QueryRouter.java
index 29254e7..6c53102 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/executor/QueryRouter.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/executor/QueryRouter.java
@@ -38,6 +38,7 @@ import
org.apache.iotdb.db.query.dataset.groupby.GroupByWithValueFilterDataSet;
import
org.apache.iotdb.db.query.dataset.groupby.GroupByWithoutValueFilterDataSet;
import org.apache.iotdb.db.query.executor.fill.IFill;
import org.apache.iotdb.db.service.IoTDB;
+import org.apache.iotdb.db.utils.TimeValuePairUtils;
import
org.apache.iotdb.tsfile.exception.filter.QueryFilterOptimizationException;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.read.expression.ExpressionType;
@@ -47,6 +48,8 @@ import
org.apache.iotdb.tsfile.read.expression.impl.GlobalTimeExpression;
import org.apache.iotdb.tsfile.read.expression.util.ExpressionOptimizer;
import org.apache.iotdb.tsfile.read.filter.GroupByFilter;
import org.apache.iotdb.tsfile.read.filter.GroupByMonthFilter;
+import org.apache.iotdb.tsfile.read.filter.basic.Filter;
+import org.apache.iotdb.tsfile.read.query.dataset.EmptyDataSet;
import org.apache.iotdb.tsfile.read.query.dataset.QueryDataSet;
import org.slf4j.Logger;
@@ -97,6 +100,14 @@ public class QueryRouter implements IQueryRouter {
throw new QueryProcessException(e);
}
return rawDataQueryExecutor.executeWithValueFilter(context);
+ } else if (optimizedExpression != null
+ && optimizedExpression.getType() == ExpressionType.GLOBAL_TIME) {
+ Filter timeFilter = ((GlobalTimeExpression)
queryPlan.getExpression()).getFilter();
+ TimeValuePairUtils.Intervals intervals =
TimeValuePairUtils.extractTimeInterval(timeFilter);
+ if (intervals.isEmpty()) {
+ logger.warn("The interval of the filter {} is empty.", timeFilter);
+ return new EmptyDataSet();
+ }
}
// Currently, we only group the vector partial paths for raw query without
value filter
diff --git
a/server/src/main/java/org/apache/iotdb/db/utils/TimeValuePairUtils.java
b/server/src/main/java/org/apache/iotdb/db/utils/TimeValuePairUtils.java
index ba560a6..1df6be0 100644
--- a/server/src/main/java/org/apache/iotdb/db/utils/TimeValuePairUtils.java
+++ b/server/src/main/java/org/apache/iotdb/db/utils/TimeValuePairUtils.java
@@ -22,6 +22,12 @@ import
org.apache.iotdb.tsfile.exception.write.UnSupportedDataTypeException;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.read.TimeValuePair;
import org.apache.iotdb.tsfile.read.common.BatchData;
+import org.apache.iotdb.tsfile.read.filter.GroupByFilter;
+import org.apache.iotdb.tsfile.read.filter.TimeFilter;
+import org.apache.iotdb.tsfile.read.filter.basic.Filter;
+import org.apache.iotdb.tsfile.read.filter.operator.AndFilter;
+import org.apache.iotdb.tsfile.read.filter.operator.NotFilter;
+import org.apache.iotdb.tsfile.read.filter.operator.OrFilter;
import org.apache.iotdb.tsfile.utils.Binary;
import org.apache.iotdb.tsfile.utils.TsPrimitiveType;
import org.apache.iotdb.tsfile.utils.TsPrimitiveType.TsBinary;
@@ -31,6 +37,8 @@ import org.apache.iotdb.tsfile.utils.TsPrimitiveType.TsFloat;
import org.apache.iotdb.tsfile.utils.TsPrimitiveType.TsInt;
import org.apache.iotdb.tsfile.utils.TsPrimitiveType.TsLong;
+import java.util.ArrayList;
+
public class TimeValuePairUtils {
private TimeValuePairUtils() {}
@@ -107,4 +115,228 @@ public class TimeValuePairUtils {
throw new UnsupportedOperationException("Unrecognized datatype: " +
dataType);
}
}
+
+ public static Intervals extractTimeInterval(Filter filter) {
+ if (filter == null) {
+ return Intervals.ALL_INTERVAL;
+ }
+ // and, or, not, value, time, group by
+ // eq, neq, gt, gteq, lt, lteq, in
+ if (filter instanceof AndFilter) {
+ AndFilter andFilter = ((AndFilter) filter);
+ Intervals leftIntervals = extractTimeInterval(andFilter.getLeft());
+ Intervals rightIntervals = extractTimeInterval(andFilter.getRight());
+ return leftIntervals.intersection(rightIntervals);
+ } else if (filter instanceof OrFilter) {
+ OrFilter orFilter = ((OrFilter) filter);
+ Intervals leftIntervals = extractTimeInterval(orFilter.getLeft());
+ Intervals rightIntervals = extractTimeInterval(orFilter.getRight());
+ return leftIntervals.union(rightIntervals);
+ } else if (filter instanceof NotFilter) {
+ NotFilter notFilter = ((NotFilter) filter);
+ return extractTimeInterval(notFilter.getFilter()).not();
+ } else if (filter instanceof TimeFilter.TimeGt) {
+ TimeFilter.TimeGt timeGt = ((TimeFilter.TimeGt) filter);
+ return new Intervals(((long) timeGt.getValue()) + 1, Long.MAX_VALUE);
+ } else if (filter instanceof TimeFilter.TimeGtEq) {
+ TimeFilter.TimeGtEq timeGtEq = ((TimeFilter.TimeGtEq) filter);
+ return new Intervals(((long) timeGtEq.getValue()), Long.MAX_VALUE);
+ } else if (filter instanceof TimeFilter.TimeEq) {
+ TimeFilter.TimeEq timeEq = ((TimeFilter.TimeEq) filter);
+ return new Intervals(((long) timeEq.getValue()), ((long)
timeEq.getValue()));
+ } else if (filter instanceof TimeFilter.TimeNotEq) {
+ TimeFilter.TimeNotEq timeNotEq = ((TimeFilter.TimeNotEq) filter);
+ Intervals intervals = new Intervals();
+ intervals.addInterval(Long.MIN_VALUE, (long) timeNotEq.getValue() - 1);
+ intervals.addInterval((long) timeNotEq.getValue() + 1, Long.MAX_VALUE);
+ return intervals;
+ } else if (filter instanceof TimeFilter.TimeLt) {
+ TimeFilter.TimeLt timeLt = ((TimeFilter.TimeLt) filter);
+ return new Intervals(Long.MIN_VALUE, (long) timeLt.getValue() - 1);
+ } else if (filter instanceof TimeFilter.TimeLtEq) {
+ TimeFilter.TimeLtEq timeLtEq = ((TimeFilter.TimeLtEq) filter);
+ return new Intervals(Long.MIN_VALUE, (long) timeLtEq.getValue());
+ } else if (filter instanceof TimeFilter.TimeIn) {
+ TimeFilter.TimeIn timeIn = ((TimeFilter.TimeIn) filter);
+ Intervals intervals = new Intervals();
+ for (Object value : timeIn.getValues()) {
+ long time = ((long) value);
+ intervals.addInterval(time, time);
+ }
+ return intervals;
+ } else if (filter instanceof GroupByFilter) {
+ GroupByFilter groupByFilter = ((GroupByFilter) filter);
+ return new Intervals(groupByFilter.getStartTime(),
groupByFilter.getEndTime() + 1);
+ }
+ // value filter
+ return Intervals.ALL_INTERVAL;
+ }
+
+ /** All intervals are closed. */
+ public static class Intervals extends ArrayList<Long> {
+
+ static final Intervals ALL_INTERVAL = new Intervals(Long.MIN_VALUE,
Long.MAX_VALUE);
+
+ public Intervals() {
+ super();
+ }
+
+ Intervals(long lowerBound, long upperBound) {
+ super();
+ addInterval(lowerBound, upperBound);
+ }
+
+ public int getIntervalSize() {
+ return size() / 2;
+ }
+
+ public long getLowerBound(int index) {
+ return get(index * 2);
+ }
+
+ public long getUpperBound(int index) {
+ return get(index * 2 + 1);
+ }
+
+ void setLowerBound(int index, long lb) {
+ set(index * 2, lb);
+ }
+
+ void setUpperBound(int index, long ub) {
+ set(index * 2 + 1, ub);
+ }
+
+ public void addInterval(long lowerBound, long upperBound) {
+ add(lowerBound);
+ add(upperBound);
+ }
+
+ Intervals intersection(Intervals that) {
+ Intervals result = new Intervals();
+ int thisSize = this.getIntervalSize();
+ int thatSize = that.getIntervalSize();
+ for (int i = 0; i < thisSize; i++) {
+ for (int j = 0; j < thatSize; j++) {
+ long thisLB = this.getLowerBound(i);
+ long thisUB = this.getUpperBound(i);
+ long thatLB = that.getLowerBound(i);
+ long thatUB = that.getUpperBound(i);
+ if (thisUB >= thatLB) {
+ if (thisUB <= thatUB) {
+ result.addInterval(Math.max(thisLB, thatLB), thisUB);
+ } else if (thisLB <= thatUB) {
+ result.addInterval(Math.max(thisLB, thatLB), thatUB);
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The union is implemented by merge, so the two intervals must be ordered.
+ *
+ * @param that
+ * @return
+ */
+ Intervals union(Intervals that) {
+ if (this.isEmpty()) {
+ return that;
+ } else if (that.isEmpty()) {
+ return this;
+ }
+ Intervals result = new Intervals();
+
+ int thisSize = this.getIntervalSize();
+ int thatSize = that.getIntervalSize();
+ int thisIndex = 0;
+ int thatIndex = 0;
+ // merge the heads of the two intervals
+ while (thisIndex < thisSize && thatIndex < thatSize) {
+ long thisLB = this.getLowerBound(thisIndex);
+ long thisUB = this.getUpperBound(thisIndex);
+ long thatLB = that.getLowerBound(thatIndex);
+ long thatUB = that.getUpperBound(thatIndex);
+ if (thisLB <= thatLB) {
+ result.mergeLast(thisLB, thisUB);
+ thisIndex++;
+ } else {
+ result.mergeLast(thatLB, thatUB);
+ thatIndex++;
+ }
+ }
+ // merge the remaining intervals
+ Intervals remainingIntervals = thisIndex < thisSize ? this : that;
+ int remainingIndex = thisIndex < thisSize ? thisIndex : thatIndex;
+ mergeRemainingIntervals(remainingIndex, remainingIntervals, result);
+
+ return result;
+ }
+
+ private void mergeRemainingIntervals(
+ int remainingIndex, Intervals remainingIntervals, Intervals result) {
+ for (int i = remainingIndex; i < remainingIntervals.getIntervalSize();
i++) {
+ long lb = remainingIntervals.getLowerBound(i);
+ long ub = remainingIntervals.getUpperBound(i);
+ result.mergeLast(lb, ub);
+ }
+ }
+
+ /**
+ * Merge an interval of [lowerBound, upperBound] with the last interval if
they can be merged,
+ * or just add it as the last interval if its lowerBound is larger than
the upperBound of the
+ * last interval. If the upperBound of the new interval is less than the
lowerBound of the last
+ * interval, nothing will be done.
+ *
+ * @param lowerBound
+ * @param upperBound
+ */
+ private void mergeLast(long lowerBound, long upperBound) {
+ if (getIntervalSize() == 0) {
+ addInterval(lowerBound, upperBound);
+ return;
+ }
+ int lastIndex = getIntervalSize() - 1;
+ long lastLB = getLowerBound(lastIndex);
+ long lastUB = getUpperBound(lastIndex);
+ if (lowerBound > lastUB + 1) {
+ // e.g., last [3, 5], new [7, 10], just add the new interval
+ addInterval(lowerBound, upperBound);
+ return;
+ }
+ if (upperBound < lastLB - 1) {
+ // e.g., last [7, 10], new [3, 5], do nothing
+ return;
+ }
+ // merge the new interval into the last one
+ setLowerBound(lastIndex, Math.min(lastLB, lowerBound));
+ setUpperBound(lastIndex, Math.max(lastUB, upperBound));
+ }
+
+ public Intervals not() {
+ if (isEmpty()) {
+ return ALL_INTERVAL;
+ }
+ Intervals result = new Intervals();
+ long firstLB = getLowerBound(0);
+ if (firstLB != Long.MIN_VALUE) {
+ result.addInterval(Long.MIN_VALUE, firstLB - 1);
+ }
+
+ int intervalSize = getIntervalSize();
+ for (int i = 0; i < intervalSize - 1; i++) {
+ long currentUB = getUpperBound(i);
+ long nextLB = getLowerBound(i + 1);
+ if (currentUB + 1 <= nextLB - 1) {
+ result.addInterval(currentUB + 1, nextLB - 1);
+ }
+ }
+
+ long lastUB = getUpperBound(result.getIntervalSize() - 1);
+ if (lastUB != Long.MAX_VALUE) {
+ result.addInterval(lastUB + 1, Long.MAX_VALUE);
+ }
+ return result;
+ }
+ }
}
diff --git
a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBSequenceDataQueryIT.java
b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBSequenceDataQueryIT.java
index 2c69a52..2fc4977 100644
---
a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBSequenceDataQueryIT.java
+++
b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBSequenceDataQueryIT.java
@@ -40,6 +40,7 @@ import
org.apache.iotdb.tsfile.read.expression.impl.GlobalTimeExpression;
import org.apache.iotdb.tsfile.read.expression.impl.SingleSeriesExpression;
import org.apache.iotdb.tsfile.read.filter.TimeFilter;
import org.apache.iotdb.tsfile.read.filter.ValueFilter;
+import org.apache.iotdb.tsfile.read.filter.operator.AndFilter;
import org.apache.iotdb.tsfile.read.query.dataset.QueryDataSet;
import org.junit.AfterClass;
@@ -316,4 +317,43 @@ public class IoTDBSequenceDataQueryIT {
QueryResourceManager.getInstance().endQuery(TEST_QUERY_JOB_ID);
}
+
+ @Test
+ public void readIncorrectTimeFilterTest()
+ throws IllegalPathException, QueryProcessException,
StorageEngineException, IOException {
+
+ QueryRouter queryRouter = new QueryRouter();
+ List<PartialPath> pathList = new ArrayList<>();
+ List<TSDataType> dataTypes = new ArrayList<>();
+ pathList.add(
+ new PartialPath(TestConstant.d0 + TsFileConstant.PATH_SEPARATOR +
TestConstant.s0));
+ dataTypes.add(TSDataType.INT32);
+ pathList.add(
+ new PartialPath(TestConstant.d1 + TsFileConstant.PATH_SEPARATOR +
TestConstant.s0));
+ dataTypes.add(TSDataType.INT32);
+
+ TimeFilter.TimeGt gtRight = TimeFilter.gt(10L);
+ TimeFilter.TimeLt ltLeft = TimeFilter.lt(5L);
+ AndFilter andFilter = new AndFilter(ltLeft, gtRight);
+
+ GlobalTimeExpression globalTimeExpression = new
GlobalTimeExpression(andFilter);
+ TEST_QUERY_JOB_ID =
+ QueryResourceManager.getInstance().assignQueryId(true, 1024,
pathList.size());
+ TEST_QUERY_CONTEXT = new QueryContext(TEST_QUERY_JOB_ID);
+
+ RawDataQueryPlan queryPlan = new RawDataQueryPlan();
+ queryPlan.setDeduplicatedDataTypes(dataTypes);
+ queryPlan.setDeduplicatedPathsAndUpdate(pathList);
+ queryPlan.setExpression(globalTimeExpression);
+ QueryDataSet queryDataSet = queryRouter.rawDataQuery(queryPlan,
TEST_QUERY_CONTEXT);
+
+ int cnt = 0;
+ while (queryDataSet.hasNext()) {
+ queryDataSet.next();
+ cnt++;
+ }
+ assertEquals(0, cnt);
+
+ QueryResourceManager.getInstance().endQuery(TEST_QUERY_JOB_ID);
+ }
}