Skip to content

fix(plan): support INT + INTERVAL / INT - INTERVAL arithmetic - #24441

Merged
mergify[bot] merged 13 commits into
matrixorigin:mainfrom
VioletQwQ-0:fix/int-interval-arithmetic
May 21, 2026
Merged

fix(plan): support INT + INTERVAL / INT - INTERVAL arithmetic#24441
mergify[bot] merged 13 commits into
matrixorigin:mainfrom
VioletQwQ-0:fix/int-interval-arithmetic

Conversation

@VioletQwQ-0

@VioletQwQ-0 VioletQwQ-0 commented May 18, 2026

Copy link
Copy Markdown
Collaborator

What type of PR is this?

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

Which issue(s) this PR fixes:

issue #24412

What this PR does / why we need it:

Fix INT - INTERVAL and INT + INTERVAL arithmetic not supported when date columns are stored as INT (YYYYMMDD format).

The binder's INTERVAL rewrite for + and - operators only covered date/datetime/timestamp/varchar types. INT columns storing dates in YYYYMMDD format would fall through to operator dispatch which has no INT-INTERVAL overload, producing "invalid argument operator -, bad value [INT INTERVAL]".

Changes

  1. base_binder.go — Add T_int32 and T_int64 branches to + and - operator INTERVAL rewrite chains, routing them to date_add/date_sub.

  2. func_binary.go — Add DateIntSub and DateIntAdd execution functions with intToDate/dateToInt helpers that convert between YYYYMMDD-format INT and internal types.Date. Return type stays INT to preserve type compatibility for BETWEEN and other comparisons.

  3. list_builtIn.go — Register T_int32 overloads for DATE_SUB and DATE_ADD returning T_int32.

Before / After

-- Before
SELECT MAX(date_id) - INTERVAL 7 DAY FROM readings;
-- ERROR 20203: invalid argument operator -, bad value [INT INTERVAL]

-- After
SELECT MAX(date_id) - INTERVAL 7 DAY FROM readings;
-- 20260508

🤖 Generated with Claude Code

The binder's INTERVAL rewrite for + and - operators only covered
date/datetime/timestamp/varchar types, leaving INT columns (common
for YYYYMMDD-format date storage) to fall through to operator dispatch
which has no INT-INTERVAL overload.

Add T_int32 and T_int64 rewrite branches that route INT-INTERVAL
expressions to date_sub/date_add, plus new overloads with DateIntSub
and DateIntAdd implementations that convert INT<->Date to preserve
INT return type (YYYYMMDD format) for type-compatible BETWEEN usage.

Fixes matrixorigin#24412.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@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 →

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ithmetic

Merge upstream/main into fix/int-interval-arithmetic
@VioletQwQ-0

Copy link
Copy Markdown
Collaborator Author

@aunjgr All three review points from your May 18 review have been addressed in follow-up commits:

  1. Sub-day interval truncationd3dcfd1df restricts INT INTERVAL rewrite to day-or-larger units (DAY, WEEK, MONTH, QUARTER, YEAR); sub-day units fall through to the original operator dispatch with the existing error
  2. INTERVAL + INT symmetriceac4eec26 adds T_interval on the left side for both plus and minus rewrite chains
  3. BVT coveragec375b04d3 adds int_interval_arithmetic.sql covering INT plus/minus INTERVAL, INTERVAL + INT, NULLs, sub-day rejection, and the CASE BETWEEN subquery shape from the issue

PTAL when you have a moment, thanks.

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

Review: INT and INTERVAL arithmetic

Request Changes

The prior correctness fixes look mostly addressed, but the BVT coverage is still missing the critical reversed-order paths.

  1. Reversed INTERVAL + INT coverage is only constant-only. The implementation has distinct binder branches for reversed INTERVAL + int32/int64, but there is no non-constant reversed test such as INTERVAL 7 DAY + date_id or INTERVAL 7 DAY + max(date_id). The INT-left runtime path is covered, but the reversed non-constant binder path is not.

  2. Reversed sub-day rejection is untested. The regression coverage checks INT + INTERVAL and INT - INTERVAL sub-day cases, but not the combined prior failure mode: INTERVAL 1 HOUR + CAST(20260515 AS INT). Since reversed-order support uses separate guarded binder logic, please add a negative BVT proving reversed sub-day arithmetic errors instead of truncating.

