You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by zy...@apache.org on 2023/04/26 14:54:27 UTC

[iotdb] branch master updated: [IOTDB-5824] Fix show devices with * cannot display satisfied devices (#9715)

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 33f5f6ec78 [IOTDB-5824] Fix show devices with * cannot display satisfied devices (#9715)
33f5f6ec78 is described below

commit 33f5f6ec7888f5c2c2ee539985dc495c3410bf01
Author: Chen YZ <43...@users.noreply.github.com>
AuthorDate: Wed Apr 26 22:54:20 2023 +0800

    [IOTDB-5824] Fix show devices with * cannot display satisfied devices (#9715)
---
 .../iotdb/confignode/manager/ConfigManager.java    | 11 ++---
 .../iotdb/db/it/schema/IoTDBMetadataFetchIT.java   | 49 ++++++++++++++++++++++
 .../org/apache/iotdb/commons/path/PartialPath.java | 40 ++++++++++++++++++
 3 files changed, 95 insertions(+), 5 deletions(-)

diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java b/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
index d3cbaa2518..6d5442e3f1 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConfigManager.java
@@ -193,7 +193,6 @@ import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 
-import static org.apache.iotdb.commons.conf.IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD;
 import static org.apache.iotdb.commons.conf.IoTDBConstant.ONE_LEVEL_PATH_WILDCARD;
 
 /** Entry of all management, AssignPartitionManager,AssignRegionManager. */
@@ -589,8 +588,11 @@ public class ConfigManager implements IManager {
     if (path.getFullPath().contains(IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD)) {
       return new ArrayList<>();
     }
-    // path doesn't contain * so the size of innerPathList should be 1
-    PartialPath innerPath = path.alterPrefixPath(database).get(0);
+    List<PartialPath> innerPathList = path.alterPrefixPath(database);
+    if (innerPathList.size() == 0) {
+      return new ArrayList<>();
+    }
+    PartialPath innerPath = innerPathList.get(0);
     // The innerPath contains `*` and the only `*` is not in last level
     if (innerPath.getDevice().contains(IoTDBConstant.ONE_LEVEL_PATH_WILDCARD)) {
       return new ArrayList<>();
@@ -626,8 +628,7 @@ public class ConfigManager implements IManager {
       for (int i = 0; i < allDatabases.size(); i++) {
         String database = allDatabases.get(i);
         PartialPath databasePath = allDatabasePaths.get(i);
-        if (path.overlapWith(databasePath.concatNode(MULTI_LEVEL_PATH_WILDCARD))
-            && !scanAllRegions.containsKey(database)) {
+        if (path.overlapWithFullPathPrefix(databasePath) && !scanAllRegions.containsKey(database)) {
           List<TSeriesPartitionSlot> relatedSlot = calculateRelatedSlot(path, databasePath);
           if (relatedSlot.isEmpty()) {
             scanAllRegions.put(database, true);
diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBMetadataFetchIT.java b/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBMetadataFetchIT.java
index d51e0e4fe5..9c877983a2 100644
--- a/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBMetadataFetchIT.java
+++ b/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBMetadataFetchIT.java
@@ -275,6 +275,55 @@ public class IoTDBMetadataFetchIT extends AbstractSchemaIT {
     }
   }
 
+  @Test
+  public void showDevicesWithWildcardTest() throws SQLException {
+    try (Connection connection = EnvFactory.getEnv().getConnection();
+        Statement statement = connection.createStatement()) {
+      String[] sqls =
+          new String[] {
+            "show devices root.l*.wf01.w*",
+            "show devices root.ln.*f01.*",
+            "show devices root.l*.*f*.*1",
+          };
+      Set<String>[] standards =
+          new Set[] {
+            new HashSet<>(
+                Arrays.asList(
+                    "root.ln.wf01.wt01,false,",
+                    "root.ln.wf01.wt02,true,",
+                    "root.ln1.wf01.wt01,false,",
+                    "root.ln2.wf01.wt01,false,")),
+            new HashSet<>(Arrays.asList("root.ln.wf01.wt01,false,", "root.ln.wf01.wt02,true,")),
+            new HashSet<>(
+                Arrays.asList(
+                    "root.ln.wf01.wt01,false,",
+                    "root.ln1.wf01.wt01,false,",
+                    "root.ln2.wf01.wt01,false,"))
+          };
+
+      for (int n = 0; n < sqls.length; n++) {
+        String sql = sqls[n];
+        Set<String> standard = standards[n];
+        try (ResultSet resultSet = statement.executeQuery(sql)) {
+          ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+          while (resultSet.next()) {
+            StringBuilder builder = new StringBuilder();
+            for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
+              builder.append(resultSet.getString(i)).append(",");
+            }
+            String string = builder.toString();
+            Assert.assertTrue(standard.contains(string));
+            standard.remove(string);
+          }
+          assertEquals(0, standard.size());
+        } catch (SQLException e) {
+          e.printStackTrace();
+          fail(e.getMessage());
+        }
+      }
+    }
+  }
+
   @Test
   public void showChildPaths() throws SQLException {
     try (Connection connection = EnvFactory.getEnv().getConnection();
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 8eea86c232..d9318996de 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
@@ -457,6 +457,46 @@ public class PartialPath extends Path implements Comparable<Path>, Cloneable {
     return this.nodes.length == rNodes.length;
   }
 
+  /**
+   * Test if this path pattern overlaps with input prefix full path. Overlap means the result sets
+   * generated by two path pattern share some common elements. e.g.
+   *
+   * <ul>
+   *   <li>"root.sg.**" overlaps with prefix full path "root" because "root.sg.**" share some common
+   *       element "root.sg.d" with "root.**"
+   *   <li>"root.*.d*.s" overlaps with prefix full path "root.sg" because "root.*.d*.s" share some
+   *       common element "root.sg.d1.s" with "root.sg.**"
+   *   <li>"root.*.d.s" doesn't overlap with prefix full path "root.sg.d1" because there is no
+   *       common element between "root.*.d.s" and "root.sg.d1.**"
+   * </ul>
+   *
+   * @param prefixFullPath prefix full path
+   * @return true if overlapping otherwise return false
+   */
+  public boolean overlapWithFullPathPrefix(PartialPath prefixFullPath) {
+    String[] rNodes = prefixFullPath.getNodes();
+    int rNodesIndex = 0;
+    for (int i = 0; i < this.nodes.length && rNodesIndex < rNodes.length; i++) {
+      // if encounter MULTI_LEVEL_PATH_WILDCARD
+      if (nodes[i].equals(MULTI_LEVEL_PATH_WILDCARD)) {
+        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()) {
+          return false;
+        } else {
+          rNodesIndex++;
+        }
+      } else if (nodes[i].equals(rNodes[rNodesIndex])) {
+        rNodesIndex++;
+      } else {
+        return false;
+      }
+    }
+    return true;
+  }
+
   /**
    * Try to check overlap between nodes1 and nodes2 with MULTI_LEVEL_PATH_WILDCARD. Time complexity
    * O(n^2).