@@ -1583,6 +1583,10 @@ bool ScanColumns(TExprNode::TPtr root, TInputs& inputs, const THashSet<TString>&
1583
1583
}
1584
1584
1585
1585
TString foundAlias;
1586
+ bool matchedAlias = false ;
1587
+ ui32 matchedAliasI = 0 ;
1588
+ TMaybe<ui32> matchedAliasIndex;
1589
+ TMaybe<ui32> matchedAliasIndexI;
1586
1590
for (ui32 priority : {TInput::Projection, TInput::Current, TInput::External}) {
1587
1591
ui32 matches = 0 ;
1588
1592
for (ui32 inputIndex = 0 ; inputIndex < inputs.size (); ++inputIndex) {
@@ -1597,6 +1601,16 @@ bool ScanColumns(TExprNode::TPtr root, TInputs& inputs, const THashSet<TString>&
1597
1601
}
1598
1602
}
1599
1603
1604
+ if (!x.Alias .empty ()) {
1605
+ if (node->Tail ().Content () == x.Alias ) {
1606
+ matchedAlias = true ;
1607
+ matchedAliasIndex = inputIndex;
1608
+ } else if (AsciiEqualsIgnoreCase (node->Tail ().Content (), x.Alias )) {
1609
+ ++matchedAliasI;
1610
+ matchedAliasIndexI = inputIndex;
1611
+ }
1612
+ }
1613
+
1600
1614
auto pos = x.Type ->FindItemI (node->Tail ().Content ());
1601
1615
if (pos) {
1602
1616
foundAlias = x.Alias ;
@@ -1624,10 +1638,39 @@ bool ScanColumns(TExprNode::TPtr root, TInputs& inputs, const THashSet<TString>&
1624
1638
return true ;
1625
1639
}
1626
1640
1627
- ctx.Expr .AddError (TIssue (ctx.Expr .GetPosition (node->Pos ()),
1628
- TStringBuilder () << " No such column: " << node->Tail ().Content ()));
1629
- isError = true ;
1630
- return false ;
1641
+ TInput* tableRefInput = nullptr ;
1642
+ if (matchedAlias) {
1643
+ tableRefInput = &inputs[*matchedAliasIndex];
1644
+ } else {
1645
+ if (matchedAliasI > 1 ) {
1646
+ ctx.Expr .AddError (TIssue (ctx.Expr .GetPosition (node->Pos ()),
1647
+ TStringBuilder () << " Table reference is ambiguous: " << node->Tail ().Content ()));
1648
+ isError = true ;
1649
+ return false ;
1650
+ }
1651
+
1652
+ if (matchedAliasI == 1 ) {
1653
+ tableRefInput = &inputs[*matchedAliasIndexI];
1654
+ }
1655
+ }
1656
+
1657
+ if (!tableRefInput) {
1658
+ ctx.Expr .AddError (TIssue (ctx.Expr .GetPosition (node->Pos ()),
1659
+ TStringBuilder () << " No such column: " << node->Tail ().Content ()));
1660
+ isError = true ;
1661
+ return false ;
1662
+ }
1663
+
1664
+ for (const auto & item : tableRefInput->Type ->GetItems ()) {
1665
+ if (!item->GetName ().StartsWith (" _yql_" )) {
1666
+ refs.insert (TString (item->GetName ()));
1667
+ if (tableRefInput->Priority == TInput::External) {
1668
+ tableRefInput->UsedExternalColumns .insert (TString (item->GetName ()));
1669
+ }
1670
+ }
1671
+ }
1672
+
1673
+ return true ;
1631
1674
}
1632
1675
}
1633
1676
@@ -1890,6 +1933,8 @@ IGraphTransformer::TStatus RebuildLambdaColumns(const TExprNode::TPtr& root, con
1890
1933
}
1891
1934
1892
1935
if (node->IsCallable (" PgColumnRef" )) {
1936
+ const TInput* matchedAliasInput = nullptr ;
1937
+ const TInput* matchedAliasInputI = nullptr ;
1893
1938
for (ui32 priority : { TInput::Projection, TInput::Current, TInput::External }) {
1894
1939
for (const auto & x : inputs) {
1895
1940
if (priority != x.Priority ) {
@@ -1902,6 +1947,14 @@ IGraphTransformer::TStatus RebuildLambdaColumns(const TExprNode::TPtr& root, con
1902
1947
}
1903
1948
}
1904
1949
1950
+ if (!x.Alias .empty ()) {
1951
+ if (node->Tail ().Content () == x.Alias ) {
1952
+ matchedAliasInput = &x;
1953
+ } else if (AsciiEqualsIgnoreCase (node->Tail ().Content (), x.Alias )) {
1954
+ matchedAliasInputI = &x;
1955
+ }
1956
+ }
1957
+
1905
1958
auto pos = x.Type ->FindItemI (node->Tail ().Content ());
1906
1959
if (pos) {
1907
1960
return ctx.Expr .Builder (node->Pos ())
@@ -1914,6 +1967,41 @@ IGraphTransformer::TStatus RebuildLambdaColumns(const TExprNode::TPtr& root, con
1914
1967
}
1915
1968
}
1916
1969
1970
+ if (!matchedAliasInput && matchedAliasInputI) {
1971
+ matchedAliasInput = matchedAliasInputI;
1972
+ }
1973
+
1974
+ if (matchedAliasInput) {
1975
+ return ctx.Expr .Builder (node->Pos ())
1976
+ .Callable (" PgToRecord" )
1977
+ .Callable (0 , " DivePrefixMembers" )
1978
+ .Add (0 , argNode)
1979
+ .List (1 )
1980
+ .Atom (0 , MakeAliasedColumn (matchedAliasInput->Alias , " " ))
1981
+ .Seal ()
1982
+ .Seal ()
1983
+ .List (1 )
1984
+ .Do ([&](TExprNodeBuilder& parent) -> TExprNodeBuilder & {
1985
+ ui32 pos = 0 ;
1986
+ for (ui32 i = 0 ; i < matchedAliasInput->Type ->GetSize (); ++i) {
1987
+ auto columnName = matchedAliasInput->Order ?
1988
+ matchedAliasInput->Order .GetRef ()[i] :
1989
+ matchedAliasInput->Type ->GetItems ()[i]->GetName ();
1990
+ if (!columnName.StartsWith (" _yql_" )) {
1991
+ parent.List (pos++)
1992
+ .Atom (0 , columnName)
1993
+ .Atom (1 , columnName)
1994
+ .Seal ();
1995
+ }
1996
+ }
1997
+
1998
+ return parent;
1999
+ })
2000
+ .Seal ()
2001
+ .Seal ()
2002
+ .Build ();
2003
+ }
2004
+
1917
2005
YQL_ENSURE (false , " Missing input" );
1918
2006
}
1919
2007
@@ -5276,5 +5364,76 @@ IGraphTransformer::TStatus PgGroupingSetWrapper(const TExprNode::TPtr& input, TE
5276
5364
return IGraphTransformer::TStatus::Ok;
5277
5365
}
5278
5366
5367
+ IGraphTransformer::TStatus PgToRecordWrapper (const TExprNode::TPtr& input, TExprNode::TPtr& output, TContext& ctx) {
5368
+ if (!EnsureArgsCount (*input, 2 , ctx.Expr )) {
5369
+ return IGraphTransformer::TStatus::Error;
5370
+ }
5371
+
5372
+ if (!EnsureStructType (input->Head (), ctx.Expr )) {
5373
+ return IGraphTransformer::TStatus::Error;
5374
+ }
5375
+
5376
+ auto structType = input->Head ().GetTypeAnn ()->Cast <TStructExprType>();
5377
+ bool hasConversions = false ;
5378
+ for (ui32 pass = 0 ; pass < 2 ; ++pass) {
5379
+ TExprNode::TListType convItems;
5380
+ for (ui32 i = 0 ; i < structType->GetSize (); ++i) {
5381
+ ui32 pgType;
5382
+ bool convertToPg;
5383
+ if (!ExtractPgType (structType->GetItems ()[i]->GetItemType (), pgType, convertToPg, input->Head ().Pos (), ctx.Expr )) {
5384
+ return IGraphTransformer::TStatus::Error;
5385
+ }
5386
+
5387
+ hasConversions = hasConversions || convertToPg;
5388
+ if (pass == 1 ) {
5389
+ auto name = ctx.Expr .NewAtom (input->Head ().Pos (), structType->GetItems ()[i]->GetName ());
5390
+ auto member = ctx.Expr .NewCallable (input->Head ().Pos (), " Member" , { input->HeadPtr (), name} );
5391
+ if (convertToPg) {
5392
+ member = ctx.Expr .NewCallable (input->Head ().Pos (), " ToPg" , { member });
5393
+ }
5394
+
5395
+ convItems.push_back (ctx.Expr .NewList (input->Head ().Pos (), { name, member }));
5396
+ }
5397
+ }
5398
+
5399
+ if (!hasConversions) {
5400
+ break ;
5401
+ }
5402
+
5403
+ if (pass == 1 ) {
5404
+ output = ctx.Expr .ChangeChild (*input, 0 , ctx.Expr .NewCallable (input->Head ().Pos (), " AsStruct" , std::move (convItems)));
5405
+ return IGraphTransformer::TStatus::Repeat;
5406
+ }
5407
+ }
5408
+
5409
+ if (!EnsureTuple (input->Tail (), ctx.Expr )) {
5410
+ return IGraphTransformer::TStatus::Error;
5411
+ }
5412
+
5413
+ for (const auto & child : input->Tail ().Children ()) {
5414
+ if (!EnsureTupleSize (*child, 2 , ctx.Expr )) {
5415
+ return IGraphTransformer::TStatus::Error;
5416
+ }
5417
+
5418
+ if (!EnsureAtom (child->Head (), ctx.Expr )) {
5419
+ return IGraphTransformer::TStatus::Error;
5420
+ }
5421
+
5422
+ if (!EnsureAtom (child->Tail (), ctx.Expr )) {
5423
+ return IGraphTransformer::TStatus::Error;
5424
+ }
5425
+
5426
+ auto pos = structType->FindItem (child->Tail ().Content ());
5427
+ if (!pos) {
5428
+ ctx.Expr .AddError (TIssue (ctx.Expr .GetPosition (child->Pos ()),
5429
+ TStringBuilder () << " Missing member: " << child->Tail ().Content ()));
5430
+ return IGraphTransformer::TStatus::Error;
5431
+ }
5432
+ }
5433
+
5434
+ input->SetTypeAnn (ctx.Expr .MakeType <TPgExprType>(NPg::LookupType (" record" ).TypeId ));
5435
+ return IGraphTransformer::TStatus::Ok;
5436
+ }
5437
+
5279
5438
} // namespace NTypeAnnImpl
5280
5439
}
0 commit comments