Please add BVT coverage for reversed-order column/aggregate execution and reversed sub-day rejection before merging.

Add non-constant reversed-order tests (column and aggregate) and
reversed sub-day rejection tests requested by reviewer.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@VioletQwQ-0

Copy link
Copy Markdown
Collaborator Author

@aunjgr Added the missing BVT coverage:

  1. Reversed INTERVAL + INT with column/aggregate — and
  2. Reversed sub-day rejection

Both paths are now covered in .

@VioletQwQ-0

Copy link
Copy Markdown
Collaborator Author

@aunjgr Added the missing BVT coverage from your May 20 review:

  1. Reversed INTERVAL + INT with column and aggregate — both non-constant binder paths now covered
  2. Reversed sub-day rejection — separate guarded binder logic now has negative tests proving it errors instead of truncating

PTAL thanks.

@mergify

mergify Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

  • Entered queue2026-05-21 06:18 UTC · Rule: main
  • Checks passed · in-place
  • Merged2026-05-21 07:20 UTC · at 37d904486b2fa20630678f60267aab6b8e110c13 · squash

This pull request spent 1 hour 1 minute 22 seconds in the queue, including 1 hour 58 seconds running CI.

Required conditions to merge
  • #approved-reviews-by >= 1 [🛡 GitHub branch protection]
  • #changes-requested-reviews-by = 0 [🛡 GitHub branch protection]
  • #review-threads-unresolved = 0 [🛡 GitHub branch protection]
  • github-review-decision = APPROVED [🛡 GitHub branch protection]
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Compose CI / multi cn e2e bvt test docker compose(PESSIMISTIC)
    • check-neutral = Matrixone Compose CI / multi cn e2e bvt test docker compose(PESSIMISTIC)
    • check-skipped = Matrixone Compose CI / multi cn e2e bvt test docker compose(PESSIMISTIC)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Standlone CI / Multi-CN e2e BVT Test on Linux/x64(LAUNCH, PROXY)
    • check-neutral = Matrixone Standlone CI / Multi-CN e2e BVT Test on Linux/x64(LAUNCH, PROXY)
    • check-skipped = Matrixone Standlone CI / Multi-CN e2e BVT Test on Linux/x64(LAUNCH, PROXY)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH, PESSIMISTIC)
    • check-neutral = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH, PESSIMISTIC)
    • check-skipped = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH, PESSIMISTIC)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone CI / SCA Test on Ubuntu/x86
    • check-neutral = Matrixone CI / SCA Test on Ubuntu/x86
    • check-skipped = Matrixone CI / SCA Test on Ubuntu/x86
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone CI / UT Test on Ubuntu/x86
    • check-neutral = Matrixone CI / UT Test on Ubuntu/x86
    • check-skipped = Matrixone CI / UT Test on Ubuntu/x86
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Compose CI / multi cn e2e bvt test docker compose(Optimistic/PUSH)
    • check-neutral = Matrixone Compose CI / multi cn e2e bvt test docker compose(Optimistic/PUSH)
    • check-skipped = Matrixone Compose CI / multi cn e2e bvt test docker compose(Optimistic/PUSH)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH,Optimistic)
    • check-neutral = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH,Optimistic)
    • check-skipped = Matrixone Standlone CI / e2e BVT Test on Linux/x64(LAUNCH,Optimistic)
  • any of [🛡 GitHub branch protection]:
    • check-success = Matrixone Upgrade CI / Compatibility Test With Target on Linux/x64(LAUNCH)
    • check-neutral = Matrixone Upgrade CI / Compatibility Test With Target on Linux/x64(LAUNCH)
    • check-skipped = Matrixone Upgrade CI / Compatibility Test With Target on Linux/x64(LAUNCH)
  • any of [🛡 GitHub branch protection]:
    • check-skipped = Matrixone Utils CI / Coverage
    • check-neutral = Matrixone Utils CI / Coverage
    • check-success = Matrixone Utils CI / Coverage

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

Labels

kind/bug Something isn't working size/M Denotes a PR that changes [100,499] lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants