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

jiangtian pushed a commit to branch dev/1.3
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/dev/1.3 by this push:
     new e286da15b98 [To dev/1.3] Fix query error after insert an all null 
aligned tablet and flush  (#17041)
e286da15b98 is described below

commit e286da15b98564514d5d36789a8004dd74be2c43
Author: Haonan <[email protected]>
AuthorDate: Mon Jan 19 21:43:22 2026 +0800

    [To dev/1.3] Fix query error after insert an all null aligned tablet and 
flush  (#17041)
    
    * cherry-pick Fix query error after insert an all null aligned tablet and 
flush (#14777)
    
    * Fix broken file genaterated after insert null to aligned timeseries 
(#15163)
    
    * fix compile
---
 .../iotdb/it/env/cluster/node/DataNodeWrapper.java |  4 +
 .../iotdb/session/it/IoTDBSessionInsertNullIT.java | 96 ++++++++++++++++++++++
 .../dataregion/flush/MemTableFlushTask.java        |  2 +-
 .../dataregion/memtable/AbstractMemTable.java      |  5 +-
 .../memtable/AlignedWritableMemChunk.java          | 23 +++++-
 .../memtable/AlignedWritableMemChunkGroup.java     |  5 ++
 .../memtable/IWritableMemChunkGroup.java           |  2 +
 .../dataregion/memtable/WritableMemChunkGroup.java |  5 ++
 8 files changed, 137 insertions(+), 5 deletions(-)

diff --git 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/node/DataNodeWrapper.java
 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/node/DataNodeWrapper.java
index 3df21cb42a6..bf4189d599b 100644
--- 
a/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/node/DataNodeWrapper.java
+++ 
b/integration-test/src/main/java/org/apache/iotdb/it/env/cluster/node/DataNodeWrapper.java
@@ -145,6 +145,10 @@ public class DataNodeWrapper extends AbstractNodeWrapper {
     return workDirFilePath("data/datanode/system/schema", 
IoTDBStartCheck.PROPERTIES_FILE_NAME);
   }
 
+  public String getDataDir() {
+    return getNodePath() + File.separator + "data";
+  }
+
   @Override
   protected MppJVMConfig initVMConfig() {
     return MppJVMConfig.builder()
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionInsertNullIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionInsertNullIT.java
index 503b61f2d7c..439f05b83ae 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionInsertNullIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionInsertNullIT.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.session.it;
 import org.apache.iotdb.isession.ISession;
 import org.apache.iotdb.isession.SessionDataSet;
 import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.env.cluster.node.DataNodeWrapper;
 import org.apache.iotdb.it.framework.IoTDBTestRunner;
 import org.apache.iotdb.itbase.category.ClusterIT;
 import org.apache.iotdb.itbase.category.LocalStandaloneIT;
@@ -43,11 +44,13 @@ import org.junit.runner.RunWith;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.fail;
 
 @RunWith(IoTDBTestRunner.class)
@@ -359,6 +362,99 @@ public class IoTDBSessionInsertNullIT {
     }
   }
 
+  @Test
+  public void insertTabletNullTest() {
+    try (ISession session = EnvFactory.getEnv().getSessionConnection()) {
+      prepareData(session);
+
+      String deviceId = "root.sg1.clsu.d1";
+      Tablet tablet =
+          new Tablet(
+              deviceId,
+              Arrays.asList(
+                  new MeasurementSchema("s1", TSDataType.BOOLEAN),
+                  new MeasurementSchema("s2", TSDataType.INT32)),
+              3);
+      tablet.addTimestamp(0, 300);
+      tablet.addValue("s1", 0, null);
+      tablet.addValue("s2", 0, null);
+      tablet.addTimestamp(1, 400);
+      tablet.addValue("s1", 1, null);
+      tablet.addValue("s2", 1, null);
+      tablet.addTimestamp(2, 500);
+      tablet.addValue("s1", 2, null);
+      tablet.addValue("s2", 2, null);
+      session.insertTablet(tablet);
+      long nums = queryCountRecords(session, "select count(s1) from " + 
deviceId);
+      assertEquals(0, nums);
+      session.executeNonQueryStatement("flush");
+      nums = queryCountRecords(session, "select count(s1) from " + deviceId);
+      assertEquals(0, nums);
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+  }
+
+  @Test
+  public void insertAlignedTabletNullTest() {
+    try (ISession session = EnvFactory.getEnv().getSessionConnection()) {
+      prepareData(session);
+
+      String deviceId = "root.sg1.clsu.aligned_d1";
+      Tablet tablet =
+          new Tablet(
+              deviceId,
+              Arrays.asList(
+                  new MeasurementSchema("s1", TSDataType.BOOLEAN),
+                  new MeasurementSchema("s2", TSDataType.INT32)),
+              3);
+      tablet.addTimestamp(0, 300);
+      tablet.addValue("s1", 0, null);
+      tablet.addValue("s2", 0, null);
+      tablet.addTimestamp(1, 400);
+      tablet.addValue("s1", 1, null);
+      tablet.addValue("s2", 1, null);
+      tablet.addTimestamp(2, 500);
+      tablet.addValue("s1", 2, null);
+      tablet.addValue("s2", 2, null);
+      session.insertAlignedTablet(tablet);
+      long nums = queryCountRecords(session, "select count(s1) from " + 
deviceId);
+      assertEquals(0, nums);
+      session.executeNonQueryStatement("flush");
+      nums = queryCountRecords(session, "select count(s1) from " + deviceId);
+      assertEquals(0, nums);
+      for (DataNodeWrapper dn : EnvFactory.getEnv().getDataNodeWrapperList()) {
+        File dir =
+            new File(
+                dn.getDataDir()
+                    + File.separator
+                    + "datanode"
+                    + File.separator
+                    + "data"
+                    + File.separator
+                    + "sequence"
+                    + File.separator
+                    + "root.sg1"
+                    + File.separator
+                    + "1"
+                    + File.separator
+                    + "0");
+        if (dir.exists() && dir.isDirectory()) {
+          File[] files = dir.listFiles();
+          if (files != null) {
+            for (File file : files) {
+              assertFalse(file.getName().endsWith("broken"));
+            }
+          }
+        }
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+  }
+
   @Test
   public void insertTabletNullMeasurementTest() {
     try (ISession session = EnvFactory.getEnv().getSessionConnection()) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/flush/MemTableFlushTask.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/flush/MemTableFlushTask.java
index 61abb78c24f..48efe55c223 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/flush/MemTableFlushTask.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/flush/MemTableFlushTask.java
@@ -159,7 +159,7 @@ public class MemTableFlushTask {
     for (IDeviceID deviceID : deviceIDList) {
       final Map<String, IWritableMemChunk> value = 
memTableMap.get(deviceID).getMemChunkMap();
       // skip the empty device/chunk group
-      if (memTableMap.get(deviceID).count() == 0 || value.isEmpty()) {
+      if (memTableMap.get(deviceID).isEmpty() || value.isEmpty()) {
         continue;
       }
       encodingTaskQueue.put(new StartFlushGroupIOTask(deviceID));
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AbstractMemTable.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AbstractMemTable.java
index 9d1078a471e..eb49d5325b0 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AbstractMemTable.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AbstractMemTable.java
@@ -972,9 +972,8 @@ public abstract class AbstractMemTable implements IMemTable 
{
   public Map<IDeviceID, Long> getMaxTime() {
     Map<IDeviceID, Long> latestTimeForEachDevice = new HashMap<>();
     for (Entry<IDeviceID, IWritableMemChunkGroup> entry : 
memTableMap.entrySet()) {
-      long maxTime = entry.getValue().getMaxTime();
-      if (entry.getValue().count() > 0) {
-        latestTimeForEachDevice.put(entry.getKey(), maxTime);
+      if (entry.getValue().count() > 0 && !entry.getValue().isEmpty()) {
+        latestTimeForEachDevice.put(entry.getKey(), 
entry.getValue().getMaxTime());
       }
     }
     return latestTimeForEachDevice;
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AlignedWritableMemChunk.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AlignedWritableMemChunk.java
index 50ae45b432c..2fca3ca398a 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AlignedWritableMemChunk.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AlignedWritableMemChunk.java
@@ -593,7 +593,28 @@ public class AlignedWritableMemChunk extends 
AbstractWritableMemChunk {
 
   @Override
   public boolean isEmpty() {
-    return rowCount() == 0;
+    if (rowCount() == 0) {
+      return true;
+    }
+    if (measurementIndexMap.isEmpty()) {
+      return true;
+    }
+
+    if (list.rowCount() > 0) {
+      BitMap allValueColDeletedMap = list.getAllValueColDeletedMap();
+      if (allValueColDeletedMap == null || 
!allValueColDeletedMap.isAllMarked()) {
+        return false;
+      }
+    }
+    for (AlignedTVList alignedTvList : sortedList) {
+      if (alignedTvList.rowCount() > 0) {
+        BitMap allValueColDeletedMap = 
alignedTvList.getAllValueColDeletedMap();
+        if (allValueColDeletedMap == null || 
!allValueColDeletedMap.isAllMarked()) {
+          return false;
+        }
+      }
+    }
+    return true;
   }
 
   @Override
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AlignedWritableMemChunkGroup.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AlignedWritableMemChunkGroup.java
index bc2031c069a..6a9571fbc6c 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AlignedWritableMemChunkGroup.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AlignedWritableMemChunkGroup.java
@@ -102,6 +102,11 @@ public class AlignedWritableMemChunkGroup implements 
IWritableMemChunkGroup {
     return Collections.singletonMap("", memChunk);
   }
 
+  @Override
+  public boolean isEmpty() {
+    return memChunk.isEmpty();
+  }
+
   @SuppressWarnings("squid:S3776")
   @Override
   public int delete(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/IWritableMemChunkGroup.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/IWritableMemChunkGroup.java
index 79baafe86fd..1738a8b9254 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/IWritableMemChunkGroup.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/IWritableMemChunkGroup.java
@@ -48,6 +48,8 @@ public interface IWritableMemChunkGroup extends WALEntryValue 
{
 
   Map<String, IWritableMemChunk> getMemChunkMap();
 
+  boolean isEmpty();
+
   int delete(
       PartialPath originalPath, PartialPath devicePath, long startTimestamp, 
long endTimestamp);
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/WritableMemChunkGroup.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/WritableMemChunkGroup.java
index 313fcd71540..226c2fd3980 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/WritableMemChunkGroup.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/WritableMemChunkGroup.java
@@ -109,6 +109,11 @@ public class WritableMemChunkGroup implements 
IWritableMemChunkGroup {
     return memChunkMap;
   }
 
+  @Override
+  public boolean isEmpty() {
+    return memChunkMap.isEmpty() || count() == 0;
+  }
+
   @SuppressWarnings("squid:S3776")
   @Override
   public int delete(

Reply via email to