This is an automated email from the ASF dual-hosted git repository.
jiangtian 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 bb0f13b78bb Enhance the last query permission && Fixed the rollback
version of alter view / table plans && Deleted the unnecessary mods in Tree
view deletion (#17465)
bb0f13b78bb is described below
commit bb0f13b78bb8651eb6f67881efbbcfb516f0a649
Author: Caideyipi <[email protected]>
AuthorDate: Wed Apr 15 17:14:26 2026 +0800
Enhance the last query permission && Fixed the rollback version of alter
view / table plans && Deleted the unnecessary mods in Tree view deletion
(#17465)
* fix
* fix
* fix
* fix
* IT1
* change
* right-1
* fixation
* fix
* partial
* 13
* limit
* fix
* fix
* mod
* remove-usls
* fix
* fix
* fix
---
.../rest/protocol/v2/impl/RestApiServiceImpl.java | 26 ++--
.../org/apache/iotdb/db/it/IoTDBRestServiceIT.java | 160 +++++++++++++++++++++
.../org/apache/iotdb/db/it/utils/TestUtils.java | 8 +-
.../iotdb/session/it/IoTDBSessionQueryIT.java | 77 ++++++++++
.../schema/table/RenameTableColumnProcedure.java | 4 +-
.../schema/table/SetTablePropertiesProcedure.java | 4 +-
.../protocol/thrift/impl/ClientRPCServiceImpl.java | 101 ++++++++-----
.../plan/parser/StatementGenerator.java | 2 +-
.../schemaengine/schemaregion/ISchemaRegion.java | 3 +-
.../schemaregion/impl/SchemaRegionMemoryImpl.java | 5 +-
.../schemaregion/impl/SchemaRegionPBTreeImpl.java | 5 +-
.../mtree/impl/mem/MTreeBelowSGMemoryImpl.java | 6 +-
12 files changed, 337 insertions(+), 64 deletions(-)
diff --git
a/external-service-impl/rest/src/main/java/org/apache/iotdb/rest/protocol/v2/impl/RestApiServiceImpl.java
b/external-service-impl/rest/src/main/java/org/apache/iotdb/rest/protocol/v2/impl/RestApiServiceImpl.java
index f6c42533a62..e05929c6a63 100644
---
a/external-service-impl/rest/src/main/java/org/apache/iotdb/rest/protocol/v2/impl/RestApiServiceImpl.java
+++
b/external-service-impl/rest/src/main/java/org/apache/iotdb/rest/protocol/v2/impl/RestApiServiceImpl.java
@@ -40,6 +40,7 @@ import
org.apache.iotdb.db.queryengine.plan.statement.Statement;
import org.apache.iotdb.db.queryengine.plan.statement.StatementType;
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;
@@ -111,7 +112,7 @@ public class RestApiServiceImpl extends RestApiService {
public Response executeFastLastQueryStatement(
PrefixPathList prefixPathList, SecurityContext securityContext) {
Long queryId = null;
- Statement statement = null;
+ QueryStatement statement = null;
boolean finish = false;
long startTime = System.nanoTime();
Throwable t = null;
@@ -123,7 +124,17 @@ public class RestApiServiceImpl extends RestApiService {
new PartialPath(prefixPathList.getPrefixPaths().toArray(new
String[0]));
final Map<TableId, Map<IDeviceID, Map<String, Pair<TSDataType,
TimeValuePair>>>> resultMap =
new HashMap<>();
- int sensorNum = 0;
+
+ // 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 (final ISchemaRegion region :
SchemaEngine.getInstance().getAllSchemaRegions()) {
@@ -131,22 +142,15 @@ public class RestApiServiceImpl extends RestApiService {
&& !region.getDatabaseFullPath().startsWith(prefixString)) {
continue;
}
- sensorNum += region.fillLastQueryMap(prefixPath, resultMap);
+ region.fillLastQueryMap(prefixPath, resultMap,
statement.getAuthorityScope());
}
+
// Check cache first
if (!TableDeviceSchemaCache.getInstance().getLastCache(resultMap)) {
- IClientSession clientSession = SESSION_MANAGER.getCurrSession();
- 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/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 76a246149cd..eb2573c7f84 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
@@ -19,6 +19,7 @@
package org.apache.iotdb.db.it;
import org.apache.iotdb.commons.schema.column.ColumnHeaderConstant;
+import org.apache.iotdb.db.it.utils.TestUtils;
import org.apache.iotdb.it.env.EnvFactory;
import org.apache.iotdb.it.env.cluster.node.DataNodeWrapper;
import org.apache.iotdb.it.framework.IoTDBTestRunner;
@@ -54,6 +55,7 @@ import java.sql.SQLException;
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;
@@ -476,6 +478,7 @@ public class IoTDBRestServiceIT {
selectLast(httpClient);
queryV2(httpClient);
+ selectFastLast(httpClient);
queryGroupByLevelV2(httpClient);
queryRowLimitV2(httpClient);
queryShowChildPathsV2(httpClient);
@@ -886,6 +889,71 @@ public class IoTDBRestServiceIT {
}
}
+ @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 {
@@ -1651,6 +1719,98 @@ public class IoTDBRestServiceIT {
}
}
+ 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 43a11647c37..9c2a09024c4 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
@@ -1451,8 +1451,9 @@ public class TestUtils {
public static void assertResultSetEqual(
SessionDataSet actualResultSet,
List<String> expectedColumnNames,
- Set<String> expectedRetArray,
+ Set<String> expectedRetSet,
boolean ignoreTimeStamp) {
+ final Set<String> copiedSet = new HashSet<>(expectedRetSet);
try {
List<String> actualColumnNames = actualResultSet.getColumnNames();
if (ignoreTimeStamp) {
@@ -1462,12 +1463,11 @@ public class TestUtils {
assertEquals(expectedColumnNames, actualColumnNames.subList(1,
actualColumnNames.size()));
}
- int count = 0;
while (actualResultSet.hasNext()) {
RowRecord rowRecord = actualResultSet.next();
- assertTrue(expectedRetArray.remove(rowRecord.toString().replace('\t',
',')));
+ assertTrue(copiedSet.remove(rowRecord.toString().replace('\t', ',')));
}
- assertEquals(expectedRetArray.size(), count);
+ assertEquals(0, copiedSet.size());
} catch (IoTDBConnectionException | StatementExecutionException e) {
e.printStackTrace();
fail(e.getMessage());
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 8bd6833ec08..f65f2b4496f 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 @@ package org.apache.iotdb.session.it;
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.it.framework.IoTDBTestRunner;
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;
@@ -249,6 +251,81 @@ public class IoTDBSessionQueryIT {
}
}
+ @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(EnvFactory.getEnv(), "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/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/RenameTableColumnProcedure.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/RenameTableColumnProcedure.java
index da51dad2672..a2a6c72577c 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/RenameTableColumnProcedure.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/RenameTableColumnProcedure.java
@@ -180,7 +180,9 @@ public class RenameTableColumnProcedure
env.getConfigManager()
.getClusterSchemaManager()
.executePlan(
- new RenameTableColumnPlan(database, tableName, newName,
oldName),
+ this instanceof RenameViewColumnProcedure
+ ? new RenameViewColumnPlan(database, tableName, newName,
oldName)
+ : new RenameTableColumnPlan(database, tableName, newName,
oldName),
isGeneratedByPipe);
if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
setFailure(new ProcedureException(new IoTDBException(status)));
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/SetTablePropertiesProcedure.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/SetTablePropertiesProcedure.java
index eedbf7fdb3d..138ae9c9b50 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/SetTablePropertiesProcedure.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/SetTablePropertiesProcedure.java
@@ -203,7 +203,9 @@ public class SetTablePropertiesProcedure
env.getConfigManager()
.getClusterSchemaManager()
.executePlan(
- new SetTablePropertiesPlan(database, tableName,
originalProperties),
+ this instanceof SetViewPropertiesProcedure
+ ? new SetViewPropertiesPlan(database, tableName,
originalProperties)
+ : new SetTablePropertiesPlan(database, tableName,
originalProperties),
isGeneratedByPipe);
if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
setFailure(new ProcedureException(new IoTDBException(status)));
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 ed754c418c6..06b60117c5f 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
@@ -42,6 +42,7 @@ import org.apache.iotdb.commons.path.IFullPath;
import org.apache.iotdb.commons.path.MeasurementPath;
import org.apache.iotdb.commons.path.NonAlignedFullPath;
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.DNAuditLogger;
import org.apache.iotdb.db.auth.AuthorityChecker;
@@ -113,6 +114,7 @@ import
org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowStatement;
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;
@@ -1170,7 +1172,7 @@ public class ClientRPCServiceImpl implements
IClientRPCServiceWithHandler {
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()) {
@@ -1184,13 +1186,26 @@ public class ClientRPCServiceImpl implements
IClientRPCServiceWithHandler {
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,
+ new TreeAccessCheckContext(
+ clientSession.getUserId(),
+ clientSession.getUsername(),
+ clientSession.getClientAddress()));
+ 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()
@@ -1286,6 +1301,20 @@ public class ClientRPCServiceImpl implements
IClientRPCServiceWithHandler {
long startTime = System.nanoTime();
Throwable t = null;
try {
+ // Place the permission check first
+ final QueryStatement s =
StatementGenerator.createStatement(convert(req));
+ // permission check
+ final TSStatus status =
+ AuthorityChecker.checkAuthority(
+ s,
+ new TreeAccessCheckContext(
+ clientSession.getUserId(),
+ clientSession.getUsername(),
+ clientSession.getClientAddress()));
+ if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+ return RpcUtils.getTSExecuteStatementResp(status);
+ }
+
String db;
String device;
PartialPath devicePath;
@@ -1315,7 +1344,7 @@ public class ClientRPCServiceImpl implements
IClientRPCServiceWithHandler {
// no valid DataRegion
if (regionReplicaSets.isEmpty()
|| regionReplicaSets.size() == 1 && NOT_ASSIGNED ==
regionReplicaSets.get(0)) {
- TSExecuteStatementResp resp =
+ final TSExecuteStatementResp resp =
createResponse(DatasetHeaderFactory.getLastQueryHeader(), queryId);
resp.setStatus(RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS, ""));
resp.setQueryResult(Collections.emptyList());
@@ -1325,7 +1354,7 @@ public class ClientRPCServiceImpl implements
IClientRPCServiceWithHandler {
return resp;
}
- TEndPoint lastRegionLeader =
+ final TEndPoint lastRegionLeader =
regionReplicaSets
.get(regionReplicaSets.size() - 1)
.dataNodeLocations
@@ -1336,41 +1365,51 @@ public class ClientRPCServiceImpl implements
IClientRPCServiceWithHandler {
// read directly from cache
if (isSameNode(lastRegionLeader)) {
// the device's all dataRegions' leader are on current node, can use
null entry in cache
- boolean canUseNullEntry =
+ final boolean canUseNullEntry =
regionReplicaSets.stream()
.limit(regionReplicaSets.size() - 1L)
.allMatch(
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;
- for (String sensor : req.sensors) {
- MeasurementPath fullPath;
+
+ PathPatternTree queryTree = new PathPatternTree();
+ for (final String sensor : req.sensors) {
+ final MeasurementPath fullPath;
if (req.isLegalPathNodes()) {
fullPath = devicePath.concatAsMeasurementPath(sensor);
} else {
fullPath = devicePath.concatAsMeasurementPath((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)) {
+ final 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.appendLastValueRespectBlob(
+ builder,
+ timeValuePair.getTimestamp(),
+ new Binary(fullPath.getFullPath(),
TSFileConfig.STRING_CHARSET),
+ timeValuePair.getValue(),
+ timeValuePair.getValue().getDataType().name());
}
- } else {
- // we don't consider TTL
- LastQueryUtil.appendLastValueRespectBlob(
- builder,
- timeValuePair.getTimestamp(),
- new Binary(fullPath.getFullPath(),
TSFileConfig.STRING_CHARSET),
- timeValuePair.getValue(),
- timeValuePair.getValue().getDataType().name());
}
}
// cache hit
@@ -1390,20 +1429,6 @@ public class ClientRPCServiceImpl implements
IClientRPCServiceWithHandler {
}
}
- // cache miss
- Statement s = StatementGenerator.createStatement(convert(req));
- // permission check
- TSStatus status =
- AuthorityChecker.checkAuthority(
- s,
- new TreeAccessCheckContext(
- clientSession.getUserId(),
- clientSession.getUsername(),
- clientSession.getClientAddress()));
- 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 4fc5e50a060..901196d0e1b 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
@@ -176,7 +176,7 @@ public class StatementGenerator {
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 4a11165353c..8d87435e108 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
@@ -359,7 +359,8 @@ public interface ISchemaRegion {
int fillLastQueryMap(
final PartialPath pattern,
- final Map<TableId, Map<IDeviceID, Map<String, Pair<TSDataType,
TimeValuePair>>>> mapToFill)
+ final Map<TableId, Map<IDeviceID, Map<String, Pair<TSDataType,
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 c5c3b7f57b8..2e200cf8e8c 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
@@ -1461,9 +1461,10 @@ public class SchemaRegionMemoryImpl implements
ISchemaRegion {
@Override
public int fillLastQueryMap(
final PartialPath pattern,
- final Map<TableId, Map<IDeviceID, Map<String, Pair<TSDataType,
TimeValuePair>>>> mapToFill)
+ final Map<TableId, Map<IDeviceID, Map<String, Pair<TSDataType,
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 2f4bec896dd..19517f90601 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
@@ -1517,8 +1517,9 @@ public class SchemaRegionPBTreeImpl implements
ISchemaRegion {
@Override
public int fillLastQueryMap(
- PartialPath pattern,
- Map<TableId, Map<IDeviceID, Map<String, Pair<TSDataType,
TimeValuePair>>>> mapToFill) {
+ final PartialPath pattern,
+ final Map<TableId, Map<IDeviceID, Map<String, Pair<TSDataType,
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 ed519030b63..d872a1130a4 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
@@ -1299,12 +1299,12 @@ public class MTreeBelowSGMemoryImpl {
public int fillLastQueryMap(
final PartialPath prefixPath,
- final Map<TableId, Map<IDeviceID, Map<String, Pair<TSDataType,
TimeValuePair>>>> mapToFill)
+ final Map<TableId, Map<IDeviceID, Map<String, Pair<TSDataType,
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) {