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

jackietien 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 810ec62f824 [IOTDB-6124] Add scope filter parameter for tree visitor 
framework
810ec62f824 is described below

commit 810ec62f824b405a68f435499db327af96ed870f
Author: Chen YZ <[email protected]>
AuthorDate: Thu Aug 24 19:02:04 2023 +0800

    [IOTDB-6124] Add scope filter parameter for tree visitor framework
---
 .../visitor/SchemaTreeDeviceVisitor.java           |   6 +
 .../visitor/SchemaTreeMeasurementVisitor.java      |   7 +
 .../schematree/visitor/SchemaTreeVisitor.java      |  36 +++++
 .../visitor/SchemaTreeVisitorFactory.java          |  23 +++
 .../schemaregion/mtree/traverser/Traverser.java    |  46 +++++-
 .../common/schematree/ClusterSchemaTreeTest.java   | 178 +++++++++++++++++++++
 .../ClusterSchemaTreeTestWithRelease.java          |  16 ++
 .../MockSchemaTreeMeasurementVisitor.java          |   6 +
 .../apache/iotdb/commons/path/fa/FAFactory.java    |  14 +-
 .../apache/iotdb/commons/path/fa/IPatternFA.java   |  17 +-
 .../iotdb/commons/path/fa/dfa/PatternDFA.java      |  60 +++++++
 .../iotdb/commons/path/fa/dfa/graph/NFAGraph.java  |  65 ++++++++
 .../commons/path/fa/match/IStateMatchInfo.java     |   2 +
 .../commons/path/fa/match/StateMultiMatchInfo.java |  14 +-
 .../path/fa/match/StateSingleMatchInfo.java        |  10 +-
 .../iotdb/commons/schema/SchemaConstant.java       |  12 +-
 .../commons/schema/tree/AbstractTreeVisitor.java   | 136 +++++++++++-----
 .../iotdb/commons/schema/tree/ITreeNode.java       |   4 +
 .../apache/iotdb/commons/path/PatternDFATest.java  |  45 ++++++
 19 files changed, 648 insertions(+), 49 deletions(-)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/visitor/SchemaTreeDeviceVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/visitor/SchemaTreeDeviceVisitor.java
index 16512a8aeb0..5a50c4bda92 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/visitor/SchemaTreeDeviceVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/visitor/SchemaTreeDeviceVisitor.java
@@ -20,6 +20,7 @@
 package org.apache.iotdb.db.queryengine.common.schematree.visitor;
 
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathPatternTree;
 import org.apache.iotdb.db.queryengine.common.schematree.DeviceSchemaInfo;
 import org.apache.iotdb.db.queryengine.common.schematree.MeasurementSchemaInfo;
 import 
org.apache.iotdb.db.queryengine.common.schematree.node.SchemaMeasurementNode;
@@ -35,6 +36,11 @@ public class SchemaTreeDeviceVisitor extends 
SchemaTreeVisitor<DeviceSchemaInfo>
     super(root, pathPattern, isPrefixMatch);
   }
 
+  public SchemaTreeDeviceVisitor(
+      SchemaNode root, PartialPath pathPattern, boolean isPrefixMatch, 
PathPatternTree scope) {
+    super(root, pathPattern, isPrefixMatch, scope);
+  }
+
   @Override
   protected boolean mayTargetNodeType(SchemaNode node) {
     return node.isEntity();
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/visitor/SchemaTreeMeasurementVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/visitor/SchemaTreeMeasurementVisitor.java
index 0b56e6a9596..ca33a519b01 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/visitor/SchemaTreeMeasurementVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/visitor/SchemaTreeMeasurementVisitor.java
@@ -21,6 +21,7 @@ package 
org.apache.iotdb.db.queryengine.common.schematree.visitor;
 
 import org.apache.iotdb.commons.path.MeasurementPath;
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathPatternTree;
 import org.apache.iotdb.commons.path.fa.IFAState;
 import org.apache.iotdb.commons.path.fa.IFATransition;
 import org.apache.iotdb.db.queryengine.common.schematree.node.SchemaNode;
@@ -37,6 +38,12 @@ public class SchemaTreeMeasurementVisitor extends 
SchemaTreeVisitor<MeasurementP
     tailNode = pathPattern.getTailNode();
   }
 
