This is an automated email from the ASF dual-hosted git repository.
jackietien 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 032df7cd8da [to dev/1.3] Fix allValueColDeletedMap index out of bound
caused by stale rowCount after TVList sort #17103
032df7cd8da is described below
commit 032df7cd8da3622c47cd47dd05959f9f8195d610
Author: shuwenwei <[email protected]>
AuthorDate: Wed Jan 28 19:37:49 2026 +0800
[to dev/1.3] Fix allValueColDeletedMap index out of bound caused by stale
rowCount after TVList sort #17103
---
.../memtable/AlignedReadOnlyMemChunk.java | 12 ++++-
.../dataregion/memtable/ReadOnlyMemChunk.java | 4 +-
.../db/utils/datastructure/AlignedTVList.java | 6 ++-
.../db/utils/datastructure/BackAlignedTVList.java | 3 +-
.../db/utils/datastructure/BackBinaryTVList.java | 3 +-
.../db/utils/datastructure/BackBooleanTVList.java | 3 +-
.../db/utils/datastructure/BackDoubleTVList.java | 3 +-
.../db/utils/datastructure/BackFloatTVList.java | 3 +-
.../db/utils/datastructure/BackIntTVList.java | 3 +-
.../db/utils/datastructure/BackLongTVList.java | 3 +-
.../db/utils/datastructure/QuickAlignedTVList.java | 3 +-
.../db/utils/datastructure/QuickBinaryTVList.java | 3 +-
.../db/utils/datastructure/QuickBooleanTVList.java | 3 +-
.../db/utils/datastructure/QuickDoubleTVList.java | 3 +-
.../db/utils/datastructure/QuickFloatTVList.java | 3 +-
.../db/utils/datastructure/QuickIntTVList.java | 3 +-
.../db/utils/datastructure/QuickLongTVList.java | 3 +-
.../iotdb/db/utils/datastructure/TVList.java | 2 +-
.../db/utils/datastructure/TimAlignedTVList.java | 3 +-
.../db/utils/datastructure/TimBinaryTVList.java | 3 +-
.../db/utils/datastructure/TimBooleanTVList.java | 3 +-
.../db/utils/datastructure/TimDoubleTVList.java | 3 +-
.../db/utils/datastructure/TimFloatTVList.java | 3 +-
.../iotdb/db/utils/datastructure/TimIntTVList.java | 3 +-
.../db/utils/datastructure/TimLongTVList.java | 3 +-
.../dataregion/memtable/PrimitiveMemTableTest.java | 54 ++++++++++++++++++++++
26 files changed, 114 insertions(+), 27 deletions(-)
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AlignedReadOnlyMemChunk.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AlignedReadOnlyMemChunk.java
index d00424856ba..bbab08d4442 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AlignedReadOnlyMemChunk.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AlignedReadOnlyMemChunk.java
@@ -113,7 +113,15 @@ public class AlignedReadOnlyMemChunk extends
ReadOnlyMemChunk {
AlignedTVList alignedTvList = (AlignedTVList) entry.getKey();
int queryRowCount = entry.getValue();
if (!alignedTvList.isSorted() && queryRowCount >
alignedTvList.seqRowCount()) {
- alignedTvList.sort();
+ // sort() returns the current row count
+ // TVList may grow between prepareTvListMapForQuery and actual query
execution(now).
+ // The queryRowCount recorded here is only a snapshot taken during
prepareTvListMapForQuery
+ // phase.
+ // Additional written rows that are not covered by the original
queryRowCount can be
+ // involved in current sort operation.
+ // We must update queryRowCount here, otherwise, it may be used later
to build
+ // BitMaps, causing bitmap array size mismatch and possible out of
bound.
+ entry.setValue(alignedTvList.sort());
long alignedTvListRamSize = alignedTvList.calculateRamSize();
alignedTvList.lockQueryList();
try {
@@ -358,7 +366,7 @@ public class AlignedReadOnlyMemChunk extends
ReadOnlyMemChunk {
AlignedTVList alignedTvList = (AlignedTVList) entry.getKey();
int queryLength = entry.getValue();
if (!alignedTvList.isSorted() && queryLength >
alignedTvList.seqRowCount()) {
- alignedTvList.sort();
+ entry.setValue(alignedTvList.sort());
long alignedTvListRamSize = alignedTvList.calculateRamSize();
alignedTvList.lockQueryList();
try {
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/ReadOnlyMemChunk.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/ReadOnlyMemChunk.java
index 3438759cfa9..38c8e9e2d13 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/ReadOnlyMemChunk.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/ReadOnlyMemChunk.java
@@ -135,7 +135,7 @@ public class ReadOnlyMemChunk {
TVList tvList = entry.getKey();
int queryRowCount = entry.getValue();
if (!tvList.isSorted() && queryRowCount > tvList.seqRowCount()) {
- tvList.sort();
+ entry.setValue(tvList.sort());
long tvListRamSize = tvList.calculateRamSize();
tvList.lockQueryList();
try {
@@ -287,7 +287,7 @@ public class ReadOnlyMemChunk {
TVList tvList = entry.getKey();
int queryLength = entry.getValue();
if (!tvList.isSorted() && queryLength > tvList.seqRowCount()) {
- tvList.sort();
+ entry.setValue(tvList.sort());
long tvListRamSize = tvList.calculateRamSize();
tvList.lockQueryList();
try {
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/AlignedTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/AlignedTVList.java
index e4230787a76..090b0574987 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/AlignedTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/AlignedTVList.java
@@ -1259,6 +1259,10 @@ public abstract class AlignedTVList extends TVList {
}
public BitMap getAllValueColDeletedMap() {
+ return getAllValueColDeletedMap(rowCount);
+ }
+
+ public BitMap getAllValueColDeletedMap(int rowCount) {
// row exists when any column value exists
if (bitMaps == null) {
return null;
@@ -1415,7 +1419,7 @@ public abstract class AlignedTVList extends TVList {
(columnIndexList == null)
? IntStream.range(0,
dataTypes.size()).boxed().collect(Collectors.toList())
: columnIndexList;
- this.allValueColDeletedMap = getAllValueColDeletedMap();
+ this.allValueColDeletedMap = getAllValueColDeletedMap(this.rows);
this.valueColumnsDeletionList = valueColumnsDeletionList;
this.floatPrecision = floatPrecision != null ? floatPrecision : 0;
this.encodingList = encodingList;
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackAlignedTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackAlignedTVList.java
index 2ad728a1a26..2603790bd66 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackAlignedTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackAlignedTVList.java
@@ -32,12 +32,13 @@ public class BackAlignedTVList extends QuickAlignedTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
if (!sorted) {
policy.backwardSort(timestamps, rowCount);
policy.clearTmp();
}
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackBinaryTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackBinaryTVList.java
index cd85976a58e..9faedb162a1 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackBinaryTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackBinaryTVList.java
@@ -26,12 +26,13 @@ public class BackBinaryTVList extends QuickBinaryTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
if (!sorted) {
policy.backwardSort(timestamps, rowCount);
policy.clearTmp();
}
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackBooleanTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackBooleanTVList.java
index 969d3981285..2186c1fa66e 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackBooleanTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackBooleanTVList.java
@@ -27,12 +27,13 @@ public class BackBooleanTVList extends QuickBooleanTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
if (!sorted) {
policy.backwardSort(timestamps, rowCount);
policy.clearTmp();
}
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackDoubleTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackDoubleTVList.java
index 6d79b9d0ab2..0cb7c438db4 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackDoubleTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackDoubleTVList.java
@@ -27,12 +27,13 @@ public class BackDoubleTVList extends QuickDoubleTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
if (!sorted) {
policy.backwardSort(timestamps, rowCount);
policy.clearTmp();
}
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackFloatTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackFloatTVList.java
index 75b09507cc4..a3208b96f6b 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackFloatTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackFloatTVList.java
@@ -27,12 +27,13 @@ public class BackFloatTVList extends QuickFloatTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
if (!sorted) {
policy.backwardSort(timestamps, rowCount);
policy.clearTmp();
}
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackIntTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackIntTVList.java
index 3ccc5cbc946..3a2af2841c9 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackIntTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackIntTVList.java
@@ -27,12 +27,13 @@ public class BackIntTVList extends QuickIntTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
if (!sorted) {
policy.backwardSort(timestamps, rowCount);
policy.clearTmp();
}
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackLongTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackLongTVList.java
index 58d4a4e2fc8..580af939c7f 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackLongTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/BackLongTVList.java
@@ -26,12 +26,13 @@ public class BackLongTVList extends QuickLongTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
if (!sorted) {
policy.backwardSort(timestamps, rowCount);
policy.clearTmp();
}
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickAlignedTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickAlignedTVList.java
index 69f24527d67..c5bd5550056 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickAlignedTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickAlignedTVList.java
@@ -31,11 +31,12 @@ public class QuickAlignedTVList extends AlignedTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
if (!sorted) {
policy.qsort(0, rowCount - 1);
}
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickBinaryTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickBinaryTVList.java
index 645d0dbce5a..b8abddaee5d 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickBinaryTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickBinaryTVList.java
@@ -26,11 +26,12 @@ public class QuickBinaryTVList extends BinaryTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
if (!sorted) {
policy.qsort(0, rowCount - 1);
}
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickBooleanTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickBooleanTVList.java
index 779159ca719..50df94c772a 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickBooleanTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickBooleanTVList.java
@@ -26,11 +26,12 @@ public class QuickBooleanTVList extends BooleanTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
if (!sorted) {
policy.qsort(0, rowCount - 1);
}
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickDoubleTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickDoubleTVList.java
index 58f3cc1ce2f..44120672fce 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickDoubleTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickDoubleTVList.java
@@ -26,11 +26,12 @@ public class QuickDoubleTVList extends DoubleTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
if (!sorted) {
policy.qsort(0, rowCount - 1);
}
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickFloatTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickFloatTVList.java
index 2fc22ab2990..6ad9b1d7257 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickFloatTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickFloatTVList.java
@@ -26,11 +26,12 @@ public class QuickFloatTVList extends FloatTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
if (!sorted) {
policy.qsort(0, rowCount - 1);
}
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickIntTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickIntTVList.java
index e83646e3202..af7e35eb655 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickIntTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickIntTVList.java
@@ -26,11 +26,12 @@ public class QuickIntTVList extends IntTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
if (!sorted) {
policy.qsort(0, rowCount - 1);
}
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickLongTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickLongTVList.java
index 5f629720c5d..98134984c0c 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickLongTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/QuickLongTVList.java
@@ -26,11 +26,12 @@ public class QuickLongTVList extends LongTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
if (!sorted) {
policy.qsort(0, rowCount - 1);
}
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TVList.java
index 8695182712f..0f4ab88441a 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TVList.java
@@ -176,7 +176,7 @@ public abstract class TVList implements WALEntryValue {
return reservedMemoryBytes;
}
- public abstract void sort();
+ public abstract int sort();
public void increaseReferenceCount() {
referenceCount.incrementAndGet();
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimAlignedTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimAlignedTVList.java
index 479e0a969a3..61d5c75096e 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimAlignedTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimAlignedTVList.java
@@ -31,7 +31,7 @@ public class TimAlignedTVList extends AlignedTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
policy.checkSortedTimestampsAndIndices();
if (!sorted) {
policy.sort(0, rowCount);
@@ -40,6 +40,7 @@ public class TimAlignedTVList extends AlignedTVList {
policy.clearSortedTime();
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
@Override
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimBinaryTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimBinaryTVList.java
index c78d67034da..df0b1795371 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimBinaryTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimBinaryTVList.java
@@ -26,7 +26,7 @@ public class TimBinaryTVList extends BinaryTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
policy.checkSortedTimestampsAndIndices();
if (!sorted) {
policy.sort(0, rowCount);
@@ -35,6 +35,7 @@ public class TimBinaryTVList extends BinaryTVList {
policy.clearSortedTime();
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
@Override
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimBooleanTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimBooleanTVList.java
index 0e7dc48faaf..e5051ec0ede 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimBooleanTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimBooleanTVList.java
@@ -26,7 +26,7 @@ public class TimBooleanTVList extends BooleanTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
policy.checkSortedTimestampsAndIndices();
if (!sorted) {
policy.sort(0, rowCount);
@@ -35,6 +35,7 @@ public class TimBooleanTVList extends BooleanTVList {
policy.clearSortedTime();
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
@Override
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimDoubleTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimDoubleTVList.java
index 29fc62d91c6..8b4b40c2da5 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimDoubleTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimDoubleTVList.java
@@ -26,7 +26,7 @@ public class TimDoubleTVList extends DoubleTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
policy.checkSortedTimestampsAndIndices();
if (!sorted) {
policy.sort(0, rowCount);
@@ -35,6 +35,7 @@ public class TimDoubleTVList extends DoubleTVList {
policy.clearSortedTime();
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
@Override
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimFloatTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimFloatTVList.java
index 83ad6aca1f6..522b8bf7d61 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimFloatTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimFloatTVList.java
@@ -26,7 +26,7 @@ public class TimFloatTVList extends FloatTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
policy.checkSortedTimestampsAndIndices();
if (!sorted) {
policy.sort(0, rowCount);
@@ -35,6 +35,7 @@ public class TimFloatTVList extends FloatTVList {
policy.clearSortedTime();
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
@Override
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimIntTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimIntTVList.java
index 8216f2eb296..594980d4546 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimIntTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimIntTVList.java
@@ -26,7 +26,7 @@ public class TimIntTVList extends IntTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
policy.checkSortedTimestampsAndIndices();
if (!sorted) {
policy.sort(0, rowCount);
@@ -35,6 +35,7 @@ public class TimIntTVList extends IntTVList {
policy.clearSortedTime();
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
@Override
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimLongTVList.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimLongTVList.java
index bcd5c3022f9..e741ca51504 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimLongTVList.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TimLongTVList.java
@@ -26,7 +26,7 @@ public class TimLongTVList extends LongTVList {
}
@Override
- public synchronized void sort() {
+ public synchronized int sort() {
policy.checkSortedTimestampsAndIndices();
if (!sorted) {
policy.sort(0, rowCount);
@@ -35,6 +35,7 @@ public class TimLongTVList extends LongTVList {
policy.clearSortedTime();
sorted = true;
seqRowCount = rowCount;
+ return rowCount;
}
@Override
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/memtable/PrimitiveMemTableTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/memtable/PrimitiveMemTableTest.java
index 572e6cd7ef8..f9186b774e1 100644
---
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/memtable/PrimitiveMemTableTest.java
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/storageengine/dataregion/memtable/PrimitiveMemTableTest.java
@@ -44,16 +44,20 @@ import
org.apache.iotdb.db.queryengine.execution.schedule.IDriverScheduler;
import
org.apache.iotdb.db.queryengine.plan.planner.memory.MemoryReservationManager;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNodeId;
import
org.apache.iotdb.db.queryengine.plan.planner.plan.node.write.InsertTabletNode;
+import org.apache.iotdb.db.queryengine.plan.statement.component.Ordering;
+import org.apache.iotdb.db.schemaengine.schemaregion.utils.ResourceByPathUtils;
import org.apache.iotdb.db.storageengine.dataregion.DataRegion;
import org.apache.iotdb.db.storageengine.dataregion.modification.Deletion;
import org.apache.iotdb.db.storageengine.dataregion.modification.Modification;
import
org.apache.iotdb.db.storageengine.dataregion.wal.utils.WALByteBufferForTest;
import org.apache.iotdb.db.utils.MathUtils;
+import org.apache.iotdb.db.utils.datastructure.MemPointIterator;
import org.apache.iotdb.db.utils.datastructure.TVList;
import org.apache.tsfile.common.conf.TSFileConfig;
import org.apache.tsfile.common.conf.TSFileDescriptor;
import org.apache.tsfile.enums.TSDataType;
+import org.apache.tsfile.file.metadata.PlainDeviceID;
import org.apache.tsfile.file.metadata.enums.CompressionType;
import org.apache.tsfile.file.metadata.enums.TSEncoding;
import org.apache.tsfile.read.TimeValuePair;
@@ -123,6 +127,56 @@ public class PrimitiveMemTableTest {
Assert.assertEquals(count, i);
}
+ /**
+ * Regression test for concurrent writes between prepare and query
execution. The test ensures
+ * that when new rows are written after the prepare phase but before TVList
sorting, the query
+ * refreshes the rowCount after sort and avoids using a stale queryRowCount
for bitmap
+ * construction, which would otherwise cause ArrayIndexOutOfBoundsException.
+ */
+ @Test
+ public void testWriteDuringPrepareTVListAndActualQueryExecution()
+ throws QueryProcessException, IOException, IllegalPathException {
+
+ PrimitiveMemTable memTable = new PrimitiveMemTable("root.test", "0");
+ List<IMeasurementSchema> measurementSchemas =
+ Arrays.asList(
+ new MeasurementSchema("s1", TSDataType.INT32),
+ new MeasurementSchema("s2", TSDataType.INT32),
+ new MeasurementSchema("s3", TSDataType.INT32));
+ for (int i = 1000; i < 2000; i++) {
+ memTable.writeAlignedRow(
+ new PlainDeviceID("root.test.d1"), measurementSchemas, i, new
Object[] {i, i, i});
+ }
+ for (int i = 100; i < 200; i++) {
+ memTable.writeAlignedRow(
+ new PlainDeviceID("root.test.d1"), measurementSchemas, i, new
Object[] {i, i, i});
+ }
+ MeasurementPath path = new MeasurementPath("root.test.d1.s1",
TSDataType.INT32);
+ memTable.delete(path, path.getDevicePath(), 150, 160);
+ path = new MeasurementPath("root.test.d1.s2", TSDataType.INT32);
+ memTable.delete(path, path.getDevicePath(), 150, 160);
+ path = new MeasurementPath("root.test.d1.s3", TSDataType.INT32);
+ memTable.delete(path, path.getDevicePath(), 150, 160);
+ ResourceByPathUtils resourcesByPathUtils =
+ ResourceByPathUtils.getResourceInstance(
+ new AlignedPath("root.test.d1", Arrays.asList("s1", "s2", "s3"),
measurementSchemas));
+ ReadOnlyMemChunk readOnlyMemChunk =
+ resourcesByPathUtils.getReadOnlyMemChunkFromMemTable(
+ new QueryContext(1), memTable, null, Long.MAX_VALUE, null);
+
+ for (int i = 1; i <= 50; i++) {
+ memTable.writeAlignedRow(
+ new PlainDeviceID("root.test.d1"), measurementSchemas, i, new
Object[] {i, i, i});
+ }
+
+ readOnlyMemChunk.sortTvLists();
+
+ MemPointIterator memPointIterator =
readOnlyMemChunk.createMemPointIterator(Ordering.ASC, null);
+ while (memPointIterator.hasNextBatch()) {
+ memPointIterator.nextBatch();
+ }
+ }
+
@Test
public void memSeriesToStringTest() throws IOException {
TSDataType dataType = TSDataType.INT32;