From bc3a759b365329decaf41b27e68bea04d38d7819 Mon Sep 17 00:00:00 2001 From: shuwenwei Date: Mon, 2 Feb 2026 11:56:11 +0800 Subject: [PATCH] Fix value and time chunk misalignment when rewriting with time deletion --- .../org/apache/tsfile/read/common/Chunk.java | 11 ++- .../apache/tsfile/write/ChunkRewriteTest.java | 72 +++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/common/Chunk.java b/java/tsfile/src/main/java/org/apache/tsfile/read/common/Chunk.java index 01937c743..55036107e 100644 --- a/java/tsfile/src/main/java/org/apache/tsfile/read/common/Chunk.java +++ b/java/tsfile/src/main/java/org/apache/tsfile/read/common/Chunk.java @@ -234,7 +234,16 @@ public Chunk rewrite(TSDataType newType, Chunk timeChunk) throws IOException { encryptParam); List valueChunks = new ArrayList<>(); valueChunks.add(this); - TableChunkReader chunkReader = new TableChunkReader(timeChunk, valueChunks, null); + TableChunkReader chunkReader = + new TableChunkReader( + new Chunk( + timeChunk.getHeader(), + timeChunk.getData(), + null, + timeChunk.getChunkStatistic(), + timeChunk.getEncryptParam()), + valueChunks, + null); List pages = chunkReader.loadPageReaderList(); for (IPageReader page : pages) { IPointReader pointReader = page.getAllSatisfiedPageData().getBatchDataIterator(); diff --git a/java/tsfile/src/test/java/org/apache/tsfile/write/ChunkRewriteTest.java b/java/tsfile/src/test/java/org/apache/tsfile/write/ChunkRewriteTest.java index 30e36055c..f9d7a4260 100644 --- a/java/tsfile/src/test/java/org/apache/tsfile/write/ChunkRewriteTest.java +++ b/java/tsfile/src/test/java/org/apache/tsfile/write/ChunkRewriteTest.java @@ -24,6 +24,7 @@ import org.apache.tsfile.read.TimeValuePair; import org.apache.tsfile.read.common.BatchData; import org.apache.tsfile.read.common.Chunk; +import org.apache.tsfile.read.common.TimeRange; import org.apache.tsfile.read.reader.IPageReader; import org.apache.tsfile.read.reader.IPointReader; import org.apache.tsfile.read.reader.chunk.AlignedChunkReader; @@ -43,6 +44,7 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import static org.junit.Assert.assertEquals; @@ -118,6 +120,76 @@ public void AlignedChunkSinglePageTest() throws IOException { } + @Test + public void AlignedChunkSinglePageWithTimeDeletionTest() throws IOException { + String[] measurements = new String[] {"s1", "s2", "s3"}; + TSDataType[] types = new TSDataType[] {TSDataType.FLOAT, TSDataType.INT32, TSDataType.DOUBLE}; + VectorMeasurementSchema measurementSchema = + new VectorMeasurementSchema("table1.d1", measurements, types); + AlignedChunkWriterImpl chunkWriter = new AlignedChunkWriterImpl(measurementSchema); + + for (int time = 1; time <= 20; time++) { + chunkWriter.write(time, (float) time, false); + chunkWriter.write(time, time, false); + chunkWriter.write(time, (double) time, false); + chunkWriter.write(time); + } + chunkWriter.sealCurrentPage(); + + TimeChunkWriter timeChunkWriter = chunkWriter.getTimeChunkWriter(); + List valueChunkWriters = chunkWriter.getValueChunkWriterList(); + + Chunk timeChunk = getTimeChunk(measurementSchema, timeChunkWriter); + + List valueChunks = getValueChunks(valueChunkWriters); + + AlignedChunkReader chunkReader = new AlignedChunkReader(timeChunk, valueChunks); + List pageReaders = chunkReader.loadPageReaderList(); + for (IPageReader page : pageReaders) { + IPointReader pointReader = ((AlignedPageReader) page).getLazyPointReader(); + int i = 1; + while (pointReader.hasNextTimeValuePair()) { + TimeValuePair point = pointReader.nextTimeValuePair(); + assertEquals((long) i, point.getTimestamp()); + assertEquals((float) i, point.getValue().getVector()[0].getValue()); + assertEquals(i, point.getValue().getVector()[1].getValue()); + assertEquals((double) i, point.getValue().getVector()[2].getValue()); + i++; + } + } + timeChunk.getData().flip(); + valueChunks.get(0).getData().flip(); + valueChunks.get(1).getData().flip(); + valueChunks.get(2).getData().flip(); + // delete + timeChunk.setDeleteIntervalList(Collections.singletonList(new TimeRange(0, 9))); + // rewrite INT32->DOUBLE + Chunk newValueChunk = valueChunks.get(1).rewrite(TSDataType.DOUBLE, timeChunk); + valueChunks.set(1, newValueChunk); + TableChunkReader newChunkReader = new TableChunkReader(timeChunk, valueChunks, null); + List newPageReaders = newChunkReader.loadPageReaderList(); + for (IPageReader page : newPageReaders) { + IPointReader pointReader = page.getAllSatisfiedPageData().getBatchDataIterator(); + int i = 1; + while (pointReader.hasNextTimeValuePair()) { + TimeValuePair point = pointReader.nextTimeValuePair(); + assertEquals((long) i + 9, point.getTimestamp()); + assertEquals((float) (i + 9), point.getValue().getVector()[0].getValue()); + assertEquals((double) (i + 9), point.getValue().getVector()[1].getValue()); + assertEquals((double) (i + 9), point.getValue().getVector()[2].getValue()); + i++; + } + assertEquals(11, i - 1); + } + timeChunk.getData().flip(); + valueChunks.get(0).getData().flip(); + valueChunks.get(1).getData().flip(); + valueChunks.get(2).getData().flip(); + + // + + } + @Test public void AlignedChunkMultiPagesTest() throws IOException { String[] measurements = new String[] {"s1", "s2", "s3"};