+  public SchemaTreeMeasurementVisitor(
+      SchemaNode root, PartialPath pathPattern, boolean isPrefixMatch, 
PathPatternTree scope) {
+    super(root, pathPattern, isPrefixMatch, scope);
+    tailNode = pathPattern.getTailNode();
+  }
+
   @Override
   protected boolean mayTargetNodeType(SchemaNode node) {
     return node.isMeasurement();
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/visitor/SchemaTreeVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/visitor/SchemaTreeVisitor.java
index 7eb97b6191f..337225813ef 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/visitor/SchemaTreeVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/visitor/SchemaTreeVisitor.java
@@ -20,12 +20,14 @@
 package org.apache.iotdb.db.queryengine.common.schematree.visitor;
 
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathPatternTree;
 import org.apache.iotdb.commons.schema.tree.AbstractTreeVisitor;
 import org.apache.iotdb.db.queryengine.common.schematree.node.SchemaNode;
 
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.NoSuchElementException;
 
 public abstract class SchemaTreeVisitor<R> extends 
AbstractTreeVisitor<SchemaNode, R> {
 
@@ -36,6 +38,12 @@ public abstract class SchemaTreeVisitor<R> extends 
AbstractTreeVisitor<SchemaNod
     initStack();
   }
 
+  protected SchemaTreeVisitor(
+      SchemaNode root, PartialPath pathPattern, boolean isPrefixMatch, 
PathPatternTree scope) {
+    super(root, pathPattern, isPrefixMatch, scope);
+    initStack();
+  }
+
   public List<R> getAllResult() {
     List<R> result = new ArrayList<>();
     while (hasNext()) {
@@ -59,6 +67,34 @@ public abstract class SchemaTreeVisitor<R> extends 
AbstractTreeVisitor<SchemaNod
     return parent.getChild(childName);
   }
 
+  @Override
+  protected Iterator<SchemaNode> getChildrenIterator(
+      SchemaNode parent, Iterator<String> childrenName) throws Exception {
+    return new Iterator<SchemaNode>() {
+      private SchemaNode next = null;
+
+      @Override
+      public boolean hasNext() {
+        if (next == null) {
+          while (next == null && childrenName.hasNext()) {
+            next = getChild(parent, childrenName.next());
+          }
+        }
+        return next != null;
+      }
+
+      @Override
+      public SchemaNode next() {
+        if (!hasNext()) {
+          throw new NoSuchElementException();
+        }
+        SchemaNode result = next;
+        next = null;
+        return result;
+      }
+    };
+  }
+
   @Override
   protected Iterator<SchemaNode> getChildrenIterator(SchemaNode parent) {
     return parent.getChildrenIterator();
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/visitor/SchemaTreeVisitorFactory.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/visitor/SchemaTreeVisitorFactory.java
index 69195fd816d..3132801696b 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/visitor/SchemaTreeVisitorFactory.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/schematree/visitor/SchemaTreeVisitorFactory.java
@@ -21,6 +21,7 @@ package 
org.apache.iotdb.db.queryengine.common.schematree.visitor;
 
 import org.apache.iotdb.commons.path.MeasurementPath;
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathPatternTree;
 import org.apache.iotdb.db.queryengine.common.schematree.node.SchemaNode;
 
 public class SchemaTreeVisitorFactory {
@@ -49,4 +50,26 @@ public class SchemaTreeVisitorFactory {
     return new SchemaTreeVisitorWithLimitOffsetWrapper<>(
         new SchemaTreeMeasurementVisitor(root, pathPattern, isPrefixMatch), 
slimit, soffset);
   }
+
+  public static SchemaTreeDeviceVisitor createSchemaTreeDeviceVisitor(
+      SchemaNode root, PartialPath pathPattern, boolean isPrefixMatch, 
PathPatternTree scope) {
+    return new SchemaTreeDeviceVisitor(root, pathPattern, isPrefixMatch, 
scope);
+  }
+
+  public static SchemaTreeMeasurementVisitor 
createSchemaTreeMeasurementVisitor(
+      SchemaNode root, PartialPath pathPattern, boolean isPrefixMatch, 
PathPatternTree scope) {
+    return new SchemaTreeMeasurementVisitor(root, pathPattern, isPrefixMatch, 
scope);
+  }
+
+  public static SchemaTreeVisitorWithLimitOffsetWrapper<MeasurementPath>
+      createSchemaTreeMeasurementVisitor(
+          SchemaNode root,
+          PartialPath pathPattern,
+          boolean isPrefixMatch,
+          int slimit,
+          int soffset,
+          PathPatternTree scope) {
+    return new SchemaTreeVisitorWithLimitOffsetWrapper<>(
+        new SchemaTreeMeasurementVisitor(root, pathPattern, isPrefixMatch, 
scope), slimit, soffset);
+  }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/traverser/Traverser.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/traverser/Traverser.java
index 745b60b4323..115ce1d27df 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/traverser/Traverser.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/traverser/Traverser.java
@@ -38,6 +38,7 @@ import org.slf4j.LoggerFactory;
 
 import java.util.Iterator;
 import java.util.Map;
+import java.util.NoSuchElementException;
 
 import static org.apache.iotdb.commons.conf.IoTDBConstant.PATH_ROOT;
 import static org.apache.iotdb.commons.schema.SchemaConstant.NON_TEMPLATE;
@@ -150,6 +151,47 @@ public abstract class Traverser<R, N extends IMNode<N>> 
extends AbstractTreeVisi
     }
   }
 
+  @Override
+  protected Iterator<N> getChildrenIterator(N parent, Iterator<String> 
childrenName)
+      throws Exception {
+    return new IMNodeIterator<N>() {
+      private N next = null;
+
+      @Override
+      public boolean hasNext() {
+        if (next == null) {
+          while (next == null && childrenName.hasNext()) {
+            try {
+              next = getChild(parent, childrenName.next());
+            } catch (Throwable e) {
+              logger.warn(e.getMessage(), e);
+              throw new RuntimeException(e);
+            }
+          }
+        }
+        return next != null;
+      }
+
+      @Override
+      public N next() {
+        if (!hasNext()) {
+          throw new NoSuchElementException();
+        }
+        N result = next;
+        next = null;
+        return result;
+      }
+
+      @Override
+      public void close() {
+        if (next != null) {
+          releaseNode(next);
+          next = null;
+        }
+      }
+    };
+  }
+
   @Override
   protected Iterator<N> getChildrenIterator(N parent) throws MetadataException 
{
     if (parent.isAboveDatabase()) {
@@ -161,7 +203,9 @@ public abstract class Traverser<R, N extends IMNode<N>> 
extends AbstractTreeVisi
 
   @Override
   protected void releaseNodeIterator(Iterator<N> nodeIterator) {
-    ((IMNodeIterator<N>) nodeIterator).close();
+    if (nodeIterator instanceof IMNodeIterator) {
+      ((IMNodeIterator<N>) nodeIterator).close();
+    }
   }
 
   @Override
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/common/schematree/ClusterSchemaTreeTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/common/schematree/ClusterSchemaTreeTest.java
index 18760f25cc9..56ae45668da 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/common/schematree/ClusterSchemaTreeTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/common/schematree/ClusterSchemaTreeTest.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.db.queryengine.common.schematree;
 import org.apache.iotdb.commons.exception.IllegalPathException;
 import org.apache.iotdb.commons.path.MeasurementPath;
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathPatternTree;
 import org.apache.iotdb.commons.schema.view.LogicalViewSchema;
 import 
org.apache.iotdb.commons.schema.view.viewExpression.leaf.TimeSeriesViewOperand;
 import org.apache.iotdb.db.queryengine.common.schematree.node.SchemaEntityNode;
@@ -468,6 +469,171 @@ public class ClusterSchemaTreeTest {
     return root;
   }
 
+  @Test
+  public void testSchemaTreeWithScope() throws Exception {
+    SchemaNode root = generateSchemaTree();
+    PathPatternTree scope = new PathPatternTree();
+    scope.appendPathPattern(new PartialPath("root.sg.d1.**"));
+    scope.appendPathPattern(new PartialPath("root.sg.d2.status"));
+    scope.appendPathPattern(new PartialPath("root.sg.d2.a.**"));
+    scope.constructTree();
+
+    SchemaTreeVisitorWithLimitOffsetWrapper<MeasurementPath> visitor =
+        createSchemaTreeVisitorWithLimitOffsetWrapper(
+            root, new PartialPath("root.sg.d2.a.s1"), 0, 0, false, scope);
+    checkVisitorResult(visitor, 1, new String[] {"root.sg.d2.a.s1"}, null, new 
boolean[] {true});
+
+    visitor =
+        createSchemaTreeVisitorWithLimitOffsetWrapper(
+            root, new PartialPath("root.sg.d2.s1"), 0, 0, false, scope);
+    checkVisitorResult(visitor, 0, new String[] {}, null, new boolean[] {});
+
+    visitor =
+        createSchemaTreeVisitorWithLimitOffsetWrapper(
+            root, new PartialPath("root.sg.*.s2"), 0, 0, false, scope);
+    checkVisitorResult(
+        visitor, 2, new String[] {"root.sg.d1.s2", "root.sg.d2.s2"}, new 
String[] {"", ""}, null);
+
+    visitor =
+        createSchemaTreeVisitorWithLimitOffsetWrapper(
+            root, new PartialPath("root.sg.*.s1"), 0, 0, false, scope);
+    checkVisitorResult(visitor, 1, new String[] {"root.sg.d1.s1"}, new 
String[] {""}, null);
+
+    visitor =
+        createSchemaTreeVisitorWithLimitOffsetWrapper(
+            root, new PartialPath("root.sg.*.status"), 0, 0, false, scope);
+    checkVisitorResult(
+        visitor,
+        2,
+        new String[] {"root.sg.d1.s2", "root.sg.d2.s2"},
+        new String[] {"status", "status"},
+        null);
+
+    visitor =
+        createSchemaTreeVisitorWithLimitOffsetWrapper(
+            root, new PartialPath("root.sg.d2.*.*"), 0, 0, false, scope);
+    checkVisitorResult(
+        visitor,
+        2,
+        new String[] {"root.sg.d2.a.s1", "root.sg.d2.a.s2"},
+        new String[] {"", ""},
+        new boolean[] {true, true});
+
+    visitor =
+        createSchemaTreeVisitorWithLimitOffsetWrapper(
+            root, new PartialPath("root.sg.d1"), 0, 0, true, scope);
+    checkVisitorResult(
+        visitor,
+        2,
+        new String[] {"root.sg.d1.s1", "root.sg.d1.s2"},
+        new String[] {"", ""},
+        new boolean[] {false, false});
+
+    visitor =
+        createSchemaTreeVisitorWithLimitOffsetWrapper(
+            root, new PartialPath("root.sg.*.a"), 0, 0, true, scope);
+    checkVisitorResult(
+        visitor,
+        2,
+        new String[] {"root.sg.d2.a.s1", "root.sg.d2.a.s2"},
+        new String[] {"", ""},
+        new boolean[] {true, true},
+        new int[] {0, 0});
+
+    visitor =
+        createSchemaTreeVisitorWithLimitOffsetWrapper(
+            root, new PartialPath("root.sg.*.*"), 2, 2, false, scope);
+    checkVisitorResult(
+        visitor,
+        1,
+        new String[] {"root.sg.d2.s2"},
+        new String[] {""},
+        new boolean[] {false},
+        new int[] {3});
+
+    visitor =
+        createSchemaTreeVisitorWithLimitOffsetWrapper(
+            root, new PartialPath("root.sg.*"), 2, 3, true, scope);
+    checkVisitorResult(
+        visitor,
+        2,
+        new String[] {"root.sg.d2.a.s2", "root.sg.d2.s2"},
+        new String[] {"", ""},
+        new boolean[] {true, false},
+        new int[] {4, 5});
+
+    visitor =
+        createSchemaTreeVisitorWithLimitOffsetWrapper(
+            root, new PartialPath("root.sg.d1.**"), 0, 0, false, scope);
+    checkVisitorResult(
+        visitor,
+        2,
+        new String[] {"root.sg.d1.s1", "root.sg.d1.s2"},
+        new String[] {"", ""},
+        new boolean[] {false, false});
+
+    visitor =
+        createSchemaTreeVisitorWithLimitOffsetWrapper(
+            root, new PartialPath("root.sg.d2.**"), 3, 1, true, scope);
+    checkVisitorResult(
+        visitor,
+        2,
+        new String[] {"root.sg.d2.a.s2", "root.sg.d2.s2"},
+        new String[] {"", ""},
+        new boolean[] {true, false},
+        new int[] {2, 3});
+
+    visitor =
+        createSchemaTreeVisitorWithLimitOffsetWrapper(
+            root, new PartialPath("root.sg.**.status"), 2, 1, true, scope);
+    checkVisitorResult(
+        visitor,
+        2,
+        new String[] {"root.sg.d2.a.s2", "root.sg.d2.s2"},
+        new String[] {"status", "status"},
+        new boolean[] {true, false},
+        new int[] {2, 3});
+
+    visitor =
+        createSchemaTreeVisitorWithLimitOffsetWrapper(
+            root, new PartialPath("root.**.*"), 10, 0, false, scope);
+    checkVisitorResult(
+        visitor,
+        5,
+        new String[] {
+          "root.sg.d1.s1", "root.sg.d1.s2", "root.sg.d2.a.s1", 
"root.sg.d2.a.s2", "root.sg.d2.s2"
+        },
+        new String[] {"", "", "", "", ""},
+        new boolean[] {false, false, true, true, false},
+        new int[] {1, 2, 3, 4, 5});
+
+    visitor =
+        createSchemaTreeVisitorWithLimitOffsetWrapper(
+            root, new PartialPath("root.**.*.**"), 10, 0, false, scope);
+    checkVisitorResult(
+        visitor,
+        5,
+        new String[] {
+          "root.sg.d1.s1", "root.sg.d1.s2", "root.sg.d2.a.s1", 
"root.sg.d2.a.s2", "root.sg.d2.s2"
+        },
+        new String[] {"", "", "", "", ""},
+        new boolean[] {false, false, true, true, false},
+        new int[] {1, 2, 3, 4, 5});
+
+    visitor =
+        createSchemaTreeVisitorWithLimitOffsetWrapper(
+            root, new PartialPath("root.*.**.**"), 10, 0, false, scope);
+    checkVisitorResult(
+        visitor,
+        5,
+        new String[] {
+          "root.sg.d1.s1", "root.sg.d1.s2", "root.sg.d2.a.s1", 
"root.sg.d2.a.s2", "root.sg.d2.s2"
+        },
+        new String[] {"", "", "", "", ""},
+        new boolean[] {false, false, true, true, false},
+        new int[] {1, 2, 3, 4, 5});
+  }
+
   private void checkVisitorResult(
       SchemaTreeVisitorWithLimitOffsetWrapper<MeasurementPath> visitor,
       int expectedNum,
@@ -731,6 +897,18 @@ public class ClusterSchemaTreeTest {
         root, pathPattern, isPrefixMatch, slimit, soffset);
   }
 
+  protected SchemaTreeVisitorWithLimitOffsetWrapper<MeasurementPath>
+      createSchemaTreeVisitorWithLimitOffsetWrapper(
+          SchemaNode root,
+          PartialPath pathPattern,
+          int slimit,
+          int soffset,
+          boolean isPrefixMatch,
+          PathPatternTree scope) {
+    return SchemaTreeVisitorFactory.createSchemaTreeMeasurementVisitor(
+        root, pathPattern, isPrefixMatch, slimit, soffset, scope);
+  }
+
   @Test
   public void testHasView() throws IllegalPathException {
     ClusterSchemaTree schemaTree = new ClusterSchemaTree();
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/common/schematree/ClusterSchemaTreeTestWithRelease.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/common/schematree/ClusterSchemaTreeTestWithRelease.java
index b7204d5d5b8..72b77254b21 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/common/schematree/ClusterSchemaTreeTestWithRelease.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/common/schematree/ClusterSchemaTreeTestWithRelease.java
@@ -20,6 +20,7 @@ package org.apache.iotdb.db.queryengine.common.schematree;
 
 import org.apache.iotdb.commons.path.MeasurementPath;
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathPatternTree;
 import org.apache.iotdb.db.queryengine.common.schematree.node.SchemaNode;
 import 
org.apache.iotdb.db.queryengine.common.schematree.visitor.SchemaTreeVisitorWithLimitOffsetWrapper;
 
@@ -36,4 +37,19 @@ public class ClusterSchemaTreeTestWithRelease extends 
ClusterSchemaTreeTest {
     return new SchemaTreeVisitorWithLimitOffsetWrapper<>(
         new MockSchemaTreeMeasurementVisitor(root, pathPattern, 
isPrefixMatch), slimit, soffset);
   }
+
+  @Override
+  protected SchemaTreeVisitorWithLimitOffsetWrapper<MeasurementPath>
+      createSchemaTreeVisitorWithLimitOffsetWrapper(
+          SchemaNode root,
+          PartialPath pathPattern,
+          int slimit,
+          int soffset,
+          boolean isPrefixMatch,
+          PathPatternTree scope) {
+    return new SchemaTreeVisitorWithLimitOffsetWrapper<>(
+        new MockSchemaTreeMeasurementVisitor(root, pathPattern, isPrefixMatch, 
scope),
+        slimit,
+        soffset);
+  }
 }
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/common/schematree/MockSchemaTreeMeasurementVisitor.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/common/schematree/MockSchemaTreeMeasurementVisitor.java
index ee8e61126d3..b1fc5db615e 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/common/schematree/MockSchemaTreeMeasurementVisitor.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/common/schematree/MockSchemaTreeMeasurementVisitor.java
@@ -20,6 +20,7 @@ package org.apache.iotdb.db.queryengine.common.schematree;
 
 import org.apache.iotdb.commons.path.MeasurementPath;
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathPatternTree;
 import org.apache.iotdb.db.queryengine.common.schematree.node.SchemaNode;
 import 
org.apache.iotdb.db.queryengine.common.schematree.visitor.SchemaTreeMeasurementVisitor;
 
@@ -43,6 +44,11 @@ public class MockSchemaTreeMeasurementVisitor extends 
SchemaTreeMeasurementVisit
     super(root, pathPattern, isPrefixMatch);
   }
 
+  public MockSchemaTreeMeasurementVisitor(
+      SchemaNode root, PartialPath pathPattern, boolean isPrefixMatch, 
PathPatternTree scope) {
+    super(root, pathPattern, isPrefixMatch, scope);
+  }
+
   @Override
   protected Iterator<SchemaNode> getChildrenIterator(SchemaNode parent) {
     return new CountIterator(super.getChildrenIterator(parent));
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/FAFactory.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/FAFactory.java
index c2b50414c3c..ea6c2d02f80 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/FAFactory.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/FAFactory.java
@@ -20,6 +20,7 @@ package org.apache.iotdb.commons.path.fa;
 
 import org.apache.iotdb.commons.path.fa.dfa.PatternDFA;
 import org.apache.iotdb.commons.path.fa.nfa.SimpleNFA;
+import org.apache.iotdb.commons.schema.SchemaConstant;
 
 import com.github.benmanes.caffeine.cache.Caffeine;
 import com.github.benmanes.caffeine.cache.LoadingCache;
@@ -41,7 +42,18 @@ public class FAFactory {
     dfaCache =
         Caffeine.newBuilder()
             .maximumSize(DFA_CACHE_SIZE)
-            .build(builder -> new PatternDFA(builder.getPathPattern(), 
builder.isPrefixMatch()));
+            .build(
+                builder -> {
+                  if (builder.getPatternTree() != null) {
+                    if 
(builder.getPatternTree().equals(SchemaConstant.ALL_MATCH_PATTERN_TREE)) {
+                      // always return the same instance for root.**
+                      return SchemaConstant.ALL_MATCH_DFA;
+                    }
+                    return new PatternDFA(builder.getPatternTree());
+                  } else {
+                    return new PatternDFA(builder.getPathPattern(), 
builder.isPrefixMatch());
+                  }
+                });
   }
 
   public static FAFactory getInstance() {
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/IPatternFA.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/IPatternFA.java
index 825531d5369..3016ab4d4a1 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/IPatternFA.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/IPatternFA.java
@@ -20,6 +20,7 @@
 package org.apache.iotdb.commons.path.fa;
 
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathPatternTree;
 
 import java.util.Iterator;
 import java.util.Map;
@@ -86,6 +87,7 @@ public interface IPatternFA {
 
   final class Builder {
     private PartialPath pathPattern;
+    private PathPatternTree patternTree;
     private boolean isPrefixMatch = false;
 
     public Builder() {}
@@ -95,6 +97,12 @@ public interface IPatternFA {
       return this;
     }
 
+    /** @param patternTree the included PartialPath must be a prefix or a 
fullPath */
+    public Builder patternTree(PathPatternTree patternTree) {
+      this.patternTree = patternTree;
+      return this;
+    }
+
     public Builder isPrefixMatch(boolean isPrefixMatch) {
       this.isPrefixMatch = isPrefixMatch;
       return this;
@@ -104,6 +112,10 @@ public interface IPatternFA {
       return pathPattern;
     }
 
+    public PathPatternTree getPatternTree() {
+      return patternTree;
+    }
+
     public boolean isPrefixMatch() {
       return isPrefixMatch;
     }
@@ -122,12 +134,13 @@ public interface IPatternFA {
       if (o == null || getClass() != o.getClass()) return false;
       Builder builder = (Builder) o;
       return isPrefixMatch == builder.isPrefixMatch
-          && Objects.equals(pathPattern, builder.pathPattern);
+          && Objects.equals(pathPattern, builder.pathPattern)
+          && Objects.equals(patternTree, builder.patternTree);
     }
 
     @Override
     public int hashCode() {
-      return Objects.hash(pathPattern, isPrefixMatch);
+      return Objects.hash(pathPattern, patternTree, isPrefixMatch);
     }
   }
 }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/dfa/PatternDFA.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/dfa/PatternDFA.java
index c0f909d84cf..2a0504c9158 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/dfa/PatternDFA.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/dfa/PatternDFA.java
@@ -20,6 +20,7 @@ package org.apache.iotdb.commons.path.fa.dfa;
 
 import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathPatternTree;
 import org.apache.iotdb.commons.path.fa.IFAState;
 import org.apache.iotdb.commons.path.fa.IFATransition;
 import org.apache.iotdb.commons.path.fa.IPatternFA;
@@ -84,6 +85,65 @@ public class PatternDFA implements IPatternFA {
     batchMatchTransitionCached = new List[dfaGraph.getStateSize()];
   }
 
+  /**
+   * Construct PatternDFA for given path pattern. Only used for authentication 
now.
+   *
+   * @param prefixOrFullPatternTree the included PartialPath must be a prefix 
or a fullPath
+   */
+  public PatternDFA(PathPatternTree prefixOrFullPatternTree) {
+    // 1. build transition
+    boolean wildcard = false;
+    AtomicInteger transitionIndex = new AtomicInteger();
+    for (PartialPath pathPattern : 
prefixOrFullPatternTree.getAllPathPatterns()) {
+      for (String node : pathPattern.getNodes()) {
+        if (IoTDBConstant.ONE_LEVEL_PATH_WILDCARD.equals(node)
+            || IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD.equals(node)) {
+          wildcard = true;
+        } else {
+          transitionMap.computeIfAbsent(
+              node,
+              i -> {
+                IFATransition transition =
+                    new 
DFAPreciseTransition(transitionIndex.getAndIncrement(), node);
+                preciseMatchTransitionList.add(transition);
+                return transition;
+              });
+        }
+      }
+    }
+    if (wildcard) {
+      IFATransition transition =
+          new DFAWildcardTransition(
+              transitionIndex.getAndIncrement(), new 
ArrayList<>(transitionMap.keySet()));
+      transitionMap.put(transition.getAcceptEvent(), transition);
+      batchMatchTransitionList.add(transition);
+    }
+
+    // 2. build NFA
+    NFAGraph nfaGraph = new NFAGraph(prefixOrFullPatternTree, transitionMap);
+
+    // 3. NFA to DFA
+    dfaGraph = new DFAGraph(nfaGraph, transitionMap.values());
+    preciseMatchTransitionCached = new HashMap[dfaGraph.getStateSize()];
+    batchMatchTransitionCached = new List[dfaGraph.getStateSize()];
+  }
+
+  public IFAState getNextState(IFAState currentState, String acceptEvent) {
+    if (transitionMap.containsKey(acceptEvent)) {
+      return dfaGraph.getNextState(currentState, 
transitionMap.get(acceptEvent));
+    } else {
+      Iterator<IFATransition> fuzzyMatchTransitionIterator =
+          getFuzzyMatchTransitionIterator(currentState);
+      while (fuzzyMatchTransitionIterator.hasNext()) {
+        IFATransition transition = fuzzyMatchTransitionIterator.next();
+        if (transition.isMatch(acceptEvent)) {
+          return dfaGraph.getNextState(currentState, transition);
+        }
+      }
+    }
+    return null;
+  }
+
   @Override
   public Map<String, IFATransition> getPreciseMatchTransition(IFAState state) {
     if (preciseMatchTransitionCached[state.getIndex()] == null) {
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/dfa/graph/NFAGraph.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/dfa/graph/NFAGraph.java
index fa6299167e6..92a40719280 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/dfa/graph/NFAGraph.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/dfa/graph/NFAGraph.java
@@ -20,6 +20,7 @@ package org.apache.iotdb.commons.path.fa.dfa.graph;
 
 import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathPatternTree;
 import org.apache.iotdb.commons.path.fa.IFAState;
 import org.apache.iotdb.commons.path.fa.IFATransition;
 import org.apache.iotdb.commons.path.fa.dfa.DFAState;
@@ -30,6 +31,7 @@ import org.apache.commons.lang3.StringUtils;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 
 /**
@@ -42,6 +44,13 @@ public class NFAGraph {
   // [transitionIndex][stateIndex]List<IFAState>
   private final List<IFAState>[][] nfaTransitionTable;
 
+  /**
+   * Construct NFA graph for given path pattern.
+   *
+   * @param pathPattern matched path pattern
+   * @param isPrefix prefix match mode, matched pattern will be pathPattern.** 
if isPrefix is true
+   * @param transitionMap transitionMap
+   */
   public NFAGraph(
       PartialPath pathPattern, boolean isPrefix, Map<String, IFATransition> 
transitionMap) {
     nfaTransitionTable = new 
List[transitionMap.size()][pathPattern.getNodeLength() + 1];
@@ -84,6 +93,62 @@ public class NFAGraph {
     }
   }
 
+  /**
+   * Construct NFA graph for given path pattern. Only used for authentication 
now.
+   *
+   * @param prefixOrFullPatternTree the included PartialPath must be a prefix 
or a fullPath
+   * @param transitionMap transitionMap
+   */
+  public NFAGraph(
+      PathPatternTree prefixOrFullPatternTree, Map<String, IFATransition> 
transitionMap) {
+    List<PartialPath> partialPathList = 
prefixOrFullPatternTree.getAllPathPatterns();
+    int maxStateSize = 
partialPathList.stream().mapToInt(PartialPath::getNodeLength).sum() + 1;
+    nfaTransitionTable = new List[transitionMap.size()][maxStateSize];
+    // init start state, curNodeIndex=0
+    AtomicInteger stateIndexGenerator = new AtomicInteger(0);
+    nfaStateList.add(new DFAState(0));
+    for (int i = 0; i < transitionMap.size(); i++) {
+      nfaTransitionTable[i][0] = new ArrayList<>();
+    }
+    for (PartialPath pathPattern : partialPathList) {
+      buildPattern(pathPattern, transitionMap, stateIndexGenerator);
+    }
+  }
+
+  private void buildPattern(
+      PartialPath pathPattern,
+      Map<String, IFATransition> transitionMap,
+      AtomicInteger stateIndexGenerator) {
+    // traverse pathPattern and construct NFA
+    int prevIndex = 0;
+    for (int i = 0; i < pathPattern.getNodeLength(); i++) {
+      String node = pathPattern.getNodes()[i];
+      // if it is tail node, transit to final state
+      DFAState state =
+          i == pathPattern.getNodeLength() - 1
+              ? new DFAState(stateIndexGenerator.incrementAndGet(), true)
+              : new DFAState(stateIndexGenerator.incrementAndGet());
+      nfaStateList.add(state);
+      for (int j = 0; j < transitionMap.size(); j++) {
+        nfaTransitionTable[j][state.getIndex()] = new ArrayList<>();
+      }
+      // construct transition
+      if (IoTDBConstant.ONE_LEVEL_PATH_WILDCARD.equals(node)) {
+        for (IFATransition transition : transitionMap.values()) {
+          nfaTransitionTable[transition.getIndex()][prevIndex].add(state);
+        }
+      } else if (IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD.equals(node)) {
+        for (IFATransition transition : transitionMap.values()) {
+          nfaTransitionTable[transition.getIndex()][prevIndex].add(state);
+          
nfaTransitionTable[transition.getIndex()][state.getIndex()].add(state);
+        }
+      } else {
+        
nfaTransitionTable[transitionMap.get(node).getIndex()][prevIndex].add(state);
+      }
+      prevIndex = state.getIndex();
+    }
+  }
+
   @TestOnly
   public void print(Map<String, IFATransition> transitionMap) {
     System.out.println();
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/match/IStateMatchInfo.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/match/IStateMatchInfo.java
index 4e050c1d7e3..da582c32282 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/match/IStateMatchInfo.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/match/IStateMatchInfo.java
@@ -76,4 +76,6 @@ public interface IStateMatchInfo {
 
   /** @param sourceTransitionIterator the iterator of current checking source 
states' transition */
   void setSourceTransitionIterator(Iterator<IFATransition> 
sourceTransitionIterator);
+
+  IFAState getScopeMatchedState();
 }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/match/StateMultiMatchInfo.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/match/StateMultiMatchInfo.java
index fbad7e70a4b..a1974ba4134 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/match/StateMultiMatchInfo.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/match/StateMultiMatchInfo.java
@@ -38,21 +38,26 @@ public class StateMultiMatchInfo implements IStateMatchInfo 
{
 
   private boolean hasFinalState = false;
 
-  public StateMultiMatchInfo(IPatternFA patternFA) {
+  private final IFAState scopeState;
+
+  public StateMultiMatchInfo(IPatternFA patternFA, IFAState scopeState) {
     this.patternFA = patternFA;
     matchedStateSet = new MatchedStateSet(patternFA.getStateSize());
+    this.scopeState = scopeState;
   }
 
   public StateMultiMatchInfo(
       IPatternFA patternFA,
       IFAState matchedState,
-      Iterator<IFATransition> sourceTransitionIterator) {
+      Iterator<IFATransition> sourceTransitionIterator,
+      IFAState scopeState) {
     this.patternFA = patternFA;
     matchedStateSet = new MatchedStateSet(patternFA.getStateSize());
     matchedStateSet.add(matchedState);
     sourceStateIndex = 0;
     this.sourceTransitionIterator = sourceTransitionIterator;
     this.hasFinalState = matchedState.isFinal();
+    this.scopeState = scopeState;
   }
 
   @Override
@@ -117,4 +122,9 @@ public class StateMultiMatchInfo implements IStateMatchInfo 
{
   public void setSourceTransitionIterator(Iterator<IFATransition> 
sourceTransitionIterator) {
     this.sourceTransitionIterator = sourceTransitionIterator;
   }
+
+  @Override
+  public IFAState getScopeMatchedState() {
+    return scopeState;
+  }
 }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/match/StateSingleMatchInfo.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/match/StateSingleMatchInfo.java
index e3ccf7df613..e94319c907e 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/match/StateSingleMatchInfo.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/fa/match/StateSingleMatchInfo.java
@@ -32,9 +32,12 @@ public class StateSingleMatchInfo implements IStateMatchInfo 
{
 
   private final IFAState matchedState;
 
-  public StateSingleMatchInfo(IPatternFA patternFA, IFAState matchedState) {
+  private final IFAState scopeState;
+
+  public StateSingleMatchInfo(IPatternFA patternFA, IFAState matchedState, 
IFAState scopeState) {
     this.patternFA = patternFA;
     this.matchedState = matchedState;
+    this.scopeState = scopeState;
   }
 
   @Override
@@ -100,4 +103,9 @@ public class StateSingleMatchInfo implements 
IStateMatchInfo {
   public void setSourceTransitionIterator(Iterator<IFATransition> 
sourceTransitionIterator) {
     throw new UnsupportedOperationException();
   }
+
+  @Override
+  public IFAState getScopeMatchedState() {
+    return scopeState;
+  }
 }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/SchemaConstant.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/SchemaConstant.java
index 3b01d82e5d7..7717b1c679b 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/SchemaConstant.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/SchemaConstant.java
@@ -20,6 +20,8 @@ package org.apache.iotdb.commons.schema;
 
 import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathPatternTree;
+import org.apache.iotdb.commons.path.fa.dfa.PatternDFA;
 
 public class SchemaConstant {
 
@@ -54,7 +56,15 @@ public class SchemaConstant {
   public static final String SYSTEM_DATABASE = "root.__system";
 
   public static final String[] ALL_RESULT_NODES = new String[] {"root", "**"};
-  public static final PartialPath ALL_MATCH_PATTERN = new PartialPath(new 
String[] {"root", "**"});
+  public static final PartialPath ALL_MATCH_PATTERN = new 
PartialPath(ALL_RESULT_NODES);
+  public static final PathPatternTree ALL_MATCH_PATTERN_TREE = new 
PathPatternTree();
+
+  static {
+    ALL_MATCH_PATTERN_TREE.appendPathPattern(ALL_MATCH_PATTERN);
+    ALL_MATCH_PATTERN_TREE.constructTree();
+  }
+
+  public static final PatternDFA ALL_MATCH_DFA = new 
PatternDFA(ALL_MATCH_PATTERN, false);
   public static final PartialPath SYSTEM_DATABASE_PATTERN =
       new PartialPath(SYSTEM_DATABASE.split("\\."));
 
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/tree/AbstractTreeVisitor.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/tree/AbstractTreeVisitor.java
index 130d3c7143d..f678f379ff4 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/tree/AbstractTreeVisitor.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/tree/AbstractTreeVisitor.java
@@ -21,12 +21,15 @@ package org.apache.iotdb.commons.schema.tree;
 
 import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PathPatternTree;
 import org.apache.iotdb.commons.path.fa.IFAState;
 import org.apache.iotdb.commons.path.fa.IFATransition;
 import org.apache.iotdb.commons.path.fa.IPatternFA;
+import org.apache.iotdb.commons.path.fa.dfa.PatternDFA;
 import org.apache.iotdb.commons.path.fa.match.IStateMatchInfo;
 import org.apache.iotdb.commons.path.fa.match.StateMultiMatchInfo;
 import org.apache.iotdb.commons.path.fa.match.StateSingleMatchInfo;
+import org.apache.iotdb.commons.schema.SchemaConstant;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -73,6 +76,9 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
 
   // finite automation constructed from given path pattern or pattern tree
   protected final IPatternFA patternFA;
+  // deterministic finite automation for filtering traversed subtrees
+  private final PatternDFA scopeDFA;
+  private final boolean allScope;
 
   // run time variables
   // stack to store children iterator of visited ancestor
@@ -99,9 +105,16 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
   protected AbstractTreeVisitor() {
     root = null;
     patternFA = null;
+    scopeDFA = SchemaConstant.ALL_MATCH_DFA;
+    allScope = true;
   }
 
   protected AbstractTreeVisitor(N root, PartialPath pathPattern, boolean 
isPrefixMatch) {
+    this(root, pathPattern, isPrefixMatch, null);
+  }
+
+  protected AbstractTreeVisitor(
+      N root, PartialPath pathPattern, boolean isPrefixMatch, PathPatternTree 
scope) {
     this.root = root;
 
     boolean usingDFA = false;
@@ -121,6 +134,11 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
         usingDFA
             ? new 
IPatternFA.Builder().pattern(pathPattern).isPrefixMatch(isPrefixMatch).buildDFA()
             : new 
IPatternFA.Builder().pattern(pathPattern).isPrefixMatch(isPrefixMatch).buildNFA();
+    this.scopeDFA =
+        scope == null
+            ? SchemaConstant.ALL_MATCH_DFA
+            : (PatternDFA) new 
IPatternFA.Builder().patternTree(scope).buildDFA();
+    this.allScope = this.scopeDFA == SchemaConstant.ALL_MATCH_DFA;
   }
 
   /** This method must be invoked before iteration */
@@ -133,7 +151,8 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
       return;
     }
     IFAState rootState = patternFA.getNextState(initialState, transition);
-    currentStateMatchInfo = new StateSingleMatchInfo(patternFA, rootState);
+    IFAState initScopeState = 
scopeDFA.getNextState(scopeDFA.getInitialState(), root.getName());
+    currentStateMatchInfo = new StateSingleMatchInfo(patternFA, rootState, 
initScopeState);
     visitorStack.push(new VisitorStackEntry(createChildrenIterator(root), 1));
     ancestorStack.add(new AncestorStackEntry(root, currentStateMatchInfo));
   }
@@ -188,7 +207,7 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
   private void getNext() {
     nextMatchedNode = null;
     VisitorStackEntry stackEntry;
-    Iterator<N> iterator;
+    AbstractChildrenIterator iterator;
     while (!visitorStack.isEmpty()) {
       stackEntry = visitorStack.peek();
       iterator = stackEntry.iterator;
@@ -242,17 +261,15 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
       return new TraceBackChildrenIterator(parent, currentStateMatchInfo);
     } else if (currentStateMatchInfo.hasOnlyPreciseMatchTransition()) {
       // the child can be got directly with the precise value of transition
-      return new PreciseMatchChildrenIterator(parent, 
currentStateMatchInfo.getOneMatchedState());
+      return new PreciseMatchChildrenIterator(parent, currentStateMatchInfo);
     } else if (currentStateMatchInfo.hasNoPreciseMatchTransition()
         && currentStateMatchInfo.isSingleFuzzyMatchTransition()) {
       // only one transition which may match batch children, need to iterate 
and check all child
-      return new SingleFuzzyMatchChildrenIterator(
-          parent, currentStateMatchInfo.getOneMatchedState());
+      return new SingleFuzzyMatchChildrenIterator(parent, 
currentStateMatchInfo);
     } else {
       // child may be matched by multi transitions, precise match or fuzzy 
match,
       // which results in one child match multi state; need to iterate and 
check all child
-      return new MultiMatchTransitionChildrenIterator(
-          parent, currentStateMatchInfo.getOneMatchedState());
+      return new MultiMatchTransitionChildrenIterator(parent, 
currentStateMatchInfo);
     }
   }
 
@@ -368,6 +385,10 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
   // Get an iterator of all children.
   protected abstract Iterator<N> getChildrenIterator(N parent) throws 
Exception;
 
+  // Get an iterator of specific children.
+  protected abstract Iterator<N> getChildrenIterator(N parent, 
Iterator<String> childrenName)
+      throws Exception;
+
   // Release a child node.
   protected void releaseNode(N node) {}
 
@@ -430,17 +451,32 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
     }
   }
 
+  protected final IFAState getNextMatchedScopeState(IFAState currentState, N 
node) {
+    IFAState nextState = scopeDFA.getNextState(currentState, node.getName());
+    if (nextState == null && node.getAlias() != null) {
+      return scopeDFA.getNextState(currentState, node.getAlias());
+    }
+    return nextState;
+  }
+
   // implement common iterating logic of different children iterator
   private abstract class AbstractChildrenIterator implements Iterator<N> {
-
+    protected final N parent;
+    protected final IFAState currentScopeState;
     private N nextMatchedChild;
 
+    protected AbstractChildrenIterator(N parent, IFAState currentScopeState) {
+      this.parent = parent;
+      this.currentScopeState = currentScopeState;
+    }
+
     @Override
     public boolean hasNext() {
       if (nextMatchedChild == null) {
         try {
           getNext();
         } catch (Throwable e) {
+          logger.warn(e.getMessage(), e);
           throw new RuntimeException(e.getMessage(), e);
         }
       }
@@ -464,6 +500,15 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
 
     protected abstract void getNext() throws Exception;
 
+    protected final Iterator<N> initChildrenIterator() throws Exception {
+      if (!allScope && scopeDFA.getFuzzyMatchTransitionSize(currentScopeState) 
== 0) {
+        return getChildrenIterator(
+            parent, 
scopeDFA.getPreciseMatchTransition(currentScopeState).keySet().iterator());
+      } else {
+        return getChildrenIterator(parent);
+      }
+    }
+
     protected void close() {
       if (nextMatchedChild != null) {
         releaseNode(nextMatchedChild);
@@ -473,13 +518,12 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
 
   // the child can be got directly with the precise value of transition, 
there's no traceback
   private class PreciseMatchChildrenIterator extends AbstractChildrenIterator {
-    private final N parent;
     private final IFAState sourceState;
     private final Iterator<IFATransition> transitionIterator;
 
-    private PreciseMatchChildrenIterator(N parent, IFAState sourceState) {
-      this.parent = parent;
-      this.sourceState = sourceState;
+    private PreciseMatchChildrenIterator(N parent, IStateMatchInfo 
stateMatchInfo) {
+      super(parent, stateMatchInfo.getScopeMatchedState());
+      this.sourceState = stateMatchInfo.getOneMatchedState();
       transitionIterator = 
patternFA.getPreciseMatchTransitionIterator(sourceState);
     }
 
@@ -492,9 +536,16 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
         if (child == null) {
           continue;
         }
+        IFAState nextScopeState =
+            allScope ? null : getNextMatchedScopeState(currentScopeState, 
child);
+        if (!allScope && nextScopeState == null) {
+          releaseNode(child);
+          continue;
+        }
         saveResult(
             child,
-            new StateSingleMatchInfo(patternFA, 
patternFA.getNextState(sourceState, transition)));
+            new StateSingleMatchInfo(
+                patternFA, patternFA.getNextState(sourceState, transition), 
nextScopeState));
         return;
       }
     }
@@ -507,23 +558,18 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
 
     private final IFAState sourceState;
     private final IFATransition transition;
-    private final StateSingleMatchInfo stateMatchInfo;
-    private final N parent;
-
     private Iterator<N> childrenIterator;
 
-    private SingleFuzzyMatchChildrenIterator(N parent, IFAState sourceState) {
-      this.sourceState = sourceState;
+    private SingleFuzzyMatchChildrenIterator(N parent, IStateMatchInfo 
stateMatchInfo) {
+      super(parent, stateMatchInfo.getScopeMatchedState());
+      this.sourceState = stateMatchInfo.getOneMatchedState();
       this.transition = 
patternFA.getFuzzyMatchTransitionIterator(sourceState).next();
-      this.stateMatchInfo =
-          new StateSingleMatchInfo(patternFA, 
patternFA.getNextState(sourceState, transition));
-      this.parent = parent;
     }
 
     @Override
     protected void getNext() throws Exception {
       if (childrenIterator == null) {
-        this.childrenIterator = getChildrenIterator(parent);
+        this.childrenIterator = initChildrenIterator();
       }
       N child;
       while (childrenIterator.hasNext()) {
@@ -532,7 +578,12 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
           releaseNode(child);
           continue;
         }
-        saveResult(child, stateMatchInfo);
+        IFAState nextScopeState =
+            allScope ? null : getNextMatchedScopeState(currentScopeState, 
child);
+        saveResult(
+            child,
+            new StateSingleMatchInfo(
+                patternFA, patternFA.getNextState(sourceState, transition), 
nextScopeState));
         return;
       }
     }
@@ -554,20 +605,18 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
 
     private final IFAState sourceState;
     private final Map<String, IFATransition> preciseMatchTransitionMap;
-    private final N parent;
-
     private Iterator<N> iterator;
 
-    private MultiMatchTransitionChildrenIterator(N parent, IFAState 
sourceState) {
-      this.sourceState = sourceState;
+    private MultiMatchTransitionChildrenIterator(N parent, IStateMatchInfo 
stateMatchInfo) {
+      super(parent, stateMatchInfo.getScopeMatchedState());
+      this.sourceState = stateMatchInfo.getOneMatchedState();
       this.preciseMatchTransitionMap = 
patternFA.getPreciseMatchTransition(sourceState);
-      this.parent = parent;
     }
 
     @Override
     protected void getNext() throws Exception {
       if (iterator == null) {
-        this.iterator = getChildrenIterator(parent);
+        this.iterator = initChildrenIterator();
       }
       N child;
 
@@ -576,7 +625,8 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
       IStateMatchInfo stateMatchInfo;
       while (iterator.hasNext()) {
         child = iterator.next();
-
+        IFAState nextScopeState =
+            allScope ? null : getNextMatchedScopeState(currentScopeState, 
child);
         // find first matched state
         if (!preciseMatchTransitionMap.isEmpty()) {
           matchedState = tryGetNextState(child, sourceState, 
preciseMatchTransitionMap);
@@ -600,7 +650,9 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
           // not accept the first matched state since this node may be a 
target result, check the
           // other states
           if (patternFA.mayTransitionOverlap() && 
transitionIterator.hasNext()) {
-            stateMatchInfo = new StateMultiMatchInfo(patternFA, matchedState, 
transitionIterator);
+            stateMatchInfo =
+                new StateMultiMatchInfo(
+                    patternFA, matchedState, transitionIterator, 
nextScopeState);
             firstAncestorOfTraceback = ancestorStack.size();
 
             while (transitionIterator.hasNext()) {
@@ -613,15 +665,17 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
               }
             }
           } else {
-            stateMatchInfo = new StateSingleMatchInfo(patternFA, matchedState);
+            stateMatchInfo = new StateSingleMatchInfo(patternFA, matchedState, 
nextScopeState);
           }
         } else {
           // accept the first matched state, directly save it
           if (patternFA.mayTransitionOverlap() && 
transitionIterator.hasNext()) {
-            stateMatchInfo = new StateMultiMatchInfo(patternFA, matchedState, 
transitionIterator);
+            stateMatchInfo =
+                new StateMultiMatchInfo(
+                    patternFA, matchedState, transitionIterator, 
nextScopeState);
             firstAncestorOfTraceback = ancestorStack.size();
           } else {
-            stateMatchInfo = new StateSingleMatchInfo(patternFA, matchedState);
+            stateMatchInfo = new StateSingleMatchInfo(patternFA, matchedState, 
nextScopeState);
           }
         }
 
@@ -643,20 +697,18 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
   // the iterating process will try to get the first matched state of a child.
   private class TraceBackChildrenIterator extends AbstractChildrenIterator {
 
-    private final N parent;
     private final IStateMatchInfo sourceStateMatchInfo;
-
     private Iterator<N> iterator;
 
-    TraceBackChildrenIterator(N parent, IStateMatchInfo sourceStateMatchInfo) {
-      this.sourceStateMatchInfo = sourceStateMatchInfo;
-      this.parent = parent;
+    TraceBackChildrenIterator(N parent, IStateMatchInfo stateMatchInfo) {
+      super(parent, stateMatchInfo.getScopeMatchedState());
+      this.sourceStateMatchInfo = stateMatchInfo;
     }
 
     @Override
     protected void getNext() throws Exception {
       if (iterator == null) {
-        iterator = getChildrenIterator(parent);
+        this.iterator = initChildrenIterator();
       }
       N child;
 
@@ -668,8 +720,10 @@ public abstract class AbstractTreeVisitor<N extends 
ITreeNode, R> implements Sch
       while (iterator.hasNext()) {
 
         child = iterator.next();
+        IFAState nextScopeState =
+            allScope ? null : getNextMatchedScopeState(currentScopeState, 
child);
 
-        stateMatchInfo = new StateMultiMatchInfo(patternFA);
+        stateMatchInfo = new StateMultiMatchInfo(patternFA, nextScopeState);
         if (mayTargetNodeType(child)) {
           for (int i = 0; i < sourceStateMatchInfo.getMatchedStateSize(); i++) 
{
             sourceState = sourceStateMatchInfo.getMatchedState(i);
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/tree/ITreeNode.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/tree/ITreeNode.java
index 71537bc303d..4b7b30b5498 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/tree/ITreeNode.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/tree/ITreeNode.java
@@ -24,4 +24,8 @@ import java.io.Serializable;
 public interface ITreeNode extends Serializable {
 
   String getName();
+
+  default String getAlias() {
+    return null;
+  }
 }
diff --git 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/path/PatternDFATest.java
 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/path/PatternDFATest.java
index f0ee0579e9b..147d9d2f505 100644
--- 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/path/PatternDFATest.java
+++ 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/path/PatternDFATest.java
@@ -34,6 +34,7 @@ import org.junit.Ignore;
 import org.junit.Test;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -74,6 +75,50 @@ public class PatternDFATest {
     dfaGraph.print(transitionMap);
   }
 
+  @Test
+  @Ignore
+  public void printFASketch2() throws IllegalPathException {
+    // Map<AcceptEvent, IFATransition>
+    Map<String, IFATransition> transitionMap = new HashMap<>();
+    List<PartialPath> partialPathList =
+        Arrays.asList(
+            new PartialPath("root.sg2.**"),
+            new PartialPath("root.sg1.d1.**"),
+            new PartialPath("root.sg1.d2.**"),
+            new PartialPath("root.sg1.d2.s1"));
+    PathPatternTree patternTree = new PathPatternTree();
+    for (PartialPath pathPattern : partialPathList) {
+      patternTree.appendPathPattern(pathPattern);
+    }
+    patternTree.constructTree();
+    // 1. build transition
+    boolean wildcard = false;
+    AtomicInteger transitionIndex = new AtomicInteger();
+    for (PartialPath pathPattern : patternTree.getAllPathPatterns()) {
+      for (String node : pathPattern.getNodes()) {
+        if (IoTDBConstant.ONE_LEVEL_PATH_WILDCARD.equals(node)
+            || IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD.equals(node)) {
+          wildcard = true;
+        } else {
+          transitionMap.computeIfAbsent(
+              node, i -> new 
DFAPreciseTransition(transitionIndex.getAndIncrement(), node));
+        }
+      }
+    }
+    if (wildcard) {
+      IFATransition transition =
+          new DFAWildcardTransition(
+              transitionIndex.getAndIncrement(), new 
ArrayList<>(transitionMap.keySet()));
+      transitionMap.put(transition.getAcceptEvent(), transition);
+    }
+    // 2. build NFA
+    NFAGraph nfaGraph = new NFAGraph(patternTree, transitionMap);
+    nfaGraph.print(transitionMap);
+    // 3. NFA to DFA
+    DFAGraph dfaGraph = new DFAGraph(nfaGraph, transitionMap.values());
+    dfaGraph.print(transitionMap);
+  }
+
   @Test
   public void testMatchFullPath() throws IllegalPathException {
     PartialPath p1 = new PartialPath("root.sg1.d1.*");

Reply via email to