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

haonan 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 bfd5af6  [IOTDB-968] Support time predicate in select last (#1898)
bfd5af6 is described below

commit bfd5af63ccd1b8d6876a5b6af6583014a1f0df26
Author: wshao08 <[email protected]>
AuthorDate: Fri Oct 30 13:33:36 2020 +0800

    [IOTDB-968] Support time predicate in select last (#1898)
    
    * Support time filter for last query
    
    * Add last with filter test
    
    * Fix test issues
    
    * Refuse to accept value filter in FROM clause
    
    * Fix code bug
    
    * Update docs
---
 .../DML Data Manipulation Language.md              |   9 +-
 docs/UserGuide/Operation Manual/SQL Reference.md   |  11 +-
 .../DML Data Manipulation Language.md              |   8 +-
 .../zh/UserGuide/Operation Manual/SQL Reference.md |   9 +-
 .../java/org/apache/iotdb/db/metadata/MTree.java   |   2 +-
 .../iotdb/db/qp/physical/crud/LastQueryPlan.java   |   8 ++
 .../query/dataset/groupby/GroupByFillDataSet.java  |   2 +-
 .../iotdb/db/query/executor/LastQueryExecutor.java | 113 +++++++--------------
 .../db/query/executor/fill/LastPointReader.java    |   3 +
 .../apache/iotdb/db/integration/IoTDBLastIT.java   | 104 +++++++++++++++++++
 10 files changed, 181 insertions(+), 88 deletions(-)

diff --git a/docs/UserGuide/Operation Manual/DML Data Manipulation Language.md 
b/docs/UserGuide/Operation Manual/DML Data Manipulation Language.md
index f2ab65b..7b61903 100644
--- a/docs/UserGuide/Operation Manual/DML Data Manipulation Language.md 
+++ b/docs/UserGuide/Operation Manual/DML Data Manipulation Language.md 
@@ -393,11 +393,13 @@ The Last point query is to return the most recent data 
point of the given timese
 The SQL statement is defined as:
 
 ```
-select last <Path> [COMMA <Path>]* from < PrefixPath > [COMMA < PrefixPath >]* 
<DISABLE ALIGN>
+select last <Path> [COMMA <Path>]* from < PrefixPath > [COMMA < PrefixPath >]* 
<WhereClause>
 ```
 
 which means: Query and return the last data points of timeseries 
prefixPath.path.
 
+Only time filter is supported in \<WhereClause\>. Any value filters given in 
the \<WhereClause\> take no effects.
+
 The result will be returned in a three column table format.
 
 ```
@@ -414,10 +416,11 @@ Example 1: get the last point of root.ln.wf01.wt01.speed:
 |  5   | root.ln.wf01.wt01.speed | 100   |
 ```
 
-Example 2: get the last speed, status and temperature points of 
root.ln.wf01.wt01
+Example 2: get the last speed, status and temperature points of 
root.ln.wf01.wt01,
+whose timestamp in range [5, 10).
 
 ```
-> select last speed, status, temperature from root.ln.wf01.wt01
+> select last speed, status, temperature from root.ln.wf01.wt01 where time >= 
5 and time < 10
 
 | Time | Path                         | Value |
 | ---  | ---------------------------- | ----- |
diff --git a/docs/UserGuide/Operation Manual/SQL Reference.md 
b/docs/UserGuide/Operation Manual/SQL Reference.md
index 08ceea0..b69b9b0 100644
--- a/docs/UserGuide/Operation Manual/SQL Reference.md  
+++ b/docs/UserGuide/Operation Manual/SQL Reference.md  
@@ -602,15 +602,22 @@ The LAST function returns the last time-value pair of the 
given timeseries. Curr
 SELECT LAST <SelectClause> FROM <FromClause>
 Select Clause : <Path> [COMMA <Path>]*
 FromClause : < PrefixPath > [COMMA < PrefixPath >]*
+WhereClause : <TimeExpr> [(AND | OR) <TimeExpr>]*
+TimeExpr : TIME PrecedenceEqualOperator (<TimeValue> | <RelativeTime>)
 
 Eg. SELECT LAST s1 FROM root.sg.d1
 Eg. SELECT LAST s1, s2 FROM root.sg.d1
 Eg. SELECT LAST s1 FROM root.sg.d1, root.sg.d2
+Eg. SELECT LAST s1 FROM root.sg.d1 where time < 100
+Eg. SELECT LAST s1, s2 FROM root.sg.d1 where time > 100 and time <= 500
+Eg. SELECT LAST s1, s2 FROM root.sg.d1 where time < 300 or time > 1000
 
 Rules:
 1. the statement needs to satisfy this constraint: <PrefixPath> + <Path> = 
<Timeseries>
 
-2. The result set of last query will always be displayed in a fixed three 
column table format.
+2. SELECT LAST does not support value filter.
+
+3. The result set of last query will always be displayed in a fixed three 
column table format.
 For example, "select last s1, s2 from root.sg.d1, root.sg.d2", the query 
result would be:
 
 | Time | Path         | Value |
@@ -620,7 +627,7 @@ For example, "select last s1, s2 from root.sg.d1, 
root.sg.d2", the query result
 |  4   | root.sg.d2.s1| 250   |
 |  9   | root.sg.d2.s2| 600   |
 
-3. It is not supported to use "diable align" in LAST query. 
+4. It is not supported to use "diable align" in LAST query. 
 
 ```
 
diff --git a/docs/zh/UserGuide/Operation Manual/DML Data Manipulation 
Language.md b/docs/zh/UserGuide/Operation Manual/DML Data Manipulation 
Language.md
index 0f8d4b7..fa2c6df 100644
--- a/docs/zh/UserGuide/Operation Manual/DML Data Manipulation Language.md      
+++ b/docs/zh/UserGuide/Operation Manual/DML Data Manipulation Language.md      
@@ -418,11 +418,13 @@ SELECT last_value(temperature) FROM root.ln.wf01.wt01 
GROUP BY([8, 39), 5m) FILL
 SQL语法:
 
 ```
-select last <Path> [COMMA <Path>]* from < PrefixPath > [COMMA < PrefixPath >]* 
<DISABLE ALIGN>
+select last <Path> [COMMA <Path>]* from < PrefixPath > [COMMA < PrefixPath >]* 
<WhereClause>
 ```
 
 其含义是:查询时间序列prefixPath.path中最近时间戳的数据
 
+\<WhereClause\>中当前只支持时间过滤条件,任何非时间过滤都将不会起任何作用。
+
 结果集为三列的结构
 
 ```
@@ -439,10 +441,10 @@ select last <Path> [COMMA <Path>]* from < PrefixPath > 
[COMMA < PrefixPath >]* <
 |  5   | root.ln.wf01.wt01.speed | 100   |
 ```
 
-示例 2:查询 root.ln.wf01.wt01 下 speed,status,temperature 的最新数据点
+示例 2:查询 root.ln.wf01.wt01 下 speed,status,temperature 的在时间区间[5, 10)之内的最新数据点
 
 ```
-> select last speed, status, temperature from root.ln.wf01
+> select last speed, status, temperature from root.ln.wf01  where time >= 5 
and time < 10
 
 | Time | Path                         | Value |
 | ---  | ---------------------------- | ----- |
diff --git a/docs/zh/UserGuide/Operation Manual/SQL Reference.md 
b/docs/zh/UserGuide/Operation Manual/SQL Reference.md
index 7af39a4..08afaaa 100644
--- a/docs/zh/UserGuide/Operation Manual/SQL Reference.md       
+++ b/docs/zh/UserGuide/Operation Manual/SQL Reference.md       
@@ -586,18 +586,23 @@ root.sg1.d0.s0 is INT32 while root.sg2.d3.s0 is FLOAT.
 Last 语句返回所要查询时间序列的最近时间戳的一条数据
 
 ```
-SELECT LAST <SelectClause> FROM <FromClause>
+SELECT LAST <SelectClause> FROM <FromClause> WHERE <WhereClause>
 Select Clause : <Path> [COMMA <Path>]*
 FromClause : < PrefixPath > [COMMA < PrefixPath >]*
+WhereClause : <TimeExpr> [(AND | OR) <TimeExpr>]*
+TimeExpr : TIME PrecedenceEqualOperator (<TimeValue> | <RelativeTime>)
 
 Eg. SELECT LAST s1 FROM root.sg.d1
 Eg. SELECT LAST s1, s2 FROM root.sg.d1
 Eg. SELECT LAST s1 FROM root.sg.d1, root.sg.d2
+Eg. SELECT LAST s1 FROM root.sg.d1 where time < 100
+Eg. SELECT LAST s1, s2 FROM root.sg.d1 where time > 100 and time <= 500
+Eg. SELECT LAST s1, s2 FROM root.sg.d1 where time < 300 or time > 1000
 
 规则:
 1. 需要满足PrefixPath.Path 为一条完整的时间序列,即 <PrefixPath> + <Path> = <Timeseries>
 
-2. SELECT LAST 语句不支持过滤条件.
+2. SELECT LAST 语句不支持值过滤条件.
 
 3. 结果集以三列的表格的固定形式返回。
 例如 "select last s1, s2 from root.sg.d1, root.sg.d2", 结果集返回如下:
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java 
b/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java
index 043742b..64ee0eb 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java
@@ -108,7 +108,7 @@ public class MTree implements Serializable {
     } else {
       try {
         last = calculateLastPairForOneSeriesLocally(node.getPartialPath(),
-            node.getSchema().getType(), queryContext, Collections.emptySet());
+            node.getSchema().getType(), queryContext, null, 
Collections.emptySet());
         return last.getTimestamp();
       } catch (Exception e) {
         logger.error("Something wrong happened while trying to get last time 
value pair of {}",
diff --git 
a/server/src/main/java/org/apache/iotdb/db/qp/physical/crud/LastQueryPlan.java 
b/server/src/main/java/org/apache/iotdb/db/qp/physical/crud/LastQueryPlan.java
index 5ab7dc5..7b3f7cb 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/qp/physical/crud/LastQueryPlan.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/qp/physical/crud/LastQueryPlan.java
@@ -20,6 +20,8 @@
 package org.apache.iotdb.db.qp.physical.crud;
 
 import org.apache.iotdb.db.qp.logical.Operator;
+import org.apache.iotdb.tsfile.read.expression.IExpression;
+import org.apache.iotdb.tsfile.read.expression.impl.GlobalTimeExpression;
 
 public class LastQueryPlan extends RawDataQueryPlan {
 
@@ -27,4 +29,10 @@ public class LastQueryPlan extends RawDataQueryPlan {
     super();
     setOperatorType(Operator.OperatorType.LAST);
   }
+
+  public void setExpression(IExpression expression) {
+    if (expression instanceof GlobalTimeExpression) {
+      super.setExpression(expression);
+    }
+  }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByFillDataSet.java
 
b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByFillDataSet.java
index ed8a0c9..4144b7b 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByFillDataSet.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByFillDataSet.java
@@ -100,7 +100,7 @@ public class GroupByFillDataSet extends QueryDataSet {
     for (int i = 0; i < paths.size(); i++) {
       TimeValuePair lastTimeValuePair;
       lastTimeValuePair = 
LastQueryExecutor.calculateLastPairForOneSeriesLocally(
-          (PartialPath) paths.get(i), dataTypes.get(i), context,
+          (PartialPath) paths.get(i), dataTypes.get(i), context, null,
           
groupByFillPlan.getAllMeasurementsInDevice(paths.get(i).getDevice()));
       if (lastTimeValuePair.getValue() != null) {
         lastTimeArray[i] = lastTimeValuePair.getTimestamp();
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/executor/LastQueryExecutor.java
 
b/server/src/main/java/org/apache/iotdb/db/query/executor/LastQueryExecutor.java
index 7799d7a..1231d08 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/executor/LastQueryExecutor.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/executor/LastQueryExecutor.java
@@ -29,7 +29,6 @@ import java.util.List;
 import java.util.Set;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.engine.querycontext.QueryDataSource;
-import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.exception.StorageEngineException;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
@@ -39,29 +38,30 @@ import org.apache.iotdb.db.qp.physical.crud.LastQueryPlan;
 import org.apache.iotdb.db.query.context.QueryContext;
 import org.apache.iotdb.db.query.control.QueryResourceManager;
 import org.apache.iotdb.db.query.dataset.ListDataSet;
+import org.apache.iotdb.db.query.executor.fill.LastPointReader;
 import org.apache.iotdb.db.service.IoTDB;
-import org.apache.iotdb.db.utils.FileLoaderUtils;
-import org.apache.iotdb.tsfile.file.metadata.ChunkMetadata;
-import org.apache.iotdb.tsfile.file.metadata.TimeseriesMetadata;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.file.metadata.statistics.Statistics;
 import org.apache.iotdb.tsfile.read.TimeValuePair;
 import org.apache.iotdb.tsfile.read.common.Field;
 import org.apache.iotdb.tsfile.read.common.RowRecord;
+import org.apache.iotdb.tsfile.read.expression.IExpression;
+import org.apache.iotdb.tsfile.read.expression.impl.GlobalTimeExpression;
+import org.apache.iotdb.tsfile.read.filter.basic.Filter;
 import org.apache.iotdb.tsfile.read.query.dataset.QueryDataSet;
 import org.apache.iotdb.tsfile.utils.Binary;
-import org.apache.iotdb.tsfile.utils.TsPrimitiveType;
 
 public class LastQueryExecutor {
 
   private List<PartialPath> selectedSeries;
   private List<TSDataType> dataTypes;
+  private IExpression expression;
   private static boolean lastCacheEnabled =
           IoTDBDescriptor.getInstance().getConfig().isLastCacheEnabled();
 
   public LastQueryExecutor(LastQueryPlan lastQueryPlan) {
     this.selectedSeries = lastQueryPlan.getDeduplicatedPaths();
     this.dataTypes = lastQueryPlan.getDeduplicatedDataTypes();
+    this.expression = lastQueryPlan.getExpression();
   }
 
   public LastQueryExecutor(List<PartialPath> selectedSeries, List<TSDataType> 
dataTypes) {
@@ -118,7 +118,7 @@ public class LastQueryExecutor {
       PartialPath seriesPath, TSDataType tsDataType, QueryContext context, 
Set<String> deviceMeasurements)
       throws IOException, QueryProcessException, StorageEngineException {
     return calculateLastPairForOneSeriesLocally(seriesPath, tsDataType, 
context,
-        deviceMeasurements);
+        expression, deviceMeasurements);
   }
 
   /**
@@ -127,103 +127,64 @@ public class LastQueryExecutor {
    * @param context query context
    * @return TimeValuePair
    */
-  @SuppressWarnings("squid:S3776") // Suppress high Cognitive Complexity 
warning
   public static TimeValuePair calculateLastPairForOneSeriesLocally(
-      PartialPath seriesPath, TSDataType tsDataType, QueryContext context, 
Set<String> deviceMeasurements)
+      PartialPath seriesPath, TSDataType tsDataType, QueryContext context,
+      IExpression expression, Set<String> deviceMeasurements)
       throws IOException, QueryProcessException, StorageEngineException {
 
     // Retrieve last value from MNode
     MeasurementMNode node = null;
+    Filter filter = null;
     if (lastCacheEnabled) {
+      if (expression != null) {
+        filter = ((GlobalTimeExpression) expression).getFilter();
+      }
       try {
         node = (MeasurementMNode) IoTDB.metaManager.getNodeByPath(seriesPath);
       } catch (MetadataException e) {
         TimeValuePair timeValuePair = 
IoTDB.metaManager.getLastCache(seriesPath);
-        if (timeValuePair != null) {
+        if (timeValuePair != null && satisfyFilter(filter, timeValuePair)) {
           return timeValuePair;
         }
       }
 
       if (node != null && node.getCachedLast() != null) {
-        return node.getCachedLast();
+        TimeValuePair timeValuePair =  node.getCachedLast();
+        if (timeValuePair != null && satisfyFilter(filter, timeValuePair)) {
+          return timeValuePair;
+        }
       }
     }
 
-    return calculateLastPairByScanningTsFiles(seriesPath, tsDataType, context, 
deviceMeasurements, node);
+    return calculateLastPairByScanningTsFiles(
+        seriesPath, tsDataType, context, filter, deviceMeasurements, node);
   }
 
   private static TimeValuePair calculateLastPairByScanningTsFiles(
-          PartialPath seriesPath, TSDataType tsDataType, QueryContext context, 
Set<String> deviceMeasurements,
-          MeasurementMNode node) throws QueryProcessException, 
StorageEngineException, IOException {
+          PartialPath seriesPath, TSDataType tsDataType, QueryContext context,
+          Filter filter, Set<String> deviceMeasurements, MeasurementMNode node)
+      throws QueryProcessException, StorageEngineException, IOException {
 
     QueryDataSource dataSource =
-        QueryResourceManager.getInstance().getQueryDataSource(seriesPath, 
context, null);
-
-    List<TsFileResource> seqFileResources = dataSource.getSeqResources();
-    List<TsFileResource> unseqFileResources = dataSource.getUnseqResources();
-
-    TimeValuePair resultPair = new TimeValuePair(Long.MIN_VALUE, null);
-
-    if (!seqFileResources.isEmpty()) {
-      for (int i = seqFileResources.size() - 1; i >= 0; i--) {
-        TimeseriesMetadata timeseriesMetadata = 
FileLoaderUtils.loadTimeSeriesMetadata(
-            seqFileResources.get(i), seriesPath, context, null, 
deviceMeasurements);
-        if (timeseriesMetadata != null) {
-          if (!timeseriesMetadata.isModified()) {
-            Statistics timeseriesMetadataStats = 
timeseriesMetadata.getStatistics();
-            resultPair = constructLastPair(
-                timeseriesMetadataStats.getEndTime(),
-                timeseriesMetadataStats.getLastValue(),
-                tsDataType);
-            break;
-          } else {
-            List<ChunkMetadata> chunkMetadataList = 
timeseriesMetadata.loadChunkMetadataList();
-            if (!chunkMetadataList.isEmpty()) {
-              ChunkMetadata lastChunkMetaData = 
chunkMetadataList.get(chunkMetadataList.size() - 1);
-              Statistics chunkStatistics = lastChunkMetaData.getStatistics();
-              resultPair =
-                  constructLastPair(
-                      chunkStatistics.getEndTime(), 
chunkStatistics.getLastValue(), tsDataType);
-              break;
-            }
-          }
-        }
-      }
-    }
+        QueryResourceManager.getInstance().getQueryDataSource(seriesPath, 
context, filter);
 
-    long version = 0;
-    for (TsFileResource resource : unseqFileResources) {
-      if (resource.getEndTime(seriesPath.getDevice()) < 
resultPair.getTimestamp()) {
-        continue;
-      }
-      TimeseriesMetadata timeseriesMetadata =
-          FileLoaderUtils
-              .loadTimeSeriesMetadata(resource, seriesPath, context, null, 
deviceMeasurements);
-      if (timeseriesMetadata != null) {
-        for (ChunkMetadata chunkMetaData : 
timeseriesMetadata.loadChunkMetadataList()) {
-          if (chunkMetaData.getEndTime() > resultPair.getTimestamp()
-              || (chunkMetaData.getEndTime() == resultPair.getTimestamp()
-              && chunkMetaData.getVersion() > version)) {
-            Statistics chunkStatistics = chunkMetaData.getStatistics();
-            resultPair =
-                constructLastPair(
-                    chunkStatistics.getEndTime(), 
chunkStatistics.getLastValue(), tsDataType);
-            version = chunkMetaData.getVersion();
-          }
-        }
-      }
-    }
+    LastPointReader lastReader = new LastPointReader(
+        seriesPath, tsDataType, deviceMeasurements, context, dataSource, 
Long.MAX_VALUE, filter);
+    TimeValuePair resultPair = lastReader.readLastPoint();
 
-    // Update cached last value with low priority
-    if (lastCacheEnabled) {
-      IoTDB.metaManager.updateLastCache(seriesPath,
-              resultPair, false, Long.MIN_VALUE, node);
+    // Update cached last value with low priority unless "FROM" expression 
exists
+    if (lastCacheEnabled && filter == null) {
+      IoTDB.metaManager.updateLastCache(
+          seriesPath, resultPair, false, Long.MIN_VALUE, node);
     }
     return resultPair;
   }
 
-  private static TimeValuePair constructLastPair(long timestamp, Object value,
-                                                 TSDataType dataType) {
-    return new TimeValuePair(timestamp, TsPrimitiveType.getByType(dataType, 
value));
+  private static boolean satisfyFilter(Filter filter, TimeValuePair tvPair) {
+    if (filter == null ||
+        filter.satisfy(tvPair.getTimestamp(), tvPair.getValue().getValue())) {
+      return true;
+    }
+    return false;
   }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/executor/fill/LastPointReader.java
 
b/server/src/main/java/org/apache/iotdb/db/query/executor/fill/LastPointReader.java
index 657a17d..2195467 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/query/executor/fill/LastPointReader.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/executor/fill/LastPointReader.java
@@ -216,6 +216,9 @@ public class LastPointReader {
   }
 
   private boolean endtimeContainedByTimeFilter(Statistics statistics) {
+    if (timeFilter == null) {
+      return true;
+    }
     return timeFilter.containStartEndTime(statistics.getEndTime(), 
statistics.getEndTime());
   }
 
diff --git 
a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBLastIT.java 
b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBLastIT.java
index 85c40c3..64f886e 100644
--- a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBLastIT.java
+++ b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBLastIT.java
@@ -446,6 +446,110 @@ public class IoTDBLastIT {
     }
   }
 
+  @Test
+  public void lastWithTimeFilterTest() throws SQLException, MetadataException {
+    String[] retArray =
+        new String[]{
+            "200,root.ln.wf01.wt01.temperature,25.2",
+            "500,root.ln.wf01.wt01.temperature,22.1",
+            "300,root.ln.wf01.wt01.temperature,15.7",
+        };
+
+    try (Connection connection =
+             DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", 
"root", "root");
+         Statement statement = connection.createStatement()) {
+
+      boolean hasResultSet = statement.execute(
+          "select last temperature from root.ln.wf01.wt01 where time < 300");
+
+      assertTrue(hasResultSet);
+      int cnt = 0;
+      try (ResultSet resultSet = statement.getResultSet()) {
+        while (resultSet.next()) {
+          String ans =
+              resultSet.getString(TIMESTAMP_STR) + ","
+                  + resultSet.getString(TIMESEIRES_STR) + ","
+                  + resultSet.getString(VALUE_STR);
+          Assert.assertEquals(retArray[cnt], ans);
+          cnt++;
+        }
+      }
+
+      statement.execute(
+          "select last temperature from root.ln.wf01.wt01 where time >= 300 
and time < 1000");
+      try (ResultSet resultSet = statement.getResultSet()) {
+        while (resultSet.next()) {
+          String ans =
+              resultSet.getString(TIMESTAMP_STR) + ","
+                  + resultSet.getString(TIMESEIRES_STR) + ","
+                  + resultSet.getString(VALUE_STR);
+          Assert.assertEquals(retArray[cnt], ans);
+          cnt++;
+        }
+      }
+
+      statement.execute(
+          "select last temperature from root.ln.wf01.wt01 where time <= 300 or 
time > 1000");
+      try (ResultSet resultSet = statement.getResultSet()) {
+        while (resultSet.next()) {
+          String ans =
+              resultSet.getString(TIMESTAMP_STR) + ","
+                  + resultSet.getString(TIMESEIRES_STR) + ","
+                  + resultSet.getString(VALUE_STR);
+          Assert.assertEquals(retArray[cnt], ans);
+          cnt++;
+        }
+      }
+      statement.execute(
+          "select last temperature from root.ln.wf01.wt01 where time > 1000");
+      try (ResultSet resultSet = statement.getResultSet()) {
+        Assert.assertFalse(resultSet.next());
+      }
+    }
+  }
+
+  @Test
+  public void lastCacheWithFilterTest() throws SQLException, MetadataException 
{
+    String[] retArray =
+        new String[]{
+            "500,root.ln.wf01.wt01.temperature,22.1",
+            "300,root.ln.wf01.wt01.temperature,15.7",
+        };
+
+    try (Connection connection =
+             DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", 
"root", "root");
+         Statement statement = connection.createStatement()) {
+
+      statement.execute("select last temperature from root.ln.wf01.wt01");
+      statement.execute(
+          "select last temperature from root.ln.wf01.wt01 where time >= 300 
and time < 1000");
+      int cnt = 0;
+      try (ResultSet resultSet = statement.getResultSet()) {
+        while (resultSet.next()) {
+          String ans =
+              resultSet.getString(TIMESTAMP_STR) + ","
+                  + resultSet.getString(TIMESEIRES_STR) + ","
+                  + resultSet.getString(VALUE_STR);
+          Assert.assertEquals(retArray[cnt], ans);
+          cnt++;
+        }
+      }
+
+      statement.execute(
+          "select last temperature from root.ln.wf01.wt01 where time <= 300");
+      try (ResultSet resultSet = statement.getResultSet()) {
+        while (resultSet.next()) {
+          String ans =
+              resultSet.getString(TIMESTAMP_STR) + ","
+                  + resultSet.getString(TIMESEIRES_STR) + ","
+                  + resultSet.getString(VALUE_STR);
+          Assert.assertEquals(retArray[cnt], ans);
+          cnt++;
+        }
+      }
+    }
+  }
+
   private void prepareData() {
     try (Connection connection = DriverManager
         .getConnection(Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root",

Reply via email to