Skip to content

fix(window): handle temporal range bound overflow - #27394

Merged
XuPeng-SH merged 10 commits into
matrixorigin:mainfrom
iamlinjunhong:m-27350
Aug 29, 2026
Merged

fix(window): handle temporal range bound overflow#27394
XuPeng-SH merged 10 commits into
matrixorigin:mainfrom
iamlinjunhong:m-27350

Conversation

@iamlinjunhong

Copy link
Copy Markdown
Contributor

What type of PR is this?

  • API-change
  • BUG
  • Improvement
  • Documentation
  • Feature
  • Test and CI
  • Code Refactoring

Which issue(s) this PR fixes:

issue #27350

What this PR does / why we need it:

fix(window): handle temporal range bound overflow

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

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

[P1] Reviewed exact head 0584f36. The new insertion-point rule is correct for DATE and DATETIME, but the same valid-query failure remains for the other temporal RANGE types supported by this operator. The T_time and T_timestamp branches in both searchLeft and searchRight still return doTimeAdd/Sub or doTimestampAdd/Sub ErrOutOfRange directly. A stored maximum TIMESTAMP such as 9999-12-31 23:59:59.999999 with an ASC FOLLOWING interval therefore still errors instead of treating the upper search key as after the partition; minimum PRECEDING, DESC, and TIME domain boundaries have the analogous failure. JudgeIntervalNumOverflow errors should continue to propagate, but AddInterval domain overflow should use temporalRangeOverflowBoundary for every supported temporal type. Please add TIME and TIMESTAMP above/below-domain coverage in both directions, including an invalid interval-magnitude control and at least one public SQL regression.

@iamlinjunhong

Copy link
Copy Markdown
Contributor Author

已修复 review 指出的问题:TIME/TIMESTAMP 在 searchLeft/searchRight 中现在和 DATE/DATETIME 一样,仅将 AddInterval 产生的 ErrOutOfRange 映射为 temporalRangeOverflowBoundary;JudgeIntervalNumOverflow 仍直接返回错误。补充了四种 temporal 类型的上/下域外、ASC/DESC 双方向与非法区间控制单测,并扩展了公共 SQL 回归。验证:CGo 环境下 go build、go vet、pkg/sql/colexec/window 全包测试均通过。

@iamlinjunhong

Copy link
Copy Markdown
Contributor Author

Follow-up to @aunjgr: the requested TIME/TIMESTAMP paths are addressed in a2d8f97. Both searchLeft and searchRight now map only AddInterval ErrOutOfRange to temporalRangeOverflowBoundary; JudgeIntervalNumOverflow is still returned. TestSearchLeftRightTemporalRangeOverflow covers DATE/DATETIME/TIME/TIMESTAMP above and below domain in ASC/DESC plus invalid interval magnitudes, and window_temporal_range_bound.sql adds public TIME/TIMESTAMP regression coverage. Fresh local validation: GOWORK=off build and vet for ./pkg/sql/colexec/window/... passed with the repository CGo include paths; mo-cgo-test -v -count=1 -timeout=120s ./pkg/sql/colexec/window/... passed (including the exact regression). The current Actions run 32350145471 has no failed completed job; remaining UT/BVT jobs are still running.

@iamlinjunhong

Copy link
Copy Markdown
Contributor Author

@aunjgr Addressed on 4d0b469. TIME and TIMESTAMP now use temporalRangeOverflowBoundary in both searchLeft/searchRight for AddInterval ErrOutOfRange only; JudgeIntervalNumOverflow still propagates. TestSearchLeftRightTemporalRangeOverflow covers DATE/DATETIME/TIME/TIMESTAMP above/below-domain, ASC/DESC, both searches, and invalid magnitudes. Public SQL coverage includes TIME and TIMESTAMP. The previous Pessimistic BVT failure was ResultParser-only: the new result file listed drop table t; before its matching SQL command; its order is now aligned. Fresh validation: mo-cgo-test focused and full ./pkg/sql/colexec/window/...; GOWORK=off build and vet all passed.

aunjgr
aunjgr previously requested changes Aug 25, 2026

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

The checked MICROSECOND branches for TIMESTAMP bypass timestampRangeBoundary: both doTimestampSub and doTimestampAdd return dt.ToTimestamp(loc) directly, while all other interval units use the new DST-gap normalization.

