|
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>
|
@@ -3228,6 +3229,99 @@ TExprNode::TPtr RemoveDeadPayloadColumns(const TCoAggregate& aggr, TExprContext&
|
3228 | 3229 | return aggr.Ptr();
|
3229 | 3230 | }
|
3230 | 3231 |
|
| 3232 | +TExprNode::TPtr RewriteAsHoppingWindowFullOutput(const TCoAggregate& aggregate, TExprContext& ctx) { |
| 3233 | + const auto pos = aggregate.Pos(); |
| 3234 | + |
| 3235 | + NHopping::EnsureNotDistinct(aggregate); |
| 3236 | + |
| 3237 | + const auto maybeHopTraits = NHopping::ExtractHopTraits(aggregate, ctx, false); |
| 3238 | + if (!maybeHopTraits) { |
| 3239 | + return nullptr; |
| 3240 | + } |
| 3241 | + const auto hopTraits = *maybeHopTraits; |
| 3242 | + |
| 3243 | + const auto aggregateInputType = GetSeqItemType(*aggregate.Ptr()->Head().GetTypeAnn()).Cast<TStructExprType>(); |
| 3244 | + NHopping::TKeysDescription keysDescription(*aggregateInputType, aggregate.Keys(), hopTraits.Column); |
| 3245 | + |
| 3246 | + const auto keyLambda = keysDescription.GetKeySelector(ctx, pos, aggregateInputType); |
| 3247 | + const auto timeExtractorLambda = NHopping::BuildTimeExtractor(hopTraits.Traits, ctx); |
| 3248 | + const auto initLambda = NHopping::BuildInitHopLambda(aggregate, ctx); |
| 3249 | + const auto updateLambda = NHopping::BuildUpdateHopLambda(aggregate, ctx); |
| 3250 | + const auto saveLambda = NHopping::BuildSaveHopLambda(aggregate, ctx); |
| 3251 | + const auto loadLambda = NHopping::BuildLoadHopLambda(aggregate, ctx); |
| 3252 | + const auto mergeLambda = NHopping::BuildMergeHopLambda(aggregate, ctx); |
| 3253 | + const auto finishLambda = NHopping::BuildFinishHopLambda(aggregate, keysDescription.GetActualGroupKeys(), hopTraits.Column, ctx); |
| 3254 | + |
| 3255 | + const auto streamArg = Build<TCoArgument>(ctx, pos).Name("stream").Done(); |
| 3256 | + auto multiHoppingCoreBuilder = Build<TCoMultiHoppingCore>(ctx, pos) |
| 3257 | + .KeyExtractor(keyLambda) |
| 3258 | + .TimeExtractor(timeExtractorLambda) |
| 3259 | + .Hop(hopTraits.Traits.Hop()) |
| 3260 | + .Interval(hopTraits.Traits.Interval()) |
| 3261 | + .Delay(hopTraits.Traits.Delay()) |
| 3262 | + .DataWatermarks(hopTraits.Traits.DataWatermarks()) |
| 3263 | + .InitHandler(initLambda) |
| 3264 | + .UpdateHandler(updateLambda) |
| 3265 | + .MergeHandler(mergeLambda) |
| 3266 | + .FinishHandler(finishLambda) |
| 3267 | + .SaveHandler(saveLambda) |
| 3268 | + .LoadHandler(loadLambda) |
| 3269 | + .template WatermarkMode<TCoAtom>().Build(ToString(false)); |
| 3270 | + |
| 3271 | + return Build<TCoPartitionsByKeys>(ctx, pos) |
| 3272 | + .Input(aggregate.Input()) |
| 3273 | + .KeySelectorLambda(keyLambda) |
| 3274 | + .SortDirections<TCoBool>() |
| 3275 | + .Literal() |
| 3276 | + .Value("true") |
| 3277 | + .Build() |
| 3278 | + .Build() |
| 3279 | + .SortKeySelectorLambda(timeExtractorLambda) |
| 3280 | + .ListHandlerLambda() |
| 3281 | + .Args(streamArg) |
| 3282 | + .template Body<TCoForwardList>() |
| 3283 | + .Stream(Build<TCoMap>(ctx, pos) |
| 3284 | + .Input(multiHoppingCoreBuilder |
| 3285 | + .template Input<TCoIterator>() |
| 3286 | + .List(streamArg) |
| 3287 | + .Build() |
| 3288 | + .Done()) |
| 3289 | + .Lambda(keysDescription.BuildUnpickleLambda(ctx, pos, *aggregateInputType)) |
| 3290 | + .Done()) |
| 3291 | + .Build() |
| 3292 | + .Build() |
| 3293 | + .Done() |
| 3294 | + .Ptr(); |
| 3295 | +} |
| 3296 | + |
| 3297 | +TExprNode::TPtr RewriteAsHoppingWindow(TExprNode::TPtr node, TExprContext& ctx) { |
| 3298 | + const auto aggregate = TCoAggregate(node); |
| 3299 | + |
| 3300 | + if (!IsPureIsolatedLambda(*aggregate.Ptr())) { |
| 3301 | + return nullptr; |
| 3302 | + } |
| 3303 | + |
| 3304 | + if (!GetSetting(aggregate.Settings().Ref(), "hopping")) { |
| 3305 | + return nullptr; |
| 3306 | + } |
| 3307 | + |
| 3308 | + auto result = RewriteAsHoppingWindowFullOutput(aggregate, ctx); |
| 3309 | + if (!result) { |
| 3310 | + return result; |
| 3311 | + } |
| 3312 | + |
| 3313 | + auto outputColumnSetting = GetSetting(aggregate.Settings().Ref(), "output_columns"); |
| 3314 | + if (!outputColumnSetting) { |
| 3315 | + return result; |
| 3316 | + } |
| 3317 | + |
| 3318 | + return Build<TCoExtractMembers>(ctx, aggregate.Pos()) |
| 3319 | + .Input(result) |
| 3320 | + .Members(outputColumnSetting->ChildPtr(1)) |
| 3321 | + .Done() |
| 3322 | + .Ptr(); |
| 3323 | +} |
| 3324 | + |
3231 | 3325 | TExprNode::TPtr PullAssumeColumnOrderOverEquiJoin(const TExprNode::TPtr& node, TExprContext& ctx, TOptimizeContext& optCtx) {
|
3232 | 3326 | TVector<ui32> withAssume;
|
3233 | 3327 | for (ui32 i = 0; i < node->ChildrenSize() - 2; i++) {
|
@@ -5007,6 +5101,11 @@ void RegisterCoSimpleCallables1(TCallableOptimizerMap& map) {
|
5007 | 5101 | return clean;
|
5008 | 5102 | }
|
5009 | 5103 |
|
| 5104 | + if (auto hopping = RewriteAsHoppingWindow(node, ctx)) { |
| 5105 | + YQL_CLOG(DEBUG, Core) << "RewriteAsHoppingWindow"; |
| 5106 | + return hopping; |
| 5107 | + } |
| 5108 | + |
5010 | 5109 | return DropReorder<false>(node, ctx);
|
5011 | 5110 | };
|
5012 | 5111 |
|
|
0 commit comments