diff options
author | aneporada <aneporada@yandex-team.ru> | 2022-03-04 01:12:52 +0300 |
---|---|---|
committer | aneporada <aneporada@yandex-team.ru> | 2022-03-04 01:12:52 +0300 |
commit | 3a535176128bdad1d83eeec320b37a01f20b50b8 (patch) | |
tree | 35430920d606357c1f1168d69fc0db3c02129e97 | |
parent | dc815b24317adc0d4a311c3504e6b50a61db0b41 (diff) | |
download | ydb-3a535176128bdad1d83eeec320b37a01f20b50b8.tar.gz |
[YQL-10265] Support all integral types in TWindowFrame settings
ref:42ac6d21a605ace9ff464ed19d4986e785baea5a
-rw-r--r-- | ydb/library/yql/core/yql_opt_window.cpp | 60 |
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(); |