You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ja...@apache.org on 2022/11/25 09:47:06 UTC
[iotdb] 01/01: [IOTDB-4940] Optimize PartitonFetch Process in query
This is an automated email from the ASF dual-hosted git repository.
jackietien pushed a commit to branch IOTDB-4940
in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit fa3c5f7254c9d894b33b7e89dee219edba5c2769
Author: JackieTien97 <ja...@gmail.com>
AuthorDate: Fri Nov 25 17:46:49 2022 +0800
[IOTDB-4940] Optimize PartitonFetch Process in query
---
.../commons/partition/DataPartitionQueryParam.java | 6 +
.../iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java | 53 ++-
.../mpp/plan/analyze/QueryTimePartitionTest.java | 526 +++++++++++++++++++++
.../iotdb/tsfile/read/filter/GroupByFilter.java | 8 +
.../iotdb/tsfile/read/filter/TimeFilter.java | 84 ++++
.../iotdb/tsfile/read/filter/basic/Filter.java | 7 +
.../tsfile/read/filter/operator/AndFilter.java | 40 ++
.../tsfile/read/filter/operator/NotFilter.java | 27 ++
.../tsfile/read/filter/operator/OrFilter.java | 66 +++
9 files changed, 813 insertions(+), 4 deletions(-)
diff --git a/node-commons/src/main/java/org/apache/iotdb/commons/partition/DataPartitionQueryParam.java b/node-commons/src/main/java/org/apache/iotdb/commons/partition/DataPartitionQueryParam.java
index 8053a2e39b..83a7cdeb2c 100644
--- a/node-commons/src/main/java/org/apache/iotdb/commons/partition/DataPartitionQueryParam.java
+++ b/node-commons/src/main/java/org/apache/iotdb/commons/partition/DataPartitionQueryParam.java
@@ -28,6 +28,12 @@ public class DataPartitionQueryParam {
private String devicePath;
private List<TTimePartitionSlot> timePartitionSlotList = new ArrayList<>();
+ public DataPartitionQueryParam(
+ String devicePath, List<TTimePartitionSlot> timePartitionSlotList) {
+ this.devicePath = devicePath;
+ this.timePartitionSlotList = timePartitionSlotList;
+ }
+
public DataPartitionQueryParam() {}
public String getDevicePath() {
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
index 9bd95df7b6..4e414ca69f 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
@@ -115,6 +115,7 @@ import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
import org.apache.iotdb.tsfile.read.TsFileSequenceReader;
+import org.apache.iotdb.tsfile.read.common.TimeRange;
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;
@@ -1112,15 +1113,18 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext>
deviceSet.add(ExpressionAnalyzer.getDeviceNameInSourceExpression(expression));
}
}
- DataPartition dataPartition = fetchDataPartitionByDevices(deviceSet, schemaTree);
+ DataPartition dataPartition =
+ fetchDataPartitionByDevices(deviceSet, schemaTree, analysis.getGlobalTimeFilter());
analysis.setDataPartitionInfo(dataPartition);
}
- private DataPartition fetchDataPartitionByDevices(Set<String> deviceSet, ISchemaTree schemaTree) {
+ private DataPartition fetchDataPartitionByDevices(
+ Set<String> deviceSet, ISchemaTree schemaTree, Filter globalTimeFilter) {
+ List<TTimePartitionSlot> timePartitionSlotList = getTimePartitionSlotList(globalTimeFilter);
Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap = new HashMap<>();
for (String devicePath : deviceSet) {
- DataPartitionQueryParam queryParam = new DataPartitionQueryParam();
- queryParam.setDevicePath(devicePath);
+ DataPartitionQueryParam queryParam =
+ new DataPartitionQueryParam(devicePath, timePartitionSlotList);
sgNameToQueryParamsMap
.computeIfAbsent(schemaTree.getBelongedDatabase(devicePath), key -> new ArrayList<>())
.add(queryParam);
@@ -1128,6 +1132,47 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext>
return partitionFetcher.getDataPartition(sgNameToQueryParamsMap);
}
+ public static List<TTimePartitionSlot> getTimePartitionSlotList(Filter timeFilter) {
+ if (timeFilter == null) {
+ return Collections.emptyList();
+ }
+ List<TimeRange> timeRangeList = timeFilter.getTimeRanges();
+ if (timeRangeList.get(0).getMin() == Long.MIN_VALUE
+ || timeRangeList.get(timeRangeList.size() - 1).getMax() == Long.MAX_VALUE) {
+ return Collections.emptyList();
+ }
+
+ List<TTimePartitionSlot> result = new ArrayList<>();
+ long startTime =
+ (timeRangeList.get(0).getMin() / TimePartitionUtils.timePartitionInterval)
+ * TimePartitionUtils.timePartitionInterval; // included
+ long endTime = startTime + TimePartitionUtils.timePartitionInterval; // excluded
+ TTimePartitionSlot timePartitionSlot =
+ TimePartitionUtils.getTimePartition(timeRangeList.get(0).getMin());
+ int index = 0, size = timeRangeList.size();
+ while (index < size) {
+ long curLeft = timeRangeList.get(index).getMin();
+ long curRight = timeRangeList.get(index).getMax();
+ if (curLeft >= endTime) {
+ result.add(timePartitionSlot);
+ // next init
+ endTime =
+ (curLeft / TimePartitionUtils.timePartitionInterval + 1)
+ * TimePartitionUtils.timePartitionInterval;
+ timePartitionSlot = TimePartitionUtils.getTimePartition(curLeft);
+ } else if (curRight >= endTime) {
+ result.add(timePartitionSlot);
+ // next init
+ timePartitionSlot = new TTimePartitionSlot(endTime);
+ endTime = endTime + TimePartitionUtils.timePartitionInterval;
+ } else {
+ index++;
+ }
+ }
+ result.add(timePartitionSlot);
+ return result;
+ }
+
private void analyzeInto(
Analysis analysis,
QueryStatement queryStatement,
diff --git a/server/src/test/java/org/apache/iotdb/db/mpp/plan/analyze/QueryTimePartitionTest.java b/server/src/test/java/org/apache/iotdb/db/mpp/plan/analyze/QueryTimePartitionTest.java
new file mode 100644
index 0000000000..53607a13ef
--- /dev/null
+++ b/server/src/test/java/org/apache/iotdb/db/mpp/plan/analyze/QueryTimePartitionTest.java
@@ -0,0 +1,526 @@
+/*
+ * 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.mpp.plan.analyze;
+
+import org.apache.iotdb.common.rpc.thrift.TTimePartitionSlot;
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.tsfile.read.common.TimeRange;
+import org.apache.iotdb.tsfile.read.filter.TimeFilter;
+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.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.apache.iotdb.db.mpp.plan.analyze.AnalyzeVisitor.getTimePartitionSlotList;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class QueryTimePartitionTest {
+
+ @Test
+ public void testAndTimeFilter() {
+ TimeFilter.TimeGt left = TimeFilter.gt(10);
+ TimeFilter.TimeLt right = TimeFilter.lt(20);
+
+ // time > 10 and time < 20
+ AndFilter andFilter = new AndFilter(left, right);
+ List<TimeRange> timeRangeList = andFilter.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(11, timeRangeList.get(0).getMin());
+ assertEquals(19, timeRangeList.get(0).getMax());
+
+ // time > 10 and time <= 20
+ andFilter = new AndFilter(left, TimeFilter.ltEq(20));
+ timeRangeList = andFilter.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(11, timeRangeList.get(0).getMin());
+ assertEquals(20, timeRangeList.get(0).getMax());
+
+ // time >= 10 and time <= 20
+ andFilter = new AndFilter(TimeFilter.gtEq(10), TimeFilter.ltEq(20));
+ timeRangeList = andFilter.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(10, timeRangeList.get(0).getMin());
+ assertEquals(20, timeRangeList.get(0).getMax());
+
+ // time <= 20 and time >= 10
+ andFilter = new AndFilter(TimeFilter.ltEq(20), TimeFilter.gtEq(10));
+ timeRangeList = andFilter.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(10, timeRangeList.get(0).getMin());
+ assertEquals(20, timeRangeList.get(0).getMax());
+
+ // time >= 20 and time <= 10
+ andFilter = new AndFilter(TimeFilter.gtEq(20), TimeFilter.ltEq(10));
+ timeRangeList = andFilter.getTimeRanges();
+ assertEquals(0, timeRangeList.size());
+
+ // time >= 20 and time < 20
+ andFilter = new AndFilter(TimeFilter.gtEq(20), TimeFilter.lt(20));
+ timeRangeList = andFilter.getTimeRanges();
+ assertEquals(0, timeRangeList.size());
+ }
+
+ @Test
+ public void testOrTimeFilter() {
+
+ // time < 10 or time > 20
+ OrFilter filter = new OrFilter(TimeFilter.lt(10), TimeFilter.gt(20));
+ List<TimeRange> timeRangeList = filter.getTimeRanges();
+ assertEquals(2, timeRangeList.size());
+ assertEquals(Long.MIN_VALUE, timeRangeList.get(0).getMin());
+ assertEquals(9, timeRangeList.get(0).getMax());
+ assertEquals(21, timeRangeList.get(1).getMin());
+ assertEquals(Long.MAX_VALUE, timeRangeList.get(1).getMax());
+
+ // time < 10 or time >= 20
+ filter = new OrFilter(TimeFilter.lt(10), TimeFilter.gtEq(20));
+ timeRangeList = filter.getTimeRanges();
+ assertEquals(2, timeRangeList.size());
+ assertEquals(Long.MIN_VALUE, timeRangeList.get(0).getMin());
+ assertEquals(9, timeRangeList.get(0).getMax());
+ assertEquals(20, timeRangeList.get(1).getMin());
+ assertEquals(Long.MAX_VALUE, timeRangeList.get(1).getMax());
+
+ // time <= 10 or time >= 20
+ filter = new OrFilter(TimeFilter.ltEq(10), TimeFilter.gtEq(20));
+ timeRangeList = filter.getTimeRanges();
+ assertEquals(2, timeRangeList.size());
+ assertEquals(Long.MIN_VALUE, timeRangeList.get(0).getMin());
+ assertEquals(10, timeRangeList.get(0).getMax());
+ assertEquals(20, timeRangeList.get(1).getMin());
+ assertEquals(Long.MAX_VALUE, timeRangeList.get(1).getMax());
+
+ // time >= 20 or time <= 10
+ filter = new OrFilter(TimeFilter.gtEq(20), TimeFilter.ltEq(10));
+ timeRangeList = filter.getTimeRanges();
+ assertEquals(2, timeRangeList.size());
+ assertEquals(Long.MIN_VALUE, timeRangeList.get(0).getMin());
+ assertEquals(10, timeRangeList.get(0).getMax());
+ assertEquals(20, timeRangeList.get(1).getMin());
+ assertEquals(Long.MAX_VALUE, timeRangeList.get(1).getMax());
+
+ // time >= 20 or time >= 10
+ filter = new OrFilter(TimeFilter.gtEq(20), TimeFilter.gtEq(10));
+ timeRangeList = filter.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(10, timeRangeList.get(0).getMin());
+ assertEquals(Long.MAX_VALUE, timeRangeList.get(0).getMax());
+
+ // time < 20 or time <= 10
+ filter = new OrFilter(TimeFilter.lt(20), TimeFilter.ltEq(10));
+ timeRangeList = filter.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(Long.MIN_VALUE, timeRangeList.get(0).getMin());
+ assertEquals(19, timeRangeList.get(0).getMax());
+ }
+
+ @Test
+ public void testAndOrTimeFilter() {
+
+ // (time >= 10 and time <= 20) or (time > 30)
+ OrFilter filter =
+ new OrFilter(new AndFilter(TimeFilter.gtEq(10), TimeFilter.ltEq(20)), TimeFilter.gt(30));
+ List<TimeRange> timeRangeList = filter.getTimeRanges();
+ assertEquals(2, timeRangeList.size());
+ assertEquals(10, timeRangeList.get(0).getMin());
+ assertEquals(20, timeRangeList.get(0).getMax());
+ assertEquals(31, timeRangeList.get(1).getMin());
+ assertEquals(Long.MAX_VALUE, timeRangeList.get(1).getMax());
+
+ // (time <= 10 or time > 20) and (time >= 30)
+ AndFilter filter1 =
+ new AndFilter(new OrFilter(TimeFilter.ltEq(10), TimeFilter.gt(20)), TimeFilter.gtEq(30));
+ timeRangeList = filter1.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(30, timeRangeList.get(0).getMin());
+ assertEquals(Long.MAX_VALUE, timeRangeList.get(0).getMax());
+
+ // (time <= 10 or time > 20) and (time <= 30)
+ filter1 =
+ new AndFilter(new OrFilter(TimeFilter.ltEq(10), TimeFilter.gt(20)), TimeFilter.ltEq(30));
+ timeRangeList = filter1.getTimeRanges();
+ assertEquals(2, timeRangeList.size());
+ assertEquals(Long.MIN_VALUE, timeRangeList.get(0).getMin());
+ assertEquals(10, timeRangeList.get(0).getMax());
+ assertEquals(21, timeRangeList.get(1).getMin());
+ assertEquals(30, timeRangeList.get(1).getMax());
+
+ // (time >= 10 and time <= 20) or (time < 99 and time > 30)
+ filter =
+ new OrFilter(
+ new AndFilter(TimeFilter.gtEq(10), TimeFilter.ltEq(20)),
+ new AndFilter(TimeFilter.lt(100), TimeFilter.gt(30)));
+ timeRangeList = filter.getTimeRanges();
+ assertEquals(2, timeRangeList.size());
+ assertEquals(10, timeRangeList.get(0).getMin());
+ assertEquals(20, timeRangeList.get(0).getMax());
+ assertEquals(31, timeRangeList.get(1).getMin());
+ assertEquals(99, timeRangeList.get(1).getMax());
+ }
+
+ @Test
+ public void testBetweenTimeFilter() {
+
+ // time between 10 and 20
+ TimeFilter.TimeBetween filter = TimeFilter.between(10, 20, false);
+ List<TimeRange> timeRangeList = filter.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(10, timeRangeList.get(0).getMin());
+ assertEquals(20, timeRangeList.get(0).getMax());
+
+ // time not between 10 and 20
+ filter = TimeFilter.between(10, 20, true);
+ timeRangeList = filter.getTimeRanges();
+ assertEquals(2, timeRangeList.size());
+ assertEquals(Long.MIN_VALUE, timeRangeList.get(0).getMin());
+ assertEquals(9, timeRangeList.get(0).getMax());
+ assertEquals(21, timeRangeList.get(1).getMin());
+ assertEquals(Long.MAX_VALUE, timeRangeList.get(1).getMax());
+
+ // time not between 10 and Long.MAX_VALUE
+ filter = TimeFilter.between(10, Long.MAX_VALUE, true);
+ timeRangeList = filter.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(Long.MIN_VALUE, timeRangeList.get(0).getMin());
+ assertEquals(9, timeRangeList.get(0).getMax());
+
+ // time not between Long.MIN_VALUE and 20
+ filter = TimeFilter.between(Long.MIN_VALUE, 20, true);
+ timeRangeList = filter.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(21, timeRangeList.get(0).getMin());
+ assertEquals(Long.MAX_VALUE, timeRangeList.get(0).getMax());
+ }
+
+ @Test
+ public void testNotTimeFilter() {
+
+ // !(time > 10 and time <= 20)
+ NotFilter filter = new NotFilter(new AndFilter(TimeFilter.gt(10), TimeFilter.ltEq(20)));
+ List<TimeRange> timeRangeList = filter.getTimeRanges();
+ assertEquals(2, timeRangeList.size());
+ assertEquals(Long.MIN_VALUE, timeRangeList.get(0).getMin());
+ assertEquals(10, timeRangeList.get(0).getMax());
+ assertEquals(21, timeRangeList.get(1).getMin());
+ assertEquals(Long.MAX_VALUE, timeRangeList.get(1).getMax());
+
+ // !(time > 20 or time <= 10)
+ filter = new NotFilter(new OrFilter(TimeFilter.gt(20), TimeFilter.ltEq(10)));
+ timeRangeList = filter.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(11, timeRangeList.get(0).getMin());
+ assertEquals(20, timeRangeList.get(0).getMax());
+ }
+
+ @Test
+ public void testTimeEqFilter() {
+
+ // time = 10
+ TimeFilter.TimeEq filter = TimeFilter.eq(10);
+ List<TimeRange> timeRangeList = filter.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(10, timeRangeList.get(0).getMin());
+ assertEquals(10, timeRangeList.get(0).getMax());
+
+ // !(time = 10)
+ NotFilter filter1 = new NotFilter(filter);
+ timeRangeList = filter1.getTimeRanges();
+ assertEquals(2, timeRangeList.size());
+ assertEquals(Long.MIN_VALUE, timeRangeList.get(0).getMin());
+ assertEquals(9, timeRangeList.get(0).getMax());
+ assertEquals(11, timeRangeList.get(1).getMin());
+ assertEquals(Long.MAX_VALUE, timeRangeList.get(1).getMax());
+ }
+
+ @Test
+ public void testTimeNotEqFilter() {
+
+ // time != 10
+ TimeFilter.TimeNotEq filter = TimeFilter.notEq(10);
+ List<TimeRange> timeRangeList = filter.getTimeRanges();
+ assertEquals(2, timeRangeList.size());
+ assertEquals(Long.MIN_VALUE, timeRangeList.get(0).getMin());
+ assertEquals(9, timeRangeList.get(0).getMax());
+ assertEquals(11, timeRangeList.get(1).getMin());
+ assertEquals(Long.MAX_VALUE, timeRangeList.get(1).getMax());
+
+ // !(time != 10)
+ NotFilter filter1 = new NotFilter(filter);
+ timeRangeList = filter1.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(10, timeRangeList.get(0).getMin());
+ assertEquals(10, timeRangeList.get(0).getMax());
+ }
+
+ @Test
+ public void testTimeGtFilter() {
+
+ // time > 10
+ TimeFilter.TimeGt filter = TimeFilter.gt(10);
+ List<TimeRange> timeRangeList = filter.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(11, timeRangeList.get(0).getMin());
+ assertEquals(Long.MAX_VALUE, timeRangeList.get(0).getMax());
+
+ // !(time > 10)
+ NotFilter filter1 = new NotFilter(filter);
+ timeRangeList = filter1.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(Long.MIN_VALUE, timeRangeList.get(0).getMin());
+ assertEquals(10, timeRangeList.get(0).getMax());
+ }
+
+ @Test
+ public void testTimeGtEqFilter() {
+
+ // time >= 10
+ TimeFilter.TimeGtEq filter = TimeFilter.gtEq(10);
+ List<TimeRange> timeRangeList = filter.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(10, timeRangeList.get(0).getMin());
+ assertEquals(Long.MAX_VALUE, timeRangeList.get(0).getMax());
+
+ // !(time >= 10)
+ NotFilter filter1 = new NotFilter(filter);
+ timeRangeList = filter1.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(Long.MIN_VALUE, timeRangeList.get(0).getMin());
+ assertEquals(9, timeRangeList.get(0).getMax());
+ }
+
+ @Test
+ public void testTimeLtFilter() {
+
+ // time < 10
+ TimeFilter.TimeLt filter = TimeFilter.lt(10);
+ List<TimeRange> timeRangeList = filter.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(Long.MIN_VALUE, timeRangeList.get(0).getMin());
+ assertEquals(9, timeRangeList.get(0).getMax());
+
+ // !(time < 10)
+ NotFilter filter1 = new NotFilter(filter);
+ timeRangeList = filter1.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(10, timeRangeList.get(0).getMin());
+ assertEquals(Long.MAX_VALUE, timeRangeList.get(0).getMax());
+ }
+
+ @Test
+ public void testTimeLtEqFilter() {
+
+ // time <= 10
+ TimeFilter.TimeLtEq filter = TimeFilter.ltEq(10);
+ List<TimeRange> timeRangeList = filter.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(Long.MIN_VALUE, timeRangeList.get(0).getMin());
+ assertEquals(10, timeRangeList.get(0).getMax());
+
+ // !(time <= 10)
+ NotFilter filter1 = new NotFilter(filter);
+ timeRangeList = filter1.getTimeRanges();
+ assertEquals(1, timeRangeList.size());
+ assertEquals(11, timeRangeList.get(0).getMin());
+ assertEquals(Long.MAX_VALUE, timeRangeList.get(0).getMax());
+ }
+
+ @Test
+ public void testGetTimePartitionSlotList() {
+ // time >= 10
+ List<TTimePartitionSlot> res = getTimePartitionSlotList(TimeFilter.gtEq(10));
+ assertTrue(res.isEmpty());
+
+ // time < 20
+ res = getTimePartitionSlotList(TimeFilter.lt(20));
+ assertTrue(res.isEmpty());
+
+ // time > 10 and time <= 20
+ res = getTimePartitionSlotList(new AndFilter(TimeFilter.gt(10), TimeFilter.ltEq(20)));
+ List<TTimePartitionSlot> expected = Collections.singletonList(new TTimePartitionSlot(0));
+ assertEquals(expected.size(), res.size());
+ for (int i = 0; i < expected.size(); i++) {
+ assertEquals(expected.get(i), res.get(i));
+ }
+
+ // time > 0 and time <= IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 3
+ // + 1
+ res =
+ getTimePartitionSlotList(
+ new AndFilter(
+ TimeFilter.gt(0),
+ TimeFilter.ltEq(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 3 + 1)));
+ expected =
+ Arrays.asList(
+ new TTimePartitionSlot(0),
+ new TTimePartitionSlot(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval()),
+ new TTimePartitionSlot(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 2),
+ new TTimePartitionSlot(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 3));
+ assertEquals(expected.size(), res.size());
+ for (int i = 0; i < expected.size(); i++) {
+ assertEquals(expected.get(i), res.get(i));
+ }
+
+ // time >= IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() - 1 and time <
+ // IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() + 1
+ res =
+ getTimePartitionSlotList(
+ new AndFilter(
+ TimeFilter.gtEq(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() - 1),
+ TimeFilter.lt(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() + 1)));
+ expected =
+ Arrays.asList(
+ new TTimePartitionSlot(0),
+ new TTimePartitionSlot(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval()));
+ assertEquals(expected.size(), res.size());
+ for (int i = 0; i < expected.size(); i++) {
+ assertEquals(expected.get(i), res.get(i));
+ }
+
+ // time between IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() - 1 and
+ // time < IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval()
+ res =
+ getTimePartitionSlotList(
+ TimeFilter.between(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() - 1,
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval(),
+ false));
+ expected =
+ Arrays.asList(
+ new TTimePartitionSlot(0),
+ new TTimePartitionSlot(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval()));
+ assertEquals(expected.size(), res.size());
+ for (int i = 0; i < expected.size(); i++) {
+ assertEquals(expected.get(i), res.get(i));
+ }
+
+ // time >= IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() and time <=
+ // IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() + 1
+ res =
+ getTimePartitionSlotList(
+ new AndFilter(
+ TimeFilter.gtEq(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval()),
+ TimeFilter.ltEq(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() + 1)));
+ expected =
+ Collections.singletonList(
+ new TTimePartitionSlot(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval()));
+ assertEquals(expected.size(), res.size());
+ for (int i = 0; i < expected.size(); i++) {
+ assertEquals(expected.get(i), res.get(i));
+ }
+
+ // time between IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() and time <=
+ // IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() + 1
+ res =
+ getTimePartitionSlotList(
+ TimeFilter.between(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval(),
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() + 1,
+ false));
+ expected =
+ Collections.singletonList(
+ new TTimePartitionSlot(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval()));
+ assertEquals(expected.size(), res.size());
+ for (int i = 0; i < expected.size(); i++) {
+ assertEquals(expected.get(i), res.get(i));
+ }
+
+ // (time >= 10 and time < IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval())
+ // or (time > IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() and time <
+ // IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 2 - 100)
+ // or (time > IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 2 - 50 and
+ // time <= IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 2 - 40)
+ // or (time > IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 2 - 20 and
+ // time <= IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 3 + 10)
+ // or (time > IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 5 + 1 and
+ // time < IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 5 + 10)
+
+ OrFilter orFilter1 =
+ new OrFilter(
+ new AndFilter(
+ TimeFilter.gtEq(10),
+ TimeFilter.lt(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval())),
+ new AndFilter(
+ TimeFilter.gt(IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval()),
+ TimeFilter.lt(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 2
+ - 100)));
+ OrFilter orFilter2 =
+ new OrFilter(
+ orFilter1,
+ new AndFilter(
+ TimeFilter.gt(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 2 - 50),
+ TimeFilter.ltEq(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 2
+ - 40)));
+ OrFilter orFilter3 =
+ new OrFilter(
+ orFilter2,
+ new AndFilter(
+ TimeFilter.gt(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 2 - 20),
+ TimeFilter.ltEq(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 3
+ + 10)));
+ OrFilter orFilter4 =
+ new OrFilter(
+ orFilter3,
+ new AndFilter(
+ TimeFilter.gt(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 5 + 1),
+ TimeFilter.lt(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 5
+ + 10)));
+
+ res = getTimePartitionSlotList(orFilter4);
+ expected =
+ Arrays.asList(
+ new TTimePartitionSlot(0),
+ new TTimePartitionSlot(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval()),
+ new TTimePartitionSlot(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 2),
+ new TTimePartitionSlot(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 3),
+ new TTimePartitionSlot(
+ IoTDBDescriptor.getInstance().getConfig().getTimePartitionInterval() * 5));
+ for (int i = 0; i < expected.size(); i++) {
+ assertEquals(expected.get(i), res.get(i));
+ }
+ }
+}
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/GroupByFilter.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/GroupByFilter.java
index 236f7a4305..179f239f8d 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/GroupByFilter.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/GroupByFilter.java
@@ -19,6 +19,7 @@
package org.apache.iotdb.tsfile.read.filter;
import org.apache.iotdb.tsfile.file.metadata.statistics.Statistics;
+import org.apache.iotdb.tsfile.read.common.TimeRange;
import org.apache.iotdb.tsfile.read.filter.basic.Filter;
import org.apache.iotdb.tsfile.read.filter.factory.FilterSerializeId;
@@ -26,6 +27,8 @@ import java.io.DataOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.List;
import java.util.Objects;
public class GroupByFilter implements Filter, Serializable {
@@ -151,4 +154,9 @@ public class GroupByFilter implements Filter, Serializable {
public long getEndTime() {
return endTime;
}
+
+ @Override
+ public List<TimeRange> getTimeRanges() {
+ return Collections.singletonList(new TimeRange(startTime, endTime - 1));
+ }
}
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/TimeFilter.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/TimeFilter.java
index e5109bf46b..e33b617e60 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/TimeFilter.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/TimeFilter.java
@@ -18,6 +18,7 @@
*/
package org.apache.iotdb.tsfile.read.filter;
+import org.apache.iotdb.tsfile.read.common.TimeRange;
import org.apache.iotdb.tsfile.read.filter.basic.Filter;
import org.apache.iotdb.tsfile.read.filter.factory.FilterType;
import org.apache.iotdb.tsfile.read.filter.operator.Between;
@@ -30,7 +31,12 @@ import org.apache.iotdb.tsfile.read.filter.operator.LtEq;
import org.apache.iotdb.tsfile.read.filter.operator.NotEq;
import org.apache.iotdb.tsfile.read.filter.operator.NotFilter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
import java.util.Set;
+import java.util.stream.Collectors;
public class TimeFilter {
@@ -77,6 +83,24 @@ public class TimeFilter {
private TimeBetween(long value1, long value2, boolean not) {
super(value1, value2, FilterType.TIME_FILTER, not);
}
+
+ @Override
+ public List<TimeRange> getTimeRanges() {
+ long left = (long) value1;
+ long right = (long) value2;
+ if (not) {
+ List<TimeRange> res = new ArrayList<>();
+ if (left != Long.MIN_VALUE) {
+ res.add(new TimeRange(Long.MIN_VALUE, left - 1));
+ }
+ if (right != Long.MAX_VALUE) {
+ res.add(new TimeRange(right + 1, Long.MAX_VALUE));
+ }
+ return res;
+ } else {
+ return Collections.singletonList(new TimeRange(left, right));
+ }
+ }
}
public static class TimeIn extends In {
@@ -84,6 +108,18 @@ public class TimeFilter {
private TimeIn(Set<Long> values, boolean not) {
super(values, FilterType.TIME_FILTER, not);
}
+
+ @Override
+ public List<TimeRange> getTimeRanges() {
+ return ((Set<Long>) values)
+ .stream()
+ .map(
+ l -> {
+ long time = l;
+ return new TimeRange(time, time);
+ })
+ .collect(Collectors.toList());
+ }
}
public static class TimeEq extends Eq {
@@ -91,6 +127,11 @@ public class TimeFilter {
private TimeEq(long value) {
super(value, FilterType.TIME_FILTER);
}
+
+ @Override
+ public List<TimeRange> getTimeRanges() {
+ return Collections.singletonList(new TimeRange((long) value, (long) value));
+ }
}
public static class TimeNotEq extends NotEq {
@@ -98,6 +139,19 @@ public class TimeFilter {
private TimeNotEq(long value) {
super(value, FilterType.TIME_FILTER);
}
+
+ @Override
+ public List<TimeRange> getTimeRanges() {
+ long time = (long) value;
+ if (time == Long.MIN_VALUE) {
+ return Collections.singletonList(new TimeRange(time + 1, Long.MAX_VALUE));
+ } else if (time == Long.MAX_VALUE) {
+ return Collections.singletonList(new TimeRange(Long.MIN_VALUE, time - 1));
+ } else {
+ return Arrays.asList(
+ new TimeRange(Long.MIN_VALUE, time - 1), new TimeRange(time + 1, Long.MAX_VALUE));
+ }
+ }
}
public static class TimeGt extends Gt {
@@ -105,6 +159,16 @@ public class TimeFilter {
private TimeGt(long value) {
super(value, FilterType.TIME_FILTER);
}
+
+ @Override
+ public List<TimeRange> getTimeRanges() {
+ long left = (long) value;
+ if (left != Long.MAX_VALUE) {
+ return Collections.singletonList(new TimeRange(left + 1, Long.MAX_VALUE));
+ } else {
+ return Collections.emptyList();
+ }
+ }
}
public static class TimeGtEq extends GtEq {
@@ -112,6 +176,11 @@ public class TimeFilter {
private TimeGtEq(long value) {
super(value, FilterType.TIME_FILTER);
}
+
+ @Override
+ public List<TimeRange> getTimeRanges() {
+ return Collections.singletonList(new TimeRange((long) value, Long.MAX_VALUE));
+ }
}
public static class TimeLt extends Lt {
@@ -119,6 +188,16 @@ public class TimeFilter {
private TimeLt(long value) {
super(value, FilterType.TIME_FILTER);
}
+
+ @Override
+ public List<TimeRange> getTimeRanges() {
+ long right = (long) value;
+ if (right != Long.MIN_VALUE) {
+ return Collections.singletonList(new TimeRange(Long.MIN_VALUE, right - 1));
+ } else {
+ return Collections.emptyList();
+ }
+ }
}
public static class TimeLtEq extends LtEq {
@@ -126,6 +205,11 @@ public class TimeFilter {
private TimeLtEq(long value) {
super(value, FilterType.TIME_FILTER);
}
+
+ @Override
+ public List<TimeRange> getTimeRanges() {
+ return Collections.singletonList(new TimeRange(Long.MIN_VALUE, (long) value));
+ }
}
public static class TimeNotFilter extends NotFilter {
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/basic/Filter.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/basic/Filter.java
index 4fb987b3a2..dc0d479c83 100755
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/basic/Filter.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/basic/Filter.java
@@ -19,11 +19,14 @@
package org.apache.iotdb.tsfile.read.filter.basic;
import org.apache.iotdb.tsfile.file.metadata.statistics.Statistics;
+import org.apache.iotdb.tsfile.read.common.TimeRange;
import org.apache.iotdb.tsfile.read.filter.factory.FilterSerializeId;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.List;
/** Filter is a top level filter abstraction. */
public interface Filter {
@@ -73,4 +76,8 @@ public interface Filter {
void deserialize(ByteBuffer buffer);
FilterSerializeId getSerializeId();
+
+ default List<TimeRange> getTimeRanges() {
+ return Collections.emptyList();
+ }
}
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/AndFilter.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/AndFilter.java
index 9fe6a6036b..6c5120a3f7 100755
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/AndFilter.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/AndFilter.java
@@ -19,10 +19,14 @@
package org.apache.iotdb.tsfile.read.filter.operator;
import org.apache.iotdb.tsfile.file.metadata.statistics.Statistics;
+import org.apache.iotdb.tsfile.read.common.TimeRange;
import org.apache.iotdb.tsfile.read.filter.basic.BinaryFilter;
import org.apache.iotdb.tsfile.read.filter.basic.Filter;
import org.apache.iotdb.tsfile.read.filter.factory.FilterSerializeId;
+import java.util.ArrayList;
+import java.util.List;
+
/** Both the left and right operators of AndExpression must satisfy the condition. */
public class AndFilter extends BinaryFilter {
@@ -70,4 +74,40 @@ public class AndFilter extends BinaryFilter {
public FilterSerializeId getSerializeId() {
return FilterSerializeId.AND;
}
+
+ @Override
+ public List<TimeRange> getTimeRanges() {
+ List<TimeRange> result = new ArrayList<>();
+ List<TimeRange> leftTimeRanges = left.getTimeRanges();
+ List<TimeRange> rightTimeRanges = right.getTimeRanges();
+
+ int leftIndex = 0,
+ rightIndex = 0,
+ leftSize = leftTimeRanges.size(),
+ rightSize = rightTimeRanges.size();
+ while (leftIndex < leftSize && rightIndex < rightSize) {
+ TimeRange leftRange = leftTimeRanges.get(leftIndex);
+ TimeRange rightRange = rightTimeRanges.get(rightIndex);
+
+ if (leftRange.getMax() < rightRange.getMin()) {
+ leftIndex++;
+ } else if (rightRange.getMax() < leftRange.getMin()) {
+ rightIndex++;
+ } else {
+ TimeRange intersection =
+ new TimeRange(
+ Math.max(leftRange.getMin(), rightRange.getMin()),
+ Math.min(leftRange.getMax(), rightRange.getMax()));
+ result.add(intersection);
+ if (leftRange.getMax() <= intersection.getMax()) {
+ leftIndex++;
+ }
+ if (rightRange.getMax() <= intersection.getMax()) {
+ rightIndex++;
+ }
+ }
+ }
+
+ return result;
+ }
}
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/NotFilter.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/NotFilter.java
index 5ed24a6308..cd983dc329 100755
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/NotFilter.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/NotFilter.java
@@ -19,6 +19,7 @@
package org.apache.iotdb.tsfile.read.filter.operator;
import org.apache.iotdb.tsfile.file.metadata.statistics.Statistics;
+import org.apache.iotdb.tsfile.read.common.TimeRange;
import org.apache.iotdb.tsfile.read.filter.basic.Filter;
import org.apache.iotdb.tsfile.read.filter.factory.FilterFactory;
import org.apache.iotdb.tsfile.read.filter.factory.FilterSerializeId;
@@ -27,6 +28,8 @@ import java.io.DataOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
/** NotFilter necessary. Use InvertExpressionVisitor */
@@ -112,4 +115,28 @@ public class NotFilter implements Filter, Serializable {
public int hashCode() {
return Objects.hash(that);
}
+
+ @Override
+ public List<TimeRange> getTimeRanges() {
+ List<TimeRange> list = that.getTimeRanges();
+ if (list.isEmpty()) {
+ return list;
+ }
+ List<TimeRange> res = new ArrayList<>();
+ if (list.get(0).getMin() != Long.MIN_VALUE) {
+ res.add(new TimeRange(Long.MIN_VALUE, list.get(0).getMin() - 1));
+ }
+ for (int i = 1, size = list.size(); i < size; i++) {
+ long left = list.get(i - 1).getMax() + 1;
+ long right = list.get(i).getMin() - 1;
+ if (left <= right) {
+ res.add(new TimeRange(left, right));
+ }
+ }
+
+ if (list.get(list.size() - 1).getMax() != Long.MAX_VALUE) {
+ res.add(new TimeRange(list.get(list.size() - 1).getMax() + 1, Long.MAX_VALUE));
+ }
+ return res;
+ }
}
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/OrFilter.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/OrFilter.java
index 32e4593651..17b0935510 100755
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/OrFilter.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/operator/OrFilter.java
@@ -19,11 +19,15 @@
package org.apache.iotdb.tsfile.read.filter.operator;
import org.apache.iotdb.tsfile.file.metadata.statistics.Statistics;
+import org.apache.iotdb.tsfile.read.common.TimeRange;
import org.apache.iotdb.tsfile.read.filter.basic.BinaryFilter;
import org.apache.iotdb.tsfile.read.filter.basic.Filter;
import org.apache.iotdb.tsfile.read.filter.factory.FilterSerializeId;
import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
/** Either of the left and right operators of AndExpression must satisfy the condition. */
public class OrFilter extends BinaryFilter implements Serializable {
@@ -72,4 +76,66 @@ public class OrFilter extends BinaryFilter implements Serializable {
public FilterSerializeId getSerializeId() {
return FilterSerializeId.OR;
}
+
+ @Override
+ public List<TimeRange> getTimeRanges() {
+ List<TimeRange> result = new ArrayList<>();
+ List<TimeRange> leftTimeRanges = left.getTimeRanges();
+ List<TimeRange> rightTimeRanges = right.getTimeRanges();
+
+ int leftIndex = 0,
+ rightIndex = 0,
+ leftSize = leftTimeRanges.size(),
+ rightSize = rightTimeRanges.size();
+ TimeRange range;
+ if (leftTimeRanges.isEmpty() && rightTimeRanges.isEmpty()) {
+ return Collections.emptyList();
+ } else if (leftTimeRanges.isEmpty()) {
+ return rightTimeRanges;
+ } else if (rightTimeRanges.isEmpty()) {
+ return leftTimeRanges;
+ } else {
+ TimeRange leftRange = leftTimeRanges.get(leftIndex);
+ TimeRange rightRange = rightTimeRanges.get(rightIndex);
+ if (leftRange.getMin() <= rightRange.getMin()) {
+ range = leftRange;
+ leftIndex++;
+ } else {
+ range = rightRange;
+ rightIndex++;
+ }
+ }
+
+ while (leftIndex < leftSize || rightIndex < rightSize) {
+ TimeRange chosenRange;
+ if (leftIndex < leftSize && rightIndex < rightSize) {
+ TimeRange leftRange = leftTimeRanges.get(leftIndex);
+ TimeRange rightRange = rightTimeRanges.get(rightIndex);
+ if (leftRange.getMin() <= rightRange.getMin()) {
+ chosenRange = leftRange;
+ leftIndex++;
+ } else {
+ chosenRange = rightRange;
+ rightIndex++;
+ }
+ } else if (leftIndex < leftSize) {
+ chosenRange = leftTimeRanges.get(leftIndex);
+ leftIndex++;
+ } else {
+ chosenRange = rightTimeRanges.get(rightIndex);
+ rightIndex++;
+ }
+
+ if (chosenRange.getMin() > range.getMax()) {
+ result.add(range);
+ range = chosenRange;
+ } else {
+ range.setMax(Math.max(range.getMax(), chosenRange.getMax()));
+ }
+ }
+
+ result.add(range);
+
+ return result;
+ }
}