[To dev/1.3] Enhance the last query permission && Fixed the rollback version of alter view / table plans && Deleted the unnecessary mods in Tree view deletion (#17465) (#17494)

* [To dev/1.3] Enhance the last query permission && Fixed the rollback version of alter view / table plans && Deleted the unnecessary mods in Tree view deletion (#17465)

* dele

* shop

* f
diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBRestServiceIT.java b/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBRestServiceIT.java
index ad1b93a..6151327 100644
--- a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBRestServiceIT.java
+++ b/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBRestServiceIT.java
@@ -18,6 +18,7 @@
  */
 package org.apache.iotdb.db.it;
 
+import org.apache.iotdb.db.it.utils.TestUtils;
 import org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant;
 import org.apache.iotdb.it.env.EnvFactory;
 import org.apache.iotdb.it.env.cluster.env.SimpleEnv;
@@ -57,6 +58,7 @@
 import java.sql.Statement;
 import java.util.ArrayList;
 import java.util.Base64;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
@@ -513,6 +515,7 @@
     selectLast(httpClient);
 
     queryV2(httpClient);
+    selectFastLast(httpClient);
     queryGroupByLevelV2(httpClient);
     queryRowLimitV2(httpClient);
     queryShowChildPathsV2(httpClient);
@@ -923,6 +926,71 @@
     }
   }
 
+  @Test
+  public void queryFastLastWithWrongAuthorization() {
+    CloseableHttpResponse response = null;
+
+    TestUtils.executeNonQuery("create user abcd 'strongPassword@1234'");
+    try {
+      final CloseableHttpClient httpClient = HttpClientBuilder.create().build();
+      final HttpPost httpPost = new HttpPost("http://127.0.0.1:" + port + "/rest/v2/fastLastQuery");
+      httpPost.addHeader("Content-type", "application/json; charset=utf-8");
+      httpPost.setHeader("Accept", "application/json");
+      final String authorization = getAuthorization("abcd", "strongPassword@1234");
+      httpPost.setHeader("Authorization", authorization);
+      final String sql = "{\"prefix_paths\":[\"root\",\"sg25\"]}";
+      httpPost.setEntity(new StringEntity(sql, Charset.defaultCharset()));
+      for (int i = 0; i < 30; i++) {
+        try {
+          response = httpClient.execute(httpPost);
+          break;
+        } catch (Exception e) {
+          if (i == 29) {
+            throw e;
+          }
+          try {
+            Thread.sleep(1000);
+          } catch (InterruptedException ex) {
+            throw new RuntimeException(ex);
+          }
+        }
+      }
+
+      Assert.assertEquals(200, response.getStatusLine().getStatusCode());
+      String message = EntityUtils.toString(response.getEntity(), "utf-8");
+      ObjectMapper mapper = new ObjectMapper();
+      Map map = mapper.readValue(message, Map.class);
+      List<Long> timestampsResult = (List<Long>) map.get("timestamps");
+      List<Long> expressionsResult = (List<Long>) map.get("expressions");
+      List<List<Object>> valuesResult = (List<List<Object>>) map.get("values");
+      Assert.assertTrue(map.size() > 0);
+      List<Object> expressions =
+          new ArrayList<Object>() {
+            {
+              add("Timeseries");
+              add("Value");
+              add("DataType");
+            }
+          };
+
+      Assert.assertEquals(expressions, expressionsResult);
+      Assert.assertEquals(Collections.emptyList(), timestampsResult);
+      Assert.assertEquals(Collections.emptyList(), valuesResult);
+    } catch (IOException e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    } finally {
+      try {
+        if (response != null) {
+          response.close();
+        }
+      } catch (IOException e) {
+        e.printStackTrace();
+        fail(e.getMessage());
+      }
+    }
+  }
+
   public void query(CloseableHttpClient httpClient) {
     CloseableHttpResponse response = null;
     try {
@@ -1677,6 +1745,98 @@
     }
   }
 
