@@ -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,17 @@ 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 () > 1 && join->Child (1 )->Content () == " using" ) {
928+
929+ for (ui32 col = 0 ; col < join->Child (3 )->ChildrenSize (); ++col) {
930+ auto lr = join->Child (3 )->Child (col);
931+ usedColumns.insert (std::make_pair (TString (lr->Child (0 )->Content ()), std::make_pair (Max<ui32>(), TString ())));
932+ usedColumns.insert (std::make_pair (TString (lr->Child (1 )->Content ()), std::make_pair (Max<ui32>(), TString ())));
933+ usedColumns.erase (TString (join->Child (2 )->Child (col)->Content ()));
934+ joinUsingColumns.emplace_back (ToString (groupNo), join->Child (2 )->Child (col)->Content ());
935+ }
936+ continue ;
937+ }
927938 if (joinType != " cross" ) {
928939 AddColumnsFromType (join->Tail ().Child (0 )->GetTypeAnn (), usedColumns);
929940 }
@@ -1519,6 +1530,63 @@ std::tuple<TVector<ui32>, TExprNode::TListType> BuildJoinGroups(TPositionHandle
15191530 current = cartesian;
15201531 continue ;
15211532 }
1533+ if (join->ChildrenSize () > 1 && join->Child (1 )->Content () == " using" ) {
1534+ Y_ENSURE (join->ChildrenSize () > 3 && join->Child (3 )->IsList (), " Excepted list of aliased columns in USING join" );
1535+ auto left = current;
1536+ auto right = with;
1537+ TExprNode::TListType leftColumns;
1538+ TExprNode::TListType rightColumns;
1539+
1540+ for (auto & col: join->Child (3 )->ChildrenList ()) {
1541+ leftColumns.push_back (col->Child (0 ));
1542+ rightColumns.push_back (col->Child (1 ));
1543+ }
1544+ current = BuildEquiJoin (pos, joinType, left, right, leftColumns, rightColumns, ctx);
1545+ auto secondStruct = ctx.Builder (pos)
1546+ .Lambda ()
1547+ .Param (" row" )
1548+ .Callable (" AsStruct" )
1549+ .Do ([&](TExprNodeBuilder& parent) -> TExprNodeBuilder& {
1550+ for (size_t i = 0 ; i < leftColumns.size (); ++i) {
1551+ parent.List (i)
1552+ .Add (0 , join->Child (2 )->Child (i))
1553+ .Callable (1 , " Coalesce" )
1554+ .Callable (0 , " Member" )
1555+ .Arg (0 , " row" )
1556+ .Add (1 , leftColumns[i])
1557+ .Seal ()
1558+ .Callable (1 , " Member" )
1559+ .Arg (0 , " row" )
1560+ .Add (1 , rightColumns[i])
1561+ .Seal ()
1562+ .Seal ()
1563+ .Seal ();
1564+ }
1565+ return parent;
1566+ })
1567+ .Seal ()
1568+ .Seal ()
1569+ .Build ();
1570+ current = ctx.Builder (pos)
1571+ .Callable (" OrderedMap" )
1572+ .Add (0 , current)
1573+ .Lambda (1 )
1574+ .Param (" row" )
1575+ .Callable (" FlattenMembers" )
1576+ .List (0 )
1577+ .Atom (0 , " " )
1578+ .Arg (1 , " row" )
1579+ .Seal ()
1580+ .List (1 )
1581+ .Atom (0 , " " )
1582+ .Apply (1 , secondStruct).With (0 , " row" ).Seal ()
1583+ .Seal ()
1584+ .Seal ()
1585+ .Seal ()
1586+ .Seal ()
1587+ .Build ();
1588+ continue ;
1589+ }
15221590
15231591 auto predicate = join->Tail ().TailPtr ();
15241592 if (!IsDepended (predicate->Tail (), predicate->Head ().Head ())) {
@@ -1709,7 +1777,7 @@ std::tuple<TVector<ui32>, TExprNode::TListType> BuildJoinGroups(TPositionHandle
17091777}
17101778
17111779TExprNode::TPtr BuildCrossJoinsBetweenGroups (TPositionHandle pos, const TExprNode::TListType& joinGroups,
1712- const TUsedColumns& usedColumns, const TVector<ui32>& groupForIndex, TExprContext& ctx) {
1780+ const TUsedColumns& usedColumns, const TVector<ui32>& groupForIndex, TExprContext& ctx, const TVector<std::pair<TString, TString>>& joinUsingColumns ) {
17131781 TExprNode::TListType args;
17141782 for (ui32 i = 0 ; i < joinGroups.size (); ++i) {
17151783 args.push_back (ctx.Builder (pos)
@@ -1742,6 +1810,16 @@ TExprNode::TPtr BuildCrossJoinsBetweenGroups(TPositionHandle pos, const TExprNod
17421810 .Build ());
17431811 }
17441812
1813+ for (const auto & x: joinUsingColumns) {
1814+ settings.push_back (ctx.Builder (pos)
1815+ .List ()
1816+ .Atom (0 , " rename" )
1817+ .Atom (1 , x.first + " ." + x.second )
1818+ .Atom (2 , x.second )
1819+ .Seal ()
1820+ .Build ());
1821+ }
1822+
17451823 auto settingsNode = ctx.NewList (pos, std::move (settings));
17461824 args.push_back (settingsNode);
17471825 return ctx.NewCallable (pos, " EquiJoin" , std::move (args));
@@ -3307,7 +3385,8 @@ TExprNode::TPtr ExpandPgSelectImpl(const TExprNode::TPtr& node, TExprContext& ct
33073385 cleanedInputs.push_back (list);
33083386 } else {
33093387 // extract all used columns
3310- auto usedColumns = GatherUsedColumns (result, joinOps, filter, groupExprs, having, extraSortColumns, window, winCtx);
3388+ TVector<std::pair<TString, TString>> joinUsingColumns;
3389+ auto usedColumns = GatherUsedColumns (result, joinOps, filter, groupExprs, having, extraSortColumns, window, winCtx, joinUsingColumns);
33113390
33123391 // fill index of input for each column
33133392 FillInputIndices (from, finalExtTypes, usedColumns, optCtx);
@@ -3323,7 +3402,7 @@ TExprNode::TPtr ExpandPgSelectImpl(const TExprNode::TPtr& node, TExprContext& ct
33233402 if (joinGroups.size () == 1 ) {
33243403 list = joinGroups.front ();
33253404 } else {
3326- list = BuildCrossJoinsBetweenGroups (node->Pos (), joinGroups, usedColumns, groupForIndex, ctx);
3405+ list = BuildCrossJoinsBetweenGroups (node->Pos (), joinGroups, usedColumns, groupForIndex, ctx, joinUsingColumns );
33273406 }
33283407 }
33293408 }
0 commit comments