|
5 | 5 | #include <ydb/library/yql/core/yql_atom_enums.h>
|
6 | 6 | #include <ydb/library/yql/core/yql_expr_type_annotation.h>
|
7 | 7 | #include <ydb/library/yql/core/yql_join.h>
|
| 8 | +#include <ydb/library/yql/core/yql_opt_hopping.h> |
8 | 9 | #include <ydb/library/yql/core/yql_opt_utils.h>
|
9 | 10 | #include <ydb/library/yql/core/yql_opt_window.h>
|
10 | 11 | #include <ydb/library/yql/core/yql_type_helpers.h>
|
@@ -3301,6 +3302,99 @@ TExprNode::TPtr RemoveDeadPayloadColumns(const TCoAggregate& aggr, TExprContext&
|
3301 | 3302 | return aggr.Ptr();
|
3302 | 3303 | }
|
3303 | 3304 |
|
| 3305 | +TExprNode::TPtr RewriteAsHoppingWindowFullOutput(const TCoAggregate& aggregate, TExprContext& ctx) { |
| 3306 | + const auto pos = aggregate.Pos(); |
| 3307 | + |
| 3308 | + NHopping::EnsureNotDistinct(aggregate); |
| 3309 | + |
| 3310 | + const auto maybeHopTraits = NHopping::ExtractHopTraits(aggregate, ctx, false); |
| 3311 | + if (!maybeHopTraits) { |
| 3312 | + return nullptr; |
| 3313 | + } |
| 3314 | + const auto hopTraits = *maybeHopTraits; |
| 3315 | + |
| 3316 | + const auto aggregateInputType = GetSeqItemType(*aggregate.Ptr()->Head().GetTypeAnn()).Cast<TStructExprType>(); |
| 3317 | + NHopping::TKeysDescription keysDescription(*aggregateInputType, aggregate.Keys(), hopTraits.Column); |
| 3318 | + |
| 3319 | + const auto keyLambda = keysDescription.GetKeySelector(ctx, pos, aggregateInputType); |
| 3320 | + const auto timeExtractorLambda = NHopping::BuildTimeExtractor(hopTraits.Traits, ctx); |
| 3321 | + const auto initLambda = NHopping::BuildInitHopLambda(aggregate, ctx); |
| 3322 | + const auto updateLambda = NHopping::BuildUpdateHopLambda(aggregate, ctx); |
| 3323 | + const auto saveLambda = NHopping::BuildSaveHopLambda(aggregate, ctx); |
| 3324 | + const auto loadLambda = NHopping::BuildLoadHopLambda(aggregate, ctx); |
| 3325 | + const auto mergeLambda = NHopping::BuildMergeHopLambda(aggregate, ctx); |
| 3326 | + const auto finishLambda = NHopping::BuildFinishHopLambda(aggregate, keysDescription.GetActualGroupKeys(), hopTraits.Column, ctx); |
| 3327 | + |
| 3328 | + const auto streamArg = Build<TCoArgument>(ctx, pos).Name("stream").Done(); |
| 3329 | + auto multiHoppingCoreBuilder = Build<TCoMultiHoppingCore>(ctx, pos) |
| 3330 | + .KeyExtractor(keyLambda) |
| 3331 | + .TimeExtractor(timeExtractorLambda) |
| 3332 | + .Hop(hopTraits.Traits.Hop()) |
| 3333 | + .Interval(hopTraits.Traits.Interval()) |
| 3334 | + .Delay(hopTraits.Traits.Delay()) |
| 3335 | + .DataWatermarks(hopTraits.Traits.DataWatermarks()) |
| 3336 | + .InitHandler(initLambda) |
| 3337 | + .UpdateHandler(updateLambda) |
| 3338 | + .MergeHandler(mergeLambda) |
| 3339 | + .FinishHandler(finishLambda) |
| 3340 | + .SaveHandler(saveLambda) |
| 3341 | + .LoadHandler(loadLambda) |
| 3342 | + .template WatermarkMode<TCoAtom>().Build(ToString(false)); |
| 3343 | + |
| 3344 | + return Build<TCoPartitionsByKeys>(ctx, pos) |
| 3345 | + .Input(aggregate.Input()) |
| 3346 | + .KeySelectorLambda(keyLambda) |
| 3347 | + .SortDirections<TCoBool>() |
| 3348 | + .Literal() |
| 3349 | + .Value("true") |
| 3350 | + .Build() |
| 3351 | + .Build() |
| 3352 | + .SortKeySelectorLambda(timeExtractorLambda) |
| 3353 | + .ListHandlerLambda() |
| 3354 | + .Args(streamArg) |
| 3355 | + .template Body<TCoForwardList>() |
| 3356 | + .Stream(Build<TCoMap>(ctx, pos) |
| 3357 | + .Input(multiHoppingCoreBuilder |
| 3358 | + .template Input<TCoIterator>() |
| 3359 | + .List(streamArg) |
| 3360 | + .Build() |
| 3361 | + .Done()) |
| 3362 | + .Lambda(keysDescription.BuildUnpickleLambda(ctx, pos, *aggregateInputType)) |
| 3363 | + .Done()) |
| 3364 | + .Build() |
| 3365 | + .Build() |
| 3366 | + .Done() |
| 3367 | + .Ptr(); |
| 3368 | +} |
| 3369 | + |
| 3370 | +TExprNode::TPtr RewriteAsHoppingWindow(TExprNode::TPtr node, TExprContext& ctx) { |
| 3371 | + const auto aggregate = TCoAggregate(node); |
| 3372 | + |
| 3373 | + if (!IsPureIsolatedLambda(*aggregate.Ptr())) { |
| 3374 | + return nullptr; |
| 3375 | + } |
| 3376 | + |
| 3377 | + if (!GetSetting(aggregate.Settings().Ref(), "hopping")) { |
| 3378 | + return nullptr; |
| 3379 | + } |
| 3380 | + |
| 3381 | + auto result = RewriteAsHoppingWindowFullOutput(aggregate, ctx); |
| 3382 | + if (!result) { |
| 3383 | + return result; |
| 3384 | + } |
| 3385 | + |
| 3386 | + auto outputColumnSetting = GetSetting(aggregate.Settings().Ref(), "output_columns"); |
| 3387 | + if (!outputColumnSetting) { |
| 3388 | + return result; |
| 3389 | + } |
| 3390 | + |
| 3391 | + return Build<TCoExtractMembers>(ctx, aggregate.Pos()) |
| 3392 | + .Input(result) |
| 3393 | + .Members(outputColumnSetting->ChildPtr(1)) |
| 3394 | + .Done() |
| 3395 | + .Ptr(); |
| 3396 | +} |
| 3397 | + |
3304 | 3398 | TExprNode::TPtr PullAssumeColumnOrderOverEquiJoin(const TExprNode::TPtr& node, TExprContext& ctx, TOptimizeContext& optCtx) {
|
3305 | 3399 | TVector<ui32> withAssume;
|
3306 | 3400 | for (ui32 i = 0; i < node->ChildrenSize() - 2; i++) {
|
@@ -5080,6 +5174,11 @@ void RegisterCoSimpleCallables1(TCallableOptimizerMap& map) {
|
5080 | 5174 | return clean;
|
5081 | 5175 | }
|
5082 | 5176 |
|
| 5177 | + if (auto hopping = RewriteAsHoppingWindow(node, ctx)) { |
| 5178 | + YQL_CLOG(DEBUG, Core) << "RewriteAsHoppingWindow"; |
| 5179 | + return hopping; |
| 5180 | + } |
| 5181 | + |
5083 | 5182 | return DropReorder<false>(node, ctx);
|
5084 | 5183 | };
|
5085 | 5184 |
|
|
0 commit comments