fix: allow free RANGE window frames over Duration and Interval ORDER BY types - #24916
fix: allow free RANGE window frames over Duration and Interval ORDER BY types#24916edubraqd wants to merge 3 commits into
Conversation
kumarUjjawal
left a comment
There was a problem hiding this comment.
Thank you @edubraqd for working on this. I left two comments, please take a look.
| // ORDER BY values to be comparable, so an ORDER BY type | ||
| // without arithmetic (Duration, Interval, Struct, Map, ...) | ||
| // is fine there. | ||
| Err(_) if window_frame.free_range() => return Ok(window_frame), |
There was a problem hiding this comment.
This fallback now admits Map and Struct order keys, but RANGE peer detection does not use the same comparison as sorting. partial_cmp_map ignores map values it compares only entry column 0 and partial_cmp_struct skips child fields when either side is NULL. Therefore, distinct keys such as map(['a'], [1]) and map(['a'], [2]) can be treated as peers, making COUNT(*) OVER (ORDER BY x) return 2, 2 instead of 1, 2.
Could we either restrict this fallback to types whose peer comparison matches the sorter, or fix those comparators and add Map and NULL-containing Struct regression tests?
| extract_window_frame_target_type(value_type.data_type()) | ||
| } else { | ||
| internal_err!("Cannot run range queries on datatype: {col_type}") | ||
| // Only reached for frames with a finite offset (free range frames |
There was a problem hiding this comment.
These comment blocks repeat the same rationale, and the comment above plan_err! is inaccurate: this function is also reached for free RANGE frames; its error is created and then discarded by the caller. Could we keep one concise explanation beside the free-range handling and remove the duplicate block?
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #24916 +/- ##
==========================================
+ Coverage 81.63% 81.64% +0.01%
==========================================
Files 1123 1123
Lines 409546 410261 +715
Branches 409546 410261 +715
==========================================
+ Hits 334319 334945 +626
- Misses 55591 55624 +33
- Partials 19636 19692 +56 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Thanks for the review, both points addressed in the follow-up commit:
|
| // comparison is sound (see `supports_free_range_frame`). | ||
| Err(_) | ||
| if window_frame.free_range() | ||
| && supports_free_range_frame(&col_type) => |
There was a problem hiding this comment.
Free RANGE frames may contain multiple ORDER BY expressions, but this check validates only the first expression’s type. For example, ORDER BY duration_col, map_col is accepted because the first type is Duration, even though the second Map key still has the peer-comparison mismatch discussed earlier.
With equal duration values and maps that have the same key but different values, sorting distinguishes the rows while the RANGE peer check treats them as peers. COUNT(*) OVER (...) can therefore return 2, 2 instead of 1, 2.
Could we validate every ORDER BY expression used for peer comparison, or restrict this fallback to a single ORDER BY expression and add a regression test?
|
Thank you for opening this pull request! Reviewer note: cargo-semver-checks reported the current version number is not SemVer-compatible with the changes in this pull request (compared against the base branch). Details |
|
@edubraqd On the side note, I see you have around 14 prs https://github.com/apache/datafusion/issues?q=is%3Apr+is%3Aopen+author%3Aedubraqd opened. Reviews take a lot of bandwidths of members so please be mindful about this. You can pick 3 prs which you want to work next and make other as drafts so its easier both for you and the members to review and move forward. |
…metic
`OVER (ORDER BY x)` defaults to `RANGE BETWEEN UNBOUNDED PRECEDING AND
CURRENT ROW`, a free range frame whose bounds carry no offset. Such a frame
only needs the ORDER BY values to be comparable, yet `coerce_window_frame`
first asked `extract_window_frame_target_type` for an arithmetic target type
and failed for e.g. Duration, Interval, Struct or Map columns:
SELECT row_number() OVER (ORDER BY x) FROM t; -- x: Duration(Second)
Internal error: Cannot run range queries on datatype: Duration(s).
This issue was likely caused by a bug in DataFusion's code ...
Only fall back to that error for frames with a finite offset, which do need
the arithmetic, and report it as a planning error in the same words the
existing offset check already uses. Frames over supported types are coerced
exactly as before.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…is sound Only accept Duration and Interval ORDER BY types for the free RANGE frame fallback. Struct and Map compare differently in the RANGE peer check (`ScalarValue::partial_cmp`) than in the sort that orders the input, so they stay rejected. Keep a single explanation next to the fallback and give the unsupported-type error a wording that fits both free and offset frames. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
All ORDER BY expressions take part in the RANGE peer comparison, so the fallback must not accept `ORDER BY duration_col, map_col` just because the first key is a duration. Require every key to be either an arithmetic type or one accepted by `supports_free_range_frame`, and add the regression cases. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Thanks, all three addressed:
On the number of open PRs: understood. I left #24916, #24903 and #24897 ready for review and converted the other eleven to drafts; I'll promote one draft at a time as these land. |
ca7eba6 to
b59902c
Compare
Which issue does this PR close?
ORDER BYon a Duration / Interval / Struct / Map column fail with "Internal error: Cannot run range queries" #24915. This PR coversDurationandIntervalORDER BY types;StructandMapstay rejected because their RANGE peer comparison (partial_cmp_struct/partial_cmp_map) does not match the sort order, and are left for a follow-up (fix the comparators, then extendsupports_free_range_frame).Rationale for this change
OVER (ORDER BY x)defaults to a free range frame with no offsets, which only needs the ORDER BY values to be comparable.coerce_window_framenevertheless required an arithmetic target type for the ORDER BY column first, sorow_number() OVER (ORDER BY x)on aDurationorIntervalcolumn failed with an internal error asking the user to file a bug.What changes are included in this PR?
Only require the arithmetic target type for frames with a finite offset. A free range frame whose ORDER BY expressions are all either arithmetic types or
Duration/Interval(also nested inDictionary/RunEndEncoded) is returned unchanged; every ORDER BY expression is checked, since all of them take part in the peer comparison. Frames over supported types are coerced exactly as before, so plans do not change. The failure for unsupported types is now a planning error,RANGE window frames are not supported for ORDER BY type ..., which fits both free and offset frames.Are these changes tested?
Yes.
window.sltgainsrow_number/rank/countoverDurationandIntervalORDER BY keys (default and explicit free range frame, single and two-column ORDER BY), and checks thatStructandMapkeys, aMapafter aDuration, and a finite offset over aStructare still rejected at planning time. The existingStructcase that pinned the internal-error text now expects the planning error.Are there any user-facing changes?
Window functions ordered by
DurationorIntervalcolumns work with the default frame. Unsupported ORDER BY types in a RANGE frame report a planning error instead of an internal error.