summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoraneporada <[email protected]>2026-07-24 15:18:06 +0300
committeraneporada <[email protected]>2026-07-24 15:59:01 +0300
commite968445dae721e2226ade66ec2f3669f1a19fc2a (patch)
tree802e34980c79778756d69115ba9cdd14be45fc39
parent07837bce5786e15438d7f5b3c9cefe791d28d20c (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
-rw-r--r--yql/essentials/core/common_opt/yql_co_finalizers.cpp4
-rw-r--r--yql/essentials/core/type_ann/type_ann_list.cpp5
-rw-r--r--yql/essentials/tests/sql/minirun/part4/canondata/result.json14
-rw-r--r--yql/essentials/tests/sql/sql2yql/canondata/result.json12
-rw-r--r--yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_window-nofuse_filter_with_session_window_nocols_/formatted.sql55
-rw-r--r--yql/essentials/tests/sql/suites/window/nofuse_filter_with_session_window_nocols.yql36
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;
+