@@ -15,17 +15,17 @@ using namespace NYql::NNodes;
15
15
namespace {
16
16
17
17
struct TJoinInputDesc {
18
- TJoinInputDesc (TMaybe<TStringBuf> label , const TExprBase& input,
18
+ TJoinInputDesc (TMaybe<THashSet< TStringBuf>> labels , const TExprBase& input,
19
19
TSet<std::pair<TStringBuf, TStringBuf>>&& keys)
20
- : Label(label )
20
+ : Labels(labels )
21
21
, Input(input)
22
22
, Keys(std::move(keys)) {}
23
23
24
24
bool IsRealTable () const {
25
- return Label .Defined ();
25
+ return Labels .Defined ();
26
26
}
27
27
28
- TMaybe<TStringBuf> Label ; // defined for real table input only, empty otherwise
28
+ TMaybe<THashSet< TStringBuf>> Labels ; // defined for real table input only, empty otherwise
29
29
TExprBase Input;
30
30
TSet<std::pair<TStringBuf, TStringBuf>> Keys; // set of (label, column_name) pairs in this input
31
31
};
@@ -129,9 +129,12 @@ TMaybe<TJoinInputDesc> BuildDqJoin(
129
129
{
130
130
TMaybe<TJoinInputDesc> left;
131
131
TVector<TString> lhsLabels;
132
+ TStringBuf leftLabel;
133
+ TStringBuf rightLabel;
132
134
if (joinTuple.LeftScope ().Maybe <TCoAtom>()) {
133
135
lhsLabels.push_back (joinTuple.LeftScope ().Cast <TCoAtom>().StringValue ());
134
136
left = inputs.at (joinTuple.LeftScope ().Cast <TCoAtom>().Value ());
137
+ leftLabel = joinTuple.LeftScope ().Cast <TCoAtom>().Value ();
135
138
YQL_ENSURE (left, " unknown scope " << joinTuple.LeftScope ().Cast <TCoAtom>().Value ());
136
139
} else {
137
140
left = BuildDqJoin (joinTuple.LeftScope ().Cast <TCoEquiJoinTuple>(), inputs, mode, ctx, typeCtx, lhsLabels, hints, useCBO);
@@ -145,6 +148,7 @@ TMaybe<TJoinInputDesc> BuildDqJoin(
145
148
if (joinTuple.RightScope ().Maybe <TCoAtom>()) {
146
149
rhsLabels.push_back (joinTuple.RightScope ().Cast <TCoAtom>().StringValue ());
147
150
right = inputs.at (joinTuple.RightScope ().Cast <TCoAtom>().Value ());
151
+ rightLabel = joinTuple.RightScope ().Cast <TCoAtom>().Value ();
148
152
YQL_ENSURE (right, " unknown scope " << joinTuple.RightScope ().Cast <TCoAtom>().Value ());
149
153
} else {
150
154
right = BuildDqJoin (joinTuple.RightScope ().Cast <TCoEquiJoinTuple>(), inputs, mode, ctx, typeCtx, rhsLabels, hints, useCBO);
@@ -188,10 +192,10 @@ TMaybe<TJoinInputDesc> BuildDqJoin(
188
192
}
189
193
190
194
auto leftTableLabel = left->IsRealTable ()
191
- ? BuildAtom (*left-> Label , left->Input .Pos (), ctx).Ptr ()
195
+ ? BuildAtom (leftLabel , left->Input .Pos (), ctx).Ptr ()
192
196
: Build<TCoVoid>(ctx, left->Input .Pos ()).Done ().Ptr ();
193
197
auto rightTableLabel = right->IsRealTable ()
194
- ? BuildAtom (*right-> Label , right->Input .Pos (), ctx).Ptr ()
198
+ ? BuildAtom (rightLabel , right->Input .Pos (), ctx).Ptr ()
195
199
: Build<TCoVoid>(ctx, right->Input .Pos ()).Done ().Ptr ();
196
200
197
201
size_t joinKeysCount = joinTuple.LeftKeys ().Size () / 2 ;
@@ -353,21 +357,37 @@ TMaybe<TJoinInputDesc> BuildDqJoin(
353
357
}
354
358
355
359
TMaybe<TJoinInputDesc> PrepareJoinInput (const TCoEquiJoinInput& input) {
356
- if (!input.Scope ().Maybe <TCoAtom>()) {
357
- YQL_CLOG (TRACE, CoreDq) << " EquiJoin input scope is not an Atom: " << input.Scope ().Ref ().Content ();
358
- return {};
360
+ THashSet<TStringBuf> labels;
361
+ if (input.Scope ().Maybe <TCoAtom>()) {
362
+ labels.insert (input.Scope ().Cast <TCoAtom>().Value ());
363
+ } else {
364
+ auto list = input.Scope ().Cast <TCoAtomList>();
365
+ for (auto atomLabel : list) {
366
+ labels.insert (atomLabel.Value ());
367
+ }
359
368
}
360
- auto scope = input.Scope ().Cast <TCoAtom>().Value ();
361
369
362
370
auto listType = input.List ().Ref ().GetTypeAnn ()->Cast <TListExprType>();
363
371
auto resultStructType = listType->GetItemType ()->Cast <TStructExprType>();
364
372
365
373
TSet<std::pair<TStringBuf, TStringBuf>> keys;
366
374
for (auto member : resultStructType->GetItems ()) {
367
- keys.emplace (scope, member->GetName ());
375
+ if (input.Scope ().Maybe <TCoAtom>()) {
376
+ keys.emplace (input.Scope ().Cast <TCoAtom>().Value (), member->GetName ());
377
+ } else {
378
+ auto fullMemberName = member->GetName ();
379
+ if (fullMemberName.find (" ." ) != TString::npos) {
380
+ TStringBuf table;
381
+ TStringBuf column;
382
+ SplitTableName (fullMemberName, table, column);
383
+ keys.emplace (table, column);
384
+ } else {
385
+ return {};
386
+ }
387
+ }
368
388
}
369
389
370
- return TJoinInputDesc (scope , input.List (), std::move (keys));
390
+ return TJoinInputDesc (labels , input.List (), std::move (keys));
371
391
}
372
392
373
393
TStringBuf RotateRightJoinType (TStringBuf joinType) {
@@ -383,6 +403,14 @@ TStringBuf RotateRightJoinType(TStringBuf joinType) {
383
403
YQL_ENSURE (false , " unexpected right join type " << joinType);
384
404
}
385
405
406
+ bool IsMultiLabelInput (TExprNode::TPtr input) {
407
+ auto * itemType = input->GetTypeAnn ()->Cast <TListExprType>()->GetItemType ();
408
+ if (itemType->Cast <TStructExprType>()->GetItems ().size ()) {
409
+ return TString (itemType->Cast <TStructExprType>()->GetItems ().front ()->GetName ()).find (" ." ) != TString::npos;
410
+ }
411
+ return false ;
412
+ }
413
+
386
414
std::pair<TVector<TCoAtom>, TVector<TCoAtom>> GetJoinKeys (const TDqJoin& join, TExprContext& ctx) {
387
415
TVector<TCoAtom> leftJoinKeys;
388
416
TVector<TCoAtom> rightJoinKeys;
@@ -394,15 +422,17 @@ std::pair<TVector<TCoAtom>, TVector<TCoAtom>> GetJoinKeys(const TDqJoin& join, T
394
422
for (const auto & keyTuple : join.JoinKeys ()) {
395
423
auto leftLabel = keyTuple.LeftLabel ().Value ();
396
424
auto rightLabel = keyTuple.RightLabel ().Value ();
425
+ bool leftMultiLabel = IsMultiLabelInput (join.LeftInput ().Ptr ());
426
+ bool rightMultiLabel = IsMultiLabelInput (join.RightInput ().Ptr ());
397
427
398
428
auto leftKey = Build<TCoAtom>(ctx, join.Pos ())
399
- .Value (join.LeftLabel ().Maybe <TCoAtom>() || keyTuple.LeftColumn ().Value ().starts_with (" _yql_dq_key_left_" )
429
+ .Value (( join.LeftLabel ().Maybe <TCoAtom>() || keyTuple.LeftColumn ().Value ().starts_with (" _yql_dq_key_left_" )) && !leftMultiLabel
400
430
? keyTuple.LeftColumn ().StringValue ()
401
431
: FullColumnName (leftLabel, keyTuple.LeftColumn ().Value ()))
402
432
.Done ();
403
433
404
434
auto rightKey = Build<TCoAtom>(ctx, join.Pos ())
405
- .Value (join.RightLabel ().Maybe <TCoAtom>() || keyTuple.RightColumn ().Value ().starts_with (" _yql_dq_key_right_" )
435
+ .Value (( join.RightLabel ().Maybe <TCoAtom>() || keyTuple.RightColumn ().Value ().starts_with (" _yql_dq_key_right_" )) && !rightMultiLabel
406
436
? keyTuple.RightColumn ().StringValue ()
407
437
: FullColumnName (rightLabel, keyTuple.RightColumn ().Value ()))
408
438
.Done ();
@@ -414,7 +444,6 @@ std::pair<TVector<TCoAtom>, TVector<TCoAtom>> GetJoinKeys(const TDqJoin& join, T
414
444
return std::make_pair (std::move (leftJoinKeys), std::move (rightJoinKeys));
415
445
}
416
446
417
-
418
447
TDqJoinBase DqMakePhyMapJoin (const TDqJoin& join, const TExprBase& leftInput, const TExprBase& rightInput,
419
448
TExprContext& ctx, bool useGraceCore)
420
449
{
@@ -521,7 +550,9 @@ TExprBase DqRewriteEquiJoin(
521
550
THashMap<TStringBuf, TJoinInputDesc> inputs;
522
551
for (size_t i = 0 ; i < equiJoin.ArgCount () - 2 ; ++i) {
523
552
if (auto input = PrepareJoinInput (equiJoin.Arg (i).Cast <TCoEquiJoinInput>())) {
524
- inputs.emplace (*input->Label , std::move (*input));
553
+ for (auto label : *(input->Labels )) {
554
+ inputs.emplace (label, *input);
555
+ }
525
556
} else {
526
557
return node;
527
558
}
0 commit comments