@@ -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
};
@@ -116,6 +116,14 @@ TExprBase BuildDqJoinInput(TExprContext& ctx, TPositionHandle pos, const TExprBa
116
116
return partition;
117
117
}
118
118
119
+ TExprNode::TPtr CreateLabelList (const THashSet<TStringBuf>& labels, const TPositionHandle& position, TExprContext& ctx) {
120
+ TExprNode::TListType newKeys;
121
+ for (const auto & label : labels) {
122
+ newKeys.push_back (ctx.NewAtom (position, label));
123
+ }
124
+ return ctx.NewList (position, std::move (newKeys));
125
+ }
126
+
119
127
TMaybe<TJoinInputDesc> BuildDqJoin (
120
128
const TCoEquiJoinTuple& joinTuple,
121
129
const THashMap<TStringBuf, TJoinInputDesc>& inputs,
@@ -129,9 +137,12 @@ TMaybe<TJoinInputDesc> BuildDqJoin(
129
137
{
130
138
TMaybe<TJoinInputDesc> left;
131
139
TVector<TString> lhsLabels;
140
+ TStringBuf leftLabel;
141
+ TStringBuf rightLabel;
132
142
if (joinTuple.LeftScope ().Maybe <TCoAtom>()) {
133
143
lhsLabels.push_back (joinTuple.LeftScope ().Cast <TCoAtom>().StringValue ());
134
144
left = inputs.at (joinTuple.LeftScope ().Cast <TCoAtom>().Value ());
145
+ leftLabel = joinTuple.LeftScope ().Cast <TCoAtom>().Value ();
135
146
YQL_ENSURE (left, " unknown scope " << joinTuple.LeftScope ().Cast <TCoAtom>().Value ());
136
147
} else {
137
148
left = BuildDqJoin (joinTuple.LeftScope ().Cast <TCoEquiJoinTuple>(), inputs, mode, ctx, typeCtx, lhsLabels, hints, useCBO);
@@ -145,6 +156,7 @@ TMaybe<TJoinInputDesc> BuildDqJoin(
145
156
if (joinTuple.RightScope ().Maybe <TCoAtom>()) {
146
157
rhsLabels.push_back (joinTuple.RightScope ().Cast <TCoAtom>().StringValue ());
147
158
right = inputs.at (joinTuple.RightScope ().Cast <TCoAtom>().Value ());
159
+ rightLabel = joinTuple.RightScope ().Cast <TCoAtom>().Value ();
148
160
YQL_ENSURE (right, " unknown scope " << joinTuple.RightScope ().Cast <TCoAtom>().Value ());
149
161
} else {
150
162
right = BuildDqJoin (joinTuple.RightScope ().Cast <TCoEquiJoinTuple>(), inputs, mode, ctx, typeCtx, rhsLabels, hints, useCBO);
@@ -187,12 +199,13 @@ TMaybe<TJoinInputDesc> BuildDqJoin(
187
199
resultKeys.insert (right->Keys .begin (), right->Keys .end ());
188
200
}
189
201
190
- auto leftTableLabel = left->IsRealTable ()
191
- ? BuildAtom (*left->Label , left->Input .Pos (), ctx).Ptr ()
192
- : Build<TCoVoid>(ctx, left->Input .Pos ()).Done ().Ptr ();
193
- auto rightTableLabel = right->IsRealTable ()
194
- ? BuildAtom (*right->Label , right->Input .Pos (), ctx).Ptr ()
195
- : Build<TCoVoid>(ctx, right->Input .Pos ()).Done ().Ptr ();
202
+ auto leftTableLabel = left->IsRealTable () ? (left->Labels ->size () > 1 ? CreateLabelList (*(left->Labels ), left->Input .Pos (), ctx)
203
+ : BuildAtom (leftLabel, left->Input .Pos (), ctx).Ptr ())
204
+ : Build<TCoVoid>(ctx, left->Input .Pos ()).Done ().Ptr ();
205
+
206
+ auto rightTableLabel = right->IsRealTable () ? (right->Labels ->size () > 1 ? CreateLabelList (*(right->Labels ), right->Input .Pos (), ctx)
207
+ : BuildAtom (rightLabel, right->Input .Pos (), ctx).Ptr ())
208
+ : Build<TCoVoid>(ctx, right->Input .Pos ()).Done ().Ptr ();
196
209
197
210
size_t joinKeysCount = joinTuple.LeftKeys ().Size () / 2 ;
198
211
TVector<TCoAtom> leftJoinKeys;
@@ -353,21 +366,37 @@ TMaybe<TJoinInputDesc> BuildDqJoin(
353
366
}
354
367
355
368
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 {};
369
+ THashSet<TStringBuf> labels;
370
+ if (input.Scope ().Maybe <TCoAtom>()) {
371
+ labels.insert (input.Scope ().Cast <TCoAtom>().Value ());
372
+ } else {
373
+ auto list = input.Scope ().Cast <TCoAtomList>();
374
+ for (auto atomLabel : list) {
375
+ labels.insert (atomLabel.Value ());
376
+ }
359
377
}
360
- auto scope = input.Scope ().Cast <TCoAtom>().Value ();
361
378
362
379
auto listType = input.List ().Ref ().GetTypeAnn ()->Cast <TListExprType>();
363
380
auto resultStructType = listType->GetItemType ()->Cast <TStructExprType>();
364
381
365
382
TSet<std::pair<TStringBuf, TStringBuf>> keys;
366
383
for (auto member : resultStructType->GetItems ()) {
367
- keys.emplace (scope, member->GetName ());
384
+ if (input.Scope ().Maybe <TCoAtom>()) {
385
+ keys.emplace (input.Scope ().Cast <TCoAtom>().Value (), member->GetName ());
386
+ } else {
387
+ auto fullMemberName = member->GetName ();
388
+ if (fullMemberName.find (" ." ) != TString::npos) {
389
+ TStringBuf table;
390
+ TStringBuf column;
391
+ SplitTableName (fullMemberName, table, column);
392
+ keys.emplace (table, column);
393
+ } else {
394
+ return {};
395
+ }
396
+ }
368
397
}
369
398
370
- return TJoinInputDesc (scope , input.List (), std::move (keys));
399
+ return TJoinInputDesc (labels , input.List (), std::move (keys));
371
400
}
372
401
373
402
TStringBuf RotateRightJoinType (TStringBuf joinType) {
@@ -396,13 +425,13 @@ std::pair<TVector<TCoAtom>, TVector<TCoAtom>> GetJoinKeys(const TDqJoin& join, T
396
425
auto rightLabel = keyTuple.RightLabel ().Value ();
397
426
398
427
auto leftKey = Build<TCoAtom>(ctx, join.Pos ())
399
- .Value (join.LeftLabel ().Maybe <TCoAtom>() || keyTuple.LeftColumn ().Value ().starts_with (" _yql_dq_key_left_" )
428
+ .Value (( join.LeftLabel ().Maybe <TCoAtom>() || keyTuple.LeftColumn ().Value ().starts_with (" _yql_dq_key_left_" )) && !join. LeftLabel (). Maybe <TCoAtomList>( )
400
429
? keyTuple.LeftColumn ().StringValue ()
401
430
: FullColumnName (leftLabel, keyTuple.LeftColumn ().Value ()))
402
431
.Done ();
403
432
404
433
auto rightKey = Build<TCoAtom>(ctx, join.Pos ())
405
- .Value (join.RightLabel ().Maybe <TCoAtom>() || keyTuple.RightColumn ().Value ().starts_with (" _yql_dq_key_right_" )
434
+ .Value (( join.RightLabel ().Maybe <TCoAtom>() || keyTuple.RightColumn ().Value ().starts_with (" _yql_dq_key_right_" )) && !join. RightLabel (). Maybe <TCoAtomList>( )
406
435
? keyTuple.RightColumn ().StringValue ()
407
436
: FullColumnName (rightLabel, keyTuple.RightColumn ().Value ()))
408
437
.Done ();
@@ -414,7 +443,6 @@ std::pair<TVector<TCoAtom>, TVector<TCoAtom>> GetJoinKeys(const TDqJoin& join, T
414
443
return std::make_pair (std::move (leftJoinKeys), std::move (rightJoinKeys));
415
444
}
416
445
417
-
418
446
TDqJoinBase DqMakePhyMapJoin (const TDqJoin& join, const TExprBase& leftInput, const TExprBase& rightInput,
419
447
TExprContext& ctx, bool useGraceCore)
420
448
{
@@ -521,7 +549,9 @@ TExprBase DqRewriteEquiJoin(
521
549
THashMap<TStringBuf, TJoinInputDesc> inputs;
522
550
for (size_t i = 0 ; i < equiJoin.ArgCount () - 2 ; ++i) {
523
551
if (auto input = PrepareJoinInput (equiJoin.Arg (i).Cast <TCoEquiJoinInput>())) {
524
- inputs.emplace (*input->Label , std::move (*input));
552
+ for (auto label : *(input->Labels )) {
553
+ inputs.emplace (label, *input);
554
+ }
525
555
} else {
526
556
return node;
527
557
}
0 commit comments