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

jt2594838 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 5a9c6b9f293 Fix SHOW TTL wildcard path scope (#18763)
5a9c6b9f293 is described below

commit 5a9c6b9f2934182f78185e7715df16b93626e264
Author: Hongzhi Gao <[email protected]>
AuthorDate: Wed Sep 30 12:09:35 2026 +0800

    Fix SHOW TTL wildcard path scope (#18763)
    
    * Fix SHOW TTL wildcard path scope
    
    * Fix SHOW TTL wildcard query and authority scope intersection
---
 .../iotdb/db/it/auth/IoTDBSeriesPermissionIT.java  | 68 ++++++++++++++++++++++
 .../config/executor/ClusterConfigTaskExecutor.java | 10 +++-
 2 files changed, 76 insertions(+), 2 deletions(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/db/it/auth/IoTDBSeriesPermissionIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/db/it/auth/IoTDBSeriesPermissionIT.java
index a0feb9712da..c6e23467413 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/db/it/auth/IoTDBSeriesPermissionIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/db/it/auth/IoTDBSeriesPermissionIT.java
@@ -354,6 +354,74 @@ public class IoTDBSeriesPermissionIT {
         "test123123456");
   }
 
+  @Test
+  public void showTTLWithMultiLevelWildcardTest() throws SQLException {
+    try (Connection connection = EnvFactory.getEnv().getConnection();
+        Statement statement = connection.createStatement()) {
+      statement.execute("create user ttl_scope_user 'test123123456'");
+      statement.execute("set ttl to root.ttl_scope_a 3600000");
+      statement.execute("set ttl to root.ttl_scope_b 7200000");
+
+      try (ResultSet resultSet = statement.executeQuery("show ttl on 
root.ttl_scope_a.g_0.**")) {
+        Assert.assertFalse(resultSet.next());
+      }
+
+      statement.execute("set ttl to root.ttl_scope_a.g_0.** 10000");
+      String[] headers =
+          
showTTLColumnHeaders.stream().map(ColumnHeader::getColumnName).toArray(String[]::new);
+      resultSetEqualTest(
+          "show ttl on root.ttl_scope_a.g_0.**",
+          headers,
+          new String[] {"root.ttl_scope_a.g_0.**,10000,"});
+
+      resultSetEqualTest(
+          "show ttl on root.*.**", headers, new String[0], "ttl_scope_user", 
"test123123456");
+      statement.execute("grant READ_SCHEMA on root.ttl_scope_a.** to user 
ttl_scope_user");
+      for (String query :
+          new String[] {"show ttl on root.*.**", "show ttl on root.ttl_*.**", 
"show all ttl"}) {
+        resultSetEqualTest(
+            query,
+            headers,
+            new String[] {"root.ttl_scope_a,3600000,", 
"root.ttl_scope_a.g_0.**,10000,"},
+            "ttl_scope_user",
+            "test123123456");
+      }
+      for (String query :
+          new String[] {"show ttl on root.*.g_*.**", "show ttl on 
root.ttl_*.g_0.**"}) {
+        resultSetEqualTest(
+            query,
+            headers,
+            new String[] {"root.ttl_scope_a.g_0.**,10000,"},
+            "ttl_scope_user",
+            "test123123456");
+      }
+      resultSetEqualTest(
+          "show ttl on root.ttl_scope_b.**",
+          headers,
+          new String[0],
+          "ttl_scope_user",
+          "test123123456");
+      statement.execute("revoke READ_SCHEMA on root.ttl_scope_a.** from user 
ttl_scope_user");
+      statement.execute("grant READ_SCHEMA on root.ttl_scope_a.g_0.** to user 
ttl_scope_user");
+      for (String query : new String[] {"show ttl on root.*.**", "show ttl on 
root.ttl_*.**"}) {
+        resultSetEqualTest(
+            query,
+            headers,
+            new String[] {"root.ttl_scope_a.g_0.**,10000,"},
+            "ttl_scope_user",
+            "test123123456");
+      }
+    } finally {
+      try (Connection connection = EnvFactory.getEnv().getConnection();
+          Statement statement = connection.createStatement()) {
+        executeQuietly(statement, "drop user ttl_scope_user");
+        executeQuietly(statement, "unset ttl from root.ttl_scope_a.g_0.**");
+        executeQuietly(statement, "unset ttl from root.ttl_scope_a");
+        executeQuietly(statement, "unset ttl from root.ttl_scope_b");
+      }
+    }
+  }
+
   @Test
   public void ttlOperationsTest() {
     try {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
index 7a3580fe66b..2ebfc3fdbc4 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
@@ -1786,13 +1786,19 @@ public class ClusterConfigTaskExecutor implements 
IConfigTaskExecutor {
           databaseToTTL.putAll(resp.getPathTTLMap());
           continue;
         }
+        PathPatternTree queryScope = new PathPatternTree();
+        queryScope.appendPathPattern(pathPattern);
+        queryScope.constructTree();
+        // Query patterns may contain wildcards before the trailing **. Only 
the authority
+        // scope is restricted to full paths and literal prefixes.
         for (PartialPath overlappedPathPattern :
-            authorityScope.getOverlappedPathPatterns(pathPattern)) {
+            
queryScope.intersectWithFullPathPrefixTree(authorityScope).getAllPathPatterns())
 {
           List<String> nodes = Arrays.asList(overlappedPathPattern.getNodes());
           TShowTTLReq req = new TShowTTLReq(nodes);
           TShowTTLResp resp = client.showTTL(req);
           databaseToTTL.putAll(resp.getPathTTLMap());
-          if (showTTLStatement.isShowAllTTL()) {
+          // TTL rules can be stored on the prefix itself as well as on 
prefix.**.
+          if (overlappedPathPattern.endWithMultiLevelWildcard()) {
             req.setPathPattern(nodes.subList(0, nodes.size() - 1));
             resp = client.showTTL(req);
             databaseToTTL.putAll(resp.getPathTTLMap());

Reply via email to