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 301033fe015 Show devices with template (#11681)
301033fe015 is described below

commit 301033fe015738d4a515b65434536d373096edac
Author: linxt20 <[email protected]>
AuthorDate: Fri Dec 15 20:24:22 2023 +0800

    Show devices with template (#11681)
    
    Show devices with template (#11681)
---
 .../org/apache/iotdb/db/it/IoTDBRestServiceIT.java | 30 ++++++++
 .../iotdb/db/it/auth/IoTDBSeriesPermissionIT.java  |  4 +-
 .../apache/iotdb/db/it/query/IoTDBResultSetIT.java |  7 +-
 .../iotdb/db/it/schema/IoTDBMetadataFetchIT.java   | 85 ++++++++++++++++++----
 .../apache/iotdb/pipe/it/IoTDBPipeExtractorIT.java | 22 +++---
 .../iotdb/zeppelin/it/IoTDBInterpreterIT.java      | 10 ++-
 .../org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4   |  6 +-
 .../common/header/ColumnHeaderConstant.java        | 10 ++-
 .../operator/schema/source/DeviceSchemaSource.java | 15 ++++
 .../db/queryengine/plan/parser/ASTVisitor.java     | 14 +++-
 .../mtree/impl/mem/MTreeBelowSGMemoryImpl.java     |  3 +-
 .../mtree/impl/pbtree/MTreeBelowSGCachedImpl.java  |  3 +-
 .../read/resp/info/IDeviceSchemaInfo.java          |  2 +
 .../read/resp/info/impl/ShowDevicesResult.java     | 11 +++
 .../utils/filter/DeviceFilterVisitor.java          | 26 +++++++
 .../schemaRegion/SchemaRegionBasicTest.java        | 42 +++++------
 .../db/protocol/rest/IoTDBRestServiceTest.java     | 15 ++++
 .../schema/SchemaQueryScanOperatorTest.java        |  6 +-
 .../apache/iotdb/commons/conf/IoTDBConstant.java   |  1 +
 .../iotdb/commons/schema/filter/SchemaFilter.java  |  3 +
 .../commons/schema/filter/SchemaFilterFactory.java |  5 ++
 .../commons/schema/filter/SchemaFilterType.java    |  3 +
 .../commons/schema/filter/SchemaFilterVisitor.java |  5 ++
 .../commons/schema/filter/impl/TemplateFilter.java | 73 +++++++++++++++++++
 24 files changed, 337 insertions(+), 64 deletions(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBRestServiceIT.java 
b/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBRestServiceIT.java
index 2db9f708c5c..39bf04adcd5 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBRestServiceIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBRestServiceIT.java
@@ -1305,6 +1305,7 @@ public class IoTDBRestServiceIT {
           {
             add("Device");
             add("IsAligned");
+            add("Template");
           }
         };
     List<Object> values1 =
@@ -1319,6 +1320,12 @@ public class IoTDBRestServiceIT {
             add(false);
           }
         };
+    List<String> values3 =
+        new ArrayList<String>() {
+          {
+            add("null");
+          }
+        };
     Assert.assertEquals(columnNames, columnNamesResult);
     Assert.assertEquals(values1, valuesResult.get(0));
   }
@@ -1335,6 +1342,7 @@ public class IoTDBRestServiceIT {
             add("Device");
             add("Database");
             add("IsAligned");
+            add("Template");
           }
         };
     List<Object> values1 =
@@ -1355,10 +1363,17 @@ public class IoTDBRestServiceIT {
             add("false");
           }
         };
+    List<Object> values4 =
+        new ArrayList<Object>() {
+          {
+            add("null");
+          }
+        };
     Assert.assertEquals(columnNames, columnNamesResult);
     Assert.assertEquals(values1, valuesResult.get(0));
     Assert.assertEquals(values2, valuesResult.get(1));
     Assert.assertEquals(values3, valuesResult.get(2));
+    Assert.assertEquals(values4, valuesResult.get(3));
   }
 
   public void listUser(CloseableHttpClient httpClient) {
@@ -1940,6 +1955,7 @@ public class IoTDBRestServiceIT {
           {
             add("Device");
             add("IsAligned");
+            add("Template");
           }
         };
     List<Object> values1 =
@@ -1954,6 +1970,12 @@ public class IoTDBRestServiceIT {
             add(false);
           }
         };
+    List<String> values3 =
+        new ArrayList<String>() {
+          {
+            add("null");
+          }
+        };
     Assert.assertEquals(columnNames, columnNamesResult);
     Assert.assertEquals(values1, valuesResult.get(0));
     // Assert.assertEquals(values2, valuesResult.get(1));
@@ -1971,6 +1993,7 @@ public class IoTDBRestServiceIT {
             add("Device");
             add("Database");
             add("IsAligned");
+            add("Template");
           }
         };
     List<Object> values1 =
@@ -1991,10 +2014,17 @@ public class IoTDBRestServiceIT {
             add("false");
           }
         };
+    List<Object> values4 =
+        new ArrayList<Object>() {
+          {
+            add("null");
+          }
+        };
     Assert.assertEquals(columnNames, columnNamesResult);
     Assert.assertEquals(values1, valuesResult.get(0));
     Assert.assertEquals(values2, valuesResult.get(1));
     Assert.assertEquals(values3, valuesResult.get(2));
