Skip to content

fix: fix the missing final window in date_bin_gapfill queries. - #19105

Open
Alchuang22-dev wants to merge 2 commits into
apache:masterfrom
Alchuang22-dev:fix/date_bin_gapfill
Open

Alchuang22-dev wants to merge 2 commits into
apache:masterfrom
Alchuang22-dev:fix/date_bin_gapfill

Conversation

@Alchuang22-dev

Copy link
Copy Markdown
Contributor

Description

Fix #18988

The final group incorrectly treated endTime as exclusive, while gap filling uses an inclusive end boundary. This caused the last window to disappear depending on device filtering or group ordering.

This PR changes the final-group boundary check from < to <= and adds a regression test covering the inclusive final window. Now the final-group boundary is unified as:

 private boolean hasRemainingGapInPreviousGroup() {
    return lastGroupKey != null && currentTime <= endTime;
  }

This PR has:

  • been self-reviewed.
    • concurrent read
    • concurrent write
    • concurrent read and write
  • added documentation for new or modified features or behaviors.
  • added Javadocs for most classes and all non-trivial methods.
  • added or updated version, license, or notice information
  • added comments explaining the "why" and the intent of the code wherever would not be obvious
    for an unfamiliar reader.
  • added unit tests or modified existing tests to cover new code paths, ensuring the threshold
    for code coverage.
  • added integration tests.
  • been tested in a test IoTDB cluster.

Key changed/added classes (or packages if there are too many classes) in this PR

@PDGGK

PDGGK commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Thanks for picking this up. I tried this change and hit one edge case: when the last window is Long.MAX_VALUE, the query never finishes.

nextDateBin saturates at Long.MAX_VALUE, so after fillGaps writes the gap row at endTime == Long.MAX_VALUE, currentTime stays equal to endTime. With <=, hasRemainingGapInPreviousGroup() stays true, so next() fills the same window again on every call. The currentTime <= previousTime check in fillGaps only ends that one call.

To reproduce it, I built calc-commons from v2.0.11 with the gapfill files from master, with and without this change, and ran each on the apache/iotdb:2.0.11-standalone image. Rows this large need timestamp_precision_check_enabled=false.

CREATE DATABASE db1;
CREATE TABLE db1.t (time TIMESTAMP TIME, d STRING TAG, v DOUBLE FIELD);
INSERT INTO db1.t(time, d, v) VALUES (9223372036854775806, 'd2', 2.0);
SELECT date_bin_gapfill(1ms, time) AS w, AVG(v) AS a FROM db1.t
WHERE time >= 9223372036854775805 AND time <= 9223372036854775807 GROUP BY 1;

Without the change it returns two rows, so the last window is missing, as in #18988. With the change it keeps returning the null row for the last window. When I cut the output off at 300 KB, that row had been repeated 7,861 times. Driving the operator directly in a unit test gives the same result: it does not finish.

One way to avoid it is to remember when nextTime() did not move currentTime forward, and stop filling from then on. That would also fix a related case that is already on master: when a group has a real row at Long.MAX_VALUE and another group follows, the group switch in next() adds a gap row at the same time right after the real row.

Also, the description mentions a regression test, but the PR only changes AbstractGapFillOperator.java. Maybe it wasn't pushed?

@Alchuang22-dev

Copy link
Copy Markdown
Contributor Author

@PDGGK Thanks for your feedback. Now timeIteratorExhausted is added to avoid the edge case mentioned in your comment. The regression test is removed because I think the issue does not need an independent test in repository. You could apply more test to confirm if there are more necessary fixes.

@PDGGK

PDGGK commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Thanks for the update. I reran the earlier checks against 7330aef, with the same setup as before:

Looks good to me. One thought on tests: the existing gap-fill operator tests and the IoTDBGapFillTableIT queries give the same results with and without this change, so they wouldn't catch either case if it came back. I have a small unit test that drives the operator directly, and I'm happy to share it if that helps.

@SpriCoder SpriCoder 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.

LGTM~

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.

[Bug] date_bin_gapfill 末尾窗口生成不稳定:受 device_id 过滤与上界运算符影响

3 participants