+  public void selectFastLast(CloseableHttpClient httpClient) {
+    // Only used in 1D scenarios
+    if (EnvFactory.getEnv().getDataNodeWrapperList().size() > 1) {
+      return;
+    }
+    CloseableHttpResponse response = null;
+    try {
+      HttpPost httpPost = getHttpPost("http://127.0.0.1:" + port + "/rest/v2/fastLastQuery");
+      String sql = "{\"prefix_paths\":[\"root\",\"sg25\"]}";
+      httpPost.setEntity(new StringEntity(sql, Charset.defaultCharset()));
+      response = httpClient.execute(httpPost);
+      HttpEntity responseEntity = response.getEntity();
+      String message = EntityUtils.toString(responseEntity, "utf-8");
+      ObjectMapper mapper = new ObjectMapper();
+      Map map = mapper.readValue(message, Map.class);
+      List<Long> timestampsResult = (List<Long>) map.get("timestamps");
+      List<Long> expressionsResult = (List<Long>) map.get("expressions");
+      List<List<Object>> valuesResult = (List<List<Object>>) map.get("values");
+      Assert.assertTrue(map.size() > 0);
+      List<Object> expressions =
+          new ArrayList<Object>() {
+            {
+              add("Timeseries");
+              add("Value");
+              add("DataType");
+            }
+          };
+      List<Object> timestamps =
+          new ArrayList<Object>() {
+            {
+              add(1635232153960l);
+              add(1635232153960l);
+              add(1635232153960l);
+              add(1635232143960l);
+              add(1635232153960l);
+              add(1635232153960l);
+            }
+          };
+      List<Object> values1 =
+          new ArrayList<Object>() {
+            {
+              add("root.sg25.s3");
+              add("root.sg25.s4");
+              add("root.sg25.s5");
+              add("root.sg25.s6");
+              add("root.sg25.s7");
+              add("root.sg25.s8");
+            }
+          };
+      List<Object> values2 =
+          new ArrayList<Object>() {
+            {
+              add("");
+              add("2");
+              add("1635000012345556");
+              add("1.41");
+              add("false");
+              add("3.5555");
+            }
+          };
+      List<Object> values3 =
+          new ArrayList<Object>() {
+            {
+              add("TEXT");
+              add("INT32");
+              add("INT64");
+              add("FLOAT");
+              add("BOOLEAN");
+              add("DOUBLE");
+            }
+          };
+
+      Assert.assertEquals(expressions, expressionsResult);
+      Assert.assertEquals(timestamps, timestampsResult);
+      Assert.assertEquals(values1, valuesResult.get(0));
+      Assert.assertEquals(values2, valuesResult.get(1));
+      Assert.assertEquals(values3, valuesResult.get(2));
+    } catch (IOException e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    } finally {
+      try {
+        if (response != null) {
+          response.close();
+        }
+      } catch (IOException e) {
+        e.printStackTrace();
+        fail(e.getMessage());
+      }
+    }
+  }
+
   public void queryGroupByLevelV2(CloseableHttpClient httpClient) {
     CloseableHttpResponse response = null;
     try {
diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java b/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java
index abf5936..f45209c 100644
--- a/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java
+++ b/integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java
@@ -684,6 +684,32 @@
     }
   }
 
+  public static void assertResultSetEqual(
+      SessionDataSet actualResultSet,
+      List<String> expectedColumnNames,
+      Set<String> expectedRetSet,
+      boolean ignoreTimeStamp) {
+    final Set<String> copiedSet = new HashSet<>(expectedRetSet);
+    try {
+      List<String> actualColumnNames = actualResultSet.getColumnNames();
+      if (ignoreTimeStamp) {
+        assertEquals(expectedColumnNames, actualColumnNames);
+      } else {
+        assertEquals(TIMESTAMP_STR, actualColumnNames.get(0));
+        assertEquals(expectedColumnNames, actualColumnNames.subList(1, actualColumnNames.size()));
+      }
+
+      while (actualResultSet.hasNext()) {
+        RowRecord rowRecord = actualResultSet.next();
+        assertTrue(copiedSet.remove(rowRecord.toString().replace('\t', ',')));
+      }
+      assertEquals(0, copiedSet.size());
+    } catch (IoTDBConnectionException | StatementExecutionException e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+  }
+
   public static void createUser(String userName, String password) {
     createUser(EnvFactory.getEnv(), userName, password);
   }
diff --git a/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionQueryIT.java b/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionQueryIT.java
index ba5c22a..7ade934 100644
--- a/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionQueryIT.java
+++ b/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionQueryIT.java
@@ -22,6 +22,7 @@
 import org.apache.iotdb.common.rpc.thrift.TAggregationType;
 import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.db.it.utils.AlignedWriteUtil;
+import org.apache.iotdb.db.it.utils.TestUtils;
 import org.apache.iotdb.isession.ISession;
 import org.apache.iotdb.isession.SessionDataSet;
 import org.apache.iotdb.it.env.EnvFactory;
@@ -29,6 +30,7 @@
 import org.apache.iotdb.itbase.category.ClusterIT;
 import org.apache.iotdb.itbase.category.LocalStandaloneIT;
 import org.apache.iotdb.rpc.IoTDBConnectionException;
+import org.apache.iotdb.rpc.RedirectException;
 import org.apache.iotdb.rpc.StatementExecutionException;
 
 import org.junit.AfterClass;
@@ -40,7 +42,9 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import static org.apache.iotdb.db.it.utils.TestUtils.assertResultSetEqual;
 import static org.junit.Assert.fail;
@@ -244,6 +248,81 @@
     }
   }
 
