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

justinchen 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 81be9cee0ff Load: Optimized the partial path split logic in 
modifications coverage judgment (#16212) && Refactored tsFile load IT && Fixed 
the bug that loading non-exist table which is deleted in file may cause NPE 
(#16217)
81be9cee0ff is described below

commit 81be9cee0ff312425a4d284e0507bbcccc20ca05
Author: Caideyipi <[email protected]>
AuthorDate: Thu Aug 21 14:38:13 2025 +0800

    Load: Optimized the partial path split logic in modifications coverage 
judgment (#16212) && Refactored tsFile load IT && Fixed the bug that loading 
non-exist table which is deleted in file may cause NPE (#16217)
    
    * fix
    
    * fix
    
    * 1-l
    
    * ci-fix
    
    * refactor
    
    * may-final
---
 .../org/apache/iotdb/it/utils/TsFileGenerator.java |  28 ++
 .../iotdb/it/utils/TsFileTableGenerator.java       |  17 +-
 .../org/apache/iotdb/db/it/IoTDBLoadTsFileIT.java  | 155 ++---------
 .../relational/it/db/it/IoTDBLoadTsFileIT.java     | 299 +++++++++++++++++++++
 .../analyze/load/LoadTsFileTableSchemaCache.java   |  19 +-
 .../analyze/load/LoadTsFileTreeSchemaCache.java    |  24 +-
 .../load/TreeSchemaAutoCreatorAndVerifier.java     |   2 +-
 .../db/storageengine/load/LoadTsFileManager.java   |  22 +-
 .../apache/iotdb/db/utils/ModificationUtils.java   |  59 ++--
 .../apache/iotdb/commons/path/PatternTreeMap.java  |   4 +
 10 files changed, 429 insertions(+), 200 deletions(-)

diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/utils/TsFileGenerator.java 
b/integration-test/src/main/java/org/apache/iotdb/it/utils/TsFileGenerator.java
index 896745ad648..bdc16201611 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/utils/TsFileGenerator.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/utils/TsFileGenerator.java
@@ -19,6 +19,7 @@
 
 package org.apache.iotdb.it.utils;
 
+import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.commons.exception.IllegalPathException;
 import org.apache.iotdb.commons.path.MeasurementPath;
 import org.apache.iotdb.db.storageengine.dataregion.modification.ModEntry;
@@ -30,6 +31,7 @@ import org.apache.tsfile.read.common.Path;
 import org.apache.tsfile.write.TsFileWriter;
 import org.apache.tsfile.write.record.Tablet;
 import org.apache.tsfile.write.schema.IMeasurementSchema;
+import org.apache.tsfile.write.schema.MeasurementSchema;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -225,6 +227,32 @@ public class TsFileGenerator implements AutoCloseable {
     tablet.addValue(row, column, String.format("test point %d", 
random.nextInt()));
   }
 
+  public void generateDeletion(final String device) throws IOException, 
IllegalPathException {
+    try (final ModificationFile modificationFile =
+        new ModificationFile(ModificationFile.getExclusiveMods(tsFile), 
false)) {
+      modificationFile.write(
+          new TreeDeletionEntry(
+              new MeasurementPath(device, 
IoTDBConstant.ONE_LEVEL_PATH_WILDCARD),
+              Long.MIN_VALUE,
+              Long.MAX_VALUE));
+      device2TimeSet.remove(device);
+      device2MeasurementSchema.remove(device);
+    }
+  }
+
+  public void generateDeletion(final String device, final MeasurementSchema 
measurement)
+      throws IOException, IllegalPathException {
+    try (final ModificationFile modificationFile =
+        new ModificationFile(ModificationFile.getExclusiveMods(tsFile), 
false)) {
+      modificationFile.write(
+          new TreeDeletionEntry(
+              new MeasurementPath(device, measurement.getMeasurementName()),
+              Long.MIN_VALUE,
+              Long.MAX_VALUE));
+      device2MeasurementSchema.get(device).remove(measurement);
+    }
+  }
+
   public void generateDeletion(final String device, final int number)
       throws IOException, IllegalPathException {
     try (final ModificationFile modificationFile =
diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/utils/TsFileTableGenerator.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/utils/TsFileTableGenerator.java
index 6d86a5079f5..7c2bd1623de 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/utils/TsFileTableGenerator.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/utils/TsFileTableGenerator.java
@@ -19,10 +19,15 @@
 
 package org.apache.iotdb.it.utils;
 
+import 
org.apache.iotdb.db.storageengine.dataregion.modification.DeletionPredicate;
+import 
org.apache.iotdb.db.storageengine.dataregion.modification.ModificationFile;
+import 
org.apache.iotdb.db.storageengine.dataregion.modification.TableDeletionEntry;
+
 import org.apache.tsfile.enums.ColumnCategory;
 import org.apache.tsfile.enums.TSDataType;
 import org.apache.tsfile.exception.write.WriteProcessException;
 import org.apache.tsfile.file.metadata.TableSchema;
+import org.apache.tsfile.read.common.TimeRange;
 import org.apache.tsfile.write.TsFileWriter;
 import org.apache.tsfile.write.record.Tablet;
 import org.apache.tsfile.write.schema.IMeasurementSchema;
@@ -173,11 +178,13 @@ public class TsFileTableGenerator implements 
AutoCloseable {
     tablet.addValue(row, column, String.format("test point %d", 
random.nextInt()));
   }
 
-  public long getTotalNumber() {
-    return table2TimeSet.entrySet().stream()
-        .mapToInt(
-            entry -> entry.getValue().size() * 
table2MeasurementSchema.get(entry.getKey()).size())
-        .sum();
+  public void generateDeletion(final String table) throws IOException {
+    try (final ModificationFile modificationFile =
+        new ModificationFile(ModificationFile.getExclusiveMods(tsFile), 
false)) {
+      modificationFile.write(
+          new TableDeletionEntry(
+              new DeletionPredicate(table), new TimeRange(Long.MIN_VALUE, 
Long.MAX_VALUE)));
+    }
   }
 
   @Override
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBLoadTsFileIT.java 
b/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBLoadTsFileIT.java
index 9c9003c2bff..a89becf1aa5 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBLoadTsFileIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBLoadTsFileIT.java
@@ -21,16 +21,14 @@ package org.apache.iotdb.db.it;
 
 import org.apache.iotdb.commons.auth.entity.PrivilegeType;
 import org.apache.iotdb.commons.schema.column.ColumnHeaderConstant;
+import org.apache.iotdb.db.it.utils.TestUtils;
 import org.apache.iotdb.it.env.EnvFactory;
 import org.apache.iotdb.it.framework.IoTDBTestRunner;
 import org.apache.iotdb.it.utils.TsFileGenerator;
-import org.apache.iotdb.it.utils.TsFileTableGenerator;
 import org.apache.iotdb.itbase.category.ClusterIT;
 import org.apache.iotdb.itbase.category.LocalStandaloneIT;
-import org.apache.iotdb.itbase.env.BaseEnv;
 import org.apache.iotdb.jdbc.IoTDBSQLException;
 
-import org.apache.tsfile.enums.ColumnCategory;
 import org.apache.tsfile.enums.TSDataType;
 import org.apache.tsfile.file.metadata.enums.TSEncoding;
 import org.apache.tsfile.read.common.Path;
@@ -107,8 +105,8 @@ public class IoTDBLoadTsFileIT {
     try (final Connection connection = EnvFactory.getEnv().getConnection();
         final Statement statement = connection.createStatement()) {
 
-      statement.execute("CREATE DATABASE " + SchemaConfig.STORAGE_GROUP_0);
-      statement.execute("CREATE DATABASE " + SchemaConfig.STORAGE_GROUP_1);
+      statement.execute("CREATE DATABASE " + SchemaConfig.DATABASE_0);
+      statement.execute("CREATE DATABASE " + SchemaConfig.DATABASE_1);
 
       statement.execute(convert2SQL(SchemaConfig.DEVICE_0, 
SchemaConfig.MEASUREMENT_00));
       statement.execute(convert2SQL(SchemaConfig.DEVICE_0, 
SchemaConfig.MEASUREMENT_01));
@@ -163,8 +161,8 @@ public class IoTDBLoadTsFileIT {
     try (final Connection connection = EnvFactory.getEnv().getConnection();
         final Statement statement = connection.createStatement()) {
 
-      statement.execute(String.format("delete database %s", 
SchemaConfig.STORAGE_GROUP_0));
-      statement.execute(String.format("delete database %s", 
SchemaConfig.STORAGE_GROUP_1));
+      statement.execute(String.format("delete database %s", 
SchemaConfig.DATABASE_0));
+      statement.execute(String.format("delete database %s", 
SchemaConfig.DATABASE_1));
     } catch (final IoTDBSQLException ignored) {
     }
   }
@@ -702,9 +700,11 @@ public class IoTDBLoadTsFileIT {
       generator.registerTimeseries(
           SchemaConfig.DEVICE_3, 
Collections.singletonList(SchemaConfig.MEASUREMENT_30));
       generator.registerAlignedTimeseries(
-          SchemaConfig.DEVICE_4, 
Collections.singletonList(SchemaConfig.MEASUREMENT_40));
+          SchemaConfig.DEVICE_4,
+          new ArrayList<>(Arrays.asList(SchemaConfig.MEASUREMENT_30, 
SchemaConfig.MEASUREMENT_40)));
       generator.generateData(SchemaConfig.DEVICE_2, 100, PARTITION_INTERVAL / 
10_000, false);
       generator.generateData(SchemaConfig.DEVICE_3, 100, PARTITION_INTERVAL / 
10_000, false);
+      generator.generateDeletion(SchemaConfig.DEVICE_3);
       generator.generateData(SchemaConfig.DEVICE_4, 100, PARTITION_INTERVAL / 
10_000, true);
       generator.generateDeletion(SchemaConfig.DEVICE_2, 2);
       generator.generateDeletion(SchemaConfig.DEVICE_4, 2);
@@ -712,6 +712,7 @@ public class IoTDBLoadTsFileIT {
       generator.generateData(SchemaConfig.DEVICE_4, 100, PARTITION_INTERVAL / 
10_000, true);
       generator.generateDeletion(SchemaConfig.DEVICE_2, 2);
       generator.generateDeletion(SchemaConfig.DEVICE_4, 2);
+      generator.generateDeletion(SchemaConfig.DEVICE_4, 
SchemaConfig.MEASUREMENT_30);
       writtenPoint2 = generator.getTotalNumber();
     }
 
@@ -731,6 +732,10 @@ public class IoTDBLoadTsFileIT {
           Assert.fail("This ResultSet is empty.");
         }
       }
+
+      TestUtils.assertSingleResultSetEqual(
+          TestUtils.executeQueryWithRetry(statement, "count timeSeries 
root.sg.**"),
+          Collections.singletonMap("count(timeseries)", "18"));
     }
   }
 
@@ -891,139 +896,9 @@ public class IoTDBLoadTsFileIT {
     return pairs;
   }
 
-  @Test
-  public void testLoadWithEmptyDatabaseForTableModel() throws Exception {
-    final int lineCount = 10000;
-
-    final List<Pair<MeasurementSchema, MeasurementSchema>> measurementSchemas =
-        generateMeasurementSchemasForDataTypeConvertion();
-    final List<ColumnCategory> columnCategories =
-        generateTabletColumnCategory(0, measurementSchemas.size());
-
-    final File file = new File(tmpDir, "1-0-0-0.tsfile");
-
-    final List<IMeasurementSchema> schemaList =
-        measurementSchemas.stream().map(pair -> 
pair.right).collect(Collectors.toList());
-
-    try (final TsFileTableGenerator generator = new 
TsFileTableGenerator(file)) {
-      generator.registerTable(SchemaConfig.TABLE_0, schemaList, 
columnCategories);
-
-      generator.generateData(SchemaConfig.TABLE_0, lineCount, 
PARTITION_INTERVAL / 10_000);
-    }
-
-    // Prepare normal user
-    try (final Connection adminCon = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
-        final Statement adminStmt = adminCon.createStatement()) {
-      adminStmt.execute("create user test 'password123456'");
-      adminStmt.execute(
-          String.format(
-              "grant create, insert on %s.%s to user test",
-              SchemaConfig.DATABASE_0, SchemaConfig.TABLE_0));
-
-      // auto-create table
-      adminStmt.execute(String.format("create database if not exists %s", 
SchemaConfig.DATABASE_0));
-    }
-
-    try (final Connection connection =
-            EnvFactory.getEnv().getConnection("test", "password123456", 
BaseEnv.TABLE_SQL_DIALECT);
-        final Statement statement = connection.createStatement()) {
-      statement.execute(String.format("use %s", SchemaConfig.DATABASE_0));
-      statement.execute(String.format("load '%s'", file.getAbsolutePath()));
-    }
-
-    try (final Connection adminCon = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
-        final Statement adminStmt = adminCon.createStatement()) {
-      adminStmt.execute(String.format("use %s", SchemaConfig.DATABASE_0));
-      try (final ResultSet resultSet =
-          adminStmt.executeQuery(String.format("select count(*) from %s", 
SchemaConfig.TABLE_0))) {
-        if (resultSet.next()) {
-          Assert.assertEquals(lineCount, resultSet.getLong(1));
-        } else {
-          Assert.fail("This ResultSet is empty.");
-        }
-      }
-    }
-  }
-
-  @Test
-  @Ignore("Load with conversion is currently banned")
-  public void testLoadWithConvertOnTypeMismatchForTableModel() throws 
Exception {
-    final int lineCount = 10000;
-
-    List<Pair<MeasurementSchema, MeasurementSchema>> measurementSchemas =
-        generateMeasurementSchemasForDataTypeConvertion();
-    List<ColumnCategory> columnCategories =
-        generateTabletColumnCategory(0, measurementSchemas.size());
-
-    final File file = new File(tmpDir, "1-0-0-0.tsfile");
-
-    List<MeasurementSchema> schemaList1 =
-        measurementSchemas.stream().map(pair -> 
pair.left).collect(Collectors.toList());
-    List<IMeasurementSchema> schemaList2 =
-        measurementSchemas.stream().map(pair -> 
pair.right).collect(Collectors.toList());
-
-    try (final TsFileTableGenerator generator = new 
TsFileTableGenerator(file)) {
-      generator.registerTable(SchemaConfig.TABLE_0, schemaList2, 
columnCategories);
-
-      generator.generateData(SchemaConfig.TABLE_0, lineCount, 
PARTITION_INTERVAL / 10_000);
-    }
-
-    try (final Connection connection =
-            EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
-        final Statement statement = connection.createStatement()) {
-      statement.execute(String.format("create database if not exists %s", 
SchemaConfig.DATABASE_0));
-      statement.execute(String.format("use %s", SchemaConfig.DATABASE_0));
-      statement.execute(convert2TableSQL(SchemaConfig.TABLE_0, schemaList1, 
columnCategories));
-      statement.execute(
-          String.format(
-              "load '%s' with ('database'='%s')", file.getAbsolutePath(), 
SchemaConfig.DATABASE_0));
-      try (final ResultSet resultSet =
-          statement.executeQuery(String.format("select count(*) from %s", 
SchemaConfig.TABLE_0))) {
-        if (resultSet.next()) {
-          Assert.assertEquals(lineCount, resultSet.getLong(1));
-        } else {
-          Assert.fail("This ResultSet is empty.");
-        }
-      }
-    }
-  }
-
-  private List<ColumnCategory> generateTabletColumnCategory(int tagNum, int 
filedNum) {
-    List<ColumnCategory> columnTypes = new ArrayList<>(tagNum + filedNum);
-    for (int i = 0; i < tagNum; i++) {
-      columnTypes.add(ColumnCategory.TAG);
-    }
-    for (int i = 0; i < filedNum; i++) {
-      columnTypes.add(ColumnCategory.FIELD);
-    }
-    return columnTypes;
-  }
-
-  private String convert2TableSQL(
-      final String tableName,
-      final List<MeasurementSchema> schemaList,
-      final List<ColumnCategory> columnCategoryList) {
-    List<String> columns = new ArrayList<>();
-    for (int i = 0; i < schemaList.size(); i++) {
-      final MeasurementSchema measurement = schemaList.get(i);
-      columns.add(
-          String.format(
-              "%s %s %s",
-              measurement.getMeasurementName(),
-              measurement.getType(),
-              columnCategoryList.get(i).name()));
-    }
-    String tableCreation =
-        String.format("create table %s(%s)", tableName, String.join(", ", 
columns));
-    LOGGER.info("schema execute: {}", tableCreation);
-    return tableCreation;
-  }
-
   private static class SchemaConfig {
-    private static final String DATABASE_0 = "root";
-    private static final String TABLE_0 = "test";
-    private static final String STORAGE_GROUP_0 = "root.sg.test_0";
-    private static final String STORAGE_GROUP_1 = "root.sg.test_1";
+    private static final String DATABASE_0 = "root.sg.test_0";
+    private static final String DATABASE_1 = "root.sg.test_1";
 
     // device 0, nonaligned, sg 0
     private static final String DEVICE_0 = "root.sg.test_0.d_0";
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBLoadTsFileIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBLoadTsFileIT.java
new file mode 100644
index 00000000000..5f88d50c9d9
--- /dev/null
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBLoadTsFileIT.java
@@ -0,0 +1,299 @@
+/*
+ * 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.relational.it.db.it;
+
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.framework.IoTDBTestRunner;
+import org.apache.iotdb.it.utils.TsFileTableGenerator;
+import org.apache.iotdb.itbase.category.TableClusterIT;
+import org.apache.iotdb.itbase.category.TableLocalStandaloneIT;
+import org.apache.iotdb.itbase.env.BaseEnv;
+
+import org.apache.tsfile.enums.ColumnCategory;
+import org.apache.tsfile.enums.TSDataType;
+import org.apache.tsfile.utils.Pair;
+import org.apache.tsfile.write.schema.IMeasurementSchema;
+import org.apache.tsfile.write.schema.MeasurementSchema;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({TableLocalStandaloneIT.class, TableClusterIT.class})
+public class IoTDBLoadTsFileIT {
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(IoTDBLoadTsFileIT.class);
+  private static final long PARTITION_INTERVAL = 10 * 1000L;
+  private static final int connectionTimeoutInMS = (int) 
TimeUnit.SECONDS.toMillis(300);
+  private static final long loadTsFileAnalyzeSchemaMemorySizeInBytes = 10 * 
1024L;
+
+  private File tmpDir;
+
+  @Before
+  public void setUp() throws Exception {
+    tmpDir = new File(Files.createTempDirectory("load").toUri());
+    
EnvFactory.getEnv().getConfig().getCommonConfig().setTimePartitionInterval(PARTITION_INTERVAL);
+    
EnvFactory.getEnv().getConfig().getCommonConfig().setEnforceStrongPassword(false);
+    EnvFactory.getEnv()
+        .getConfig()
+        .getDataNodeConfig()
+        .setConnectionTimeoutInMS(connectionTimeoutInMS)
+        
.setLoadTsFileAnalyzeSchemaMemorySizeInBytes(loadTsFileAnalyzeSchemaMemorySizeInBytes);
+    EnvFactory.getEnv().initClusterEnvironment();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    EnvFactory.getEnv().cleanClusterEnvironment();
+
+    if (!deleteDir()) {
+      LOGGER.error("Can not delete tmp dir for loading tsfile.");
+    }
+  }
+
+  private boolean deleteDir() {
+    for (final File file : tmpDir.listFiles()) {
+      if (!file.delete()) {
+        return false;
+      }
+    }
+    return tmpDir.delete();
+  }
+
+  private List<Pair<MeasurementSchema, MeasurementSchema>> 
generateMeasurementSchemas() {
+    TSDataType[] dataTypes = {
+      TSDataType.STRING,
+      TSDataType.TEXT,
+      TSDataType.BLOB,
+      TSDataType.TIMESTAMP,
+      TSDataType.BOOLEAN,
+      TSDataType.DATE,
+      TSDataType.DOUBLE,
+      TSDataType.FLOAT,
+      TSDataType.INT32,
+      TSDataType.INT64
+    };
+    List<Pair<MeasurementSchema, MeasurementSchema>> pairs = new ArrayList<>();
+
+    for (TSDataType type : dataTypes) {
+      for (TSDataType dataType : dataTypes) {
+        String id = String.format("%s2%s", type.name(), dataType.name());
+        pairs.add(new Pair<>(new MeasurementSchema(id, type), new 
MeasurementSchema(id, dataType)));
+      }
+    }
+    return pairs;
+  }
+
+  @Test
+  public void testLoadWithEmptyDatabaseForTableModel() throws Exception {
+    final int lineCount = 10000;
+
+    final List<Pair<MeasurementSchema, MeasurementSchema>> measurementSchemas =
+        generateMeasurementSchemas();
+    final List<ColumnCategory> columnCategories =
+        generateTabletColumnCategory(0, measurementSchemas.size());
+
+    final File file = new File(tmpDir, "1-0-0-0.tsfile");
+
+    final List<IMeasurementSchema> schemaList =
+        measurementSchemas.stream().map(pair -> 
pair.right).collect(Collectors.toList());
+
+    try (final TsFileTableGenerator generator = new 
TsFileTableGenerator(file)) {
+      generator.registerTable(SchemaConfig.TABLE_0, schemaList, 
columnCategories);
+
+      generator.generateData(SchemaConfig.TABLE_0, lineCount, 
PARTITION_INTERVAL / 10_000);
+    }
+
+    // Prepare normal user
+    try (final Connection adminCon = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        final Statement adminStmt = adminCon.createStatement()) {
+      adminStmt.execute("create user test 'password123456'");
+      adminStmt.execute(
+          String.format(
+              "grant create, insert on %s.%s to user test",
+              SchemaConfig.DATABASE_0, SchemaConfig.TABLE_0));
+
+      // auto-create table
+      adminStmt.execute(String.format("create database if not exists %s", 
SchemaConfig.DATABASE_0));
+    }
+
+    try (final Connection connection =
+            EnvFactory.getEnv().getConnection("test", "password123456", 
BaseEnv.TABLE_SQL_DIALECT);
+        final Statement statement = connection.createStatement()) {
+      statement.execute(String.format("use %s", SchemaConfig.DATABASE_0));
+      statement.execute(String.format("load '%s'", file.getAbsolutePath()));
+    }
+
+    try (final Connection adminCon = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        final Statement adminStmt = adminCon.createStatement()) {
+      adminStmt.execute(String.format("use %s", SchemaConfig.DATABASE_0));
+      try (final ResultSet resultSet =
+          adminStmt.executeQuery(String.format("select count(*) from %s", 
SchemaConfig.TABLE_0))) {
+        if (resultSet.next()) {
+          Assert.assertEquals(lineCount, resultSet.getLong(1));
+        } else {
+          Assert.fail("This ResultSet is empty.");
+        }
+      }
+    }
+  }
+
+  @Test
+  @Ignore("Load with conversion is currently banned")
+  public void testLoadWithConvertOnTypeMismatchForTableModel() throws 
Exception {
+    final int lineCount = 10000;
+
+    List<Pair<MeasurementSchema, MeasurementSchema>> measurementSchemas =
+        generateMeasurementSchemas();
+    List<ColumnCategory> columnCategories =
+        generateTabletColumnCategory(0, measurementSchemas.size());
+
+    final File file = new File(tmpDir, "1-0-0-0.tsfile");
+
+    List<MeasurementSchema> schemaList1 =
+        measurementSchemas.stream().map(pair -> 
pair.left).collect(Collectors.toList());
+    List<IMeasurementSchema> schemaList2 =
+        measurementSchemas.stream().map(pair -> 
pair.right).collect(Collectors.toList());
+
+    try (final TsFileTableGenerator generator = new 
TsFileTableGenerator(file)) {
+      generator.registerTable(SchemaConfig.TABLE_0, schemaList2, 
columnCategories);
+
+      generator.generateData(SchemaConfig.TABLE_0, lineCount, 
PARTITION_INTERVAL / 10_000);
+    }
+
+    try (final Connection connection =
+            EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        final Statement statement = connection.createStatement()) {
+      statement.execute(String.format("create database if not exists %s", 
SchemaConfig.DATABASE_0));
+      statement.execute(String.format("use %s", SchemaConfig.DATABASE_0));
+      statement.execute(convert2TableSQL(SchemaConfig.TABLE_0, schemaList1, 
columnCategories));
+      statement.execute(
+          String.format(
+              "load '%s' with ('database'='%s')", file.getAbsolutePath(), 
SchemaConfig.DATABASE_0));
+      try (final ResultSet resultSet =
+          statement.executeQuery(String.format("select count(*) from %s", 
SchemaConfig.TABLE_0))) {
+        if (resultSet.next()) {
+          Assert.assertEquals(lineCount, resultSet.getLong(1));
+        } else {
+          Assert.fail("This ResultSet is empty.");
+        }
+      }
+    }
+  }
+
+  @Test
+  public void testLoadWithTableMod() throws Exception {
+    final int lineCount = 10000;
+
+    List<Pair<MeasurementSchema, MeasurementSchema>> measurementSchemas =
+        generateMeasurementSchemas();
+    List<ColumnCategory> columnCategories =
+        generateTabletColumnCategory(0, measurementSchemas.size());
+
+    final File file = new File(tmpDir, "1-0-0-0.tsfile");
+
+    List<MeasurementSchema> schemaList1 =
+        measurementSchemas.stream().map(pair -> 
pair.left).collect(Collectors.toList());
+
+    try (final TsFileTableGenerator generator = new 
TsFileTableGenerator(file)) {
+      generator.registerTable(SchemaConfig.TABLE_0, new 
ArrayList<>(schemaList1), columnCategories);
+      generator.generateData(SchemaConfig.TABLE_0, lineCount, 
PARTITION_INTERVAL / 10_000);
+
+      generator.registerTable(SchemaConfig.TABLE_1, new 
ArrayList<>(schemaList1), columnCategories);
+      generator.generateData(SchemaConfig.TABLE_1, lineCount, 
PARTITION_INTERVAL / 10_000);
+      generator.generateDeletion(SchemaConfig.TABLE_1);
+    }
+
+    try (final Connection connection =
+            EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        final Statement statement = connection.createStatement()) {
+      statement.execute(String.format("create database if not exists %s", 
SchemaConfig.DATABASE_0));
+      statement.execute(String.format("use %s", SchemaConfig.DATABASE_0));
+      statement.execute(
+          String.format(
+              "load '%s' with ('database'='%s')", file.getAbsolutePath(), 
SchemaConfig.DATABASE_0));
+      try (final ResultSet resultSet =
+          statement.executeQuery(String.format("select count(*) from %s", 
SchemaConfig.TABLE_0))) {
+        if (resultSet.next()) {
+          Assert.assertEquals(lineCount, resultSet.getLong(1));
+        } else {
+          Assert.fail("This ResultSet is empty.");
+        }
+      }
+
+      try (final ResultSet resultSet = statement.executeQuery("show tables")) {
+        Assert.assertTrue(resultSet.next());
+        Assert.assertFalse(resultSet.next());
+      }
+    }
+  }
+
+  private List<ColumnCategory> generateTabletColumnCategory(int tagNum, int 
filedNum) {
+    List<ColumnCategory> columnTypes = new ArrayList<>(tagNum + filedNum);
+    for (int i = 0; i < tagNum; i++) {
+      columnTypes.add(ColumnCategory.TAG);
+    }
+    for (int i = 0; i < filedNum; i++) {
+      columnTypes.add(ColumnCategory.FIELD);
+    }
+    return columnTypes;
+  }
+
+  private String convert2TableSQL(
+      final String tableName,
+      final List<MeasurementSchema> schemaList,
+      final List<ColumnCategory> columnCategoryList) {
+    List<String> columns = new ArrayList<>();
+    for (int i = 0; i < schemaList.size(); i++) {
+      final MeasurementSchema measurement = schemaList.get(i);
+      columns.add(
+          String.format(
+              "%s %s %s",
+              measurement.getMeasurementName(),
+              measurement.getType(),
+              columnCategoryList.get(i).name()));
+    }
+    String tableCreation =
+        String.format("create table %s(%s)", tableName, String.join(", ", 
columns));
+    LOGGER.info("schema execute: {}", tableCreation);
+    return tableCreation;
+  }
+
+  private static class SchemaConfig {
+    private static final String DATABASE_0 = "root";
+    private static final String TABLE_0 = "test";
+    private static final String TABLE_1 = "test1";
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/LoadTsFileTableSchemaCache.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/LoadTsFileTableSchemaCache.java
index 7ea5154714c..1fb6da702c3 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/LoadTsFileTableSchemaCache.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/LoadTsFileTableSchemaCache.java
@@ -20,6 +20,7 @@
 package org.apache.iotdb.db.queryengine.plan.analyze.load;
 
 import org.apache.iotdb.commons.exception.IllegalPathException;
+import org.apache.iotdb.commons.path.PatternTreeMap;
 import org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory;
 import org.apache.iotdb.confignode.rpc.thrift.TDatabaseSchema;
 import org.apache.iotdb.db.conf.IoTDBConfig;
@@ -46,6 +47,7 @@ import 
org.apache.iotdb.db.storageengine.dataregion.tsfile.timeindex.ITimeIndex;
 import org.apache.iotdb.db.storageengine.load.memory.LoadTsFileMemoryBlock;
 import org.apache.iotdb.db.storageengine.load.memory.LoadTsFileMemoryManager;
 import org.apache.iotdb.db.utils.ModificationUtils;
+import org.apache.iotdb.db.utils.datastructure.PatternTreeMapFactory;
 import org.apache.iotdb.rpc.TSStatusCode;
 
 import com.google.common.util.concurrent.ListenableFuture;
@@ -58,7 +60,6 @@ import org.slf4j.LoggerFactory;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -101,7 +102,7 @@ public class LoadTsFileTableSchemaCache {
   // tableName -> Pair<device column count, device column mapping>
   private Map<String, Pair<Integer, Map<Integer, Integer>>> 
tableIdColumnMapper = new HashMap<>();
 
-  private Collection<ModEntry> currentModifications;
+  private PatternTreeMap<ModEntry, PatternTreeMapFactory.ModsSerializer> 
currentModifications;
   private ITimeIndex currentTimeIndex;
 
   private long batchTable2DevicesMemoryUsageSizeInBytes = 0;
@@ -120,7 +121,7 @@ public class LoadTsFileTableSchemaCache {
     this.metadata = metadata;
     this.context = context;
     this.currentBatchTable2Devices = new HashMap<>();
-    this.currentModifications = new ArrayList<>();
+    this.currentModifications = PatternTreeMapFactory.getModsPatternTreeMap();
     this.needToCreateDatabase = needToCreateDatabase;
   }
 
@@ -385,10 +386,12 @@ public class LoadTsFileTableSchemaCache {
       TsFileResource resource, TsFileSequenceReader reader) throws IOException 
{
     clearModificationsAndTimeIndex();
 
-    currentModifications = 
ModificationFile.readAllModifications(resource.getTsFile(), false);
-    for (final ModEntry modification : currentModifications) {
-      currentModificationsMemoryUsageSizeInBytes += 
modification.serializedSize();
-    }
+    ModificationFile.readAllModifications(resource.getTsFile(), false)
+        .forEach(
+            modification ->
+                currentModifications.append(modification.keyOfPatternTree(), 
modification));
+
+    currentModificationsMemoryUsageSizeInBytes = 
currentModifications.ramBytesUsed();
 
     // If there are too many modifications, a larger memory block is needed to 
avoid frequent
     // flush.
@@ -438,7 +441,7 @@ public class LoadTsFileTableSchemaCache {
   }
 
   private void clearModificationsAndTimeIndex() {
-    currentModifications.clear();
+    currentModifications = PatternTreeMapFactory.getModsPatternTreeMap();
     currentTimeIndex = null;
     block.reduceMemoryUsage(currentModificationsMemoryUsageSizeInBytes);
     block.reduceMemoryUsage(currentTimeIndexMemoryUsageSizeInBytes);
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/LoadTsFileTreeSchemaCache.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/LoadTsFileTreeSchemaCache.java
index 59068bde706..d0335d1b3bd 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/LoadTsFileTreeSchemaCache.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/LoadTsFileTreeSchemaCache.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.db.queryengine.plan.analyze.load;
 
 import org.apache.iotdb.commons.exception.IllegalPathException;
 import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.commons.path.PatternTreeMap;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.exception.load.LoadRuntimeOutOfMemoryException;
@@ -32,6 +33,7 @@ import 
org.apache.iotdb.db.storageengine.dataregion.tsfile.timeindex.ITimeIndex;
 import org.apache.iotdb.db.storageengine.load.memory.LoadTsFileMemoryBlock;
 import org.apache.iotdb.db.storageengine.load.memory.LoadTsFileMemoryManager;
 import org.apache.iotdb.db.utils.ModificationUtils;
+import org.apache.iotdb.db.utils.datastructure.PatternTreeMapFactory;
 
 import org.apache.tsfile.file.metadata.IDeviceID;
 import org.apache.tsfile.file.metadata.TimeseriesMetadata;
@@ -41,8 +43,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -76,7 +76,7 @@ public class LoadTsFileTreeSchemaCache {
   private Map<IDeviceID, Boolean> tsFileDevice2IsAligned;
   private Set<PartialPath> alreadySetDatabases;
 
-  private Collection<ModEntry> currentModifications;
+  private PatternTreeMap<ModEntry, PatternTreeMapFactory.ModsSerializer> 
currentModifications;
   private ITimeIndex currentTimeIndex;
 
   private long batchDevice2TimeSeriesSchemasMemoryUsageSizeInBytes = 0;
@@ -94,7 +94,7 @@ public class LoadTsFileTreeSchemaCache {
     this.currentBatchDevice2TimeSeriesSchemas = new HashMap<>();
     this.tsFileDevice2IsAligned = new HashMap<>();
     this.alreadySetDatabases = new HashSet<>();
-    this.currentModifications = new ArrayList<>();
+    this.currentModifications = PatternTreeMapFactory.getModsPatternTreeMap();
   }
 
   public Map<IDeviceID, Set<MeasurementSchema>> getDevice2TimeSeries() {
@@ -154,10 +154,12 @@ public class LoadTsFileTreeSchemaCache {
       TsFileResource resource, TsFileSequenceReader reader) throws IOException 
{
     clearModificationsAndTimeIndex();
 
-    currentModifications = 
ModificationFile.readAllModifications(resource.getTsFile(), true);
-    for (final ModEntry modification : currentModifications) {
-      currentModificationsMemoryUsageSizeInBytes += 
modification.serializedSize();
-    }
+    ModificationFile.readAllModifications(resource.getTsFile(), true)
+        .forEach(
+            modification ->
+                currentModifications.append(modification.keyOfPatternTree(), 
modification));
+
+    currentModificationsMemoryUsageSizeInBytes = 
currentModifications.ramBytesUsed();
 
     // If there are too many modifications, a larger memory block is needed to 
avoid frequent
     // flush.
@@ -196,9 +198,9 @@ public class LoadTsFileTreeSchemaCache {
     return ModificationUtils.isDeviceDeletedByMods(currentModifications, 
currentTimeIndex, device);
   }
 
-  public boolean isTimeseriesDeletedByMods(IDeviceID device, 
TimeseriesMetadata timeseriesMetadata)
+  public boolean isTimeSeriesDeletedByMods(IDeviceID device, 
TimeseriesMetadata timeseriesMetadata)
       throws IllegalPathException {
-    return ModificationUtils.isTimeseriesDeletedByMods(
+    return ModificationUtils.isTimeSeriesDeletedByMods(
         currentModifications,
         device,
         timeseriesMetadata.getMeasurementId(),
@@ -235,7 +237,7 @@ public class LoadTsFileTreeSchemaCache {
   }
 
   public void clearModificationsAndTimeIndex() {
-    currentModifications.clear();
+    currentModifications = PatternTreeMapFactory.getModsPatternTreeMap();
     currentTimeIndex = null;
     block.reduceMemoryUsage(currentModificationsMemoryUsageSizeInBytes);
     block.reduceMemoryUsage(currentTimeIndexMemoryUsageSizeInBytes);
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/TreeSchemaAutoCreatorAndVerifier.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/TreeSchemaAutoCreatorAndVerifier.java
index a15a3013db2..1b4e1f908d6 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/TreeSchemaAutoCreatorAndVerifier.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/TreeSchemaAutoCreatorAndVerifier.java
@@ -128,7 +128,7 @@ public class TreeSchemaAutoCreatorAndVerifier {
 
       for (final TimeseriesMetadata timeseriesMetadata : entry.getValue()) {
         try {
-          if (schemaCache.isTimeseriesDeletedByMods(device, 
timeseriesMetadata)) {
+          if (schemaCache.isTimeSeriesDeletedByMods(device, 
timeseriesMetadata)) {
             continue;
           }
         } catch (IllegalPathException e) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/LoadTsFileManager.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/LoadTsFileManager.java
index 5876a884660..0d8a3ca85b6 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/LoadTsFileManager.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/LoadTsFileManager.java
@@ -26,6 +26,7 @@ import org.apache.iotdb.commons.consensus.ConsensusGroupId;
 import org.apache.iotdb.commons.consensus.index.ProgressIndex;
 import org.apache.iotdb.commons.consensus.index.impl.MinimumProgressIndex;
 import org.apache.iotdb.commons.file.SystemFileFactory;
+import org.apache.iotdb.commons.schema.table.TsTable;
 import org.apache.iotdb.commons.service.metric.MetricService;
 import org.apache.iotdb.commons.service.metric.enums.Metric;
 import org.apache.iotdb.commons.service.metric.enums.Tag;
@@ -463,16 +464,17 @@ public class LoadTsFileManager {
           chunkData.getDevice() != null ? chunkData.getDevice().getTableName() 
: null;
       if (tableName != null
           && !(tableName.startsWith(TREE_MODEL_DATABASE_PREFIX) || 
tableName.equals(ROOT))) {
-        writer
-            .getSchema()
-            .getTableSchemaMap()
-            .computeIfAbsent(
-                tableName,
-                t ->
-                    TableSchema.of(
-                            DataNodeTableCache.getInstance()
-                                
.getTable(partitionInfo.getDataRegion().getDatabaseName(), t))
-                        .toTsFileTableSchemaNoAttribute());
+        // If the table does not exist, it means that the table is all deleted 
by mods
+        final TsTable table =
+            DataNodeTableCache.getInstance()
+                .getTable(partitionInfo.getDataRegion().getDatabaseName(), 
tableName);
+        if (Objects.nonNull(table)) {
+          writer
+              .getSchema()
+              .getTableSchemaMap()
+              .computeIfAbsent(
+                  tableName, t -> 
TableSchema.of(table).toTsFileTableSchemaNoAttribute());
+        }
       }
 
       if (!Objects.equals(chunkData.getDevice(), 
dataPartition2LastDevice.get(partitionInfo))) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/ModificationUtils.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/ModificationUtils.java
index d5b477e61e4..95d90dfa63d 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/ModificationUtils.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/ModificationUtils.java
@@ -20,12 +20,16 @@
 package org.apache.iotdb.db.utils;
 
 import org.apache.iotdb.commons.exception.IllegalPathException;
+import org.apache.iotdb.commons.path.AlignedPath;
+import org.apache.iotdb.commons.path.PatternTreeMap;
+import 
org.apache.iotdb.db.storageengine.dataregion.compaction.execute.utils.CompactionPathUtils;
 import 
org.apache.iotdb.db.storageengine.dataregion.compaction.selector.impl.SettleSelectorImpl;
 import org.apache.iotdb.db.storageengine.dataregion.memtable.IMemTable;
 import org.apache.iotdb.db.storageengine.dataregion.modification.ModEntry;
 import 
org.apache.iotdb.db.storageengine.dataregion.modification.TableDeletionEntry;
 import 
org.apache.iotdb.db.storageengine.dataregion.modification.TreeDeletionEntry;
 import 
org.apache.iotdb.db.storageengine.dataregion.tsfile.timeindex.ITimeIndex;
+import org.apache.iotdb.db.utils.datastructure.PatternTreeMapFactory;
 
 import org.apache.tsfile.file.metadata.AbstractAlignedChunkMetadata;
 import org.apache.tsfile.file.metadata.AlignedChunkMetadata;
@@ -35,7 +39,6 @@ import org.apache.tsfile.read.common.TimeRange;
 import org.apache.tsfile.utils.Pair;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
@@ -248,18 +251,23 @@ public class ModificationUtils {
    * There are some slight differences from that in {@link SettleSelectorImpl}.
    */
   public static boolean isAllDeletedByMods(
-      Collection<ModEntry> modifications, IDeviceID device, long startTime, 
long endTime) {
-    for (ModEntry modification : modifications) {
-      if (modification.affectsAll(device)
-          && modification.getTimeRange().contains(startTime, endTime)) {
-        return true;
-      }
-    }
-    return false;
+      final PatternTreeMap<ModEntry, PatternTreeMapFactory.ModsSerializer> 
modifications,
+      final IDeviceID device,
+      final long startTime,
+      final long endTime)
+      throws IllegalPathException {
+    final List<ModEntry> mods =
+        modifications.getOverlapped(
+            CompactionPathUtils.getPath(device, 
AlignedPath.VECTOR_PLACEHOLDER));
+    return mods.stream()
+        .anyMatch(
+            modification ->
+                modification.getTimeRange().contains(startTime, endTime)
+                    && (!device.isTableModel() || 
modification.affects(device)));
   }
 
   public static boolean isAllDeletedByMods(
-      Collection<ModEntry> modifications, long startTime, long endTime) {
+      final List<ModEntry> modifications, final long startTime, final long 
endTime) {
     if (modifications == null || modifications.isEmpty()) {
       return false;
     }
@@ -271,20 +279,21 @@ public class ModificationUtils {
     return false;
   }
 
-  public static boolean isTimeseriesDeletedByMods(
-      Collection<ModEntry> modifications,
-      IDeviceID device,
-      String timeseriesId,
-      long startTime,
-      long endTime) {
-    for (ModEntry modification : modifications) {
-      if (modification.affects(device)
-          && modification.affects(timeseriesId)
-          && modification.getTimeRange().contains(startTime, endTime)) {
-        return true;
-      }
-    }
-    return false;
+  public static boolean isTimeSeriesDeletedByMods(
+      final PatternTreeMap<ModEntry, PatternTreeMapFactory.ModsSerializer> 
modifications,
+      final IDeviceID device,
+      final String measurement,
+      final long startTime,
+      final long endTime)
+      throws IllegalPathException {
+    final List<ModEntry> mods =
+        modifications.getOverlapped(CompactionPathUtils.getPath(device, 
measurement));
+    return mods.stream()
+        .anyMatch(
+            modification ->
+                modification.getTimeRange().contains(startTime, endTime)
+                    && (!device.isTableModel()
+                        || modification.affects(device) && 
modification.affects(measurement)));
   }
 
   private static void doModifyChunkMetaData(ModEntry modification, 
IChunkMetadata metaData) {
@@ -403,7 +412,7 @@ public class ModificationUtils {
   }
 
   public static boolean isDeviceDeletedByMods(
-      final Collection<ModEntry> currentModifications,
+      final PatternTreeMap<ModEntry, PatternTreeMapFactory.ModsSerializer> 
currentModifications,
       final ITimeIndex currentTimeIndex,
       final IDeviceID device)
       throws IllegalPathException {
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/PatternTreeMap.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/PatternTreeMap.java
index 8e3bbdf5f9a..2dafb8b99a1 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/PatternTreeMap.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/path/PatternTreeMap.java
@@ -68,6 +68,10 @@ public class PatternTreeMap<V, VSerializer extends 
PathPatternNode.Serializer<V>
     return rootMap.computeIfAbsent(rootName, r -> new PathPatternNode<>(r, 
supplier, serializer));
   }
 
+  public boolean isEmpty() {
+    return rootMap.values().stream().allMatch(node -> node.isLeaf() && 
node.getValues().isEmpty());
+  }
+
   /**
    * Append key and value to PatternTreeMap.
    *


Reply via email to