Skip to content

Commit bb0f13b

Browse files
authored
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
1 parent 2d20fc8 commit bb0f13b

12 files changed

Lines changed: 337 additions & 64 deletions

File tree

external-service-impl/rest/src/main/java/org/apache/iotdb/rest/protocol/v2/impl/RestApiServiceImpl.java

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.apache.iotdb.db.queryengine.plan.statement.StatementType;
4141
import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowsStatement;
4242
import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertTabletStatement;
43+
import org.apache.iotdb.db.queryengine.plan.statement.crud.QueryStatement;
4344
import org.apache.iotdb.db.schemaengine.SchemaEngine;
4445
import org.apache.iotdb.db.schemaengine.schemaregion.ISchemaRegion;
4546
import org.apache.iotdb.db.utils.CommonUtils;
@@ -111,7 +112,7 @@ public RestApiServiceImpl() {
111112
public Response executeFastLastQueryStatement(
112113
PrefixPathList prefixPathList, SecurityContext securityContext) {
113114
Long queryId = null;
114-
Statement statement = null;
115+
QueryStatement statement = null;
115116
boolean finish = false;
116117
long startTime = System.nanoTime();
117118
Throwable t = null;
@@ -123,30 +124,33 @@ public Response executeFastLastQueryStatement(
123124
new PartialPath(prefixPathList.getPrefixPaths().toArray(new String[0]));
124125
final Map<TableId, Map<IDeviceID, Map<String, Pair<TSDataType, TimeValuePair>>>> resultMap =
125126
new HashMap<>();
126-
int sensorNum = 0;
127+
128+
// Check permission, the cost is rather low because the req only contains one prefix path
129+
final IClientSession clientSession = SESSION_MANAGER.getCurrSession();
130+
final TSLastDataQueryReq tsLastDataQueryReq =
131+
FastLastHandler.createTSLastDataQueryReq(clientSession, prefixPathList);
132+
statement = StatementGenerator.createStatement(tsLastDataQueryReq);
133+
134+
final Response response = authorizationHandler.checkAuthority(securityContext, statement);
135+
if (response != null) {
136+
return response;
137+
}
127138

128139
final String prefixString = prefixPath.toString();
129140
for (final ISchemaRegion region : SchemaEngine.getInstance().getAllSchemaRegions()) {
130141
if (!prefixString.startsWith(region.getDatabaseFullPath())
131142
&& !region.getDatabaseFullPath().startsWith(prefixString)) {
132143
continue;
133144
}
134-
sensorNum += region.fillLastQueryMap(prefixPath, resultMap);
145+
region.fillLastQueryMap(prefixPath, resultMap, statement.getAuthorityScope());
135146
}
147+
136148
// Check cache first
137149
if (!TableDeviceSchemaCache.getInstance().getLastCache(resultMap)) {
138-
IClientSession clientSession = SESSION_MANAGER.getCurrSession();
139-
TSLastDataQueryReq tsLastDataQueryReq =
140-
FastLastHandler.createTSLastDataQueryReq(clientSession, prefixPathList);
141-
statement = StatementGenerator.createStatement(tsLastDataQueryReq);
142-
143150
if (ExecuteStatementHandler.validateStatement(statement)) {
144151
return FastLastHandler.buildErrorResponse(TSStatusCode.EXECUTE_STATEMENT_ERROR);
145152
}
146153

147-
Optional.ofNullable(authorizationHandler.checkAuthority(securityContext, statement))
148-
.ifPresent(Response.class::cast);
149-
150154
queryId = SESSION_MANAGER.requestQueryId();
151155
SessionInfo sessionInfo = SESSION_MANAGER.getSessionInfo(clientSession);
152156

integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBRestServiceIT.java

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package org.apache.iotdb.db.it;
2020

2121
import org.apache.iotdb.commons.schema.column.ColumnHeaderConstant;
22+
import org.apache.iotdb.db.it.utils.TestUtils;
2223
import org.apache.iotdb.it.env.EnvFactory;
2324
import org.apache.iotdb.it.env.cluster.node.DataNodeWrapper;
2425
import org.apache.iotdb.it.framework.IoTDBTestRunner;
@@ -54,6 +55,7 @@
5455
import java.sql.Statement;
5556
import java.util.ArrayList;
5657
import java.util.Base64;
58+
import java.util.Collections;
5759
import java.util.List;
5860
import java.util.Map;
5961
import java.util.concurrent.TimeUnit;
@@ -476,6 +478,7 @@ public void insertAndQuery() {
476478
selectLast(httpClient);
477479

478480
queryV2(httpClient);
481+
selectFastLast(httpClient);
479482
queryGroupByLevelV2(httpClient);
480483
queryRowLimitV2(httpClient);
481484
queryShowChildPathsV2(httpClient);
@@ -886,6 +889,71 @@ public void queryWithWrongAuthorization() {
886889
}
887890
}
888891

892+
@Test
893+
public void queryFastLastWithWrongAuthorization() {
894+
CloseableHttpResponse response = null;
895+
896+
TestUtils.executeNonQuery("create user abcd 'strongPassword@1234'");
897+
try {
898+
final CloseableHttpClient httpClient = HttpClientBuilder.create().build();
899+
final HttpPost httpPost = new HttpPost("http://127.0.0.1:" + port + "/rest/v2/fastLastQuery");
900+
httpPost.addHeader("Content-type", "application/json; charset=utf-8");
901+
httpPost.setHeader("Accept", "application/json");
902+
final String authorization = getAuthorization("abcd", "strongPassword@1234");
903+
httpPost.setHeader("Authorization", authorization);
904+
final String sql = "{\"prefix_paths\":[\"root\",\"sg25\"]}";
905+
httpPost.setEntity(new StringEntity(sql, Charset.defaultCharset()));
906+
for (int i = 0; i < 30; i++) {
907+
try {
908+
response = httpClient.execute(httpPost);
909+
break;
910+
} catch (Exception e) {
911+
if (i == 29) {
912+
throw e;
913+
}
914+
try {
915+
Thread.sleep(1000);
916+
} catch (InterruptedException ex) {
917+
throw new RuntimeException(ex);
918+
}
919+
}
920+
}
921+
922+
Assert.assertEquals(200, response.getStatusLine().getStatusCode());
923+
String message = EntityUtils.toString(response.getEntity(), "utf-8");
924+
ObjectMapper mapper = new ObjectMapper();
925+
Map map = mapper.readValue(message, Map.class);
926+
List<Long> timestampsResult = (List<Long>) map.get("timestamps");
927+
List<Long> expressionsResult = (List<Long>) map.get("expressions");
928+
List<List<Object>> valuesResult = (List<List<Object>>) map.get("values");
929+
Assert.assertTrue(map.size() > 0);
930+
List<Object> expressions =
931+
new ArrayList<Object>() {
932+
{
933+
add("Timeseries");
934+
add("Value");
935+
add("DataType");
936+
}
937+
};
938+
939+
Assert.assertEquals(expressions, expressionsResult);
940+
Assert.assertEquals(Collections.emptyList(), timestampsResult);
941+
Assert.assertEquals(Collections.emptyList(), valuesResult);
942+
} catch (IOException e) {
943+
e.printStackTrace();
944+
fail(e.getMessage());
945+
} finally {
946+
try {
947+
if (response != null) {
948+
response.close();
949+
}
950+
} catch (IOException e) {
951+
e.printStackTrace();
952+
fail(e.getMessage());
953+
}
954+
}
955+
}
956+
889957
public void query(CloseableHttpClient httpClient) {
890958
CloseableHttpResponse response = null;
891959
try {
@@ -1651,6 +1719,98 @@ public void queryV2(CloseableHttpClient httpClient) {
16511719
}
16521720
}
16531721

1722+
public void selectFastLast(CloseableHttpClient httpClient) {
1723+
// Only used in 1D scenarios
1724+
if (EnvFactory.getEnv().getDataNodeWrapperList().size() > 1) {
1725+
return;
1726+
}
1727+
CloseableHttpResponse response = null;
1728+
try {
1729+
HttpPost httpPost = getHttpPost("http://127.0.0.1:" + port + "/rest/v2/fastLastQuery");
1730+
String sql = "{\"prefix_paths\":[\"root\",\"sg25\"]}";
1731+
httpPost.setEntity(new StringEntity(sql, Charset.defaultCharset()));
1732+
response = httpClient.execute(httpPost);
1733+
HttpEntity responseEntity = response.getEntity();
1734+
String message = EntityUtils.toString(responseEntity, "utf-8");
1735+
ObjectMapper mapper = new ObjectMapper();
1736+
Map map = mapper.readValue(message, Map.class);
1737+
List<Long> timestampsResult = (List<Long>) map.get("timestamps");
1738+
List<Long> expressionsResult = (List<Long>) map.get("expressions");
1739+
List<List<Object>> valuesResult = (List<List<Object>>) map.get("values");
1740+
Assert.assertTrue(map.size() > 0);
1741+
List<Object> expressions =
1742+
new ArrayList<Object>() {
1743+
{
1744+
add("Timeseries");
1745+
add("Value");
1746+
add("DataType");
1747+
}
1748+
};
1749+
List<Object> timestamps =
1750+
new ArrayList<Object>() {
1751+
{
1752+
add(1635232153960l);
1753+
add(1635232153960l);
1754+
add(1635232153960l);
1755+
add(1635232143960l);
1756+
add(1635232153960l);
1757+
add(1635232153960l);
1758+
}
1759+
};
1760+
List<Object> values1 =
1761+
new ArrayList<Object>() {
1762+
{
1763+
add("root.sg25.s3");
1764+
add("root.sg25.s4");
1765+
add("root.sg25.s5");
1766+
add("root.sg25.s6");
1767+
add("root.sg25.s7");
1768+
add("root.sg25.s8");
1769+
}
1770+
};
1771+
List<Object> values2 =
1772+
new ArrayList<Object>() {
1773+
{
1774+
add("");
1775+
add("2");
1776+
add("1635000012345556");
1777+
add("1.41");
1778+
add("false");
1779+
add("3.5555");
1780+
}
1781+
};
1782+
List<Object> values3 =
1783+
new ArrayList<Object>() {
1784+
{
1785+
add("TEXT");
1786+
add("INT32");
1787+
add("INT64");
1788+
add("FLOAT");
1789+
add("BOOLEAN");
1790+
add("DOUBLE");
1791+
}
1792+
};
1793+
1794+
Assert.assertEquals(expressions, expressionsResult);
1795+
Assert.assertEquals(timestamps, timestampsResult);
1796+
Assert.assertEquals(values1, valuesResult.get(0));
1797+
Assert.assertEquals(values2, valuesResult.get(1));
1798+
Assert.assertEquals(values3, valuesResult.get(2));
1799+
} catch (IOException e) {
1800+
e.printStackTrace();
1801+
fail(e.getMessage());
1802+
} finally {
1803+
try {
1804+
if (response != null) {
1805+
response.close();
1806+
}
1807+
} catch (IOException e) {
1808+
e.printStackTrace();
1809+
fail(e.getMessage());
1810+
}
1811+
}
1812+
}
1813+
16541814
public void queryGroupByLevelV2(CloseableHttpClient httpClient) {
16551815
CloseableHttpResponse response = null;
16561816
try {

integration-test/src/test/java/org/apache/iotdb/db/it/utils/TestUtils.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,8 +1451,9 @@ public static void assertResultSetEqual(
14511451
public static void assertResultSetEqual(
14521452
SessionDataSet actualResultSet,
14531453
List<String> expectedColumnNames,
1454-
Set<String> expectedRetArray,
1454+
Set<String> expectedRetSet,
14551455
boolean ignoreTimeStamp) {
1456+
final Set<String> copiedSet = new HashSet<>(expectedRetSet);
14561457
try {
14571458
List<String> actualColumnNames = actualResultSet.getColumnNames();
14581459
if (ignoreTimeStamp) {
@@ -1462,12 +1463,11 @@ public static void assertResultSetEqual(
14621463
assertEquals(expectedColumnNames, actualColumnNames.subList(1, actualColumnNames.size()));
14631464
}
14641465

1465-
int count = 0;
14661466
while (actualResultSet.hasNext()) {
14671467
RowRecord rowRecord = actualResultSet.next();
1468-
assertTrue(expectedRetArray.remove(rowRecord.toString().replace('\t', ',')));
1468+
assertTrue(copiedSet.remove(rowRecord.toString().replace('\t', ',')));
14691469
}
1470-
assertEquals(expectedRetArray.size(), count);
1470+
assertEquals(0, copiedSet.size());
14711471
} catch (IoTDBConnectionException | StatementExecutionException e) {
14721472
e.printStackTrace();
14731473
fail(e.getMessage());

integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionQueryIT.java

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@
2222
import org.apache.iotdb.common.rpc.thrift.TAggregationType;
2323
import org.apache.iotdb.commons.conf.IoTDBConstant;
2424
import org.apache.iotdb.db.it.utils.AlignedWriteUtil;
25+
import org.apache.iotdb.db.it.utils.TestUtils;
2526
import org.apache.iotdb.isession.ISession;
2627
import org.apache.iotdb.isession.SessionDataSet;
2728
import org.apache.iotdb.it.env.EnvFactory;
2829
import org.apache.iotdb.it.framework.IoTDBTestRunner;
2930
import org.apache.iotdb.itbase.category.ClusterIT;
3031
import org.apache.iotdb.itbase.category.LocalStandaloneIT;
3132
import org.apache.iotdb.rpc.IoTDBConnectionException;
33+
import org.apache.iotdb.rpc.RedirectException;
3234
import org.apache.iotdb.rpc.StatementExecutionException;
3335

3436
import org.junit.AfterClass;
@@ -249,6 +251,81 @@ public void lastQueryForOneDeviceNoSchema() throws IoTDBConnectionException {
249251
}
250252
}
251253

254+
@Test
255+
public void lastQueryWithPrefixTest() throws IoTDBConnectionException {
256+
// Only used in 1D scenarios
257+
if (EnvFactory.getEnv().getDataNodeWrapperList().size() > 1) {
258+
return;
259+
}
260+
final Set<String> retArray =
261+
new HashSet<>(
262+
Arrays.asList(
263+
"30,root.sg1.d1.s3,30,INT64",
264+
"30,root.sg1.d1.s4,false,BOOLEAN",
265+
"40,root.sg1.d1.s5,aligned_test40,TEXT",
266+
"23,root.sg1.d1.s1,230000.0,FLOAT",
267+
"40,root.sg1.d1.s2,40,INT32"));
268+
269+
try (final ISession session = EnvFactory.getEnv().getSessionConnection()) {
270+
// Push last cache first
271+
try (final SessionDataSet resultSet =
272+
session.executeFastLastDataQueryForOnePrefixPath(Arrays.asList("root", "sg1", "d1"))) {
273+
assertResultSetEqual(resultSet, lastQueryColumnNames, retArray, true);
274+
}
275+
276+
try (final SessionDataSet resultSet =
277+
session.executeFastLastDataQueryForOnePrefixPath(Arrays.asList("root", "sg1", "d1"))) {
278+
assertResultSetEqual(resultSet, lastQueryColumnNames, retArray, true);
279+
}
280+
} catch (StatementExecutionException | RedirectException e) {
281+
e.printStackTrace();
282+
fail(e.getMessage());
283+
}
284+
}
285+
286+
@Test
287+
public void lastQueryWithoutPermissionTest() throws IoTDBConnectionException {
288+
// Only used in 1D scenarios
289+
if (EnvFactory.getEnv().getDataNodeWrapperList().size() > 1) {
290+
return;
291+
}
292+
final String[] retArray = new String[] {};
293+
final Set<String> retArray2 =
294+
new HashSet<>(
295+
Arrays.asList(
296+
"30,root.sg1.d1.s3,30,INT64",
297+
"30,root.sg1.d1.s4,false,BOOLEAN",
298+
"40,root.sg1.d1.s5,aligned_test40,TEXT",
299+
"23,root.sg1.d1.s1,230000.0,FLOAT",
300+
"40,root.sg1.d1.s2,40,INT32"));
301+
TestUtils.executeNonQuery(EnvFactory.getEnv(), "create user abcd 'veryComplexPassword@123'");
302+
303+
try (final ISession session =
304+
EnvFactory.getEnv().getSessionConnection("abcd", "veryComplexPassword@123");
305+
final ISession rootSession = EnvFactory.getEnv().getSessionConnection()) {
306+
// Push last cache first
307+
try (final SessionDataSet resultSet =
308+
rootSession.executeFastLastDataQueryForOnePrefixPath(
309+
Arrays.asList("root", "sg1", "d1"))) {
310+
assertResultSetEqual(resultSet, lastQueryColumnNames, retArray2, true);
311+
}
312+
313+
try (final SessionDataSet resultSet =
314+
session.executeLastDataQueryForOneDevice(
315+
"root.sg1", "root.sg1.d1", Arrays.asList("notExist", "s1"), true)) {
316+
assertResultSetEqual(resultSet, lastQueryColumnNames, retArray, true);
317+
}
318+
319+
try (final SessionDataSet resultSet =
320+
session.executeFastLastDataQueryForOnePrefixPath(Arrays.asList("root", "sg1", "d1"))) {
321+
assertResultSetEqual(resultSet, lastQueryColumnNames, retArray, true);
322+
}
323+
} catch (StatementExecutionException | RedirectException e) {
324+
e.printStackTrace();
325+
fail(e.getMessage());
326+
}
327+
}
328+
252329
// ------------------------------ Aggregation Query ------------------------------
253330
@Test
254331
public void aggregationQueryTest() {

iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/RenameTableColumnProcedure.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,9 @@ private void rollbackRenameColumn(final ConfigNodeProcedureEnv env) {
180180
env.getConfigManager()
181181
.getClusterSchemaManager()
182182
.executePlan(
183-
new RenameTableColumnPlan(database, tableName, newName, oldName),
183+
this instanceof RenameViewColumnProcedure
184+
? new RenameViewColumnPlan(database, tableName, newName, oldName)
185+
: new RenameTableColumnPlan(database, tableName, newName, oldName),
184186
isGeneratedByPipe);
185187
if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
186188
setFailure(new ProcedureException(new IoTDBException(status)));

0 commit comments

Comments
 (0)