@@ -267,6 +267,24 @@ bool IsCompatibleWithBlocks(TPositionHandle pos, const TStructExprType& type, TE
267267 return resolveStatus == IArrowResolver::OK;
268268}
269269
270+ // XXX: Unfortunately, KQP optimizer pipeline is not quite
271+ // predictable, so there is no guarantees whether the pair
272+ // (FromFlow(ToFlow(...)) are already squashed or not.
273+ // The helper below checks both cases to find WideFromBlocks
274+ // input node:
275+ // * (WideFromBlocks(...))
276+ // * (FromFlow(ToFlow(WideFromBlocks(...))))
277+ // FIXME: To suppress compiler warnings when the constexpr value
278+ // NYql::NBlockStreamIO::WideFromBlocks is false, Y_DECLARE_UNUSED
279+ // quantifier is used.
280+ Y_DECLARE_UNUSED
281+ static inline bool IsNodeWideFromBlocks (const TMaybeNode<TExprBase> body) {
282+ return body.Maybe <TCoWideFromBlocks>() ||
283+ body.Maybe <TCoFromFlow>() &&
284+ body.Cast <TCoFromFlow>().Input ().Maybe <TCoToFlow>() &&
285+ body.Cast <TCoFromFlow>().Input ().Cast <TCoToFlow>().Input ().Maybe <TCoWideFromBlocks>();
286+ }
287+
270288// TODO: composite copy-paste from https://github.com/ydb-platform/ydb/blob/122f053354c5df4fc559bf06fe0302f92d813032/ydb/library/yql/dq/opt/dq_opt_build.cpp#L388
271289bool CanPropagateWideBlockThroughChannel (
272290 const TDqOutput& output,
@@ -293,11 +311,20 @@ bool CanPropagateWideBlockThroughChannel(
293311 return false ;
294312 }
295313
296- // Ensure that stage has blocks on top level (i.e. FromFlow(WideFromBlocks(...)))
297- if (!program.Lambda ().Body ().Maybe <TCoFromFlow>() ||
298- !program.Lambda ().Body ().Cast <TCoFromFlow>().Input ().Maybe <TCoWideFromBlocks>())
299- {
300- return false ;
314+ if constexpr (!NYql::NBlockStreamIO::WideFromBlocks) {
315+ // Ensure that stage has blocks on top level (i.e. (FromFlow(WideFromBlocks(...)))).
316+ if (!program.Lambda ().Body ().Maybe <TCoFromFlow>() ||
317+ !program.Lambda ().Body ().Cast <TCoFromFlow>().Input ().Maybe <TCoWideFromBlocks>())
318+ {
319+ return false ;
320+ }
321+ } else {
322+ // Ensure that stage has blocks on top level (i.e. either
323+ // (WideFromBlocks(...)) or (FromFlow(ToFlow(WideFromBlocks(...))))).
324+ // See the rationale for alternatives nearby IsNodeWideFromBlocks.
325+ if (!IsNodeWideFromBlocks (program.Lambda ().Body ())) {
326+ return false ;
327+ }
301328 }
302329
303330 auto typeAnnotation = program.Lambda ().Ref ().GetTypeAnn ();
@@ -371,31 +398,61 @@ TMaybeNode<TKqpPhysicalTx> PeepholeOptimize(const TKqpPhysicalTx& tx, TExprConte
371398 if (auto connection = stage.Inputs ().Item (i).Maybe <TDqConnection>(); connection &&
372399 CanPropagateWideBlockThroughChannel (connection.Cast ().Output (), programs, TDqStageSettings::Parse (stage), ctx, typesCtx))
373400 {
374- TExprNode::TPtr newArgNode = ctx.Builder (oldArg.Pos ())
375- .Callable (" FromFlow" )
376- .Callable (0 , " WideFromBlocks" )
377- .Callable (0 , " ToFlow" )
378- .Add (0 , newArg.Ptr ())
401+ TExprNode::TPtr newArgNode;
402+ if constexpr (!NYql::NBlockStreamIO::WideFromBlocks) {
403+ newArgNode = ctx.Builder (oldArg.Pos ())
404+ .Callable (" FromFlow" )
405+ .Callable (0 , " WideFromBlocks" )
406+ .Callable (0 , " ToFlow" )
407+ .Add (0 , newArg.Ptr ())
408+ .Seal ()
379409 .Seal ()
380410 .Seal ()
381- .Seal ()
382- .Build ();
411+ .Build ();
412+ } else {
413+ newArgNode = ctx.Builder (oldArg.Pos ())
414+ .Callable (" WideFromBlocks" )
415+ .Add (0 , newArg.Ptr ())
416+ .Seal ()
417+ .Build ();
418+ }
419+
383420 argsMap.emplace (oldArg.Raw (), newArgNode);
384421
385422 auto stageUid = connection.Cast ().Output ().Stage ().Ref ().UniqueId ();
386423
387- // Update input program with: FromFlow(WideFromBlocks($1)) → FromFlow($1)
388- if (const auto & inputProgram = programs.at (stageUid); inputProgram.Lambda ().Body ().Maybe <TCoFromFlow>() &&
389- inputProgram.Lambda ().Body ().Cast <TCoFromFlow>().Input ().Maybe <TCoWideFromBlocks>())
390- {
391- auto newBody = Build<TCoFromFlow>(ctx, inputProgram.Lambda ().Body ().Cast <TCoFromFlow>().Pos ())
392- .Input (inputProgram.Lambda ().Body ().Cast <TCoFromFlow>().Input ().Cast <TCoWideFromBlocks>().Input ())
393- .Done ();
424+ const auto & inputProgram = programs.at (stageUid);
425+ TMaybeNode<TExprBase> newBody;
426+ if constexpr (!NYql::NBlockStreamIO::WideFromBlocks) {
427+ // Update input program with: (FromFlow(WideFromBlocks($1))) -> (FromFlow($1))
428+ if (inputProgram.Lambda ().Body ().Maybe <TCoFromFlow>() &&
429+ inputProgram.Lambda ().Body ().Cast <TCoFromFlow>().Input ().Maybe <TCoWideFromBlocks>())
430+ {
431+ newBody = Build<TCoFromFlow>(ctx, inputProgram.Lambda ().Body ().Cast <TCoFromFlow>().Pos ())
432+ .Input (inputProgram.Lambda ().Body ().Cast <TCoFromFlow>().Input ().Cast <TCoWideFromBlocks>().Input ())
433+ .Done ();
434+ }
435+ } else {
436+ // Update input program with one of the following:
437+ // * (WideFromBlocks($1)) -> ($1)
438+ // * (FromFlow(ToFlow(WideFromBlocks($1)))) -> ($1)
439+ const auto & body = inputProgram.Lambda ().Body ();
440+ if (IsNodeWideFromBlocks (body)) {
441+ if (body.Maybe <TCoWideFromBlocks>()) {
442+ newBody = body.Cast <TCoWideFromBlocks>().Input ();
443+ } else {
444+ newBody = body.Cast <TCoFromFlow>().Input ()
445+ .Cast <TCoToFlow>().Input ()
446+ .Cast <TCoWideFromBlocks>().Input ();
447+ }
448+ }
449+ }
394450
451+ if (newBody) {
395452 auto newInputProgram = Build<TKqpProgram>(ctx, inputProgram.Pos ())
396453 .Lambda ()
397454 .Args (inputProgram.Lambda ().Args ())
398- .Body (newBody)
455+ .Body (newBody. Cast () )
399456 .Build ()
400457 .ArgsType (inputProgram.ArgsType ())
401458 .Done ();
0 commit comments