+    Assert.assertEquals(values4, valuesResult.get(3));
   }
 
   public void listUserV2(CloseableHttpClient httpClient) {
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 c857ea5e8a3..f9c337bb488 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
@@ -173,14 +173,14 @@ public class IoTDBSeriesPermissionIT {
     resultSetEqualTest(
         "show devices",
         
showDevicesColumnHeaders.stream().map(ColumnHeader::getColumnName).toArray(String[]::new),
-        new String[] {"root.test.d1,false,"},
+        new String[] {"root.test.d1,false,null,"},
         "test1",
         "test123");
     grantUserSeriesPrivilege("test1", PrivilegeType.READ_SCHEMA, 
"root.test1.d1.**");
     resultSetEqualTest(
         "show devices",
         
showDevicesColumnHeaders.stream().map(ColumnHeader::getColumnName).toArray(String[]::new),
-        new String[] {"root.test.d1,false,", "root.test1.d1,false,"},
+        new String[] {"root.test.d1,false,null,", "root.test1.d1,false,null,"},
         "test1",
         "test123");
     resultSetEqualTest(
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBResultSetIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBResultSetIT.java
index e102e75bf31..696091069b5 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBResultSetIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBResultSetIT.java
@@ -186,7 +186,12 @@ public class IoTDBResultSetIT {
   @Test
   public void emptyShowDeviceTest() {
     String expectedHeader =
-        ColumnHeaderConstant.DEVICE + "," + ColumnHeaderConstant.IS_ALIGNED + 
",";
+        ColumnHeaderConstant.DEVICE
+            + ","
+            + ColumnHeaderConstant.IS_ALIGNED
+            + ","
+            + ColumnHeaderConstant.TEMPLATE
+            + ",";
     resultSetEqualTest("show devices root.sg1.**", expectedHeader, 
emptyResultSet);
   }
 
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 07fb82076f2..eb513a2bdb1 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
@@ -229,15 +229,67 @@ public class IoTDBMetadataFetchIT extends 
AbstractSchemaIT {
         Statement statement = connection.createStatement()) {
       String[] sqls =
           new String[] {
-            "show devices root.ln.** with database", "show devices 
root.ln.wf01.wt01.temperature"
+            "show devices root.ln.** with database", "show devices 
root.ln.wf01.wt01.temperature",
           };
       Set<String>[] standards =
           new Set[] {
             new HashSet<>(
                 Arrays.asList(
-                    "root.ln.wf01.wt01,root.ln.wf01.wt01,false,",
-                    "root.ln.wf01.wt02,root.ln.wf01.wt02,true,")),
-            new HashSet<>()
+                    "root.ln.wf01.wt01,root.ln.wf01.wt01,false,null,",
+                    "root.ln.wf01.wt02,root.ln.wf01.wt02,true,null,")),
+            new HashSet<>(),
+          };
+
+      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 showDevicesWithTemplate() throws SQLException {
+    try (Connection connection = EnvFactory.getEnv().getConnection();
+        Statement statement = connection.createStatement()) {
+      statement.execute("CREATE DATABASE root.sg1");
+      statement.execute("CREATE DATABASE root.sg2");
+      statement.execute("CREATE DEVICE TEMPLATE t1 (s1 INT64, s2 DOUBLE)");
+      statement.execute("CREATE DEVICE TEMPLATE t2 aligned (s1 INT64, s2 
DOUBLE)");
+      statement.execute("SET DEVICE TEMPLATE t1 TO root.sg1.d1");
+      statement.execute("SET DEVICE TEMPLATE t2 TO root.sg1.d2");
+      statement.execute("SET DEVICE TEMPLATE t1 TO root.sg2.d1");
+      statement.execute("SET DEVICE TEMPLATE t2 TO root.sg2.d2");
+      statement.execute("CREATE TIMESERIES OF DEVICE TEMPLATE ON root.sg1.d2");
+      statement.execute("CREATE TIMESERIES OF DEVICE TEMPLATE ON root.sg2.d1");
+      statement.execute("CREATE TIMESERIES OF DEVICE TEMPLATE ON root.sg2.d2");
+
+      String[] sqls =
+          new String[] {
+            "show devices root.** where template != null",
+            "show devices root.sg2.** with database where template = t2",
+          };
+      Set<String>[] standards =
+          new Set[] {
+            new HashSet<>(
+                Arrays.asList(
+                    "root.sg1.d2,true,t2,", "root.sg2.d1,false,t1,", 
"root.sg2.d2,true,t2,")),
+            new HashSet<>(Arrays.asList("root.sg2.d2,root.sg2,true,t2,")),
           };
 
       for (int n = 0; n < sqls.length; n++) {
@@ -251,7 +303,6 @@ public class IoTDBMetadataFetchIT extends AbstractSchemaIT {
               builder.append(resultSet.getString(i)).append(",");
             }
             String string = builder.toString();
-            System.out.println(string);
             Assert.assertTrue(standard.contains(string));
             standard.remove(string);
           }
@@ -272,13 +323,14 @@ public class IoTDBMetadataFetchIT extends 
AbstractSchemaIT {
           new String[] {
             "show devices root.ln.**",
             "show devices root.ln.wf01.wt01.temperature",
-            "show devices root.** where device contains 'wt02'"
+            "show devices root.** where device contains 'wt02'",
           };
       Set<String>[] standards =
           new Set[] {
-            new HashSet<>(Arrays.asList("root.ln.wf01.wt01,false,", 
"root.ln.wf01.wt02,true,")),
+            new HashSet<>(
+                Arrays.asList("root.ln.wf01.wt01,false,null,", 
"root.ln.wf01.wt02,true,null,")),
             new HashSet<>(),
-            new HashSet<>(Arrays.asList("root.ln.wf01.wt02,true,")),
+            new HashSet<>(Arrays.asList("root.ln.wf01.wt02,true,null,")),
           };
 
       for (int n = 0; n < sqls.length; n++) {
@@ -318,16 +370,17 @@ public class IoTDBMetadataFetchIT extends 
AbstractSchemaIT {
           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,")),
+                    "root.ln.wf01.wt01,false,null,",
+                    "root.ln.wf01.wt02,true,null,",
+                    "root.ln1.wf01.wt01,false,null,",
+                    "root.ln2.wf01.wt01,false,null,")),
+            new HashSet<>(
+                Arrays.asList("root.ln.wf01.wt01,false,null,", 
"root.ln.wf01.wt02,true,null,")),
             new HashSet<>(
                 Arrays.asList(
-                    "root.ln.wf01.wt01,false,",
-                    "root.ln1.wf01.wt01,false,",
-                    "root.ln2.wf01.wt01,false,"))
+                    "root.ln.wf01.wt01,false,null,",
+                    "root.ln1.wf01.wt01,false,null,",
+                    "root.ln2.wf01.wt01,false,null,"))
           };
 
       for (int n = 0; n < sqls.length; n++) {
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/pipe/it/IoTDBPipeExtractorIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/pipe/it/IoTDBPipeExtractorIT.java
index f3b363db345..7a8840a31b6 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/pipe/it/IoTDBPipeExtractorIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/pipe/it/IoTDBPipeExtractorIT.java
@@ -272,19 +272,19 @@ public class IoTDBPipeExtractorIT extends 
AbstractPipeDualIT {
       TestUtils.assertDataOnEnv(
           receiverEnv,
           "show devices",
-          "Device,IsAligned,",
+          "Device,IsAligned,Template,",
           new HashSet<>(
               Arrays.asList(
-                  "root.nonAligned.1TS,false,",
-                  "root.nonAligned.100TS,false,",
-                  "root.nonAligned.1000TS,false,",
-                  "root.nonAligned.`1(TS)`,false,",
-                  "root.nonAligned.6TS.`6`,false,",
-                  "root.aligned.1TS,true,",
-                  "root.aligned.100TS,true,",
-                  "root.aligned.1000TS,true,",
-                  "root.aligned.`1(TS)`,true,",
-                  "root.aligned.6TS.`6`,true,")));
+                  "root.nonAligned.1TS,false,null,",
+                  "root.nonAligned.100TS,false,null,",
+                  "root.nonAligned.1000TS,false,null,",
+                  "root.nonAligned.`1(TS)`,false,null,",
+                  "root.nonAligned.6TS.`6`,false,null,",
+                  "root.aligned.1TS,true,null,",
+                  "root.aligned.100TS,true,null,",
+                  "root.aligned.1000TS,true,null,",
+                  "root.aligned.`1(TS)`,true,null,",
+                  "root.aligned.6TS.`6`,true,null,")));
     }
   }
 
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/zeppelin/it/IoTDBInterpreterIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/zeppelin/it/IoTDBInterpreterIT.java
index 92a26f70ff1..e64afb2ea00 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/zeppelin/it/IoTDBInterpreterIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/zeppelin/it/IoTDBInterpreterIT.java
@@ -326,7 +326,9 @@ public class IoTDBInterpreterIT {
   public void testShowDevices() {
     InterpreterResult actual = interpreter.internalInterpret("show devices", 
null);
     String gt =
-        "Device\tIsAligned\n" + "root.test.wf01.wt01\tfalse\n" + 
"root.test.wf02.wt02\tfalse";
+        "Device\tIsAligned\tTemplate\n"
+            + "root.test.wf01.wt01\tfalse\tnull\n"
+            + "root.test.wf02.wt02\tfalse\tnull";
     Assert.assertNotNull(actual);
     Assert.assertEquals(Code.SUCCESS, actual.code());
     Assert.assertEquals(gt, actual.message().get(0).getData());
@@ -336,9 +338,9 @@ public class IoTDBInterpreterIT {
   public void testShowDevicesWithSg() {
     InterpreterResult actual = interpreter.internalInterpret("show devices 
with database", null);
     String gt =
-        "Device\tDatabase\tIsAligned\n"
-            + "root.test.wf01.wt01\troot.test.wf01\tfalse\n"
-            + "root.test.wf02.wt02\troot.test.wf02\tfalse";
+        "Device\tDatabase\tIsAligned\tTemplate\n"
+            + "root.test.wf01.wt01\troot.test.wf01\tfalse\tnull\n"
+            + "root.test.wf02.wt02\troot.test.wf02\tfalse\tnull";
     Assert.assertNotNull(actual);
     Assert.assertEquals(Code.SUCCESS, actual.code());
     Assert.assertEquals(gt, actual.message().get(0).getData());
diff --git 
a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 
b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
index 2269df84f16..9167ef49aa5 100644
--- 
a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
+++ 
b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
@@ -210,7 +210,11 @@ countNodes
 
 // ---- Timeseries Where Clause
 devicesWhereClause
-    : WHERE deviceContainsExpression
+    : WHERE (deviceContainsExpression | templateEqualExpression)
+    ;
+
+templateEqualExpression
+    : TEMPLATE (OPERATOR_SEQ | OPERATOR_NEQ)  templateName=identifier
     ;
 
 deviceContainsExpression
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/header/ColumnHeaderConstant.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/header/ColumnHeaderConstant.java
index 9c81c761cd5..39456586239 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/header/ColumnHeaderConstant.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/common/header/ColumnHeaderConstant.java
@@ -49,6 +49,8 @@ public class ColumnHeaderConstant {
   public static final String DEADBAND = "Deadband";
   public static final String DEADBAND_PARAMETERS = "DeadbandParameters";
   public static final String IS_ALIGNED = "IsAligned";
+  public static final String TEMPLATE = "Template";
+
   public static final String COUNT = "Count";
   public static final String COLUMN_TTL = "TTL";
   public static final String SCHEMA_REPLICATION_FACTOR = 
"SchemaReplicationFactor";
@@ -210,12 +212,14 @@ public class ColumnHeaderConstant {
       ImmutableList.of(
           new ColumnHeader(DEVICE, TSDataType.TEXT),
           new ColumnHeader(DATABASE, TSDataType.TEXT),
-          new ColumnHeader(IS_ALIGNED, TSDataType.TEXT));
+          new ColumnHeader(IS_ALIGNED, TSDataType.TEXT),
+          new ColumnHeader(TEMPLATE, TSDataType.TEXT));
 
   public static final List<ColumnHeader> showDevicesColumnHeaders =
       ImmutableList.of(
-          new ColumnHeader(DEVICE, TSDataType.TEXT), new 
ColumnHeader(IS_ALIGNED, TSDataType.TEXT));
-
+          new ColumnHeader(DEVICE, TSDataType.TEXT),
+          new ColumnHeader(IS_ALIGNED, TSDataType.TEXT),
+          new ColumnHeader(TEMPLATE, TSDataType.TEXT));
   public static final List<ColumnHeader> showTTLColumnHeaders =
       ImmutableList.of(
           new ColumnHeader(DATABASE, TSDataType.TEXT),
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/DeviceSchemaSource.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/DeviceSchemaSource.java
index 4601a429c0f..75706cc3003 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/DeviceSchemaSource.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/schema/source/DeviceSchemaSource.java
@@ -31,12 +31,14 @@ import 
org.apache.iotdb.db.schemaengine.schemaregion.ISchemaRegion;
 import 
org.apache.iotdb.db.schemaengine.schemaregion.read.req.SchemaRegionReadPlanFactory;
 import 
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.IDeviceSchemaInfo;
 import 
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.reader.ISchemaReader;
+import org.apache.iotdb.db.schemaengine.template.ClusterTemplateManager;
 import org.apache.iotdb.tsfile.common.conf.TSFileConfig;
 import org.apache.iotdb.tsfile.read.common.block.TsBlockBuilder;
 import org.apache.iotdb.tsfile.utils.Binary;
 
 import java.util.List;
 
+import static org.apache.iotdb.commons.conf.IoTDBConstant.STRING_NULL;
 import static org.apache.iotdb.commons.schema.SchemaConstant.ALL_MATCH_PATTERN;
 
 public class DeviceSchemaSource implements ISchemaSource<IDeviceSchemaInfo> {
@@ -96,15 +98,28 @@ public class DeviceSchemaSource implements 
ISchemaSource<IDeviceSchemaInfo> {
     builder
         .getColumnBuilder(0)
         .writeBinary(new Binary(device.getFullPath(), 
TSFileConfig.STRING_CHARSET));
+
+    String templateName = STRING_NULL;
+    int templateId = device.getTemplateId();
+    if (templateId != -1) {
+      templateName = 
ClusterTemplateManager.getInstance().getTemplate(templateId).getName();
+    }
+
     if (hasSgCol) {
       builder.getColumnBuilder(1).writeBinary(new Binary(database, 
TSFileConfig.STRING_CHARSET));
       builder
           .getColumnBuilder(2)
           .writeBinary(new Binary(String.valueOf(device.isAligned()), 
TSFileConfig.STRING_CHARSET));
+      builder
+          .getColumnBuilder(3)
+          .writeBinary(new Binary(String.valueOf(templateName), 
TSFileConfig.STRING_CHARSET));
     } else {
       builder
           .getColumnBuilder(1)
           .writeBinary(new Binary(String.valueOf(device.isAligned()), 
TSFileConfig.STRING_CHARSET));
+      builder
+          .getColumnBuilder(2)
+          .writeBinary(new Binary(String.valueOf(templateName), 
TSFileConfig.STRING_CHARSET));
     }
     builder.declarePosition();
   }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
index 43e1e95465a..a451232ccde 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
@@ -709,8 +709,18 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
 
   private SchemaFilter 
parseDevicesWhereClause(IoTDBSqlParser.DevicesWhereClauseContext ctx) {
     // path contains filter
-    return SchemaFilterFactory.createPathContainsFilter(
-        parseStringLiteral(ctx.deviceContainsExpression().value.getText()));
+    if (ctx.deviceContainsExpression() != null) {
+      return SchemaFilterFactory.createPathContainsFilter(
+          parseStringLiteral(ctx.deviceContainsExpression().value.getText()));
+    } else {
+      if (ctx.templateEqualExpression().OPERATOR_SEQ() != null) {
+        return SchemaFilterFactory.createTemplateNameFilter(
+            
parseIdentifier(ctx.templateEqualExpression().templateName.getText()), true);
+      } else {
+        return SchemaFilterFactory.createTemplateNameFilter(
+            
parseIdentifier(ctx.templateEqualExpression().templateName.getText()), false);
+      }
+    }
   }
 
   // Count Devices 
========================================================================
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/MTreeBelowSGMemoryImpl.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/MTreeBelowSGMemoryImpl.java
index ffb8cf41052..6ae0817ea39 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/MTreeBelowSGMemoryImpl.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/MTreeBelowSGMemoryImpl.java
@@ -949,7 +949,8 @@ public class MTreeBelowSGMemoryImpl {
 
           protected IDeviceSchemaInfo collectEntity(IDeviceMNode<IMemMNode> 
node) {
             PartialPath device = 
getPartialPathFromRootToNode(node.getAsMNode());
-            return new ShowDevicesResult(device.getFullPath(), 
node.isAlignedNullable());
+            return new ShowDevicesResult(
+                device.getFullPath(), node.isAlignedNullable(), 
node.getSchemaTemplateId());
           }
         };
     if (showDevicesPlan.usingSchemaTemplate()) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/MTreeBelowSGCachedImpl.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/MTreeBelowSGCachedImpl.java
index 7b695f5e0e6..b334ea163d0 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/MTreeBelowSGCachedImpl.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/MTreeBelowSGCachedImpl.java
@@ -1267,7 +1267,8 @@ public class MTreeBelowSGCachedImpl {
 
           protected IDeviceSchemaInfo collectEntity(IDeviceMNode<ICachedMNode> 
node) {
             PartialPath device = 
getPartialPathFromRootToNode(node.getAsMNode());
-            return new ShowDevicesResult(device.getFullPath(), 
node.isAlignedNullable());
+            return new ShowDevicesResult(
+                device.getFullPath(), node.isAlignedNullable(), 
node.getSchemaTemplateId());
           }
         };
     if (showDevicesPlan.usingSchemaTemplate()) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/resp/info/IDeviceSchemaInfo.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/resp/info/IDeviceSchemaInfo.java
index e709a3f114b..9a670f9b44b 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/resp/info/IDeviceSchemaInfo.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/resp/info/IDeviceSchemaInfo.java
@@ -22,4 +22,6 @@ package 
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info;
 public interface IDeviceSchemaInfo extends ISchemaInfo {
 
   Boolean isAligned();
+
+  int getTemplateId();
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/resp/info/impl/ShowDevicesResult.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/resp/info/impl/ShowDevicesResult.java
index fb111bffe84..47c5abb8293 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/resp/info/impl/ShowDevicesResult.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/read/resp/info/impl/ShowDevicesResult.java
@@ -24,16 +24,27 @@ import java.util.Objects;
 
 public class ShowDevicesResult extends ShowSchemaResult implements 
IDeviceSchemaInfo {
   private Boolean isAligned;
+  private int templateId;
 
   public ShowDevicesResult(String name, Boolean isAligned) {
     super(name);
     this.isAligned = isAligned;
   }
 
+  public ShowDevicesResult(String name, Boolean isAligned, int templateId) {
+    super(name);
+    this.isAligned = isAligned;
+    this.templateId = templateId;
+  }
+
   public Boolean isAligned() {
     return isAligned;
   }
 
+  public int getTemplateId() {
+    return templateId;
+  }
+
   @Override
   public String toString() {
     return "ShowDevicesResult{"
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/utils/filter/DeviceFilterVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/utils/filter/DeviceFilterVisitor.java
index c28e4b1ceb3..d643e8d74ac 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/utils/filter/DeviceFilterVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/utils/filter/DeviceFilterVisitor.java
@@ -22,7 +22,11 @@ package 
org.apache.iotdb.db.schemaengine.schemaregion.utils.filter;
 import org.apache.iotdb.commons.schema.filter.SchemaFilter;
 import org.apache.iotdb.commons.schema.filter.SchemaFilterVisitor;
 import org.apache.iotdb.commons.schema.filter.impl.PathContainsFilter;
+import org.apache.iotdb.commons.schema.filter.impl.TemplateFilter;
 import 
org.apache.iotdb.db.schemaengine.schemaregion.read.resp.info.IDeviceSchemaInfo;
+import org.apache.iotdb.db.schemaengine.template.ClusterTemplateManager;
+
+import static org.apache.iotdb.commons.conf.IoTDBConstant.STRING_NULL;
 
 public class DeviceFilterVisitor extends 
SchemaFilterVisitor<IDeviceSchemaInfo> {
   @Override
@@ -38,4 +42,26 @@ public class DeviceFilterVisitor extends 
SchemaFilterVisitor<IDeviceSchemaInfo>
     }
     return 
info.getFullPath().toLowerCase().contains(pathContainsFilter.getContainString());
   }
+
+  @Override
+  public boolean visitTemplateFilter(TemplateFilter templateFilter, 
IDeviceSchemaInfo info) {
+    if (templateFilter.getTemplateName() == null) {
+      return true;
+    }
+    String templateName = STRING_NULL;
+    boolean equalAns;
+    int TemplateId = info.getTemplateId();
+    if (TemplateId != -1) {
+      templateName = 
ClusterTemplateManager.getInstance().getTemplate(TemplateId).getName();
+      equalAns = templateName.equals(templateFilter.getTemplateName());
+    } else {
+      equalAns = 
templateName.equalsIgnoreCase(templateFilter.getTemplateName());
+    }
+
+    if (templateFilter.isEqual()) {
+      return equalAns;
+    } else {
+      return !equalAns;
+    }
+  }
 }
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionBasicTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionBasicTest.java
index 9b341681576..6365934b407 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionBasicTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionBasicTest.java
@@ -679,29 +679,29 @@ public class SchemaRegionBasicTest extends 
AbstractSchemaRegionTest {
 
     // CASE 02. Query an existing device.
     Assert.assertEquals(
-        Collections.singletonList(new ShowDevicesResult("root.laptop.d1", 
false)),
+        Collections.singletonList(new ShowDevicesResult("root.laptop.d1", 
false, -1)),
         SchemaRegionTestUtil.getMatchedDevices(schemaRegion, new 
PartialPath("root.laptop.d1")));
     Assert.assertEquals(
-        Collections.singletonList(new ShowDevicesResult("root.laptop.d2", 
false)),
+        Collections.singletonList(new ShowDevicesResult("root.laptop.d2", 
false, -1)),
         SchemaRegionTestUtil.getMatchedDevices(schemaRegion, new 
PartialPath("root.laptop.d2")));
 
     // CASE 03. Query an existing device, which has a sub device
     Assert.assertEquals(
-        Collections.singletonList(new ShowDevicesResult("root.laptop", false)),
+        Collections.singletonList(new ShowDevicesResult("root.laptop", false, 
-1)),
         SchemaRegionTestUtil.getMatchedDevices(schemaRegion, new 
PartialPath("root.laptop")));
 
     // CASE 04. Query devices using '*'
     Assert.assertEquals(
-        Collections.singletonList(new ShowDevicesResult("root.laptop", false)),
+        Collections.singletonList(new ShowDevicesResult("root.laptop", false, 
-1)),
         SchemaRegionTestUtil.getMatchedDevices(schemaRegion, new 
PartialPath("root.*")));
 
     // CASE 05. Query all devices using 'root.**'
     List<IDeviceSchemaInfo> expectedList =
         Arrays.asList(
-            new ShowDevicesResult("root.laptop", false),
-            new ShowDevicesResult("root.laptop.d1", false),
-            new ShowDevicesResult("root.laptop.d2", false),
-            new ShowDevicesResult("root.laptop.d1.s2", false));
+            new ShowDevicesResult("root.laptop", false, -1),
+            new ShowDevicesResult("root.laptop.d1", false, -1),
+            new ShowDevicesResult("root.laptop.d2", false, -1),
+            new ShowDevicesResult("root.laptop.d1.s2", false, -1));
     List<IDeviceSchemaInfo> actualResult =
         SchemaRegionTestUtil.getMatchedDevices(schemaRegion, new 
PartialPath("root.**"));
     // Compare hash sets because the order does not matter.
@@ -712,8 +712,8 @@ public class SchemaRegionBasicTest extends 
AbstractSchemaRegionTest {
     // CASE 06. show devices root.**.d*
     expectedList =
         Arrays.asList(
-            new ShowDevicesResult("root.laptop.d1", false),
-            new ShowDevicesResult("root.laptop.d2", false));
+            new ShowDevicesResult("root.laptop.d1", false, -1),
+            new ShowDevicesResult("root.laptop.d2", false, -1));
     actualResult =
         SchemaRegionTestUtil.getMatchedDevices(schemaRegion, new 
PartialPath("root.**.d*"));
     // Compare hash sets because the order does not matter.
@@ -744,10 +744,10 @@ public class SchemaRegionBasicTest extends 
AbstractSchemaRegionTest {
     // CASE 11. show devices root.** where device contains 'laptop'
     expectedList =
         Arrays.asList(
-            new ShowDevicesResult("root.laptop", false),
-            new ShowDevicesResult("root.laptop.d1", false),
-            new ShowDevicesResult("root.laptop.d1.s2", false),
-            new ShowDevicesResult("root.laptop.d2", false));
+            new ShowDevicesResult("root.laptop", false, -1),
+            new ShowDevicesResult("root.laptop.d1", false, -1),
+            new ShowDevicesResult("root.laptop.d1.s2", false, -1),
+            new ShowDevicesResult("root.laptop.d2", false, -1));
     actualResult =
         SchemaRegionTestUtil.getMatchedDevices(
             schemaRegion,
@@ -762,8 +762,8 @@ public class SchemaRegionBasicTest extends 
AbstractSchemaRegionTest {
     // CASE 11. show devices root.** where device contains 'laptop.d' limit 2 
offset 0
     expectedList =
         Arrays.asList(
-            new ShowDevicesResult("root.laptop.d1", false),
-            new ShowDevicesResult("root.laptop.d1.s2", false));
+            new ShowDevicesResult("root.laptop.d1", false, -1),
+            new ShowDevicesResult("root.laptop.d1.s2", false, -1));
     actualResult =
         SchemaRegionTestUtil.getMatchedDevices(
             schemaRegion,
@@ -968,9 +968,9 @@ public class SchemaRegionBasicTest extends 
AbstractSchemaRegionTest {
 
     List<IDeviceSchemaInfo> expectedList =
         Arrays.asList(
-            new ShowDevicesResult("root.test.d1", false),
-            new ShowDevicesResult("root.test.dac.device1", false),
-            new ShowDevicesResult("root.test.dac.device1.d1", false));
+            new ShowDevicesResult("root.test.d1", false, -1),
+            new ShowDevicesResult("root.test.dac.device1", false, -1),
+            new ShowDevicesResult("root.test.dac.device1.d1", false, -1));
     List<IDeviceSchemaInfo> actualResult =
         SchemaRegionTestUtil.getMatchedDevices(schemaRegion, new 
PartialPath("root.**.d*"));
     // Compare hash sets because the order does not matter.
@@ -1008,8 +1008,8 @@ public class SchemaRegionBasicTest extends 
AbstractSchemaRegionTest {
     // case1: show devices root.**.*b*.*
     List<IDeviceSchemaInfo> expectedList =
         Arrays.asList(
-            new ShowDevicesResult("root.test.abc57.bcde22.def89", false),
-            new ShowDevicesResult("root.test.abc57.bcd22.def89", false));
+            new ShowDevicesResult("root.test.abc57.bcde22.def89", false, -1),
+            new ShowDevicesResult("root.test.abc57.bcd22.def89", false, -1));
     List<IDeviceSchemaInfo> actualResult =
         SchemaRegionTestUtil.getMatchedDevices(schemaRegion, new 
PartialPath("root.**.*b*.*"));
     // Compare hash sets because the order does not matter.
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/protocol/rest/IoTDBRestServiceTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/protocol/rest/IoTDBRestServiceTest.java
index 62d43b9018c..e87bfa58335 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/protocol/rest/IoTDBRestServiceTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/protocol/rest/IoTDBRestServiceTest.java
@@ -754,6 +754,7 @@ public class IoTDBRestServiceTest {
           {
             add("devices");
             add("isAligned");
+            add("Template");
           }
         };
     List<Object> values1 =
@@ -768,6 +769,12 @@ public class IoTDBRestServiceTest {
             add(false);
           }
         };
+    List<String> values3 =
+        new ArrayList<String>() {
+          {
+            add("null");
+          }
+        };
     Assert.assertEquals(columnNames, columnNamesResult);
     Assert.assertEquals(values1, valuesResult.get(0));
     // Assert.assertEquals(values2, valuesResult.get(1));
@@ -785,6 +792,7 @@ public class IoTDBRestServiceTest {
             add("devices");
             add("database");
             add("isAligned");
+            add("Template");
           }
         };
     List<Object> values1 =
@@ -805,10 +813,17 @@ public class IoTDBRestServiceTest {
             add("false");
           }
         };
+    List<Object> values4 =
+        new ArrayList<Object>() {
+          {
+            add("null");
+          }
+        };
     Assert.assertEquals(columnNames, columnNamesResult);
     Assert.assertEquals(values1, valuesResult.get(0));
     Assert.assertEquals(values2, valuesResult.get(1));
     Assert.assertEquals(values3, valuesResult.get(2));
+    Assert.assertEquals(values4, valuesResult.get(3));
   }
 
   public void listUser(CloseableHttpClient httpClient) {
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaQueryScanOperatorTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaQueryScanOperatorTest.java
index d64cb543c03..615dae412ed 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaQueryScanOperatorTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/execution/operator/schema/SchemaQueryScanOperatorTest.java
@@ -88,6 +88,7 @@ public class SchemaQueryScanOperatorTest {
       Mockito.when(deviceSchemaInfo.getFullPath())
           .thenReturn(META_SCAN_OPERATOR_TEST_SG + ".device0");
       Mockito.when(deviceSchemaInfo.isAligned()).thenReturn(false);
+      Mockito.when(deviceSchemaInfo.getTemplateId()).thenReturn(-1);
       operatorContext.setDriverContext(
           new SchemaDriverContext(fragmentInstanceContext, schemaRegion, 0));
       ISchemaSource<IDeviceSchemaInfo> deviceSchemaSource =
@@ -107,7 +108,7 @@ public class SchemaQueryScanOperatorTest {
       //
       while (devicesSchemaScanOperator.hasNext()) {
         TsBlock tsBlock = devicesSchemaScanOperator.next();
-        assertEquals(3, tsBlock.getValueColumnCount());
+        assertEquals(4, tsBlock.getValueColumnCount());
         assertTrue(tsBlock.getColumn(0) instanceof BinaryColumn);
         assertEquals(1, tsBlock.getPositionCount());
         for (int i = 0; i < tsBlock.getPositionCount(); i++) {
@@ -126,6 +127,9 @@ public class SchemaQueryScanOperatorTest {
               case 2:
                 assertEquals("false", 
tsBlock.getColumn(j).getBinary(i).toString());
                 break;
+              case 3:
+                assertEquals("null", 
tsBlock.getColumn(j).getBinary(i).toString());
+                break;
               default:
                 break;
             }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/IoTDBConstant.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/IoTDBConstant.java
index 9b7c37782b3..df1aec9eaa4 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/IoTDBConstant.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/conf/IoTDBConstant.java
@@ -336,4 +336,5 @@ public class IoTDBConstant {
   public static final String TIER_SEPARATOR = ";";
 
   public static final String OBJECT_STORAGE_DIR = "object_storage";
+  public static final String STRING_NULL = "null";
 }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilter.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilter.java
index 09a8ab70215..ef76ddcd69b 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilter.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilter.java
@@ -23,6 +23,7 @@ import org.apache.iotdb.commons.schema.filter.impl.AndFilter;
 import org.apache.iotdb.commons.schema.filter.impl.DataTypeFilter;
 import org.apache.iotdb.commons.schema.filter.impl.PathContainsFilter;
 import org.apache.iotdb.commons.schema.filter.impl.TagFilter;
+import org.apache.iotdb.commons.schema.filter.impl.TemplateFilter;
 import org.apache.iotdb.commons.schema.filter.impl.ViewTypeFilter;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
@@ -69,6 +70,8 @@ public abstract class SchemaFilter {
         return new ViewTypeFilter(byteBuffer);
       case AND:
         return new AndFilter(byteBuffer);
+      case TEMPLATE_FILTER:
+        return new TemplateFilter(byteBuffer);
       default:
         throw new IllegalArgumentException("Unsupported schema filter type: " 
+ type);
     }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterFactory.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterFactory.java
index 84dcc5b8a2a..05bb764e1ea 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterFactory.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterFactory.java
@@ -22,6 +22,7 @@ import org.apache.iotdb.commons.schema.filter.impl.AndFilter;
 import org.apache.iotdb.commons.schema.filter.impl.DataTypeFilter;
 import org.apache.iotdb.commons.schema.filter.impl.PathContainsFilter;
 import org.apache.iotdb.commons.schema.filter.impl.TagFilter;
+import org.apache.iotdb.commons.schema.filter.impl.TemplateFilter;
 import org.apache.iotdb.commons.schema.filter.impl.ViewTypeFilter;
 import org.apache.iotdb.commons.schema.view.ViewType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
@@ -44,6 +45,10 @@ public class SchemaFilterFactory {
     return new ViewTypeFilter(viewType);
   }
 
+  public static SchemaFilter createTemplateNameFilter(String templateName, 
boolean isEqual) {
+    return new TemplateFilter(templateName, isEqual);
+  }
+
   public static SchemaFilter and(SchemaFilter left, SchemaFilter right) {
     if (left == null) {
       return right;
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterType.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterType.java
index cf7abdca63a..285130f778e 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterType.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterType.java
@@ -25,6 +25,7 @@ public enum SchemaFilterType {
   DATA_TYPE((short) 3),
   VIEW_TYPE((short) 4),
   AND((short) 5),
+  TEMPLATE_FILTER((short) 6),
   ;
 
   private final short code;
@@ -51,6 +52,8 @@ public enum SchemaFilterType {
         return VIEW_TYPE;
       case 5:
         return AND;
+      case 6:
+        return TEMPLATE_FILTER;
       default:
         throw new IllegalArgumentException("Invalid input: " + code);
     }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterVisitor.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterVisitor.java
index 56084dd377f..d6861baab68 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterVisitor.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/SchemaFilterVisitor.java
@@ -22,6 +22,7 @@ import org.apache.iotdb.commons.schema.filter.impl.AndFilter;
 import org.apache.iotdb.commons.schema.filter.impl.DataTypeFilter;
 import org.apache.iotdb.commons.schema.filter.impl.PathContainsFilter;
 import org.apache.iotdb.commons.schema.filter.impl.TagFilter;
+import org.apache.iotdb.commons.schema.filter.impl.TemplateFilter;
 import org.apache.iotdb.commons.schema.filter.impl.ViewTypeFilter;
 
 /**
@@ -61,6 +62,10 @@ public abstract class SchemaFilterVisitor<C> {
     return visitFilter(viewTypeFilter, context);
   }
 
+  public boolean visitTemplateFilter(TemplateFilter templateFilter, C context) 
{
+    return visitFilter(templateFilter, context);
+  }
+
   public boolean visitAndFilter(AndFilter andFilter, C context) {
     return andFilter.getLeft().accept(this, context) && 
andFilter.getRight().accept(this, context);
   }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/impl/TemplateFilter.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/impl/TemplateFilter.java
new file mode 100644
index 00000000000..a5f658780a0
--- /dev/null
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/filter/impl/TemplateFilter.java
@@ -0,0 +1,73 @@
+/*
+ * 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.schema.filter.impl;
+
+import org.apache.iotdb.commons.schema.filter.SchemaFilter;
+import org.apache.iotdb.commons.schema.filter.SchemaFilterType;
+import org.apache.iotdb.commons.schema.filter.SchemaFilterVisitor;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public class TemplateFilter extends SchemaFilter {
+  private final String templateName;
+  private final boolean isEqual;
+
+  public TemplateFilter(String templateName, boolean isEqual) {
+    this.templateName = templateName;
+    this.isEqual = isEqual;
+  }
+
+  public TemplateFilter(ByteBuffer byteBuffer) {
+    this.templateName = ReadWriteIOUtils.readString(byteBuffer);
+    this.isEqual = ReadWriteIOUtils.readBool(byteBuffer);
+  }
+
+  public String getTemplateName() {
+    return templateName;
+  }
+
+  public boolean isEqual() {
+    return isEqual;
+  }
+
+  @Override
+  public <C> boolean accept(SchemaFilterVisitor<C> visitor, C node) {
+    return visitor.visitTemplateFilter(this, node);
+  }
+
+  @Override
+  public SchemaFilterType getSchemaFilterType() {
+    return SchemaFilterType.TEMPLATE_FILTER;
+  }
+
+  @Override
+  public void serialize(ByteBuffer byteBuffer) {
+    ReadWriteIOUtils.write(templateName, byteBuffer);
+    ReadWriteIOUtils.write(isEqual, byteBuffer);
+  }
+
+  @Override
+  public void serialize(DataOutputStream stream) throws IOException {
+    ReadWriteIOUtils.write(templateName, stream);
+    ReadWriteIOUtils.write(isEqual, stream);
+  }
+}


Reply via email to