@@ -4154,4 +4154,123 @@ TExprNode::TPtr ExpandPgGrouping(const TExprNode::TPtr& node, TExprContext& ctx,
41544154 .Build ();
41554155}
41564156
4157+ TExprNode::TPtr ExpandPgIterate (const TExprNode::TPtr& node, TExprContext& ctx, TOptimizeContext& optCtx) {
4158+ const bool all = node->Content ().EndsWith (" All" );
4159+ auto init = node->HeadPtr ();
4160+ init = ctx.WrapByCallableIf (!all, " ListUniq" , std::move (init));
4161+ auto lambda = node->TailPtr ();
4162+ const auto limit = optCtx.Types ->PgIterateLimit ;
4163+ auto itemArg = ctx.NewArgument (node->Pos (), " item" );
4164+ auto stateArg = ctx.NewArgument (node->Pos (), " state" );
4165+ auto state = ctx.Builder (node->Pos ())
4166+ .Callable (" Ensure" )
4167+ .Add (0 , stateArg)
4168+ .Callable (1 , " <" )
4169+ .Add (0 , itemArg)
4170+ .Callable (1 , " Uint32" )
4171+ .Atom (0 , limit)
4172+ .Seal ()
4173+ .Seal ()
4174+ .Callable (2 , " String" )
4175+ .Atom (0 , " Too many CTE iterations: " + ToString (limit))
4176+ .Seal ()
4177+ .Seal ()
4178+ .Build ();
4179+
4180+ auto currentIter = ctx.NewCallable (node->Pos (), " Nth" , { state, ctx.NewAtom (node->Pos (), 1 )});
4181+ auto add = ctx.Builder (node->Pos ())
4182+ .Apply (lambda)
4183+ .With (0 , currentIter)
4184+ .Seal ()
4185+ .Build ();
4186+
4187+ auto currentRes = ctx.NewCallable (node->Pos (), " Nth" , { state, ctx.NewAtom (node->Pos (), 0 )});
4188+ add = ctx.WrapByCallableIf (!all, " ListUniq" , std::move (add));
4189+ if (!all) {
4190+ auto id = ctx.Builder (node->Pos ())
4191+ .Lambda ()
4192+ .Param (" x" )
4193+ .Arg (" x" )
4194+ .Seal ()
4195+ .Build ();
4196+
4197+ add = ctx.Builder (node->Pos ())
4198+ .Callable (" Filter" )
4199+ .Add (0 , add)
4200+ .Lambda (1 )
4201+ .Param (" item" )
4202+ .Callable (" Not" )
4203+ .Callable (0 , " Contains" )
4204+ .Callable (0 , " ToDict" )
4205+ .Add (0 , currentRes)
4206+ .Add (1 , id)
4207+ .Add (2 , id)
4208+ .List (3 )
4209+ .Atom (0 , " Auto" , TNodeFlags::Default)
4210+ .Atom (1 , " One" , TNodeFlags::Default)
4211+ .Seal ()
4212+ .Seal ()
4213+ .Arg (1 , " item" )
4214+ .Seal ()
4215+ .Seal ()
4216+ .Seal ()
4217+ .Seal ()
4218+ .Build ();
4219+ }
4220+
4221+ auto res = ctx.NewCallable (node->Pos (), " Extend" , { currentRes, add });
4222+ auto p = ctx.NewList (node->Pos (), { res, add });
4223+ auto foldLambdaBody = ctx.NewList (node->Pos (), { p, p});
4224+ auto foldLambda = ctx.NewLambda (node->Pos (), ctx.NewArguments (node->Pos (), { itemArg, stateArg}), std::move (foldLambdaBody));
4225+ auto foldMap = ctx.Builder (node->Pos ())
4226+ .Callable (" FoldMap" )
4227+ .Callable (0 , " ListFromRange" )
4228+ .Callable (0 , " Uint32" )
4229+ .Atom (0 , 0 )
4230+ .Seal ()
4231+ .Callable (1 , " Uint32" )
4232+ .Atom (0 , limit + 1 )
4233+ .Seal ()
4234+ .Seal ()
4235+ .List (1 )
4236+ .Add (0 , init)
4237+ .Add (1 , init)
4238+ .Seal ()
4239+ .Add (2 , foldLambda)
4240+ .Seal ()
4241+ .Build ();
4242+
4243+ return ctx.Builder (node->Pos ())
4244+ .Callable (" Coalesce" )
4245+ .Callable (0 , " Nth" )
4246+ .Callable (0 , " ListLast" )
4247+ .Callable (0 , " ListTakeWhile" )
4248+ .Callable (0 , " ListExtend" )
4249+ .Callable (0 , " AsList" )
4250+ .List (0 )
4251+ .Add (0 , init)
4252+ .Add (1 , init)
4253+ .Seal ()
4254+ .Seal ()
4255+ .Add (1 , foldMap)
4256+ .Seal ()
4257+ .Lambda (1 )
4258+ .Param (" x" )
4259+ .Callable (" HasItems" )
4260+ .Callable (0 , " Nth" )
4261+ .Arg (0 , " x" )
4262+ .Atom (1 , 1 )
4263+ .Seal ()
4264+ .Seal ()
4265+ .Seal ()
4266+ .Seal ()
4267+ .Seal ()
4268+ .Atom (1 , 0 )
4269+ .Seal ()
4270+ .Callable (1 , " AsList" )
4271+ .Seal ()
4272+ .Seal ()
4273+ .Build ();
4274+ }
4275+
41574276} // namespace NYql
0 commit comments