Skip to content

Commit 29357c4

Browse files
authored
fix(tests): Keep an explicit ROWS window frame (facebookincubator#18639)
Differential Revision: D117099096 Pull Request resolved: facebookincubator#18639
1 parent 683854b commit 29357c4

3 files changed

Lines changed: 47 additions & 3 deletions

File tree

velox/duckdb/conversion/DuckParser.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1079,8 +1079,13 @@ core::WindowCallExprPtr buildWindowCallExpr(
10791079
}
10801080

10811081
auto endType = parseBoundType(windowExpr.end);
1082+
// Without ORDER BY every row is a peer, so a RANGE frame ending at the
1083+
// current row covers the whole partition. That is the frame a window with no
1084+
// frame clause gets. A ROWS frame counts rows rather than peers and ends
1085+
// where it says, so read the DuckDB boundary: `parseBoundType` maps both
1086+
// spellings of CURRENT ROW to the same bound.
10821087
if (options.correctWindowFrameDefault && orderByKeys.empty() &&
1083-
endType == core::WindowCallExpr::BoundType::kCurrentRow) {
1088+
windowExpr.end == WindowBoundary::CURRENT_ROW_RANGE) {
10841089
endType = core::WindowCallExpr::BoundType::kUnboundedFollowing;
10851090
}
10861091

velox/duckdb/conversion/DuckParser.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ struct ParseOptions {
3131

3232
// DuckDB defaults the window frame end bound to CURRENT ROW even when ORDER
3333
// BY is absent. The SQL standard requires UNBOUNDED FOLLOWING in that case.
34-
// When true, corrects this default. Cannot distinguish defaulted from
35-
// explicit frames, so an explicit CURRENT ROW may be incorrectly overridden.
34+
// When true, corrects this default. An explicit RANGE frame ending at the
35+
// current row is corrected as well, since unordered it covers the whole
36+
// partition either way. An explicit ROWS frame ends where it says.
3637
bool correctWindowFrameDefault = false;
3738

3839
/// SQL functions could be registered with different prefixes by the user.

velox/duckdb/conversion/tests/DuckParserTest.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,44 @@ TEST(DuckParserTest, window) {
624624
parseWindow("nth_value(x, 3) over ()"));
625625
}
626626

627+
TEST(DuckParserTest, correctWindowFrameDefault) {
628+
auto parse = [](const std::string& expr) {
629+
ParseOptions options;
630+
options.correctWindowFrameDefault = true;
631+
return parseWindowExpr(expr, options)->toString();
632+
};
633+
634+
// Without ORDER BY every row is a peer, so a RANGE frame ending at the
635+
// current row covers the whole partition. A window with no frame clause
636+
// gets that frame.
637+
EXPECT_EQ(
638+
"row_number() OVER (PARTITION BY \"a\" "
639+
"RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)",
640+
parse("row_number() over (partition by a)"));
641+
EXPECT_EQ(
642+
"row_number() OVER (PARTITION BY \"a\" "
643+
"RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)",
644+
parse(
645+
"row_number() over (partition by a "
646+
"range between unbounded preceding and current row)"));
647+
648+
// A ROWS frame counts rows rather than peers, so it ends at the current row
649+
// even with nothing ordered.
650+
EXPECT_EQ(
651+
"row_number() OVER (PARTITION BY \"a\" "
652+
"ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)",
653+
parse(
654+
"row_number() over (partition by a "
655+
"rows between unbounded preceding and current row)"));
656+
657+
// With ORDER BY the peers are the rows that tie, so the default frame ends
658+
// at the current row as written.
659+
EXPECT_EQ(
660+
"row_number() OVER (PARTITION BY \"a\" ORDER BY \"b\" ASC NULLS LAST "
661+
"RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)",
662+
parse("row_number() over (partition by a order by b)"));
663+
}
664+
627665
TEST(DuckParserTest, windowWithIntegerConstant) {
628666
ParseOptions options;
629667
options.parseIntegerAsBigint = false;

0 commit comments

Comments
 (0)