This is an automated email from the ASF dual-hosted git repository.
shuwenwei pushed a commit to branch fixFetchDeviceNotInCache
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/fixFetchDeviceNotInCache by
this push:
new 4210205ff42 add it
4210205ff42 is described below
commit 4210205ff42d506616c15b87464ecba45fcd71b3
Author: shuwenwei <[email protected]>
AuthorDate: Mon Jul 14 17:17:02 2025 +0800
add it
---
.../IoTDBTableViewQueryWithCachedDeviceIT.java | 144 +++++++++++++++++++++
.../relational/DeviceIteratorScanOperator.java | 3 +-
.../metadata/fetcher/TableDeviceSchemaFetcher.java | 41 +++---
.../relational/sql/ast/AbstractTraverseDevice.java | 1 +
4 files changed, 172 insertions(+), 17 deletions(-)
diff --git
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/view/recent/IoTDBTableViewQueryWithCachedDeviceIT.java
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/view/recent/IoTDBTableViewQueryWithCachedDeviceIT.java
new file mode 100644
index 00000000000..32835598cd2
--- /dev/null
+++
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/view/recent/IoTDBTableViewQueryWithCachedDeviceIT.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.relational.it.query.view.recent;
+
+import org.apache.iotdb.commons.cluster.NodeStatus;
+import org.apache.iotdb.isession.ISession;
+import org.apache.iotdb.isession.ITableSession;
+import org.apache.iotdb.isession.SessionDataSet;
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.env.cluster.node.DataNodeWrapper;
+import org.apache.iotdb.rpc.IoTDBConnectionException;
+import org.apache.iotdb.rpc.StatementExecutionException;
+import org.apache.iotdb.session.Session;
+import org.apache.iotdb.session.TableSessionBuilder;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Collections;
+
+import static org.apache.iotdb.db.it.utils.TestUtils.prepareData;
+import static org.apache.iotdb.db.it.utils.TestUtils.prepareTableData;
+
+public class IoTDBTableViewQueryWithCachedDeviceIT {
+
+ protected static final String DATABASE_NAME = "test";
+
+ protected static String[] createTreeNonAlignedDataSqls = {
+ "CREATE TIMESERIES root.db.battery.b1.voltage INT32",
+ "CREATE TIMESERIES root.db.battery.b1.current FLOAT",
+ "INSERT INTO root.db.battery.b1(time, voltage, current) values (1, 1, 1)",
+ "CREATE TIMESERIES root.db.battery.b2.voltage INT32",
+ "CREATE TIMESERIES root.db.battery.b2.current FLOAT",
+ "INSERT INTO root.db.battery.b2(time, voltage, current) values (1, 2, 2)",
+ "CREATE TIMESERIES root.db.battery.b3.voltage INT32",
+ "CREATE TIMESERIES root.db.battery.b3.current FLOAT",
+ "INSERT INTO root.db.battery.b3(time, voltage, current) values (1, 3, 3)",
+ "CREATE TIMESERIES root.db.battery.b4.voltage INT32",
+ "CREATE TIMESERIES root.db.battery.b4.current FLOAT",
+ "INSERT INTO root.db.battery.b4(time, voltage, current) values (1, 4, 4)",
+ "FLUSH",
+ };
+
+ protected static String[] createTableSqls = {
+ "CREATE DATABASE " + DATABASE_NAME,
+ "USE " + DATABASE_NAME,
+ "CREATE VIEW view1 (battery TAG, voltage INT32 FIELD, current FLOAT FIELD)
as root.db.battery.**",
+ };
+
+ public static void main(String[] args)
+ throws IoTDBConnectionException, StatementExecutionException {
+ try (ISession session = new Session.Builder().build()) {
+ session.open();
+ for (String sql : createTreeNonAlignedDataSqls) {
+ session.executeNonQueryStatement(sql);
+ }
+ }
+ try (ITableSession session = new TableSessionBuilder().build()) {
+ for (String createTableSql : createTableSqls) {
+ session.executeNonQueryStatement(createTableSql);
+ }
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ EnvFactory.getEnv().getConfig().getCommonConfig().setSortBufferSize(128 *
1024);
+
EnvFactory.getEnv().getConfig().getCommonConfig().setMaxTsBlockSizeInByte(4 *
1024);
+ EnvFactory.getEnv().initClusterEnvironment();
+ prepareData(createTreeNonAlignedDataSqls);
+ prepareTableData(createTableSqls);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ EnvFactory.getEnv().cleanClusterEnvironment();
+ }
+
+ @Test
+ public void test1() throws IoTDBConnectionException,
StatementExecutionException {
+ int count1 = 0;
+ int count2 = 0;
+ try (ITableSession session =
EnvFactory.getEnv().getTableSessionConnection()) {
+ session.executeNonQueryStatement("use " + DATABASE_NAME);
+ SessionDataSet sessionDataSet =
+ session.executeQueryStatement(
+ "select * from view1 where battery = 'b1' or battery = 'b2' or
battery = 'b3'");
+ while (sessionDataSet.hasNext()) {
+ sessionDataSet.next();
+ count1++;
+ }
+ }
+ EnvFactory.getEnv().shutdownAllDataNodes();
+ for (DataNodeWrapper dataNodeWrapper :
EnvFactory.getEnv().getDataNodeWrapperList()) {
+ EnvFactory.getEnv()
+ .ensureNodeStatus(
+ Collections.singletonList(dataNodeWrapper),
+ Collections.singletonList(NodeStatus.Unknown));
+ }
+ EnvFactory.getEnv().startAllDataNodes();
+ for (DataNodeWrapper dataNodeWrapper :
EnvFactory.getEnv().getDataNodeWrapperList()) {
+ EnvFactory.getEnv()
+ .ensureNodeStatus(
+ Collections.singletonList(dataNodeWrapper),
+ Collections.singletonList(NodeStatus.Running));
+ }
+
+ try (ISession session = EnvFactory.getEnv().getSessionConnection()) {
+ session.executeNonQueryStatement(
+ "INSERT INTO root.db.battery.b3(time, voltage, current) aligned
values (2, 1, 1)");
+ }
+
+ try (ITableSession session =
EnvFactory.getEnv().getTableSessionConnection()) {
+ session.executeNonQueryStatement("use " + DATABASE_NAME);
+ SessionDataSet sessionDataSet =
+ session.executeQueryStatement(
+ "select * from view1 where (battery = 'b1' or battery = 'b2' or
battery = 'b3') and time = 1");
+ while (sessionDataSet.hasNext()) {
+ sessionDataSet.next();
+ count2++;
+ }
+ }
+ Assert.assertEquals(count1, count2);
+ }
+}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/DeviceIteratorScanOperator.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/DeviceIteratorScanOperator.java
index 1689fd2fd84..f088e448fd7 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/DeviceIteratorScanOperator.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/DeviceIteratorScanOperator.java
@@ -34,7 +34,6 @@ import org.apache.tsfile.utils.RamUsageEstimator;
import org.apache.tsfile.write.schema.IMeasurementSchema;
import java.util.List;
-import java.util.NoSuchElementException;
import java.util.Set;
public class DeviceIteratorScanOperator extends AbstractDataSourceOperator {
@@ -134,7 +133,7 @@ public class DeviceIteratorScanOperator extends
AbstractDataSourceOperator {
@Override
public TsBlock next() throws Exception {
if (!hasNext()) {
- throw new NoSuchElementException();
+ return null;
}
if (!currentDeviceInit) {
return null;
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableDeviceSchemaFetcher.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableDeviceSchemaFetcher.java
index a89c94ea61e..d5672db3e31 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableDeviceSchemaFetcher.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableDeviceSchemaFetcher.java
@@ -205,6 +205,7 @@ public class TableDeviceSchemaFetcher {
attributeColumns,
queryContext,
mayContainDuplicateDevice,
+ false,
false)) {
fetchMissingDeviceSchemaForQuery(
database, tableInstance, attributeColumns, statement,
deviceEntryMap, queryContext);
@@ -232,7 +233,8 @@ public class TableDeviceSchemaFetcher {
final List<String> attributeColumns,
final MPPQueryContext queryContext,
final AtomicBoolean mayContainDuplicateDevice,
- final boolean isDirectDeviceQuery) {
+ final boolean isDirectDeviceQuery,
+ final boolean fetchAllIfSomeDeviceNotInCache) {
final Pair<List<Expression>, List<Expression>> separatedExpression =
SchemaPredicateUtil.separateTagDeterminedPredicate(
expressionList, tableInstance, queryContext, isDirectDeviceQuery);
@@ -307,25 +309,34 @@ public class TableDeviceSchemaFetcher {
index2FilterMapList.size()
- tagSingleMatchIndexList.size()
+ tagSingleMatchPredicateNotInCache.size());
- int idx1 = 0;
- int idx2 = 0;
- for (int i = 0; i < index2FilterMapList.size(); i++) {
- if (idx1 >= tagSingleMatchIndexList.size() || i !=
tagSingleMatchIndexList.get(idx1)) {
- tagPredicateForFetch.add(
- index2FilterMapList.get(i).values().stream()
- .flatMap(Collection::stream)
- .collect(Collectors.toList()));
- } else {
- idx1++;
- if (idx2 < tagSingleMatchPredicateNotInCache.size()
- && i == tagSingleMatchPredicateNotInCache.get(idx2)) {
+ if (!fetchAllIfSomeDeviceNotInCache) {
+ int idx1 = 0;
+ int idx2 = 0;
+ for (int i = 0; i < index2FilterMapList.size(); i++) {
+ if (idx1 >= tagSingleMatchIndexList.size() || i !=
tagSingleMatchIndexList.get(idx1)) {
tagPredicateForFetch.add(
index2FilterMapList.get(i).values().stream()
.flatMap(Collection::stream)
.collect(Collectors.toList()));
- idx2++;
+ } else {
+ idx1++;
+ if (idx2 < tagSingleMatchPredicateNotInCache.size()
+ && i == tagSingleMatchPredicateNotInCache.get(idx2)) {
+ tagPredicateForFetch.add(
+ index2FilterMapList.get(i).values().stream()
+ .flatMap(Collection::stream)
+ .collect(Collectors.toList()));
+ idx2++;
+ }
}
}
+ } else {
+ for (Map<Integer, List<SchemaFilter>> integerListMap :
index2FilterMapList) {
+ tagPredicateForFetch.add(
+ integerListMap.values().stream()
+ .flatMap(Collection::stream)
+ .collect(Collectors.toList()));
+ }
}
statement.setTagDeterminedFilterList(tagPredicateForFetch);
statement.setTagFuzzyPredicate(compactedTagFuzzyPredicate);
@@ -562,7 +573,7 @@ public class TableDeviceSchemaFetcher {
deviceEntryList.add(deviceEntry);
// Only cache those exact device query
// Fetch paths is null iff there are fuzzy queries related to id columns
- if (Objects.nonNull(statement.getPartitionKeyList())) {
+ if (false && Objects.nonNull(statement.getPartitionKeyList())) {
cache.putAttributes(statement.getDatabase(), deviceID, attributeMap);
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractTraverseDevice.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractTraverseDevice.java
index 2493418b671..7714fee3487 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractTraverseDevice.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractTraverseDevice.java
@@ -149,6 +149,7 @@ public abstract class AbstractTraverseDevice extends
Statement {
attributeColumns,
context,
new AtomicBoolean(false),
+ true,
true);
}