@@ -911,7 +911,7 @@ void GatherUsedWindows(const TExprNode::TPtr& window, const TExprNode::TPtr& pro
911911
912912TUsedColumns GatherUsedColumns (const TExprNode::TPtr& result, const TExprNode::TPtr& joinOps,
913913 const TExprNode::TPtr& filter, const TExprNode::TPtr& groupExprs, const TExprNode::TPtr& having, const TExprNode::TPtr& extraSortColumns,
914- const TExprNode::TPtr& window, const TWindowsCtx& winCtx) {
914+ const TExprNode::TPtr& window, const TWindowsCtx& winCtx, TVector<std::pair<TString, TString>>& joinUsingColumns ) {
915915 TUsedColumns usedColumns;
916916 for (const auto & x : result->Tail ().Children ()) {
917917 AddColumnsFromType (x->Child (1 )->GetTypeAnn (), usedColumns);
@@ -924,6 +924,21 @@ TUsedColumns GatherUsedColumns(const TExprNode::TPtr& result, const TExprNode::T
924924 for (ui32 i = 0 ; i < groupTuple->ChildrenSize (); ++i) {
925925 auto join = groupTuple->Child (i);
926926 auto joinType = join->Child (0 )->Content ();
927+ if (join->ChildrenSize () > 2 ) {
928+ Y_ENSURE (join->Child (1 )->ChildrenSize () > 3 , " Excepted at least 4 args there" );
929+ Y_ENSURE (join->Child (1 )->IsAtom (), " Supported only USING clause there" );
930+ Y_ENSURE (join->Child (1 )->Content () == " using" , " Supported only USING clause there" );
931+ for (ui32 col = 0 ; col < join->Child (3 )->ChildrenSize (); ++col) {
932+ auto lr = join->Child (3 )->Child (col);
933+ if (lr->Child (0 )->IsAtom ()) {
934+ usedColumns.insert (std::make_pair (TString (lr->Child (0 )->Content ()), std::make_pair (Max<ui32>(), TString ())));
935+ }
936+ usedColumns.insert (std::make_pair (TString (lr->Child (1 )->Content ()), std::make_pair (Max<ui32>(), TString ())));
937+ usedColumns.erase (TString (join->Child (2 )->Child (col)->Content ()));
938+ joinUsingColumns.emplace_back (ToString (groupNo), join->Child (2 )->Child (col)->Content ());
939+ }
940+ continue ;
941+ }
927942 if (joinType != " cross" ) {
928943 AddColumnsFromType (join->Tail ().Child (0 )->GetTypeAnn (), usedColumns);
929944 }
@@ -1519,6 +1534,85 @@ std::tuple<TVector<ui32>, TExprNode::TListType> BuildJoinGroups(TPositionHandle
15191534 current = cartesian;
15201535 continue ;
15211536 }
1537+ if (join->ChildrenSize () > 2 ) {
1538+ Y_ENSURE (join->Child (1 )->IsAtom (), " expected only USING clause when join_ops children size > 2" );
1539+ Y_ENSURE (join->Child (1 )->Content () == " using" , " expected only USING clause when join_ops children size > 2" );
1540+ Y_ENSURE (join->ChildrenSize () > 3 && join->Child (3 )->IsList (), " Excepted list of aliased columns in USING join" );
1541+ auto left = current;
1542+ auto right = with;
1543+ TExprNode::TListType leftColumns;
1544+ TExprNode::TListType rightColumns;
1545+ TExprNode::TListType toRemove;
1546+ for (auto & col: join->Child (3 )->ChildrenList ()) {
1547+ if (col->Child (0 )->IsAtom ()) {
1548+ leftColumns.push_back (col->Child (0 ));
1549+ } else {
1550+ toRemove.push_back (col->Child (0 )->Child (0 ));
1551+ leftColumns.push_back (col->Child (0 )->Child (0 ));
1552+ }
1553+ rightColumns.push_back (col->Child (1 ));
1554+ }
1555+ current = BuildEquiJoin (pos, joinType, left, right, leftColumns, rightColumns, ctx);
1556+ auto secondStruct = ctx.Builder (pos)
1557+ .Lambda ()
1558+ .Param (" row" )
1559+ .Callable (" AsStruct" )
1560+ .Do ([&](TExprNodeBuilder& parent) -> TExprNodeBuilder& {
1561+ for (size_t i = 0 ; i < leftColumns.size (); ++i) {
1562+ parent.List (i)
1563+ .Add (0 , join->Child (2 )->Child (i))
1564+ .Callable (1 , " Coalesce" )
1565+ .Callable (0 , " Member" )
1566+ .Arg (0 , " row" )
1567+ .Add (1 , leftColumns[i])
1568+ .Seal ()
1569+ .Callable (1 , " Member" )
1570+ .Arg (0 , " row" )
1571+ .Add (1 , rightColumns[i])
1572+ .Seal ()
1573+ .Seal ()
1574+ .Seal ();
1575+ }
1576+ return parent;
1577+ })
1578+ .Seal ()
1579+ .Seal ()
1580+ .Build ();
1581+ auto removeProjection = ctx.Builder (pos)
1582+ .Lambda ()
1583+ .Param (" row" )
1584+ .Arg (0 , " row" )
1585+ .Seal ().Build ();
1586+ current = ctx.Builder (pos)
1587+ .Callable (" OrderedMap" )
1588+ .Add (0 , current)
1589+ .Lambda (1 )
1590+ .Param (" row" )
1591+ .Callable (" FlattenMembers" )
1592+ .List (0 )
1593+ .Atom (0 , " " )
1594+ .Do ([&](TExprNodeBuilder& parent) -> TExprNodeBuilder& {
1595+ if (toRemove.size ()) {
1596+ parent.Callable (1 , " RemoveMembers" )
1597+ .Arg (0 , " row" )
1598+ .Add (1 , ctx.NewList (pos, std::move (toRemove)))
1599+ .Seal ();
1600+ } else {
1601+ parent.Arg (1 , " row" );
1602+ }
1603+ return parent;
1604+ })
1605+ .Seal ()
1606+ .List (1 )
1607+ .Atom (0 , " " )
1608+ .Apply (1 , secondStruct).With (0 , " row" ).Seal ()
1609+ .Seal ()
1610+ .Seal ()
1611+ .Seal ()
1612+ .Seal ()
1613+ .Build ();
1614+ continue ;
1615+ }
15221616
15231617 auto predicate = join->Tail ().TailPtr ();
15241618 if (!IsDepended (predicate->Tail (), predicate->Head ().Head ())) {
@@ -1709,7 +1803,7 @@ std::tuple<TVector<ui32>, TExprNode::TListType> BuildJoinGroups(TPositionHandle
17091803}
17101804
17111805TExprNode::TPtr BuildCrossJoinsBetweenGroups (TPositionHandle pos, const TExprNode::TListType& joinGroups,
1712- const TUsedColumns& usedColumns, const TVector<ui32>& groupForIndex, TExprContext& ctx) {
1806+ const TUsedColumns& usedColumns, const TVector<ui32>& groupForIndex, TExprContext& ctx, const TVector<std::pair<TString, TString>>& joinUsingColumns ) {
17131807 TExprNode::TListType args;
17141808 for (ui32 i = 0 ; i < joinGroups.size (); ++i) {
17151809 args.push_back (ctx.Builder (pos)
@@ -1742,6 +1836,16 @@ TExprNode::TPtr BuildCrossJoinsBetweenGroups(TPositionHandle pos, const TExprNod
17421836 .Build ());
17431837 }
17441838
1839+ for (const auto & x: joinUsingColumns) {
1840+ settings.push_back (ctx.Builder (pos)
1841+ .List ()
1842+ .Atom (0 , " rename" )
1843+ .Atom (1 , x.first + " ." + x.second )
1844+ .Atom (2 , x.second )
1845+ .Seal ()
1846+ .Build ());
1847+ }
1848+
17451849 auto settingsNode = ctx.NewList (pos, std::move (settings));
17461850 args.push_back (settingsNode);
17471851 return ctx.NewCallable (pos, " EquiJoin" , std::move (args));
@@ -3366,7 +3470,8 @@ TExprNode::TPtr ExpandPgSelectImpl(const TExprNode::TPtr& node, TExprContext& ct
33663470 cleanedInputs.push_back (list);
33673471 } else {
33683472 // extract all used columns
3369- auto usedColumns = GatherUsedColumns (result, joinOps, filter, groupExprs, having, extraSortColumns, window, winCtx);
3473+ TVector<std::pair<TString, TString>> joinUsingColumns;
3474+ auto usedColumns = GatherUsedColumns (result, joinOps, filter, groupExprs, having, extraSortColumns, window, winCtx, joinUsingColumns);
33703475
33713476 // fill index of input for each column
33723477 FillInputIndices (from, finalExtTypes, usedColumns, optCtx);
@@ -3382,7 +3487,7 @@ TExprNode::TPtr ExpandPgSelectImpl(const TExprNode::TPtr& node, TExprContext& ct
33823487 if (joinGroups.size () == 1 ) {
33833488 list = joinGroups.front ();
33843489 } else {
3385- list = BuildCrossJoinsBetweenGroups (node->Pos (), joinGroups, usedColumns, groupForIndex, ctx);
3490+ list = BuildCrossJoinsBetweenGroups (node->Pos (), joinGroups, usedColumns, groupForIndex, ctx, joinUsingColumns );
33863491 }
33873492 }
33883493 }
0 commit comments