Skip to content

feat: allow non-decreasing (duplicate) timestamps behind an opt-in flag - #1085

Merged
jt2594838 merged 7 commits into
developfrom
colin/allow-nondecreasing-timestamps-51acf1
Nov 12, 2026
Merged

jt2594838 merged 7 commits into
developfrom
colin/allow-nondecreasing-timestamps-51acf1

Conversation

@ColinLeeo

@ColinLeeo ColinLeeo commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Closes #1056.

Summary

Adds an opt-in allowNonDecreasingTimestamps flag (default off) across Java, C++, and Python. When enabled, a writer accepts a timestamp equal to the previously written timestamp and only rejects strictly decreasing timestamps. When disabled, behavior and error messages are unchanged.

  • Java — TSFileConfig.allowNonDecreasingTimestamps, threaded through AlignedChunkGroupWriterImpl, NonAlignedChunkGroupWriterImpl, and TabletWriteContext.
  • C++ — ConfigValue::allow_non_decreasing_timestamps_ plus a C API setter set_allow_non_decreasing_timestamps(bool), applied in TimePageWriter::write/write_batch and TsFileWriter's recovered-last-time ordering checks.
  • Python — allow_non_decreasing_timestamps= keyword argument on TsFileWriter and TsFileTableWriter.

Duplicate semantics

  • Duplicates are preserved as separate rows; deduplication is left to the query layer (no write-time dedup).
  • The flag only relaxes equality. Out-of-order timestamps within a tablet batch (timestamps[i] < timestamps[i-1]) are still rejected; strictly decreasing timestamps still fail in every path.
  • Applies uniformly across row, tablet, and table APIs, and across aligned and non-aligned devices, including page/chunk/chunk-group boundaries. The recovered-last-time check (append/recovery) also honors the flag.

File property

When the flag is enabled, the writer registers the file-level property allowNonDecreasingTimestamps = "true" in the TsFile metadata (Java TsFileIOWriter, including the RestorableTsFileIOWriter append path; C++ TsFileIOWriter::init, used by both tree and table writers). Downstream applications such as an IoTDB load can read it and avoid assuming strictly increasing times within a series. Flag-off writes add nothing, so existing files keep their metadata unchanged.

Tests

  • Java: AllowNonDecreasingTimestampsTest (flag on/off, aligned + non-aligned, round-trip read, property present/absent).
  • C++: TsFileWriterTest.AllowNonDecreasing* (aligned and non-aligned write+read round-trips, plus strictly-decreasing rejection), EqualTimestampsRejectedAlignedWhenFlagOff, and TsFilePropertiesTest.RecordsAllowNonDecreasingTimestampsPolicy / OmitsPolicyPropertyWhenFlagOff.
  • Python: test_allow_non_decreasing_timestamps.py (duplicates round-trip, property present/absent, rejection cases).
  • Cross-language: compatibility-matrix.csv adds table_int32_plain_dups and tree_int32_plain_dups (timestampProfile=duplicates); the compatibility workflow writes each with Java and C++ and validates the other side's fixture returns the duplicate timestamps as separate rows.

…ag (#1056)

Add an opt-in `allowNonDecreasingTimestamps` flag (default off) across all
three implementations so a writer can accept a timestamp equal to the last
written one while still rejecting strictly decreasing timestamps.

Java: `TSFileConfig` flag threaded through the aligned/non-aligned chunk
group writers and the tablet write context.
C++: `ConfigValue` field plus a C API setter, applied in TimePageWriter's
single and batch paths and the recovered-last-time ordering checks.
Python: `allow_non_decreasing_timestamps` keyword argument on the writer
constructors.

Duplicate timestamps are preserved as separate rows (no write-time dedup).
Tests cover flag on/off in Java, C++, and Python, plus a cross-language
round-trip (Java writes duplicates, C++ reads them back).
@codecov-commenter

codecov-commenter commented Nov 11, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 75.00000% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.51%. Comparing base (545e8f0) to head (421cd65).

Files with missing lines Patch % Lines
cpp/src/writer/tsfile_writer.cc 47.05% 3 Missing and 6 partials ⚠️
cpp/src/cwrapper/tsfile_cwrapper.cc 0.00% 2 Missing ⚠️
...le/write/chunk/NonAlignedChunkGroupWriterImpl.java 75.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #1085      +/-   ##
===========================================
+ Coverage    66.49%   66.51%   +0.02%     
===========================================
  Files          778      778              
  Lines        56559    56577      +18     
  Branches      9098     9105       +7     
===========================================
+ Hits         37607    37632      +25     
+ Misses       17301    17291      -10     
- Partials      1651     1654       +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

… tests

The rejected write leaves the C++ writer unrecoverable, so its file handle
stays open on Windows; deleting a fixed-named file then fails with WinError
32 and leaks into the next test. Write to a unique temp dir and clean up
best-effort.
…mitting a binary

Replace the committed Java-written binary fixture with a self-contained
non-aligned write+read round-trip test in TsFileWriterTest, and remove the
now-unused standalone reader test and binary fixture.

The new test writes {0, 1, 1, 2} through the non-aligned row path with
allow_non_decreasing_timestamps enabled and asserts the duplicate
timestamps are read back as separate rows.
Add an optional trailing timestampProfile column to the compatibility
matrix. The duplicates profile writes timestamps as row/2 (each value
appears twice) with allow_non_decreasing_timestamps enabled. Two new
INT32/PLAIN cases (table + tree) let each side write the fixture and
validate the other side's file returns the duplicates as separate rows.

@jt2594838 jt2594838 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May register this config into TsFile properties so that the down-stream applications (like IoTDB load) may know how to handle the file correctly.

When the writer runs with allowNonDecreasingTimestamps, register the
file-level property "allowNonDecreasingTimestamps" = "true" so downstream
applications (e.g. an IoTDB load) can tell the file may contain duplicate
timestamps and must not assume strictly increasing times within a series.

The property is added at writer initialization in both Java (TsFileIOWriter,
including the append path in RestorableTsFileIOWriter) and C++ (TsFileIOWriter
init, which both the tree and table writers use). Flag-off writes add
nothing, so existing files are unchanged.
@ColinLeeo

Copy link
Copy Markdown
Contributor Author

Thanks for the review. The flag is now recorded in the file metadata: when allowNonDecreasingTimestamps is enabled, the writer registers the file-level property allowNonDecreasingTimestamps = "true" (Java TsFileIOWriter — also on the RestorableTsFileIOWriter append path — and C++ TsFileIOWriter::init, shared by the tree and table writers), so downstream loaders can read it via the normal TsFile property API. Flag-off writes add nothing, keeping existing files' metadata unchanged. Tests cover presence/absence in Java, C++, and Python.

CTest runs cases of one binary in parallel (--parallel 4). All cases in this
fixture shared one fixed file name, so the new policy-property cases
truncated or removed the file while WriterPreservesBinaryNullAndEmptyValues
was still using it, failing that test on Linux and Windows CI. Derive the
file name from the current test name instead.
@jt2594838
jt2594838 merged commit 90c7862 into develop Nov 12, 2026
68 of 71 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Allow non-decreasing (duplicate) timestamps when writing, behind an opt-in flag

3 participants