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(