That produces an incorrect and even non-monotonic RANGE key. In America/New_York, 2024-03-10 01:59:59.999999 + INTERVAL 1 MICROSECOND yields the nonexistent civil time 02:00:00. Go maps that direct conversion back to 01:00 EST, whereas this PRs helper deliberately clamps a gap value to the first valid instant, 03:00 EDT. The frame boundary can therefore jump backward and select the wrong rows.

Please route both MICROSECOND TIMESTAMP results through timestampRangeBoundary(dt, loc) and add add/subtract regressions crossing the spring-forward gap in both sort directions.

aptend
aptend previously requested changes Aug 25, 2026

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

Deep re-review completed on exact head c513527ad2fae12e2d6db0eb0138404f4ce4ab47. I read every historical review and issue comment, checked the (empty) inline/thread history and resolved state, compared the increment from my previous reviewed head 8455db803ac38ca2724f0afe26e8dd69e7ffbb8a, and rechecked the full six-file diff. The prior TIME/TIMESTAMP domain handling, signed MICROSECOND wrap, negative-interval direction, and MinInt64 validation findings are closed. Two blocking boundary-calculation holes remain: the MICROSECOND TIMESTAMP path bypasses the existing DST-gap normalization, and accepted non-MICROSECOND magnitudes can overflow during unit conversion before any domain error is produced.

Validation on this exact head, after make thirdparties with the required CGO environment:

  • go test ./pkg/sql/colexec/window ./pkg/container/types -count=1: pass
  • TestSearchLeftRightTemporalRangeOverflow at count 10 and under -race at count 3: pass
  • go vet ./pkg/sql/colexec/window ./pkg/container/types: pass
  • git diff --check refs/codex/review/pr27394-base...HEAD: pass
  • exact DST-gap helper counterexample: expected 03:00 EDT, got 01:00 EST
  • exact unit-conversion counterexample: expected insertion point 2, got 1
  • public SQL INTERVAL 307445734562 MINUTE regression: expected window sums [11,10], got [1,10]

All temporary counterexample tests were removed and the review worktree is clean. CI is green on this head.

Comment thread pkg/sql/colexec/window/window.go Outdated
Comment thread pkg/container/types/interval.go

@XuPeng-SH XuPeng-SH 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.

P1: calendar-sized RANGE intervals can still wrap back into the valid temporal domain and return silently incorrect frames.

The new temporalRangeIntervalConversionOK closes fixed-duration multiplication overflow, but returns true for MONTH, QUARTER, and YEAR. Those units reach Datetime.AddDateTime, which computes the year in int64 and then narrows it with y = int32(year) before ValidDate/ValidDatetime. A magnitude that differs by 2^32 years therefore wraps to the original year and is accepted.

I reproduced this on exact head 04b5262860f1e243cd3375d91a7d789e54e3cbc5: doDateAdd, doDatetimeAdd, and doTimestampAdd for 2024-01-01 + INTERVAL (1<<32) YEAR all returned 2024-01-01 with no error. In a RANGE frame, the conceptually unreachable upper bound is consequently searched as the current in-domain key, so an enormous FOLLOWING frame can collapse to the current peer instead of reaching the partition end. This is wrong-result risk, not just error handling.

Please validate calendar-unit arithmetic in the wide representation before narrowing (including the month/quarter-to-year conversion), return the same directional domain-overflow signal, and add search-level add/subtract coverage for MONTH, QUARTER, and YEAR in both sort directions. The focused DST-gap, fixed-duration conversion, signed-overflow, and interval-limit tests otherwise pass on this head.

@mergify

mergify Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

  • Entered queue2026-08-29 14:50 UTC · Rule: main · triggered by rule Automatic queue on approval for main
  • 🟠 Checks running · in-place
  • 🚫 Left the queue2026-08-29 14:51 UTC · at 5e5d866da3ab44db7baccfb722119c933999c5d8

This pull request spent 1 minute 11 seconds in the queue, with no time running CI.

