You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by qi...@apache.org on 2021/06/18 06:35:54 UTC

[iotdb] branch rel/0.12 updated: [To rel/0.12] [IOTDB-1442] Time filter & TTL is not used during the construction of ClusterTimeGenerator (#3421)

This is an automated email from the ASF dual-hosted git repository.

qiaojialin pushed a commit to branch rel/0.12
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/rel/0.12 by this push:
     new 784ac10  [To rel/0.12] [IOTDB-1442] Time filter & TTL is not used during the construction of ClusterTimeGenerator (#3421)
784ac10 is described below

commit 784ac108ae8978ffea8e76b6c38505bcc8f7c9bb
Author: Jiang Tian <jt...@163.com>
AuthorDate: Fri Jun 18 14:33:16 2021 +0800

    [To rel/0.12] [IOTDB-1442] Time filter & TTL is not used during the construction of ClusterTimeGenerator (#3421)
---
 .../iotdb/cluster/query/LocalQueryExecutor.java    | 16 ++---
 .../cluster/query/reader/ClusterReaderFactory.java | 19 +++--
 .../cluster/query/reader/ClusterTimeGenerator.java | 45 ++++++++----
 .../apache/iotdb/cluster/query/BaseQueryTest.java  |  4 +-
 .../query/ClusterDataQueryExecutorTest.java        |  6 +-
 .../query/reader/ClusterReaderFactoryTest.java     | 82 ++++++++++++++++++++++
 .../query/reader/ClusterTimeGeneratorTest.java     | 58 +++++++++++++++
 .../iotdb/cluster/server/member/BaseMember.java    |  2 +-
 .../reader/series/SeriesRawDataBatchReader.java    |  5 ++
 .../iotdb/db/query/reader/series/SeriesReader.java |  5 ++
 .../reader/universal/PriorityMergeReader.java      |  1 +
 .../query/timegenerator/ServerTimeGenerator.java   |  2 +-
 12 files changed, 202 insertions(+), 43 deletions(-)

diff --git a/cluster/src/main/java/org/apache/iotdb/cluster/query/LocalQueryExecutor.java b/cluster/src/main/java/org/apache/iotdb/cluster/query/LocalQueryExecutor.java
index f078519..460180d 100644
--- a/cluster/src/main/java/org/apache/iotdb/cluster/query/LocalQueryExecutor.java
+++ b/cluster/src/main/java/org/apache/iotdb/cluster/query/LocalQueryExecutor.java
@@ -91,6 +91,7 @@ import static org.apache.iotdb.session.Config.DEFAULT_FETCH_SIZE;
 public class LocalQueryExecutor {
 
   private static final Logger logger = LoggerFactory.getLogger(LocalQueryExecutor.class);
+  public static final String DEBUG_SHOW_QUERY_ID = "{}: local queryId for {}#{} is {}";
   private DataGroupMember dataGroupMember;
   private ClusterReaderFactory readerFactory;
   private String name;
@@ -172,7 +173,7 @@ public class LocalQueryExecutor {
     Map<String, ByteBuffer> pathByteBuffers = Maps.newHashMap();
 
     for (String path : paths) {
-      ByteBuffer byteBuffer = null;
+      ByteBuffer byteBuffer;
       if (reader.hasNextBatch(path)) {
         BatchData batchData = reader.nextBatch(path);
 
@@ -236,7 +237,7 @@ public class LocalQueryExecutor {
             request.getFetchSize(),
             request.getDeduplicatedPathNum());
     logger.debug(
-        "{}: local queryId for {}#{} is {}",
+        DEBUG_SHOW_QUERY_ID,
         name,
         request.getQueryId(),
         request.getPath(),
@@ -310,12 +311,7 @@ public class LocalQueryExecutor {
             });
 
     List<TSDataType> dataTypes = Lists.newArrayList();
-    request
-        .getDataTypeOrdinal()
-        .forEach(
-            dataType -> {
-              dataTypes.add(TSDataType.values()[dataType]);
-            });
+    request.getDataTypeOrdinal().forEach(dataType -> dataTypes.add(TSDataType.values()[dataType]));
 
     Filter timeFilter = null;
     Filter valueFilter = null;
@@ -335,7 +331,7 @@ public class LocalQueryExecutor {
             request.getFetchSize(),
             request.getDeduplicatedPathNum());
     logger.debug(
-        "{}: local queryId for {}#{} is {}",
+        DEBUG_SHOW_QUERY_ID,
         name,
         request.getQueryId(),
         request.getPath(),
@@ -502,7 +498,7 @@ public class LocalQueryExecutor {
             request.getFetchSize(),
             request.getDeduplicatedPathNum());
     logger.debug(
-        "{}: local queryId for {}#{} is {}",
+        DEBUG_SHOW_QUERY_ID,
         name,
         request.getQueryId(),
         request.getPath(),
diff --git a/cluster/src/main/java/org/apache/iotdb/cluster/query/reader/ClusterReaderFactory.java b/cluster/src/main/java/org/apache/iotdb/cluster/query/reader/ClusterReaderFactory.java
index 23603b7..64a2e3b 100644
--- a/cluster/src/main/java/org/apache/iotdb/cluster/query/reader/ClusterReaderFactory.java
+++ b/cluster/src/main/java/org/apache/iotdb/cluster/query/reader/ClusterReaderFactory.java
@@ -236,11 +236,10 @@ public class ClusterReaderFactory {
     for (PartialPath partialPath : paths) {
       List<PartitionGroup> partitionGroups = metaGroupMember.routeFilter(timeFilter, partialPath);
       partitionGroups.forEach(
-          partitionGroup -> {
-            partitionGroupListMap
-                .computeIfAbsent(partitionGroup, n -> new ArrayList<>())
-                .add(partialPath);
-          });
+          partitionGroup ->
+              partitionGroupListMap
+                  .computeIfAbsent(partitionGroup, n -> new ArrayList<>())
+                  .add(partialPath));
     }
 
     List<AbstractMultPointReader> multPointReaders = Lists.newArrayList();
@@ -513,6 +512,7 @@ public class ClusterReaderFactory {
         ((SlotPartitionTable) metaGroupMember.getPartitionTable()).getNodeSlots(header);
     QueryDataSource queryDataSource =
         QueryResourceManager.getInstance().getQueryDataSource(path, context, timeFilter);
+    valueFilter = queryDataSource.updateFilterUsingTTL(valueFilter);
     return new SeriesReader(
         path,
         allSensors,
@@ -584,7 +584,7 @@ public class ClusterReaderFactory {
       return new MultEmptyReader(fullPaths);
     }
     throw new StorageEngineException(
-        new RequestTimeOutException("Query " + paths + " in " + partitionGroup));
+        new RequestTimeOutException("Query multi-series: " + paths + " in " + partitionGroup));
   }
 
   /**
@@ -666,10 +666,7 @@ public class ClusterReaderFactory {
         });
 
     List<Integer> dataTypeOrdinals = Lists.newArrayList();
-    dataTypes.forEach(
-        dataType -> {
-          dataTypeOrdinals.add(dataType.ordinal());
-        });
+    dataTypes.forEach(dataType -> dataTypeOrdinals.add(dataType.ordinal()));
 
     request.setPath(fullPaths);
     request.setHeader(partitionGroup.getHeader());
@@ -971,7 +968,7 @@ public class ClusterReaderFactory {
       QueryContext context,
       DataGroupMember dataGroupMember,
       boolean ascending)
-      throws StorageEngineException, QueryProcessException, IOException {
+      throws StorageEngineException, QueryProcessException {
     // pull the newest data
     try {
       dataGroupMember.syncLeaderWithConsistencyCheck(false);
diff --git a/cluster/src/main/java/org/apache/iotdb/cluster/query/reader/ClusterTimeGenerator.java b/cluster/src/main/java/org/apache/iotdb/cluster/query/reader/ClusterTimeGenerator.java
index 43d2668..4b13e98 100644
--- a/cluster/src/main/java/org/apache/iotdb/cluster/query/reader/ClusterTimeGenerator.java
+++ b/cluster/src/main/java/org/apache/iotdb/cluster/query/reader/ClusterTimeGenerator.java
@@ -31,6 +31,7 @@ import org.apache.iotdb.db.query.context.QueryContext;
 import org.apache.iotdb.db.query.reader.series.ManagedSeriesReader;
 import org.apache.iotdb.db.query.timegenerator.ServerTimeGenerator;
 import org.apache.iotdb.db.service.IoTDB;
+import org.apache.iotdb.db.utils.TestOnly;
 import org.apache.iotdb.tsfile.exception.write.UnSupportedDataTypeException;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.read.expression.ExpressionType;
@@ -79,13 +80,38 @@ public class ClusterTimeGenerator extends ServerTimeGenerator {
     }
   }
 
+  @TestOnly
+  public ClusterTimeGenerator(
+      QueryContext context,
+      MetaGroupMember metaGroupMember,
+      ClusterReaderFactory clusterReaderFactory,
+      RawDataQueryPlan rawDataQueryPlan,
+      boolean onlyCheckLocalData)
+      throws StorageEngineException {
+    super(context);
+    this.queryPlan = rawDataQueryPlan;
+    this.readerFactory = clusterReaderFactory;
+    try {
+      readerFactory.syncMetaGroup();
+      if (onlyCheckLocalData) {
+        whetherHasLocalDataGroup(
+            queryPlan.getExpression(), metaGroupMember, queryPlan.isAscending());
+      } else {
+        constructNode(queryPlan.getExpression());
+      }
+    } catch (IOException | CheckConsistencyException e) {
+      throw new StorageEngineException(e);
+    }
+  }
+
   @Override
   protected IBatchReader generateNewBatchReader(SingleSeriesExpression expression)
       throws IOException {
     Filter filter = expression.getFilter();
+    Filter timeFilter = getTimeFilter(filter);
     PartialPath path = (PartialPath) expression.getSeriesPath();
     TSDataType dataType;
-    ManagedSeriesReader mergeReader = null;
+    ManagedSeriesReader mergeReader;
     try {
       dataType =
           ((CMManager) IoTDB.metaManager)
@@ -97,7 +123,7 @@ public class ClusterTimeGenerator extends ServerTimeGenerator {
               path,
               queryPlan.getAllMeasurementsInDevice(path.getDevice()),
               dataType,
-              null,
+              timeFilter,
               filter,
               context,
               queryPlan.isAscending());
@@ -111,18 +137,6 @@ public class ClusterTimeGenerator extends ServerTimeGenerator {
     return hasLocalReader;
   }
 
-  public void setHasLocalReader(boolean hasLocalReader) {
-    this.hasLocalReader = hasLocalReader;
-  }
-
-  public QueryDataSet.EndPoint getEndPoint() {
-    return endPoint;
-  }
-
-  public void setEndPoint(QueryDataSet.EndPoint endPoint) {
-    this.endPoint = endPoint;
-  }
-
   @Override
   public String toString() {
     return super.toString() + ", has local reader:" + hasLocalReader;
@@ -161,6 +175,7 @@ public class ClusterTimeGenerator extends ServerTimeGenerator {
   private void checkHasLocalReader(
       SingleSeriesExpression expression, MetaGroupMember metaGroupMember) throws IOException {
     Filter filter = expression.getFilter();
+    Filter timeFilter = getTimeFilter(filter);
     PartialPath path = (PartialPath) expression.getSeriesPath();
     TSDataType dataType;
     try {
@@ -184,7 +199,7 @@ public class ClusterTimeGenerator extends ServerTimeGenerator {
                   path,
                   queryPlan.getAllMeasurementsInDevice(path.getDevice()),
                   dataType,
-                  null,
+                  timeFilter,
                   filter,
                   context,
                   dataGroupMember,
diff --git a/cluster/src/test/java/org/apache/iotdb/cluster/query/BaseQueryTest.java b/cluster/src/test/java/org/apache/iotdb/cluster/query/BaseQueryTest.java
index eb04872..c0ab4cc 100644
--- a/cluster/src/test/java/org/apache/iotdb/cluster/query/BaseQueryTest.java
+++ b/cluster/src/test/java/org/apache/iotdb/cluster/query/BaseQueryTest.java
@@ -50,8 +50,8 @@ import static org.junit.Assert.assertNull;
  */
 public class BaseQueryTest extends BaseMember {
 
-  List<PartialPath> pathList;
-  List<TSDataType> dataTypes;
+  protected List<PartialPath> pathList;
+  protected List<TSDataType> dataTypes;
 
   protected static void checkAggregations(
       List<AggregateResult> aggregationResults, Object[] answer) {
diff --git a/cluster/src/test/java/org/apache/iotdb/cluster/query/ClusterDataQueryExecutorTest.java b/cluster/src/test/java/org/apache/iotdb/cluster/query/ClusterDataQueryExecutorTest.java
index 8b7e98d..c6dfb93 100644
--- a/cluster/src/test/java/org/apache/iotdb/cluster/query/ClusterDataQueryExecutorTest.java
+++ b/cluster/src/test/java/org/apache/iotdb/cluster/query/ClusterDataQueryExecutorTest.java
@@ -60,7 +60,7 @@ public class ClusterDataQueryExecutorTest extends BaseQueryTest {
   }
 
   @Test
-  public void testNoFilter() throws IOException, StorageEngineException, QueryProcessException {
+  public void testNoFilter() throws IOException, StorageEngineException {
     RawDataQueryPlan plan = new RawDataQueryPlan();
     plan.setDeduplicatedPaths(pathList);
     plan.setDeduplicatedDataTypes(dataTypes);
@@ -97,7 +97,7 @@ public class ClusterDataQueryExecutorTest extends BaseQueryTest {
   }
 
   @Test
-  public void testNoFilterWithRedirect() throws StorageEngineException, QueryProcessException {
+  public void testNoFilterWithRedirect() throws StorageEngineException {
     RawDataQueryPlan plan = new RawDataQueryPlan();
     plan.setDeduplicatedPaths(pathList);
     plan.setDeduplicatedDataTypes(dataTypes);
@@ -137,7 +137,7 @@ public class ClusterDataQueryExecutorTest extends BaseQueryTest {
 
   @Test
   public void testFilterWithTimeFilterRedirect()
-      throws IOException, StorageEngineException, QueryProcessException, IllegalPathException {
+      throws StorageEngineException, QueryProcessException {
     IExpression expression =
         new GlobalTimeExpression(new AndFilter(TimeFilter.gtEq(5), TimeFilter.ltEq(10)));
     RawDataQueryPlan plan = new RawDataQueryPlan();
diff --git a/cluster/src/test/java/org/apache/iotdb/cluster/query/reader/ClusterReaderFactoryTest.java b/cluster/src/test/java/org/apache/iotdb/cluster/query/reader/ClusterReaderFactoryTest.java
new file mode 100644
index 0000000..e40be6a
--- /dev/null
+++ b/cluster/src/test/java/org/apache/iotdb/cluster/query/reader/ClusterReaderFactoryTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.cluster.query.reader;
+
+import org.apache.iotdb.cluster.common.TestUtils;
+import org.apache.iotdb.cluster.query.BaseQueryTest;
+import org.apache.iotdb.cluster.query.RemoteQueryContext;
+import org.apache.iotdb.db.engine.StorageEngine;
+import org.apache.iotdb.db.exception.StorageEngineException;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
+import org.apache.iotdb.db.exception.query.QueryProcessException;
+import org.apache.iotdb.db.metadata.PartialPath;
+import org.apache.iotdb.db.query.control.QueryResourceManager;
+import org.apache.iotdb.db.query.reader.series.SeriesRawDataBatchReader;
+
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.Collections;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+public class ClusterReaderFactoryTest extends BaseQueryTest {
+
+  @Test
+  public void testTTL()
+      throws StorageEngineException, MetadataException, QueryProcessException, IOException {
+
+    ClusterReaderFactory readerFactory = new ClusterReaderFactory(testMetaMember);
+    RemoteQueryContext context =
+        new RemoteQueryContext(QueryResourceManager.getInstance().assignQueryId(true, 1024, -1));
+
+    try {
+      SeriesRawDataBatchReader seriesReader =
+          (SeriesRawDataBatchReader)
+              readerFactory.getSeriesBatchReader(
+                  pathList.get(0),
+                  Collections.singleton(pathList.get(0).getMeasurement()),
+                  dataTypes.get(0),
+                  null,
+                  null,
+                  context,
+                  dataGroupMemberMap.get(TestUtils.getNode(10)),
+                  true);
+      assertNotNull(seriesReader);
+      StorageEngine.getInstance().setTTL(new PartialPath(TestUtils.getTestSg(0)), 100);
+      seriesReader =
+          (SeriesRawDataBatchReader)
+              readerFactory.getSeriesBatchReader(
+                  pathList.get(0),
+                  Collections.singleton(pathList.get(0).getMeasurement()),
+                  dataTypes.get(0),
+                  null,
+                  null,
+                  context,
+                  dataGroupMemberMap.get(TestUtils.getNode(10)),
+                  true);
+      assertNull(seriesReader);
+    } finally {
+      QueryResourceManager.getInstance().endQuery(context.getQueryId());
+      StorageEngine.getInstance().setTTL(new PartialPath(TestUtils.getTestSg(0)), Long.MAX_VALUE);
+    }
+  }
+}
diff --git a/cluster/src/test/java/org/apache/iotdb/cluster/query/reader/ClusterTimeGeneratorTest.java b/cluster/src/test/java/org/apache/iotdb/cluster/query/reader/ClusterTimeGeneratorTest.java
index a414fd9..17261b2 100644
--- a/cluster/src/test/java/org/apache/iotdb/cluster/query/reader/ClusterTimeGeneratorTest.java
+++ b/cluster/src/test/java/org/apache/iotdb/cluster/query/reader/ClusterTimeGeneratorTest.java
@@ -20,6 +20,7 @@
 package org.apache.iotdb.cluster.query.reader;
 
 import org.apache.iotdb.cluster.common.TestUtils;
+import org.apache.iotdb.cluster.exception.EmptyIntervalException;
 import org.apache.iotdb.cluster.query.BaseQueryTest;
 import org.apache.iotdb.cluster.query.RemoteQueryContext;
 import org.apache.iotdb.db.exception.StorageEngineException;
@@ -29,14 +30,21 @@ import org.apache.iotdb.db.metadata.PartialPath;
 import org.apache.iotdb.db.qp.physical.crud.RawDataQueryPlan;
 import org.apache.iotdb.db.query.context.QueryContext;
 import org.apache.iotdb.db.query.control.QueryResourceManager;
+import org.apache.iotdb.db.query.reader.series.ManagedSeriesReader;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.read.expression.IExpression;
 import org.apache.iotdb.tsfile.read.expression.impl.BinaryExpression;
 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.basic.Filter;
+import org.apache.iotdb.tsfile.read.filter.operator.AndFilter;
 
 import org.junit.Test;
 
 import java.io.IOException;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -72,4 +80,54 @@ public class ClusterTimeGeneratorTest extends BaseQueryTest {
       QueryResourceManager.getInstance().endQuery(context.getQueryId());
     }
   }
+
+  @Test
+  public void testTimeFilter()
+      throws StorageEngineException, IOException, IllegalPathException, QueryProcessException {
+    RawDataQueryPlan dataQueryPlan = new RawDataQueryPlan();
+    QueryContext context =
+        new RemoteQueryContext(QueryResourceManager.getInstance().assignQueryId(true, 1024, -1));
+    Filter valueFilter = ValueFilter.gtEq(3.0);
+    Filter timeFilter = TimeFilter.ltEq(8);
+    try {
+      IExpression expression =
+          new SingleSeriesExpression(
+              new PartialPath(TestUtils.getTestSeries(0, 0)),
+              new AndFilter(valueFilter, timeFilter));
+      dataQueryPlan.setExpression(expression);
+      dataQueryPlan.addDeduplicatedPaths(new PartialPath(TestUtils.getTestSeries(0, 0)));
+
+      // capture the time filter used to create a reader
+      AtomicReference<Filter> timeFilterRef = new AtomicReference<>(null);
+      ClusterReaderFactory clusterReaderFactory =
+          new ClusterReaderFactory(testMetaMember) {
+            @Override
+            public ManagedSeriesReader getSeriesReader(
+                PartialPath path,
+                Set<String> deviceMeasurements,
+                TSDataType dataType,
+                Filter timeFilter,
+                Filter valueFilter,
+                QueryContext context,
+                boolean ascending)
+                throws StorageEngineException, EmptyIntervalException {
+              timeFilterRef.set(timeFilter);
+              return super.getSeriesReader(
+                  path, deviceMeasurements, dataType, timeFilter, valueFilter, context, ascending);
+            }
+          };
+      ClusterTimeGenerator timeGenerator =
+          new ClusterTimeGenerator(
+              context, testMetaMember, clusterReaderFactory, dataQueryPlan, false);
+
+      for (int i = 3; i <= 8; i++) {
+        assertTrue(timeGenerator.hasNext());
+        assertEquals(i, timeGenerator.next());
+      }
+      assertFalse(timeGenerator.hasNext());
+      assertEquals(timeFilter, timeFilterRef.get());
+    } finally {
+      QueryResourceManager.getInstance().endQuery(context.getQueryId());
+    }
+  }
 }
diff --git a/cluster/src/test/java/org/apache/iotdb/cluster/server/member/BaseMember.java b/cluster/src/test/java/org/apache/iotdb/cluster/server/member/BaseMember.java
index d2eeca4..ea82303 100644
--- a/cluster/src/test/java/org/apache/iotdb/cluster/server/member/BaseMember.java
+++ b/cluster/src/test/java/org/apache/iotdb/cluster/server/member/BaseMember.java
@@ -75,7 +75,7 @@ public class BaseMember {
 
   public static AtomicLong dummyResponse = new AtomicLong(Response.RESPONSE_AGREE);
 
-  Map<Node, DataGroupMember> dataGroupMemberMap;
+  protected Map<Node, DataGroupMember> dataGroupMemberMap;
   private Map<Node, MetaGroupMember> metaGroupMemberMap;
   PartitionGroup allNodes;
   protected MetaGroupMember testMetaMember;
diff --git a/server/src/main/java/org/apache/iotdb/db/query/reader/series/SeriesRawDataBatchReader.java b/server/src/main/java/org/apache/iotdb/db/query/reader/series/SeriesRawDataBatchReader.java
index 8698955..6af9c4e 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/reader/series/SeriesRawDataBatchReader.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/reader/series/SeriesRawDataBatchReader.java
@@ -191,4 +191,9 @@ public class SeriesRawDataBatchReader implements ManagedSeriesReader {
   private boolean isEmpty(BatchData batchData) {
     return batchData == null || !batchData.hasCurrent();
   }
+
+  @TestOnly
+  public SeriesReader getSeriesReader() {
+    return seriesReader;
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/query/reader/series/SeriesReader.java b/server/src/main/java/org/apache/iotdb/db/query/reader/series/SeriesReader.java
index dc3b4bb..a03e8fa 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/reader/series/SeriesReader.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/reader/series/SeriesReader.java
@@ -1201,4 +1201,9 @@ public class SeriesReader {
   public TimeOrderUtils getOrderUtils() {
     return orderUtils;
   }
+
+  @TestOnly
+  public Filter getValueFilter() {
+    return valueFilter;
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/query/reader/universal/PriorityMergeReader.java b/server/src/main/java/org/apache/iotdb/db/query/reader/universal/PriorityMergeReader.java
index 0982f6d..2b7db36 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/reader/universal/PriorityMergeReader.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/reader/universal/PriorityMergeReader.java
@@ -27,6 +27,7 @@ import java.util.Objects;
 import java.util.PriorityQueue;
 
 /** This class implements {@link IPointReader} for data sources with different priorities. */
+@SuppressWarnings("ConstantConditions") // heap is ensured by hasNext non-empty
 public class PriorityMergeReader implements IPointReader {
 
   // max time of all added readers in PriorityMergeReader
diff --git a/server/src/main/java/org/apache/iotdb/db/query/timegenerator/ServerTimeGenerator.java b/server/src/main/java/org/apache/iotdb/db/query/timegenerator/ServerTimeGenerator.java
index 5a9ce98..4cd1f0b 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/timegenerator/ServerTimeGenerator.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/timegenerator/ServerTimeGenerator.java
@@ -123,7 +123,7 @@ public class ServerTimeGenerator extends TimeGenerator {
   }
 
   /** extract time filter from a value filter */
-  private Filter getTimeFilter(Filter filter) {
+  protected Filter getTimeFilter(Filter filter) {
     if (filter instanceof UnaryFilter
         && ((UnaryFilter) filter).getFilterType() == FilterType.TIME_FILTER) {
       return filter;