aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoraneporada <aneporada@yandex-team.ru>2022-03-04 01:12:52 +0300
committeraneporada <aneporada@yandex-team.ru>2022-03-04 01:12:52 +0300
commit3a535176128bdad1d83eeec320b37a01f20b50b8 (patch)
tree35430920d606357c1f1168d69fc0db3c02129e97
parentdc815b24317adc0d4a311c3504e6b50a61db0b41 (diff)
downloadydb-3a535176128bdad1d83eeec320b37a01f20b50b8.tar.gz
[YQL-10265] Support all integral types in TWindowFrame settings
ref:42ac6d21a605ace9ff464ed19d4986e785baea5a
-rw-r--r--ydb/library/yql/core/yql_opt_window.cpp60
1 files changed, 59 insertions, 1 deletions
diff --git a/ydb/library/yql/core/yql_opt_window.cpp b/ydb/library/yql/core/yql_opt_window.cpp
index cc9804b7cd..aebe6e901a 100644
--- a/ydb/library/yql/core/yql_opt_window.cpp
+++ b/ydb/library/yql/core/yql_opt_window.cpp
@@ -2568,6 +2568,7 @@ TMaybe<TWindowFrameSettings> TWindowFrameSettings::TryParse(const TExprNode& nod
auto type = fb->Head().Content();
if (type == "currentRow") {
if (fb->ChildrenSize() == 1) {
+ frameBound = fb;
continue;
}
ctx.AddError(TIssue(ctx.GetPosition(fb->Pos()), TStringBuilder() << "Expecting no value for '" << type << "'"));
@@ -2575,10 +2576,67 @@ TMaybe<TWindowFrameSettings> TWindowFrameSettings::TryParse(const TExprNode& nod
}
if (!(type == "preceding" || type == "following")) {
- ctx.AddError(TIssue(ctx.GetPosition(fb->Pos()), TStringBuilder() << "Expecting preceding or follwing, but got '" << type << "'"));
+ ctx.AddError(TIssue(ctx.GetPosition(fb->Pos()), TStringBuilder() << "Expecting preceding or following, but got '" << type << "'"));
return {};
}
+ if (!EnsureTupleSize(*fb, 2, ctx)) {
+ return {};
+ }
+
+ auto boundValue = fb->ChildPtr(1);
+ if (boundValue->IsAtom()) {
+ if (boundValue->Content() == "unbounded") {
+ continue;
+ }
+ ctx.AddError(TIssue(ctx.GetPosition(fb->Pos()), TStringBuilder() << "Expecting unbounded, but got '" << boundValue->Content() << "'"));
+ return {};
+ }
+
+ if (node.IsCallable({"WinOnRows", "WinOnGroups"})) {
+ if (!EnsureDataType(*boundValue, ctx)) {
+ return {};
+ }
+
+ auto slot = boundValue->GetTypeAnn()->Cast<TDataExprType>()->GetSlot();
+ bool groups = node.IsCallable("WinOnGroups");
+ if (!IsDataTypeIntegral(slot)) {
+ ctx.AddError(TIssue(ctx.GetPosition(boundValue->Pos()),
+ TStringBuilder() << "Expecting integral values for " << (groups ? "GROUPS" : "ROWS") << " but got " << *boundValue->GetTypeAnn()));
+ return {};
+ }
+
+ if (!groups) {
+ auto maybeIntLiteral = TMaybeNode<TCoIntegralCtor>(boundValue);
+ if (!maybeIntLiteral) {
+ // TODO: this is not strictly necessary, and only needed for current implementation via Queue
+ ctx.AddError(TIssue(ctx.GetPosition(boundValue->Pos()),
+ TStringBuilder() << "Expecting literal values for ROWS"));
+ return {};
+ }
+ auto strLiteralValue = maybeIntLiteral.Cast().Literal().Value();
+ if (strLiteralValue.StartsWith("-")) {
+ ctx.AddError(TIssue(ctx.GetPosition(boundValue->Pos()),
+ TStringBuilder() << "Expecting positive literal values for ROWS, but got " << strLiteralValue));
+ return {};
+ }
+
+ ui64 literalValue = FromString<ui64>(strLiteralValue);
+ if (literalValue > std::numeric_limits<i32>::max()) {
+ ctx.AddError(TIssue(ctx.GetPosition(boundValue->Pos()),
+ TStringBuilder() << "ROWS offset too big: " << strLiteralValue << ", maximum is " << std::numeric_limits<i32>::max()));
+ return {};
+ }
+
+ i32 castedValue = (i32)literalValue;
+ if (type == "preceding") {
+ castedValue = -castedValue;
+ }
+ boundOffset = castedValue;
+ }
+ } else if (!EnsureComparableType(boundValue->Pos(), *boundValue->GetTypeAnn(), ctx)) {
+ return {};
+ }
frameBound = fb;
} else if (setting->Tail().IsCallable("Int32")) {
auto& valNode = setting->Tail().Head();