Waiting for
  • any of: [🛡 GitHub branch protection]
    • check-neutral = Matrixone CI / UT Test on Ubuntu/x86
    • check-skipped = Matrixone CI / UT Test on Ubuntu/x86
    • check-success = Matrixone CI / UT Test on Ubuntu/x86
  • any of: [🛡 GitHub branch protection]
    • check-neutral = Matrixone CI / SCA Test on Linux/arm64
    • check-skipped = Matrixone CI / SCA Test on Linux/arm64
    • check-success = Matrixone CI / SCA Test on Linux/arm64
  • any of: [🛡 GitHub branch protection]
    • check-neutral = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
    • check-skipped = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
    • check-success = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
  • any of: [🛡 GitHub branch protection]
    • check-neutral = Matrixone Utils CI / Coverage
    • check-skipped = Matrixone Utils CI / Coverage
    • check-success = Matrixone Utils CI / Coverage
  • any of: [🛡 GitHub branch protection]
    • check-neutral = Matrixone UT Coverage / UT Coverage on Ubuntu/x86
    • check-skipped = Matrixone UT Coverage / UT Coverage on Ubuntu/x86
    • check-success = Matrixone UT Coverage / UT Coverage on Ubuntu/x86
  • any of: [🛡 GitHub branch protection]
    • check-neutral = Matrixone Standlone CI / multi CN e2e BVT Test on Linux/x64(COMPOSE, PESSIMISTIC)
    • check-skipped = Matrixone Standlone CI / multi CN e2e BVT Test on Linux/x64(COMPOSE, PESSIMISTIC)
    • check-success = Matrixone Standlone CI / multi CN e2e BVT Test on Linux/x64(COMPOSE, PESSIMISTIC)
All conditions
  • any of [🛡 GitHub branch protection]:
    • check-neutral = Matrixone CI / UT Test on Ubuntu/x86
    • check-skipped = Matrixone CI / UT Test on Ubuntu/x86
    • check-success = Matrixone CI / UT Test on Ubuntu/x86
  • any of [🛡 GitHub branch protection]:
    • check-neutral = Matrixone CI / SCA Test on Linux/arm64
    • check-skipped = Matrixone CI / SCA Test on Linux/arm64
    • check-success = Matrixone CI / SCA Test on Linux/arm64
  • any of [🛡 GitHub branch protection]:
    • check-neutral = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
    • check-skipped = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
    • check-success = Matrixone Compose CI / multi cn e2e bvt test docker compose(PROXY)
  • any of [🛡 GitHub branch protection]:
    • check-neutral = Matrixone Utils CI / Coverage
    • check-skipped = Matrixone Utils CI / Coverage
    • check-success = Matrixone Utils CI / Coverage
  • any of [🛡 GitHub branch protection]:
    • check-neutral = Matrixone UT Coverage / UT Coverage on Ubuntu/x86
    • check-skipped = Matrixone UT Coverage / UT Coverage on Ubuntu/x86
    • check-success = Matrixone UT Coverage / UT Coverage on Ubuntu/x86
  • any of [🛡 GitHub branch protection]:
    • check-neutral = Matrixone Standlone CI / multi CN e2e BVT Test on Linux/x64(COMPOSE, PESSIMISTIC)
    • check-skipped = Matrixone Standlone CI / multi CN e2e BVT Test on Linux/x64(COMPOSE, PESSIMISTIC)
    • check-success = Matrixone Standlone CI / multi CN e2e BVT Test on Linux/x64(COMPOSE, PESSIMISTIC)
  • #review-threads-unresolved = 0 [🛡 GitHub branch protection]
  • github-review-approved [🛡 GitHub branch protection]

Reason

Pull request #27394 has been dequeued

Pull request from fork cannot be queued. This pull request comes from a fork, and Mergify needs the author's permission to update its branch.

The author needs to enable "Allow edits from maintainers" on this pull request.

Failing checks:

Hint

You should look at the reason for the failure and decide if the pull request needs to be fixed or if you want to requeue it.
If you do update this pull request, it will automatically be requeued once the queue conditions match again.
If you think this was a flaky issue instead, you can requeue the pull request, without updating it, by posting a @mergifyio queue comment.

Tick the box to put this pull request back in the merge queue (same as @mergifyio queue).

  • Requeue this pull request

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dequeued size/L Denotes a PR that changes [500,999] lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants