diff options
| author | aneporada <[email protected]> | 2026-07-24 15:18:06 +0300 |
|---|---|---|
| committer | aneporada <[email protected]> | 2026-07-24 15:59:01 +0300 |
| commit | e968445dae721e2226ade66ec2f3669f1a19fc2a (patch) | |
| tree | 802e34980c79778756d69115ba9cdd14be45fc39 | |
| parent | 07837bce5786e15438d7f5b3c9cefe791d28d20c (diff) | |
Fix handling SessionWindow without session columns
#### Fix handling of SessionWindow without session columns ✎
- Corrected logic for detecting and handling SessionWindow operations when no session columns are specified, ensuring proper validation and error reporting
- Updated type annotation checks to correctly identify session windows and prevent unsupported WinFilter usage with them
- Added test case to verify correct behavior when SessionWindow is used without explicit session columns, preventing incorrect fusion of filters with such windows
<a href="https://nda.ya.ru/t/qa0kX64r7DqvtN"><font size="2">Autodescription by Yandex Code Assistant</font></a>
commit_hash:9ee57415718e3b085d3eebf843a30a7e919f5e5e
6 files changed, 122 insertions, 4 deletions
diff --git a/yql/essentials/core/common_opt/yql_co_finalizers.cpp b/yql/essentials/core/common_opt/yql_co_finalizers.cpp index aff124e1188..09ef928e2a2 100644 --- a/yql/essentials/core/common_opt/yql_co_finalizers.cpp +++ b/yql/essentials/core/common_opt/yql_co_finalizers.cpp @@ -424,11 +424,11 @@ TExprNode::TPtr FuseFilterWithCalcOverWindow(const TCoFlatMapBase& node, TExprCo auto calcs = ExtractCalcsOverWindow(node.Input().Ptr(), ctx); YQL_ENSURE(!calcs.empty(), "Empty CalcOverWindow should be processed earlier"); TCoCalcOverWindowTuple calc(calcs.back()); - if (!calc.SessionColumns().Empty()) { + if (!calc.SessionSpec().Maybe<TCoVoid>()) { // we are not ready for fusing session windows yet return node.Ptr(); } - YQL_ENSURE(calc.SessionSpec().Maybe<TCoVoid>()); + YQL_ENSURE(calc.SessionColumns().Empty()); TExprNode::TPtr calcInput = node.Input().Cast<TCoInputBase>().Input().Ptr(); const TCoConditionalValueBase body = node.Lambda().Body().Cast<TCoConditionalValueBase>(); diff --git a/yql/essentials/core/type_ann/type_ann_list.cpp b/yql/essentials/core/type_ann/type_ann_list.cpp index 37b14cd9d6f..d1d0ac03ee7 100644 --- a/yql/essentials/core/type_ann/type_ann_list.cpp +++ b/yql/essentials/core/type_ann/type_ann_list.cpp @@ -563,15 +563,16 @@ namespace { if (!EnsureTuple(winList, ctx)) { return IGraphTransformer::TStatus::Error; } + const bool isSession = sessionSpec && TCoSessionWindowTraits::Match(sessionSpec.Get()); for (auto winOn: winList.Children()) { if (!TCoWinOnBase::Match(winOn.Get())) { auto errMsg = TStringBuilder() << "Expected WinOnRows/WinOnGroups/WinOnRange"; - if (!sessionColumns) { + if (!isSession) { errMsg << "/WinFilter"; } ctx.AddError(TIssue(ctx.GetPosition(winOn->Pos()), errMsg)); return IGraphTransformer::TStatus::Error; - } else if (sessionColumns && sessionColumns->ChildrenSize() && TCoWinFilter::Match(winOn.Get())) { + } else if (isSession && TCoWinFilter::Match(winOn.Get())) { ctx.AddError(TIssue(ctx.GetPosition(winOn->Pos()), "WinFilter is not supported with SessionWindow")); return IGraphTransformer::TStatus::Error; } diff --git a/yql/essentials/tests/sql/minirun/part4/canondata/result.json b/yql/essentials/tests/sql/minirun/part4/canondata/result.json index 05e92a8724e..ea5a507ba59 100644 --- a/yql/essentials/tests/sql/minirun/part4/canondata/result.json +++ b/yql/essentials/tests/sql/minirun/part4/canondata/result.json @@ -1491,6 +1491,20 @@ "uri": "https://{canondata_backend}/1781765/06cae327ea6c6fc81b5ac8d206f80c5f2f779d8e/resource.tar.gz#test.test_weak_field-weak_member_string_copy-default.txt-Results_/results.txt" } ], + "test.test[window-nofuse_filter_with_session_window_nocols-default.txt-Debug]": [ + { + "checksum": "24b2d69edd036c007918636bd7248c1f", + "size": 2053, + "uri": "https://{canondata_backend}/1814674/c63be47c63f9f12740fe21b1d8bc050b143151f7/resource.tar.gz#test.test_window-nofuse_filter_with_session_window_nocols-default.txt-Debug_/opt.yql" + } + ], + "test.test[window-nofuse_filter_with_session_window_nocols-default.txt-Results]": [ + { + "checksum": "d48d8ae990ffa6bd4b265c56820624e5", + "size": 2985, + "uri": "https://{canondata_backend}/1814674/c63be47c63f9f12740fe21b1d8bc050b143151f7/resource.tar.gz#test.test_window-nofuse_filter_with_session_window_nocols-default.txt-Results_/results.txt" + } + ], "test.test[window-range_pg/win_range_int_double--Debug]": [ { "checksum": "4c66a67b8095d5d6499ed0d67dd1bea8", diff --git a/yql/essentials/tests/sql/sql2yql/canondata/result.json b/yql/essentials/tests/sql/sql2yql/canondata/result.json index c40d47f19c5..e5f9898ca32 100644 --- a/yql/essentials/tests/sql/sql2yql/canondata/result.json +++ b/yql/essentials/tests/sql/sql2yql/canondata/result.json @@ -11633,6 +11633,13 @@ "uri": "https://{canondata_backend}/1942173/8c5157c555883078451557793ef27b73eb262e7a/resource.tar.gz#test_sql2yql.test_window-nofuse_filter_with_session_window_/sql.yql" } ], + "test_sql2yql.test[window-nofuse_filter_with_session_window_nocols]": [ + { + "checksum": "1d42dd66418571202904f17f7d1813f5", + "size": 5643, + "uri": "https://{canondata_backend}/1942415/b03cb88bfc10f1e7662c3cf258890791821a1e96/resource.tar.gz#test_sql2yql.test_window-nofuse_filter_with_session_window_nocols_/sql.yql" + } + ], "test_sql2yql.test[window-null_type]": [ { "checksum": "e1ea14ebf16ad22d262fb37141f82707", @@ -19540,6 +19547,11 @@ "uri": "file://test_sql_format.test_window-nofuse_filter_with_session_window_/formatted.sql" } ], + "test_sql_format.test[window-nofuse_filter_with_session_window_nocols]": [ + { + "uri": "file://test_sql_format.test_window-nofuse_filter_with_session_window_nocols_/formatted.sql" + } + ], "test_sql_format.test[window-null_type]": [ { "uri": "file://test_sql_format.test_window-null_type_/formatted.sql" diff --git a/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_window-nofuse_filter_with_session_window_nocols_/formatted.sql b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_window-nofuse_filter_with_session_window_nocols_/formatted.sql new file mode 100644 index 00000000000..91f51fb194b --- /dev/null +++ b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_window-nofuse_filter_with_session_window_nocols_/formatted.sql @@ -0,0 +1,55 @@ +PRAGMA config.flags('OptimizerFlags', 'PushdownFiltersOverWindow'); + +$src = ( + SELECT + * + FROM + as_table([ + <|user: Nothing(String?), ts: Nothing(Int32?), payload: 1|>, + <|user: 'u1', ts: Nothing(Int32?), payload: 2|>, + <|user: Nothing(String?), ts: Nothing(Int32?), payload: 3|>, + <|user: 'u1', ts: Nothing(Int32?), payload: 4|>, + <|user: Nothing(String?), ts: 1, payload: 5|>, + <|user: 'u1', ts: 2, payload: 6|>, + <|user: Nothing(String?), ts: 2, payload: 7|>, + <|user: 'u1', ts: 3, payload: 8|>, + <|user: Nothing(String?), ts: 3, payload: 9|>, + <|user: 'u1', ts: 4, payload: 10|>, + <|user: Nothing(String?), ts: 10, payload: 11|>, + <|user: 'u1', ts: 11, payload: 12|>, + <|user: Nothing(String?), ts: 21, payload: 13|>, + <|user: 'u1', ts: 22, payload: 14|>, + <|user: Nothing(String?), ts: 31, payload: 15|>, + <|user: 'u1', ts: 32, payload: 16|>, + <|user: Nothing(String?), ts: 50, payload: 17|>, + <|user: 'u1', ts: 51, payload: 18|>, + ]) +); + +$src = ( + SELECT + user, + ts, + RowNumber() OVER w AS rn, + FROM + $src + WINDOW + w AS ( + PARTITION BY + user, + SessionWindow(ts, 10) + ORDER BY + ts + ) +); + +SELECT + * +FROM + $src +WHERE + rn == 1 +ORDER BY + user, + ts +; diff --git a/yql/essentials/tests/sql/suites/window/nofuse_filter_with_session_window_nocols.yql b/yql/essentials/tests/sql/suites/window/nofuse_filter_with_session_window_nocols.yql new file mode 100644 index 00000000000..4bbf3432d10 --- /dev/null +++ b/yql/essentials/tests/sql/suites/window/nofuse_filter_with_session_window_nocols.yql @@ -0,0 +1,36 @@ +PRAGMA config.flags('OptimizerFlags', 'PushdownFiltersOverWindow'); + +$src = select * from as_table([ + <|user:Nothing(String?), ts:Nothing(Int32?), payload:1|>, + <|user:"u1" , ts:Nothing(Int32?), payload:2|>, + <|user:Nothing(String?), ts:Nothing(Int32?), payload:3|>, + <|user:"u1" , ts:Nothing(Int32?), payload:4|>, + <|user:Nothing(String?), ts:1, payload:5|>, + <|user:"u1", ts:2, payload:6|>, + <|user:Nothing(String?), ts:2, payload:7|>, + <|user:"u1", ts:3, payload:8|>, + <|user:Nothing(String?), ts:3, payload:9|>, + <|user:"u1", ts:4, payload:10|>, + <|user:Nothing(String?), ts:10, payload:11|>, + <|user:"u1", ts:11, payload:12|>, + <|user:Nothing(String?), ts:21, payload:13|>, + <|user:"u1", ts:22, payload:14|>, + <|user:Nothing(String?), ts:31, payload:15|>, + <|user:"u1", ts:32, payload:16|>, + <|user:Nothing(String?), ts:50, payload:17|>, + <|user:"u1", ts:51, payload:18|>, +]); + +$src = SELECT + user, + ts, + RowNumber() over w as rn, +FROM $src +WINDOW w AS ( + PARTITION BY user, SessionWindow(ts, 10) + ORDER BY ts +); + +select * from $src where rn == 1 +ORDER BY user, ts; + |