+  @Test
+  public void lastQueryWithPrefixTest() throws IoTDBConnectionException {
+    // Only used in 1D scenarios
+    if (EnvFactory.getEnv().getDataNodeWrapperList().size() > 1) {
+      return;
+    }
+    final Set<String> retArray =
+        new HashSet<>(
+            Arrays.asList(
+                "30,root.sg1.d1.s3,30,INT64",
+                "30,root.sg1.d1.s4,false,BOOLEAN",
+                "40,root.sg1.d1.s5,aligned_test40,TEXT",
+                "23,root.sg1.d1.s1,230000.0,FLOAT",
+                "40,root.sg1.d1.s2,40,INT32"));
+
+    try (final ISession session = EnvFactory.getEnv().getSessionConnection()) {
+      // Push last cache first
+      try (final SessionDataSet resultSet =
+          session.executeFastLastDataQueryForOnePrefixPath(Arrays.asList("root", "sg1", "d1"))) {
+        assertResultSetEqual(resultSet, lastQueryColumnNames, retArray, true);
+      }
+
+      try (final SessionDataSet resultSet =
+          session.executeFastLastDataQueryForOnePrefixPath(Arrays.asList("root", "sg1", "d1"))) {
+        assertResultSetEqual(resultSet, lastQueryColumnNames, retArray, true);
+      }
+    } catch (StatementExecutionException | RedirectException e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+  }
+
+  @Test
+  public void lastQueryWithoutPermissionTest() throws IoTDBConnectionException {
+    // Only used in 1D scenarios
+    if (EnvFactory.getEnv().getDataNodeWrapperList().size() > 1) {
+      return;
+    }
+    final String[] retArray = new String[] {};
+    final Set<String> retArray2 =
+        new HashSet<>(
+            Arrays.asList(
+                "30,root.sg1.d1.s3,30,INT64",
+                "30,root.sg1.d1.s4,false,BOOLEAN",
+                "40,root.sg1.d1.s5,aligned_test40,TEXT",
+                "23,root.sg1.d1.s1,230000.0,FLOAT",
+                "40,root.sg1.d1.s2,40,INT32"));
+    TestUtils.executeNonQuery("create user abcd 'veryComplexPassword@123'");
+
+    try (final ISession session =
+            EnvFactory.getEnv().getSessionConnection("abcd", "veryComplexPassword@123");
+        final ISession rootSession = EnvFactory.getEnv().getSessionConnection()) {
+      // Push last cache first
+      try (final SessionDataSet resultSet =
+          rootSession.executeFastLastDataQueryForOnePrefixPath(
+              Arrays.asList("root", "sg1", "d1"))) {
+        assertResultSetEqual(resultSet, lastQueryColumnNames, retArray2, true);
+      }
+
+      try (final SessionDataSet resultSet =
+          session.executeLastDataQueryForOneDevice(
+              "root.sg1", "root.sg1.d1", Arrays.asList("notExist", "s1"), true)) {
+        assertResultSetEqual(resultSet, lastQueryColumnNames, retArray, true);
+      }
+
+      try (final SessionDataSet resultSet =
+          session.executeFastLastDataQueryForOnePrefixPath(Arrays.asList("root", "sg1", "d1"))) {
+        assertResultSetEqual(resultSet, lastQueryColumnNames, retArray, true);
+      }
+    } catch (StatementExecutionException | RedirectException e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+  }
+
   // ------------------------------ Aggregation Query ------------------------------
   @Test
   public void aggregationQueryTest() {
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/impl/RestApiServiceImpl.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/impl/RestApiServiceImpl.java
index 05fc4b8..0030980 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/impl/RestApiServiceImpl.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/v2/impl/RestApiServiceImpl.java
@@ -55,6 +55,7 @@
 import org.apache.iotdb.db.queryengine.plan.statement.Statement;
 import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowsStatement;
 import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertTabletStatement;
+import org.apache.iotdb.db.queryengine.plan.statement.crud.QueryStatement;
 import org.apache.iotdb.db.schemaengine.SchemaEngine;
 import org.apache.iotdb.db.schemaengine.schemaregion.ISchemaRegion;
 import org.apache.iotdb.db.utils.CommonUtils;
@@ -102,7 +103,7 @@
   public Response executeFastLastQueryStatement(
       PrefixPathList prefixPathList, SecurityContext securityContext) {
     Long queryId = null;
-    Statement statement = null;
+    QueryStatement statement = null;
     boolean finish = false;
     long startTime = System.nanoTime();
 
@@ -113,28 +114,31 @@
           new PartialPath(prefixPathList.getPrefixPaths().toArray(new String[0]));
       final Map<PartialPath, Map<String, TimeValuePair>> resultMap = new HashMap<>();
 
+      // Check permission, the cost is rather low because the req only contains one prefix path
+      final IClientSession clientSession = SESSION_MANAGER.getCurrSession();
+      final TSLastDataQueryReq tsLastDataQueryReq =
+          FastLastHandler.createTSLastDataQueryReq(clientSession, prefixPathList);
+      statement = StatementGenerator.createStatement(tsLastDataQueryReq);
+
+      final Response response = authorizationHandler.checkAuthority(securityContext, statement);
+      if (response != null) {
+        return response;
+      }
+
       final String prefixString = prefixPath.toString();
       for (ISchemaRegion region : SchemaEngine.getInstance().getAllSchemaRegions()) {
         if (!prefixString.startsWith(region.getDatabaseFullPath())
             && !region.getDatabaseFullPath().startsWith(prefixString)) {
           continue;
         }
-        region.fillLastQueryMap(prefixPath, resultMap);
+        region.fillLastQueryMap(prefixPath, resultMap, statement.getAuthorityScope());
       }
       // Check cache first
       if (!DataNodeSchemaCache.getInstance().getDeviceSchemaCache().getLastCache(resultMap)) {
-        IClientSession clientSession = SESSION_MANAGER.getCurrSessionAndUpdateIdleTime();
-        TSLastDataQueryReq tsLastDataQueryReq =
-            FastLastHandler.createTSLastDataQueryReq(clientSession, prefixPathList);
-        statement = StatementGenerator.createStatement(tsLastDataQueryReq);
-
         if (ExecuteStatementHandler.validateStatement(statement)) {
           return FastLastHandler.buildErrorResponse(TSStatusCode.EXECUTE_STATEMENT_ERROR);
         }
 
-        Optional.ofNullable(authorizationHandler.checkAuthority(securityContext, statement))
-            .ifPresent(Response.class::cast);
-
         queryId = SESSION_MANAGER.requestQueryId();
         SessionInfo sessionInfo = SESSION_MANAGER.getSessionInfo(clientSession);
 
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
index 8a498fc..2ae50d3 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
@@ -37,6 +37,7 @@
 import org.apache.iotdb.commons.path.AlignedPath;
 import org.apache.iotdb.commons.path.MeasurementPath;
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathPatternTree;
 import org.apache.iotdb.commons.utils.PathUtils;
 import org.apache.iotdb.db.audit.AuditLogger;
 import org.apache.iotdb.db.auth.AuthorityChecker;
@@ -87,6 +88,7 @@
 import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowsOfOneDeviceStatement;
 import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowsStatement;
 import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertTabletStatement;
+import org.apache.iotdb.db.queryengine.plan.statement.crud.QueryStatement;
 import org.apache.iotdb.db.queryengine.plan.statement.metadata.CreateAlignedTimeSeriesStatement;
 import org.apache.iotdb.db.queryengine.plan.statement.metadata.CreateMultiTimeSeriesStatement;
 import org.apache.iotdb.db.queryengine.plan.statement.metadata.CreateTimeSeriesStatement;
@@ -819,7 +821,7 @@
 
     try {
       final long queryId = SESSION_MANAGER.requestQueryId(clientSession, req.statementId);
-      // 1. Map<Device, String[] measurements> ISchemaFetcher.getAllSensors(prefix) ~= 50ms
+      // 1.1 Map<Device, String[] measurements> ISchemaFetcher.getAllSensors(prefix) ~= 50ms
 
       final PartialPath prefixPath = new PartialPath(req.getPrefixes().toArray(new String[0]));
       if (prefixPath.hasWildcard()) {
@@ -832,13 +834,20 @@
       final Map<PartialPath, Map<String, TimeValuePair>> resultMap = new HashMap<>();
       int sensorNum = 0;
 
+      // 1.2 Check permission, the cost is rather low because the req only contains one prefix path
+      final QueryStatement s = StatementGenerator.createStatement(convert(req));
+      final TSStatus status = AuthorityChecker.checkAuthority(s, clientSession);
+      if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+        return RpcUtils.getTSExecuteStatementResp(status);
+      }
+
       final String prefixString = prefixPath.toString();
       for (final ISchemaRegion region : SchemaEngine.getInstance().getAllSchemaRegions()) {
         if (!prefixString.startsWith(region.getDatabaseFullPath())
             && !region.getDatabaseFullPath().startsWith(prefixString)) {
           continue;
         }
-        sensorNum += region.fillLastQueryMap(prefixPath, resultMap);
+        sensorNum += region.fillLastQueryMap(prefixPath, resultMap, s.getAuthorityScope());
       }
 
       // 2.DATA_NODE_SCHEMA_CACHE.getLastCache()
@@ -914,6 +923,13 @@
     long startTime = System.nanoTime();
     Throwable t = null;
     try {
+      // Place the permission check first
+      final QueryStatement s = StatementGenerator.createStatement(convert(req));
+      final TSStatus status = AuthorityChecker.checkAuthority(s, clientSession);
+      if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+        return RpcUtils.getTSExecuteStatementResp(status);
+      }
+
       String db;
       String deviceId;
       PartialPath devicePath;
@@ -969,9 +985,11 @@
                     regionReplicaSet ->
                         isSameNode(
                             regionReplicaSet.dataNodeLocations.get(0).mPPDataExchangeEndPoint));
-        int sensorNum = req.sensors.size();
-        TsBlockBuilder builder = LastQueryUtil.createTsBlockBuilder(sensorNum);
+        final int sensorNum = req.sensors.size();
+        final TsBlockBuilder builder = LastQueryUtil.createTsBlockBuilder(sensorNum);
         boolean allCached = true;
+
+        PathPatternTree queryTree = new PathPatternTree();
         for (String sensor : req.sensors) {
           PartialPath fullPath;
           if (req.isLegalPathNodes()) {
@@ -979,24 +997,32 @@
           } else {
             fullPath = devicePath.concatNode((new PartialPath(sensor)).getFullPath());
           }
-          TimeValuePair timeValuePair = DATA_NODE_SCHEMA_CACHE.getLastCache(fullPath);
-          if (timeValuePair == null) {
-            allCached = false;
-            break;
-          } else if (timeValuePair.getValue() == null) {
-            // there is no data for this sensor
-            if (!canUseNullEntry) {
+          queryTree.appendPathPattern(fullPath);
+        }
+        queryTree.constructTree();
+        queryTree = s.getAuthorityScope().intersectWithFullPathPrefixTree(queryTree);
+
+        if (!queryTree.isEmpty()) {
+          for (final MeasurementPath fullPath : queryTree.getAllPathPatterns(true)) {
+            TimeValuePair timeValuePair = DATA_NODE_SCHEMA_CACHE.getLastCache(fullPath);
+            if (timeValuePair == null) {
               allCached = false;
               break;
+            } else if (timeValuePair.getValue() == null) {
+              // there is no data for this sensor
+              if (!canUseNullEntry) {
+                allCached = false;
+                break;
+              }
+            } else {
+              // we don't consider TTL
+              LastQueryUtil.appendLastValue(
+                  builder,
+                  timeValuePair.getTimestamp(),
+                  new Binary(fullPath.getFullPath(), TSFileConfig.STRING_CHARSET),
+                  timeValuePair.getValue().getStringValue(),
+                  timeValuePair.getValue().getDataType().name());
             }
-          } else {
-            // we don't consider TTL
-            LastQueryUtil.appendLastValue(
-                builder,
-                timeValuePair.getTimestamp(),
-                new Binary(fullPath.getFullPath(), TSFileConfig.STRING_CHARSET),
-                timeValuePair.getValue().getStringValue(),
-                timeValuePair.getValue().getDataType().name());
           }
         }
         // cache hit
@@ -1016,14 +1042,6 @@
         }
       }
 
-      // cache miss
-      Statement s = StatementGenerator.createStatement(convert(req));
-      // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(s, clientSession);
-      if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
-        return RpcUtils.getTSExecuteStatementResp(status);
-      }
-
       quota =
           DataNodeThrottleQuotaManager.getInstance()
               .checkQuota(SESSION_MANAGER.getCurrSession().getUsername(), s);
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/StatementGenerator.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/StatementGenerator.java
index b220309..9f149ab 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/StatementGenerator.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/StatementGenerator.java
@@ -170,7 +170,7 @@
     return queryStatement;
   }
 
-  public static Statement createStatement(TSLastDataQueryReq lastDataQueryReq)
+  public static QueryStatement createStatement(TSLastDataQueryReq lastDataQueryReq)
       throws IllegalPathException {
     final long startTime = System.nanoTime();
     // construct query statement
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/ISchemaRegion.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/ISchemaRegion.java
index df69657..7248fe2 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/ISchemaRegion.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/ISchemaRegion.java
@@ -317,7 +317,9 @@
       throws MetadataException;
 
   int fillLastQueryMap(
-      final PartialPath pattern, final Map<PartialPath, Map<String, TimeValuePair>> mapToFill)
+      final PartialPath pattern,
+      final Map<PartialPath, Map<String, TimeValuePair>> mapToFill,
+      final PathPatternTree scope)
       throws MetadataException;
 
   // endregion
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionMemoryImpl.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionMemoryImpl.java
index 7f8074c..6fc556a 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionMemoryImpl.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionMemoryImpl.java
@@ -1335,9 +1335,11 @@
 
   @Override
   public int fillLastQueryMap(
-      final PartialPath pattern, final Map<PartialPath, Map<String, TimeValuePair>> mapToFill)
+      final PartialPath pattern,
+      final Map<PartialPath, Map<String, TimeValuePair>> mapToFill,
+      final PathPatternTree scope)
       throws MetadataException {
-    return mtree.fillLastQueryMap(pattern, mapToFill);
+    return mtree.fillLastQueryMap(pattern, mapToFill, scope);
   }
 
   @Override
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionPBTreeImpl.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionPBTreeImpl.java
index fd8d7c5..73bbce2 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionPBTreeImpl.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionPBTreeImpl.java
@@ -1440,7 +1440,9 @@
 
   @Override
   public int fillLastQueryMap(
-      final PartialPath pattern, final Map<PartialPath, Map<String, TimeValuePair>> mapToFill) {
+      final PartialPath pattern,
+      final Map<PartialPath, Map<String, TimeValuePair>> mapToFill,
+      final PathPatternTree scope) {
     throw new UnsupportedOperationException("Not implemented");
   }
 
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/MTreeBelowSGMemoryImpl.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/MTreeBelowSGMemoryImpl.java
index 63d1e4c..b6f1221 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/MTreeBelowSGMemoryImpl.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/MTreeBelowSGMemoryImpl.java
@@ -1085,12 +1085,13 @@
   }
 
   public int fillLastQueryMap(
-      final PartialPath prefixPath, final Map<PartialPath, Map<String, TimeValuePair>> mapToFill)
+      final PartialPath prefixPath,
+      final Map<PartialPath, Map<String, TimeValuePair>> mapToFill,
+      final PathPatternTree scope)
       throws MetadataException {
     final int[] sensorNum = {0};
     try (final EntityUpdater<IMemMNode> updater =
-        new EntityUpdater<IMemMNode>(
-            rootNode, prefixPath, store, true, SchemaConstant.ALL_MATCH_SCOPE) {
+        new EntityUpdater<IMemMNode>(rootNode, prefixPath, store, true, scope) {
 
           @Override
           protected void updateEntity(final IDeviceMNode<IMemMNode> node) {
diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/PathPatternTree.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/PathPatternTree.java
index 3b40a3b..53014d0 100644
--- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/PathPatternTree.java
+++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/PathPatternTree.java
@@ -37,6 +37,7 @@
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 public class PathPatternTree {
 
@@ -94,7 +95,6 @@
     appendBranchWithoutPrune(root, pathNodes, 0);
   }
 
-  /** Add a pathPattern (may contain wildcards) to pathPatternList. */
   public void appendPathPattern(PartialPath pathPattern) {
     if (useWildcard) {
       boolean isExist = false;
@@ -120,7 +120,8 @@
     for (PartialPath path : pathPatternList) {
       appendBranchWithoutPrune(root, path.getNodes(), 0);
     }
-    pathPatternList.clear();
+    // Do not clear to avoid concurrent modification
+    pathPatternList = new LinkedList<>();
   }
 
   private void appendBranchWithoutPrune(
@@ -245,16 +246,24 @@
   public List<PartialPath> getAllPathPatterns() {
     List<PartialPath> result = new ArrayList<>();
     Deque<String> ancestors = new ArrayDeque<>();
-    searchPathPattern(root, ancestors, result);
+    searchPathPattern(root, ancestors, result, false);
     return result;
   }
 
-  private void searchPathPattern(
+  public List<MeasurementPath> getAllPathPatterns(boolean asMeasurementPath) {
+    List<MeasurementPath> result = new ArrayList<>();
+    Deque<String> ancestors = new ArrayDeque<>();
+    searchPathPattern(root, ancestors, result, asMeasurementPath);
+    return result;
+  }
+
+  private <T extends PartialPath> void searchPathPattern(
       PathPatternNode<Void, VoidSerializer> node,
       Deque<String> ancestors,
-      List<PartialPath> fullPaths) {
+      List<T> fullPaths,
+      boolean asMeasurementPath) {
     if (node.isPathPattern()) {
-      fullPaths.add(convertNodesToPartialPath(node, ancestors));
+      fullPaths.add((T) convertNodesToPartialPath(node, ancestors, asMeasurementPath));
       if (node.isLeaf()) {
         return;
       }
@@ -262,23 +271,19 @@
 
     ancestors.push(node.getName());
     for (PathPatternNode<Void, VoidSerializer> child : node.getChildren().values()) {
-      searchPathPattern(child, ancestors, fullPaths);
+      searchPathPattern(child, ancestors, fullPaths, asMeasurementPath);
     }
     ancestors.pop();
   }
 
-  public List<PartialPath> getOverlappedPathPatterns(PartialPath pattern) {
-    if (pathPatternList.isEmpty()) {
-      pathPatternList = getAllPathPatterns();
+  public List<PartialPath> getOverlappedPathPatterns(final PartialPath pattern) {
+    List<PartialPath> patternList = pathPatternList;
+    if (Objects.isNull(patternList) || patternList.isEmpty()) {
+      patternList = getAllPathPatterns();
+      pathPatternList = patternList;
     }
 
-    List<PartialPath> results = new ArrayList<>();
-    for (PartialPath path : pathPatternList) {
-      if (pattern.overlapWith(path)) {
-        results.add(path);
-      }
-    }
-    return results;
+    return patternList.stream().filter(pattern::overlapWith).collect(Collectors.toList());
   }
 
   private String convertNodesToString(List<String> nodes) {
@@ -290,14 +295,20 @@
   }
 
   private PartialPath convertNodesToPartialPath(
-      PathPatternNode<Void, VoidSerializer> node, Deque<String> ancestors) {
+      PathPatternNode<Void, VoidSerializer> node,
+      Deque<String> ancestors,
+      boolean asMeasurementPath) {
     Iterator<String> iterator = ancestors.descendingIterator();
     List<String> nodeList = new ArrayList<>(ancestors.size() + 1);
     while (iterator.hasNext()) {
       nodeList.add(iterator.next());
     }
     nodeList.add(node.getName());
-    return new PartialPath(nodeList.toArray(new String[0]));
+    if (asMeasurementPath) {
+      return new MeasurementPath(nodeList.toArray(new String[0]));
+    } else {
+      return new PartialPath(nodeList.toArray(new String[0]));
+    }
   }
 
   public boolean isOverlapWith(PathPatternTree patternTree) {