Repository navigation
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
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. Comment |
JanJakes
force-pushed
the
interval-arithmetic
branch
from
October 19, 2026 12:07
850e0c6 to
dd2ddda
Compare
MySQL accepts `expr + INTERVAL n unit`, `expr - INTERVAL n unit` and `INTERVAL n unit + expr`, and the parser already does too, but the translator passed the expression through unchanged, so SQLite rejected it with a syntax error. The three forms now share the DATETIME() translation used by DATE_ADD() and DATE_SUB(), which gains two fixes on the way: a negative value no longer produces a modifier that SQLite rejects, and a computed value is parenthesized so that `||` does not bind to it first. Fixes #454 Fixes #90
JanJakes
force-pushed
the
interval-arithmetic
branch
from
October 19, 2026 14:39
dd2ddda to
918410c
Compare
The grammar doesn't group "INTERVAL n unit + expr" like MySQL. Its operand includes AND, OR, and XOR, which MySQL applies to the whole expression, so this query deleted every row, while MySQL deletes none: DELETE FROM t WHERE INTERVAL 30 DAY + d < '2025-01-01' AND id = 99 The parser also matches "expr + INTERVAL 1 DAY + x" as "expr + (INTERVAL 1 DAY + x)". The prefix form is rare, and the reported queries use the suffix form, so reject it until the grammar follows MySQL's precedence.
The grammar nests "op bitExpr" to the right, regardless of operator precedence. In "1 + d + INTERVAL 1 DAY", the interval was applied to "d" only, while MySQL applies it to "1 + d". Reject an interval in such a nested operand, and suggest parentheses. The rewritten fold also no longer duplicates translate_sequence(), and the docblock no longer claims that INTERVAL is the only "bitExpr" form that SQLite can't run.
The unit was taken from the token text, so units SQLite doesn't support produced an invalid DATETIME() modifier, and the result was NULL. With the INTERVAL operators, "UPDATE t SET d = d + INTERVAL 1 QUARTER" wrote NULL into the column, while MySQL adds 3 months. The same happened with the SQL_TSI_* synonyms, whose text differs from the unit they map to. Units are now looked up by token type. QUARTER becomes 3 months, and MICROSECOND and the composite units, such as HOUR_MINUTE, are rejected.
JanJakes
force-pushed
the
interval-arithmetic
branch
from
October 20, 2026 08:36
918410c to
5b7787c
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds date arithmetic with
INTERVAL, building on #510 by @samuelmbabhazi:These queries previously failed with a syntax error. They now use SQLite’s
DATETIME()function, sharing the translation withDATE_ADD()andDATE_SUB().Why the extra fixes
Our current parser groups some expressions differently from MySQL. Translating them directly can produce wrong results—or update or delete the wrong rows.
This PR adds safeguards to the implementation in #510:
INTERVAL 1 DAY + d,1 + d + INTERVAL 1 DAY, andd + INTERVAL 1 DAY + x. Errors suggest adding parentheses.QUARTERandSQL_TSI_*units, and handle negative and computed interval values.MICROSECONDand composite units such asHOUR_MINUTE, instead of silently returningNULL.The supported forms cover the linked issues. The expression restrictions can be revisited after the planned switch to a parser based on MySQL’s own grammar.
Remaining limitations
The existing date translation still differs from MySQL in these cases:
20240101are not interpreted as MySQL dates.INTERVAL 1.5 DAYadds 36 hours instead of 2 days, and a string such as' 1'returnsNULLwith+but works with-.DATEvalues can be wrong. For example,d < CURDATE() - INTERVAL 7 DAYalso matches the boundary day.TIMEvalues also return datetime strings, and times past midnight wrap around instead of going over 24 hours.ADDDATE()andSUBDATE(): These functions remain unsupported.Expected results in the new tests were checked against MySQL 8.4.
Fixes #454
Fixes #90