feat(sql): recognize OR of timestamp IN predicates as interval intrinsics#6673
feat(sql): recognize OR of timestamp IN predicates as interval intrinsics#6673bluestreak01 merged 7 commits intomasterfrom
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughAdds OR-based extraction of timestamp IN/=/interval predicates into the WHERE parser, new string-based interval union APIs, modernizes several switch statements to switch expressions, and updates/extends tests to validate OR-to-interval extraction and related planner output. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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 |
|
@CodeRabbit review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In
`@core/src/main/java/io/questdb/griffin/model/RuntimeIntervalModelBuilder.java`:
- Around line 382-410: unionIntervals currently parses an interval string into
staticIntervals then only extracts and re-adds the last [lo,hi] pair, dropping
any earlier pairs produced by IntervalUtils.parseInterval; change the flow to
keep the full parsed range appended by IntervalUtils.parseInterval (remove the
staticIntervals.setPos(size) and the manual add of only the last pair) and then
merge those new pairs into the existing set by calling
IntervalUtils.unionInPlace(staticIntervals, size) when intervalApplied is true
(or just set intervalApplied = true if this is the first parsed batch). Locate
this logic in unionIntervals and adjust handling of size, the parsed range
slice, and the calls to IntervalUtils.applyLastEncodedInterval /
IntervalUtils.unionInPlace accordingly.
In `@core/src/test/java/io/questdb/test/griffin/WindowJoinTest.java`:
- Around line 2616-2618: In WindowJoinTest.java inside the SQL string used for
the window join (the snippet building "from (trades limit 5) t window join
(select * from prices where ts in '2023-01-01T09:03:00.000000Z' or ts =
'2023-01-01T09:07:00.000000Z' and ts = '2023-01-01T09:08:00.000000Z') p on
(t.sym = p.sym)"), replace the mistaken AND between the two ts equality clauses
with OR (or adjust parentheses to express the intended logic) so the timestamp
conditions are not mutually exclusive; update the SQL string in the test method
in WindowJoinTest to use OR for the third timestamp check.
core/src/main/java/io/questdb/griffin/model/RuntimeIntervalModelBuilder.java
Show resolved
Hide resolved
- Add testTimestampMixedInAndEqualsOr: mixed IN and = operators in OR - Add testTimestampOrWithRangeFilter: OR combined with > filter - Add testTimestampOrNotExtractedWhenIntervalFilterFirst: documents current limitation - Add testTimestampOrWithBindVariables: bind variables fall back to filter - Add testTimestampOrWithPeriodicIntervals: periodic intervals in OR - Fix unionIntervals to properly handle periodic intervals that expand to multiple pairs - Update testTimestampEqualsOrSingleValues to use date-only format (24-hour span) Co-Authored-By: Claude Opus 4.5 <[email protected]>
|
@CodeRabbit review again |
|
🧠 Learnings used✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In `@core/src/main/java/io/questdb/griffin/WhereClauseParser.java`:
- Around line 2170-2190: The '=' branch in extractOrTimestampIntervals currently
treats the RHS as a quoted interval string (using valueNode.token with offsets
1..len-1), which expands date-only equality into a full-day interval and
mishandles numeric literals; change this to parse the timestamp into a point and
call model.intersectIntervals(...) or model.unionIntervals(...) with identical
start and end values (i.e., a [ts,ts] interval) instead of slicing the token,
using the same leftFirst conditional, and mirror the behavior used by
analyzeEquals; use ExpressionNode, isTimestamp(node.lhs), valueNode, and
model.intersectIntervals/model.unionIntervals to locate and update the logic.
In `@core/src/test/java/io/questdb/test/griffin/WhereClauseParserTest.java`:
- Around line 3303-3314: The test name and comments are inconsistent with the
assertion: update the test method name
testTimestampOrNotExtractedWhenIntervalFilterFirst to reflect that OR-derived
intervals are extracted when an interval filter appears first (e.g.,
testTimestampOrExtractedWhenIntervalFilterFirst) and change the comment above
the IntrinsicModel m = modelOf(...) to state that OR clauses are extracted into
interval filters (and thus intervalToString should contain the two intervals);
ensure any mention of "OR extraction is skipped" is removed or inverted, keeping
references to IntrinsicModel, modelOf, hasIntervalFilters, and intervalToString
so reviewers can locate the change.
|
@CodeRabbit review again, check if your concerns have been addressed |
|
🧠 Learnings used✅ Actions performedReview triggered.
|
|
@CodeRabbit did you find any bugs? |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 3779 🏁 Script executed: Length of output: 13959
Bugs Found (Major Issues)
Maintenance Issues (Minor)
All concerns have been resolved! The code looks good now. 🎉 🧠 Learnings usedIf you found this review helpful, would you consider giving us a shout-out on X? Thank you for using CodeRabbit! |
[PR Coverage check]😍 pass : 100 / 120 (83.33%) file detail
|
Summary
Fixes #6668
This PR enables QuestDB to recognize
ORcombinations of timestampINpredicates as intrinsic interval filters, allowing the query optimizer to use efficient interval forward scans instead of falling back to row-by-row JIT filtering.Before
After
Both queries now use efficient interval forward scans.
Changes
WhereClauseParser.java: Added support for extracting timestamp intrinsics from OR trees
isOrOfTimestampIn()- checks if an OR tree consists entirely of timestamp IN/= predicatesextractOrTimestampIntervals()- extracts intervals using union semanticstryExtractOrTimestampIntrinsics()- wrapper with precondition checksextract()to handle OR nodes during tree traversalRuntimeIntervalModelBuilder.java: Added
unionIntervals(CharSequence seq, ...)method to parse and union string intervals (e.g.,'2018-01-01'spanning a full day)IntrinsicModel.java: Added corresponding wrapper method
Behavior
timestamp IN '2018-01-01'timestamp IN ('2018-01-01', '2018-01-02')timestamp IN '2018-01-01' OR timestamp IN '2018-01-02'timestamp = 'x' OR timestamp = 'y'Test plan
WhereClauseParserTestwith new test cases🤖 Generated with Claude Code