dragonknightk opened a new pull request, #70461:
URL: https://github.com/apache/doris/pull/70461
### Background
Nereids folds date and datetime constants with `java.time.LocalDateTime`,
which treats year 0 as leap because `0 % 400 == 0`. Doris already treats year 0
as a common year. The FE parser (`DateLiteral.checkDate`) accepts February 29
only when `year > 0`, and BE `is_leap` requires `&& year`
(`be/src/util/time_lut.h`). MySQL documents the same rule in WL#16895 and
implements it as `year % 400 == 0 && year` in `mysys/my_time.cc`.
### What problem does this PR solve?
Issue Number: close #68723
Related PR: None
PR Type: Bugfix
Problem Summary:
Queries whose year-0 date constants are folded by FE can return results that
differ from BE execution. For example, FE folding produced
`date_add('0000-02-28', 1) = 0000-02-29` and `last_day('0000-02-01') =
0000-02-29`, while BE returns `0000-03-01` and `0000-02-28`. This fix aligns FE
folding with the existing Doris common-year convention and leaves BE unchanged;
changing BE would change parsing and date arithmetic across the engine. After
upgrading, folded year-0 constants match BE.
### Details
- **Change map:** 494 lines: 154 production, 313 tests (161 FE unit, 152
regression suite), 27 generated `.out`, 0 docs. Production: date literal
`plus*` and day-of-year arithmetic across 0000-02-29 (`DateLiteral` and five
subclasses, 119 lines); `last_day`, `weekday`, `week`, and `makedate` folding
(`DateTimeExtractAndTransform`, 35 lines).
- **Frequency:** FE folds of `date_add`, `last_day`, `dayofyear`, `weekday`,
`week`, and `makedate` that land on or cross 0000-02-29.
- **Root cause:** Java inserts 0000-02-29; Doris `is_leap` and `checkDate`
treat year 0 as a common year.
- **Why existing tests missed it:** Tests only constructed `0000-02-29` and
checked the parser exception.
- **Fix:** Shift day/week arithmetic that crosses 0000-02-29, and clamp
month/year/`last_day` results of 0000-02-29 to 0000-02-28.
- **Other paths and branches:** `plusHours`/`plusMinutes`/`plusSeconds` and
`next_day`/`previous_day`/`to_monday` still use Java day counts; `week()` keeps
the existing 0000-01-01/02 lookup.
- **Behavior change:** Folded year-0 dates that crossed 0000-02-29 now
follow the Doris common-year calendar.
### Testing
- `mvn checkstyle:check -pl fe-core`: 0 violations.
- `FoldConstantTest`: 34 passed. `DateLiteralTest`: 16 passed, 2 skipped.
- Regression suite `test_year0_common_year_fold`: passed. It fails on the
old FE (`HEAD^`).
- The local cluster paired this branch's FE with the official 4.1.5 prebuilt
BE.
### Release note
FE constant folding of year-0 dates now matches BE: `date_add('0000-02-28',
1)` is `0000-03-01`, and `last_day('0000-02-01')` is `0000-02-28`.
### Check List (For Author)
- Behavior changed: Yes (see Details)
- Does this need documentation: No
- Pre-submission status: Ready
### AI Disclosure
- Tool: Grok Bot
- Generated: production date helpers and folding adjustments, unit tests,
the new regression suite, and this description
- Human review: the generated production changes, tests, and this
description were fully reviewed
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]