Skip to content

expression: keep month and day when a year/month interval underflows to year 0#70004

Open
anshgoyalevil wants to merge 2 commits into
pingcap:masterfrom
anshgoyalevil:fix/date-underflow-year-zero-59789
Open

expression: keep month and day when a year/month interval underflows to year 0#70004
anshgoyalevil wants to merge 2 commits into
pingcap:masterfrom
anshgoyalevil:fix/date-underflow-year-zero-59789

Conversation

@anshgoyalevil

@anshgoyalevil anshgoyalevil commented Jul 23, 2026

Copy link
Copy Markdown

What problem does this PR solve?

Issue Number: close #59789

Problem Summary:

DATE_SUB('1000-01-01', INTERVAL 1000 YEAR) returned 0000-00-00, while MySQL returns 0000-01-01. When an interval drives the resulting year down to 0, addDate cleared the month and day unconditionally.

What changed and how does it work?

The year-0 handling was added for day/time intervals that underflow past the minimum datetime, where MySQL does return a zero date and keeps the wrapped time (e.g. DATE_ADD('0001-01-01 00:00:00', INTERVAL -2 HOUR) -> 0000-00-00 22:00:00, issue #11329). Year/month intervals instead do calendar arithmetic, so MySQL preserves the month and day.

ParseDurationValue yields day == 0 && nano == 0 only for YEAR/MONTH/QUARTER intervals; DAY/WEEK and all time units set day or nano. Gating the clearing on day == 0 && nano == 0 keeps the month/day for calendar intervals and leaves the existing day/time underflow behaviour untouched.

Check List

Tests

  • Unit test

Side effects

  • Performance regression: Consumes more CPU
  • Performance regression: Consumes more Memory
  • Breaking backward compatibility

Documentation

  • Affects user behaviors
  • Contains syntax changes
  • Contains variable changes
  • Contains experimental features
  • Changes MySQL compatibility

Release note

Fix `DATE_ADD`/`DATE_SUB` returning `0000-00-00` instead of `0000-MM-DD` when a YEAR or MONTH interval brings the year down to 0, matching MySQL.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed date arithmetic edge cases when year-based calculations reach year zero.
    • When using year/month-style intervals without day/sub-second components, the resulting month and day are now preserved (MySQL-compatible), instead of being incorrectly cleared.
    • Extended test coverage to validate the new behavior for 1000-01-01 with a -1000 year interval.

…to year 0

DATE_SUB('1000-01-01', INTERVAL 1000 YEAR) returned 0000-00-00 instead of
0000-01-01. addDate cleared the month and day whenever the result year hit 0,
which is only correct for day/time intervals that underflow past the minimum
datetime (issue pingcap#11329). Year and month intervals do calendar arithmetic, so
MySQL keeps the month and day. Gate the clearing on day == 0 && nano == 0 so
only day/time intervals zero them out.

Issue Number: close pingcap#59789

Signed-off-by: Miles Porter <anshgoyal1704@gmail.com>
@ti-chi-bot ti-chi-bot Bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. do-not-merge/needs-tests-checked contribution This PR is from a community contributor. needs-ok-to-test Indicates a PR created by contributors and need ORG member send '/ok-to-test' to start testing. labels Jul 23, 2026
@ti-chi-bot

ti-chi-bot Bot commented Jul 23, 2026

Copy link
Copy Markdown

Hi @anshgoyalevil. Thanks for your PR.

I'm waiting for a pingcap member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@ti-chi-bot ti-chi-bot Bot added size/S Denotes a PR that changes 10-29 lines, ignoring generated files. first-time-contributor Indicates that the PR was contributed by an external member and is a first-time contributor. labels Jul 23, 2026
@ti-chi-bot

ti-chi-bot Bot commented Jul 23, 2026

Copy link
Copy Markdown

Welcome @anshgoyalevil!

It looks like this is your first PR to pingcap/tidb 🎉.

I'm the bot to help you request reviewers, add labels and more, See available commands.

We want to make sure your contribution gets all the attention it needs!



Thank you, and welcome to pingcap/tidb. 😃

@ti-chi-bot

ti-chi-bot Bot commented Jul 23, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign gengliqi for approval. For more information see the Code Review Process.
Please ensure that each of them provides their approval before proceeding.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@pingcap-cla-assistant

pingcap-cla-assistant Bot commented Jul 23, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d8fc3a93-07d2-488a-b06a-2ce8880d9cee

📥 Commits

Reviewing files that changed from the base of the PR and between 3228f4b and 94a7f65.

📒 Files selected for processing (1)
  • pkg/expression/builtin_time.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/expression/builtin_time.go

📝 Walkthrough

Walkthrough

Date arithmetic now preserves the computed month and day when subtracting years reaches year zero. A regression test covers subtracting 1000 years from 1000-01-01, expecting 0000-01-01.

Changes

Date arithmetic correction

Layer / File(s) Summary
Preserve month and day at year zero
pkg/expression/builtin_time.go, pkg/expression/builtin_time_test.go
Year-based underflow retains the computed month and day, while other underflow cases keep the existing 0000-00-00 normalization. A test covers 1000-01-01 minus 1000 years.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

A rabbit hops through dates so bright,
Past year zero in moonlit light.
Month and day stay snug and true,
“0000-01-01” comes hopping through!
Carrots cheer the fixed-time queue.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main fix: preserving month and day for year/month interval underflow to year 0.
Description check ✅ Passed The description includes the required issue number, problem summary, change explanation, checklist, and release note.
Linked Issues check ✅ Passed The code and tests address #59789 by returning 0000-01-01 for year/month underflow instead of zeroing month and day.
Out of Scope Changes check ✅ Passed The changes stay focused on the year-0 date arithmetic fix and its test coverage, with no obvious unrelated edits.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
pkg/expression/builtin_time_test.go (1)

2399-2401: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a MONTH-underflow regression case.

The changed production branch is shared by YEAR and MONTH intervals, but this test only exercises YEAR. Add a table entry that crosses year zero with a MONTH interval and verifies that the computed month and day are preserved.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/expression/builtin_time_test.go` around lines 2399 - 2401, Add a
regression table entry alongside the existing YEAR case in the relevant
time-interval tests, using a MONTH interval that crosses year zero and asserting
the resulting month and day remain unchanged. Keep the case focused on the
shared production branch and match the existing test table’s input, interval,
and expected-value format.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/expression/builtin_time.go`:
- Around line 3207-3217: Update the branch in the date arithmetic logic around
SetCoreTime so zero-valued day/time intervals are not treated as calendar
intervals: require year or month to be nonzero in addition to day == 0 and nano
== 0 before preserving goTime’s month/day. Keep the existing zero-date
normalization for INTERVAL 0 DAY, 0 HOUR, and other intervals without year/month
components.

---

Nitpick comments:
In `@pkg/expression/builtin_time_test.go`:
- Around line 2399-2401: Add a regression table entry alongside the existing
YEAR case in the relevant time-interval tests, using a MONTH interval that
crosses year zero and asserting the resulting month and day remain unchanged.
Keep the case focused on the shared production branch and match the existing
test table’s input, interval, and expected-value format.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d046b541-02e6-4fb5-8998-8ba3a6b5e9a5

📥 Commits

Reviewing files that changed from the base of the PR and between e09d2bd and 3228f4b.

📒 Files selected for processing (2)
  • pkg/expression/builtin_time.go
  • pkg/expression/builtin_time_test.go

Comment thread pkg/expression/builtin_time.go Outdated
… fields

Guard the year-0 calendar branch with year != 0 || month != 0 so a zero
interval (INTERVAL 0 DAY / 0 HOUR) on a year-0 date keeps the existing
zero-date normalization instead of being treated as a calendar interval.

Signed-off-by: Miles Porter <anshgoyal1704@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contribution This PR is from a community contributor. first-time-contributor Indicates that the PR was contributed by an external member and is a first-time contributor. needs-ok-to-test Indicates a PR created by contributors and need ORG member send '/ok-to-test' to start testing. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/S Denotes a PR that changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DATE_SUB gives wrong result for near zero date

1 participant