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

zyk 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 e66c4e502b Support schema cache when querying all measurement of 
devices using template (#9871)
e66c4e502b is described below

commit e66c4e502bef58090a51d938d4c159264eedacbf
Author: Marcos_Zyk <[email protected]>
AuthorDate: Thu May 18 09:04:48 2023 +0800

    Support schema cache when querying all measurement of devices using 
template (#9871)
---
 .../org/apache/iotdb/commons/path/PartialPath.java | 47 ++++++++++++++-----
 .../apache/iotdb/commons/path/PathPatternNode.java |  2 +-
 .../apache/iotdb/commons/path/PathPatternUtil.java | 52 ++++++++++++++++++++++
 .../iotdb/commons/path/fa/nfa/SimpleNFA.java       |  3 +-
 .../memtable/AlignedWritableMemChunkGroup.java     | 10 ++---
 .../db/engine/memtable/WritableMemChunkGroup.java  | 10 ++---
 .../db/metadata/cache/DataNodeSchemaCache.java     |  4 ++
 .../cache/DeviceUsingTemplateSchemaCache.java      | 32 +++++++++++++
 .../metadata/template/ClusterTemplateManager.java  |  4 +-
 .../analyze/schema/ClusterSchemaFetchExecutor.java |  2 +-
 .../plan/analyze/schema/ClusterSchemaFetcher.java  | 50 ++++++++++++++-------
 11 files changed, 176 insertions(+), 40 deletions(-)

diff --git 
a/node-commons/src/main/java/org/apache/iotdb/commons/path/PartialPath.java 
b/node-commons/src/main/java/org/apache/iotdb/commons/path/PartialPath.java
index a266b1f79e..45868472a6 100644
--- a/node-commons/src/main/java/org/apache/iotdb/commons/path/PartialPath.java
+++ b/node-commons/src/main/java/org/apache/iotdb/commons/path/PartialPath.java
@@ -40,7 +40,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 import static 
org.apache.iotdb.commons.conf.IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD;
@@ -107,13 +106,28 @@ public class PartialPath extends Path implements 
Comparable<Path>, Cloneable {
 
   public boolean hasWildcard() {
     for (String node : nodes) {
-      if (ONE_LEVEL_PATH_WILDCARD.equals(node) || 
MULTI_LEVEL_PATH_WILDCARD.equals(node)) {
+      // *, ** , d*, *d*
+      if (PathPatternUtil.hasWildcard(node)) {
         return true;
       }
     }
     return false;
   }
 
+  // e.g. root.db.d.s, root.db.d.*, root.db.d.s*, not include patterns like 
root.db.d.**
+  public boolean hasExplicitDevice() {
+    if (nodes[nodes.length - 1].equals(MULTI_LEVEL_PATH_WILDCARD)) {
+      return false;
+    }
+    for (int i = 0; i < nodes.length - 1; i++) {
+      // *, ** , d*, *d*
+      if (PathPatternUtil.hasWildcard(nodes[i])) {
+        return false;
+      }
+    }
+    return true;
+  }
+
   /**
    * it will return a new partial path
    *
@@ -325,8 +339,8 @@ public class PartialPath extends Path implements 
Comparable<Path>, Cloneable {
     if (patternNode.equals(MULTI_LEVEL_PATH_WILDCARD)) {
       isMatch = matchPath(pathNodes, pathIndex + 1, patternIndex + 1, true, 
pathIsPrefix);
     } else {
-      if (patternNode.contains(ONE_LEVEL_PATH_WILDCARD)) {
-        if (Pattern.matches(patternNode.replace("*", ".*"), pathNode)) {
+      if (PathPatternUtil.hasWildcard(patternNode)) {
+        if (PathPatternUtil.isNodeMatch(patternNode, pathNode)) {
           isMatch = matchPath(pathNodes, pathIndex + 1, patternIndex + 1, 
false, pathIsPrefix);
         }
       } else {
@@ -363,6 +377,13 @@ public class PartialPath extends Path implements 
Comparable<Path>, Cloneable {
       if (nodes[i].equals(ONE_LEVEL_PATH_WILDCARD)) {
         continue;
       }
+      if (PathPatternUtil.hasWildcard(nodes[i])) {
+        if (PathPatternUtil.isNodeMatch(nodes[i], rNodes[i])) {
+          continue;
+        } else {
+          return false;
+        }
+      }
       if (!nodes[i].equals(rNodes[i])) {
         return false;
       }
@@ -417,7 +438,8 @@ public class PartialPath extends Path implements 
Comparable<Path>, Cloneable {
         } else {
           // if without MULTI_LEVEL_PATH_WILDCARD, scan and check
           if (!rNodes[j - 1].equals(MULTI_LEVEL_PATH_WILDCARD)
-              && (lNodes[i - 1].equals(ONE_LEVEL_PATH_WILDCARD)
+              && ((PathPatternUtil.hasWildcard(lNodes[i - 1])
+                      && PathPatternUtil.isNodeMatch(lNodes[i - 1], rNodes[j - 
1]))
                   || lNodes[i - 1].equals(rNodes[j - 1]))) {
             // if nodes1[i-1] includes rNodes[j-1], dp[i][j] = dp[i-1][j-1]
             newDp[j] |= dp[j - 1];
@@ -447,7 +469,10 @@ public class PartialPath extends Path implements 
Comparable<Path>, Cloneable {
         return checkOverlapWithMultiLevelWildcard(nodes, rNodes);
       }
       // if without MULTI_LEVEL_PATH_WILDCARD, scan and check
-      if (nodes[i].equals(ONE_LEVEL_PATH_WILDCARD) || 
rNodes[i].equals(ONE_LEVEL_PATH_WILDCARD)) {
+      if ((PathPatternUtil.hasWildcard(nodes[i])
+              && PathPatternUtil.isNodeMatch(nodes[i], rNodes[i]))
+          || (PathPatternUtil.hasWildcard(rNodes[i])
+              && PathPatternUtil.isNodeMatch(rNodes[i], nodes[i]))) {
         continue;
       }
       if (!nodes[i].equals(rNodes[i])) {
@@ -482,8 +507,8 @@ public class PartialPath extends Path implements 
Comparable<Path>, Cloneable {
         return true;
       } else if (nodes[i].equals(ONE_LEVEL_PATH_WILDCARD)) {
         rNodesIndex++;
-      } else if (nodes[i].contains(ONE_LEVEL_PATH_WILDCARD)) {
-        if (!Pattern.compile(nodes[i].replace("*", 
".*")).matcher(rNodes[rNodesIndex]).matches()) {
+      } else if (PathPatternUtil.hasWildcard(nodes[i])) {
+        if (!PathPatternUtil.isNodeMatch(nodes[i], rNodes[rNodesIndex])) {
           return false;
         } else {
           rNodesIndex++;
@@ -530,8 +555,10 @@ public class PartialPath extends Path implements 
Comparable<Path>, Cloneable {
           }
         } else {
           // if without MULTI_LEVEL_PATH_WILDCARD, scan and check
-          if (nodes1[i - 1].equals(ONE_LEVEL_PATH_WILDCARD)
-              || nodes2[j - 1].equals(ONE_LEVEL_PATH_WILDCARD)
+          if ((PathPatternUtil.hasWildcard(nodes1[i - 1])
+                  && PathPatternUtil.isNodeMatch(nodes1[i - 1], nodes2[j - 1]))
+              || (PathPatternUtil.hasWildcard(nodes2[j - 1])
+                  && PathPatternUtil.isNodeMatch(nodes2[j - 1], nodes1[i - 1]))
               || nodes1[i - 1].equals(nodes2[j - 1])) {
             // if nodes1[i-1] and nodes[2] is matched, dp[i][j] = dp[i-1][j-1]
             dp[i][j] |= dp[i - 1][j - 1];
diff --git 
a/node-commons/src/main/java/org/apache/iotdb/commons/path/PathPatternNode.java 
b/node-commons/src/main/java/org/apache/iotdb/commons/path/PathPatternNode.java
index d26a1f8126..a5ea9dddb1 100644
--- 
a/node-commons/src/main/java/org/apache/iotdb/commons/path/PathPatternNode.java
+++ 
b/node-commons/src/main/java/org/apache/iotdb/commons/path/PathPatternNode.java
@@ -122,7 +122,7 @@ public class PathPatternNode<V, VSerializer extends 
PathPatternNode.Serializer<V
   }
 
   public boolean isWildcard() {
-    return name.equals(ONE_LEVEL_PATH_WILDCARD) || 
name.equals(MULTI_LEVEL_PATH_WILDCARD);
+    return PathPatternUtil.hasWildcard(name);
   }
 
   public boolean isMultiLevelWildcard() {
diff --git 
a/node-commons/src/main/java/org/apache/iotdb/commons/path/PathPatternUtil.java 
b/node-commons/src/main/java/org/apache/iotdb/commons/path/PathPatternUtil.java
new file mode 100644
index 0000000000..3c867a44ae
--- /dev/null
+++ 
b/node-commons/src/main/java/org/apache/iotdb/commons/path/PathPatternUtil.java
@@ -0,0 +1,52 @@
+/*
+ * 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.commons.path;
+
+import java.util.regex.Pattern;
+
+import static 
org.apache.iotdb.commons.conf.IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD;
+import static 
org.apache.iotdb.commons.conf.IoTDBConstant.ONE_LEVEL_PATH_WILDCARD;
+
+public class PathPatternUtil {
+
+  private PathPatternUtil() {}
+
+  /**
+   * The input string is a single node of a path pattern. Return true if the 
node may be a
+   * patternNode that can match batch explicit node names. e.g. *, e.g. *, **, 
d*, *d*.
+   */
+  public static boolean hasWildcard(String node) {
+    return node.startsWith(ONE_LEVEL_PATH_WILDCARD) || 
node.endsWith(ONE_LEVEL_PATH_WILDCARD);
+  }
+
+  /**
+   * Determine if a node pattern matches a node name.
+   *
+   * @param patternNode must be a string starts or ends with *, e.g. *, **, 
d*, *d*
+   * @param nodeName node to match
+   */
+  public static boolean isNodeMatch(String patternNode, String nodeName) {
+    if (patternNode.equals(ONE_LEVEL_PATH_WILDCARD)
+        || patternNode.equals(MULTI_LEVEL_PATH_WILDCARD)) {
+      return true;
+    }
+    return Pattern.matches(patternNode.replace("*", ".*"), nodeName);
+  }
+}
diff --git 
a/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/nfa/SimpleNFA.java
 
b/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/nfa/SimpleNFA.java
index 07638db799..698f27b37c 100644
--- 
a/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/nfa/SimpleNFA.java
+++ 
b/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/nfa/SimpleNFA.java
@@ -20,6 +20,7 @@
 package org.apache.iotdb.commons.path.fa.nfa;
 
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathPatternUtil;
 import org.apache.iotdb.commons.path.fa.IFAState;
 import org.apache.iotdb.commons.path.fa.IFATransition;
 import org.apache.iotdb.commons.path.fa.IPatternFA;
@@ -127,7 +128,7 @@ public class SimpleNFA implements IPatternFA {
       } else if (rawNodes[nextIndex].equals(ONE_LEVEL_PATH_WILDCARD)) {
         patternNodes[nextIndex] =
             new OneLevelWildcardMatchNode(nextIndex, 
currentNode.getTracebackNode());
-      } else if (rawNodes[nextIndex].contains(ONE_LEVEL_PATH_WILDCARD)) {
+      } else if (PathPatternUtil.hasWildcard(rawNodes[nextIndex])) {
         patternNodes[nextIndex] = new RegexMatchNode(nextIndex, 
currentNode.getTracebackNode());
       } else {
         patternNodes[nextIndex] = new NameMatchNode(nextIndex, 
currentNode.getTracebackNode());
diff --git 
a/server/src/main/java/org/apache/iotdb/db/engine/memtable/AlignedWritableMemChunkGroup.java
 
b/server/src/main/java/org/apache/iotdb/db/engine/memtable/AlignedWritableMemChunkGroup.java
index 878f3b691e..d3834ccce8 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/engine/memtable/AlignedWritableMemChunkGroup.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/engine/memtable/AlignedWritableMemChunkGroup.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.db.engine.memtable;
 
 import org.apache.iotdb.commons.path.AlignedPath;
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathPatternUtil;
 import org.apache.iotdb.db.wal.buffer.IWALByteBufferView;
 import org.apache.iotdb.tsfile.utils.BitMap;
 import org.apache.iotdb.tsfile.utils.Pair;
@@ -34,9 +35,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import static 
org.apache.iotdb.commons.conf.IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD;
-import static 
org.apache.iotdb.commons.conf.IoTDBConstant.ONE_LEVEL_PATH_WILDCARD;
-
 public class AlignedWritableMemChunkGroup implements IWritableMemChunkGroup {
 
   private AlignedWritableMemChunk memChunk;
@@ -103,9 +101,11 @@ public class AlignedWritableMemChunkGroup implements 
IWritableMemChunkGroup {
     Set<String> measurements = memChunk.getAllMeasurements();
     List<String> columnsToBeRemoved = new ArrayList<>();
     String targetMeasurement = originalPath.getMeasurement();
-    if (targetMeasurement.equals(ONE_LEVEL_PATH_WILDCARD)
-        || targetMeasurement.equals(MULTI_LEVEL_PATH_WILDCARD)) {
+    if (PathPatternUtil.hasWildcard(targetMeasurement)) {
       for (String measurement : measurements) {
+        if (!PathPatternUtil.isNodeMatch(targetMeasurement, measurement)) {
+          continue;
+        }
         Pair<Integer, Boolean> deleteInfo =
             memChunk.deleteDataFromAColumn(startTimestamp, endTimestamp, 
measurement);
         deletedPointsNumber += deleteInfo.left;
diff --git 
a/server/src/main/java/org/apache/iotdb/db/engine/memtable/WritableMemChunkGroup.java
 
b/server/src/main/java/org/apache/iotdb/db/engine/memtable/WritableMemChunkGroup.java
index e8f2d12e3c..6e763b6946 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/engine/memtable/WritableMemChunkGroup.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/engine/memtable/WritableMemChunkGroup.java
@@ -20,6 +20,7 @@
 package org.apache.iotdb.db.engine.memtable;
 
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathPatternUtil;
 import org.apache.iotdb.db.wal.buffer.IWALByteBufferView;
 import org.apache.iotdb.db.wal.utils.WALWriteUtils;
 import org.apache.iotdb.tsfile.utils.BitMap;
@@ -34,9 +35,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import static 
org.apache.iotdb.commons.conf.IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD;
-import static 
org.apache.iotdb.commons.conf.IoTDBConstant.ONE_LEVEL_PATH_WILDCARD;
-
 public class WritableMemChunkGroup implements IWritableMemChunkGroup {
 
   private Map<String, IWritableMemChunk> memChunkMap;
@@ -121,11 +119,13 @@ public class WritableMemChunkGroup implements 
IWritableMemChunkGroup {
       PartialPath originalPath, PartialPath devicePath, long startTimestamp, 
long endTimestamp) {
     int deletedPointsNumber = 0;
     String targetMeasurement = originalPath.getMeasurement();
-    if (targetMeasurement.equals(ONE_LEVEL_PATH_WILDCARD)
-        || targetMeasurement.equals(MULTI_LEVEL_PATH_WILDCARD)) {
+    if (PathPatternUtil.hasWildcard(targetMeasurement)) {
       Iterator<Entry<String, IWritableMemChunk>> iter = 
memChunkMap.entrySet().iterator();
       while (iter.hasNext()) {
         Entry<String, IWritableMemChunk> entry = iter.next();
+        if (!PathPatternUtil.isNodeMatch(targetMeasurement, entry.getKey())) {
+          continue;
+        }
         IWritableMemChunk chunk = entry.getValue();
         if (startTimestamp == Long.MIN_VALUE && endTimestamp == 
Long.MAX_VALUE) {
           iter.remove();
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/cache/DataNodeSchemaCache.java
 
b/server/src/main/java/org/apache/iotdb/db/metadata/cache/DataNodeSchemaCache.java
index b63fa02bbe..01ab162a2d 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/metadata/cache/DataNodeSchemaCache.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/metadata/cache/DataNodeSchemaCache.java
@@ -122,6 +122,10 @@ public class DataNodeSchemaCache {
     }
   }
 
+  public ClusterSchemaTree getMatchedSchemaWithTemplate(PartialPath path) {
+    return deviceUsingTemplateSchemaCache.getMatchedSchemaWithTemplate(path);
+  }
+
   public List<Integer> computeWithoutTemplate(ISchemaComputation 
schemaComputation) {
     return timeSeriesSchemaCache.compute(schemaComputation);
   }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/cache/DeviceUsingTemplateSchemaCache.java
 
b/server/src/main/java/org/apache/iotdb/db/metadata/cache/DeviceUsingTemplateSchemaCache.java
index d9ddeebfbd..4a39103373 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/metadata/cache/DeviceUsingTemplateSchemaCache.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/metadata/cache/DeviceUsingTemplateSchemaCache.java
@@ -20,6 +20,7 @@
 package org.apache.iotdb.db.metadata.cache;
 
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathPatternUtil;
 import org.apache.iotdb.commons.schema.view.LogicalViewSchema;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
@@ -92,6 +93,37 @@ public class DeviceUsingTemplateSchemaCache {
     return schemaTree;
   }
 
+  public ClusterSchemaTree getMatchedSchemaWithTemplate(PartialPath path) {
+    PartialPath devicePath = path.getDevicePath();
+    DeviceCacheEntry deviceCacheEntry = cache.getIfPresent(devicePath);
+    ClusterSchemaTree schemaTree = new ClusterSchemaTree();
+    if (deviceCacheEntry != null) {
+      Template template = 
templateManager.getTemplate(deviceCacheEntry.getTemplateId());
+      String measurement = path.getMeasurement();
+      if (PathPatternUtil.hasWildcard(measurement)) {
+        for (Map.Entry<String, IMeasurementSchema> entry : 
template.getSchemaMap().entrySet()) {
+          if (PathPatternUtil.isNodeMatch(measurement, entry.getKey())) {
+            schemaTree.appendSingleMeasurement(
+                devicePath.concatNode(entry.getKey()),
+                entry.getValue(),
+                null,
+                null,
+                template.isDirectAligned());
+            
schemaTree.setDatabases(Collections.singleton(deviceCacheEntry.getDatabase()));
+          }
+        }
+      } else {
+        IMeasurementSchema measurementSchema = template.getSchema(measurement);
+        if (measurementSchema != null) {
+          schemaTree.appendSingleMeasurement(
+              path, measurementSchema, null, null, template.isDirectAligned());
+          
schemaTree.setDatabases(Collections.singleton(deviceCacheEntry.getDatabase()));
+        }
+      }
+    }
+    return schemaTree;
+  }
+
   /**
    * CONFORM indicates that the provided devicePath had been cached as a 
template activated path,
    * ensuring that the alignment of the device, as well as the name and schema 
of every measurement
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/template/ClusterTemplateManager.java
 
b/server/src/main/java/org/apache/iotdb/db/metadata/template/ClusterTemplateManager.java
index e7e6871d70..809c835a00 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/metadata/template/ClusterTemplateManager.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/metadata/template/ClusterTemplateManager.java
@@ -27,6 +27,7 @@ import 
org.apache.iotdb.commons.exception.IllegalPathException;
 import org.apache.iotdb.commons.exception.IoTDBException;
 import org.apache.iotdb.commons.exception.MetadataException;
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathPatternUtil;
 import org.apache.iotdb.commons.utils.TestOnly;
 import org.apache.iotdb.confignode.rpc.thrift.TCreateSchemaTemplateReq;
 import org.apache.iotdb.confignode.rpc.thrift.TGetAllTemplatesResp;
@@ -61,7 +62,6 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import static 
org.apache.iotdb.commons.conf.IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD;
-import static 
org.apache.iotdb.commons.conf.IoTDBConstant.ONE_LEVEL_PATH_WILDCARD;
 
 public class ClusterTemplateManager implements ITemplateManager {
 
@@ -379,7 +379,7 @@ public class ClusterTemplateManager implements 
ITemplateManager {
     // and the following logic is equivalent with the above expression
 
     String measurement = pathPattern.getTailNode();
-    if (measurement.contains(ONE_LEVEL_PATH_WILDCARD)) {
+    if (PathPatternUtil.hasWildcard(measurement)) {
       // if measurement is wildcard, e.g. root.sg.d1.**, root.sg.d1.*, 
root.sg.d1.s*
       return pathPattern.overlapWithFullPathPrefix(pathSetTemplate);
     }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/schema/ClusterSchemaFetchExecutor.java
 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/schema/ClusterSchemaFetchExecutor.java
index 7e1da20136..38d69b7ab4 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/schema/ClusterSchemaFetchExecutor.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/schema/ClusterSchemaFetchExecutor.java
@@ -91,7 +91,7 @@ class ClusterSchemaFetchExecutor {
    * @param rawPatternTree the pattern tree consisting of the fullPathList
    * @return fetched schema
    */
-  ClusterSchemaTree fetchSchemaOfPreciseMatch(
+  ClusterSchemaTree fetchSchemaOfPreciseMatchOrPreciseDeviceUsingTemplate(
       List<PartialPath> fullPathList, PathPatternTree rawPatternTree) {
     ClusterSchemaTree schemaTree =
         executeSchemaFetchQuery(
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/schema/ClusterSchemaFetcher.java
 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/schema/ClusterSchemaFetcher.java
index 53fa5ee128..5d2c272072 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/schema/ClusterSchemaFetcher.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/schema/ClusterSchemaFetcher.java
@@ -110,14 +110,18 @@ public class ClusterSchemaFetcher implements 
ISchemaFetcher {
     this.context = context;
     patternTree.constructTree();
     List<PartialPath> pathPatternList = patternTree.getAllPathPatterns();
-    List<PartialPath> fullPathList = new ArrayList<>();
+    List<PartialPath> explicitPathList = new ArrayList<>();
+    List<PartialPath> explicitDevicePatternList = new ArrayList<>();
     for (PartialPath pattern : pathPatternList) {
       if (!pattern.hasWildcard()) {
-        fullPathList.add(pattern);
+        explicitPathList.add(pattern);
+      } else if (pattern.hasExplicitDevice()
+          && templateManager.checkTemplateSetInfo(pattern) != null) {
+        explicitDevicePatternList.add(pattern);
       }
     }
 
-    if (fullPathList.size() < pathPatternList.size()) {
+    if (explicitPathList.size() + explicitDevicePatternList.size() < 
pathPatternList.size()) {
       return clusterSchemaFetchExecutor.fetchSchemaOfFuzzyMatch(patternTree, 
false);
     }
 
@@ -125,14 +129,14 @@ public class ClusterSchemaFetcher implements 
ISchemaFetcher {
     // operation executed by delete timeseries will be effective.
     schemaCache.takeReadLock();
     try {
-      ClusterSchemaTree schemaTree;
-      if (fullPathList.size() == pathPatternList.size()) {
-        boolean isAllCached = true;
-        schemaTree = new ClusterSchemaTree();
-        ClusterSchemaTree cachedSchema;
-        Set<String> storageGroupSet = new HashSet<>();
-        for (PartialPath fullPath : fullPathList) {
-          cachedSchema = schemaCache.get(fullPath);
+      ClusterSchemaTree schemaTree = new ClusterSchemaTree();
+      boolean isAllCached = true;
+
+      ClusterSchemaTree cachedSchema;
+      Set<String> storageGroupSet = new HashSet<>();
+      if (!explicitDevicePatternList.isEmpty()) {
+        for (PartialPath explicitDevicePattern : explicitDevicePatternList) {
+          cachedSchema = 
schemaCache.getMatchedSchemaWithTemplate(explicitDevicePattern);
           if (cachedSchema.isEmpty()) {
             isAllCached = false;
             break;
@@ -141,13 +145,29 @@ public class ClusterSchemaFetcher implements 
ISchemaFetcher {
             storageGroupSet.addAll(cachedSchema.getDatabases());
           }
         }
-        if (isAllCached) {
-          schemaTree.setDatabases(storageGroupSet);
-          return schemaTree;
+      }
+
+      if (isAllCached && !explicitPathList.isEmpty()) {
+        for (PartialPath fullPath : explicitPathList) {
+          cachedSchema = schemaCache.get(fullPath);
+          if (cachedSchema.isEmpty()) {
+            isAllCached = false;
+            break;
+          } else {
+            schemaTree.mergeSchemaTree(cachedSchema);
+            storageGroupSet.addAll(cachedSchema.getDatabases());
+          }
         }
       }
 
-      return 
clusterSchemaFetchExecutor.fetchSchemaOfPreciseMatch(fullPathList, patternTree);
+      if (isAllCached) {
+        schemaTree.setDatabases(storageGroupSet);
+        return schemaTree;
+      }
+
+      return 
clusterSchemaFetchExecutor.fetchSchemaOfPreciseMatchOrPreciseDeviceUsingTemplate(
+          pathPatternList, patternTree);
+
     } finally {
       schemaCache.releaseReadLock();
     }

Reply via email to