@@ -111,20 +111,32 @@ object V2ScanRelationPushDown extends Rule[LogicalPlan] with PredicateHelper {
111
111
def pushDownJoin (plan : LogicalPlan ): LogicalPlan = plan.transformUp {
112
112
// Join can be attempted to be pushed down only if left and right side of join are
113
113
// compatible (same data source, for example). Also, another requirement is that if
114
- // there are projections between Join and ScanBuilderHolder, these projec
114
+ // there are projections between Join and ScanBuilderHolder, these projections need to be
115
+ // AttributeReferences. We could probably support Alias as well, but this should be on
116
+ // TODO list.
117
+ // Alias can exist between Join and sHolder node because the query below is not valid:
118
+ // SELECT * FROM
119
+ // (SELECT * FROM tbl t1 JOIN tbl2 t2) p
120
+ // JOIN
121
+ // (SELECT * FROM tbl t3 JOIN tbl3 t4) q
122
+ // ON p.t1.col = q.t3.col (this is not possible)
123
+ // It's because there are 2 same tables in both sides of top level join and it not possible
124
+ // to fully qualified the column names in condition. Therefore, query should be rewritten so
125
+ // that each of the outputs of child joins are aliased, so there would be a projection
126
+ // with aliases between top level join and scanBuilderHolder (that has pushed child joins).
115
127
case node @ Join (
116
- PhysicalOperation (
117
- leftProjections,
118
- Nil ,
119
- leftHolder @ ScanBuilderHolder (_, _, lBuilder : SupportsPushDownJoin )
120
- ),
121
- PhysicalOperation (
122
- rightProjections,
123
- Nil ,
124
- rightHolder @ ScanBuilderHolder (_, _, rBuilder : SupportsPushDownJoin )
125
- ),
126
- joinType,
127
- condition,
128
+ PhysicalOperation (
129
+ leftProjections,
130
+ Nil ,
131
+ leftHolder @ ScanBuilderHolder (_, _, lBuilder : SupportsPushDownJoin )
132
+ ),
133
+ PhysicalOperation (
134
+ rightProjections,
135
+ Nil ,
136
+ rightHolder @ ScanBuilderHolder (_, _, rBuilder : SupportsPushDownJoin )
137
+ ),
138
+ joinType,
139
+ condition,
128
140
_) if conf.dataSourceV2JoinPushdown &&
129
141
// TODO: I think projections will always be Seq[AttributeReference] because
130
142
// When
@@ -184,7 +196,6 @@ object V2ScanRelationPushDown extends Rule[LogicalPlan] with PredicateHelper {
184
196
185
197
leftHolder.exprIdToOriginalName ++= rightHolder.exprIdToOriginalName
186
198
leftHolder.output = newOutput
187
- leftHolder.isJoinPushed = true
188
199
leftHolder
189
200
} else {
190
201
node
@@ -206,15 +217,15 @@ object V2ScanRelationPushDown extends Rule[LogicalPlan] with PredicateHelper {
206
217
207
218
val aggExprToOutputOrdinal = mutable.HashMap .empty[Expression , Int ]
208
219
val aggregates = collectAggregates(actualResultExprs, aggExprToOutputOrdinal)
209
- val normalizedAggExprs = if (holder.isJoinPushed ) {
220
+ val normalizedAggExprs = if (holder.joinedRelations.nonEmpty ) {
210
221
DataSourceStrategy .normalizeExprs(aggregates, holder.output)
211
222
.asInstanceOf [Seq [AggregateExpression ]]
212
223
} else {
213
224
DataSourceStrategy .normalizeExprs(aggregates, holder.relation.output)
214
225
.asInstanceOf [Seq [AggregateExpression ]]
215
226
}
216
227
val normalizedGroupingExpr =
217
- if (holder.isJoinPushed ) {
228
+ if (holder.joinedRelations.nonEmpty ) {
218
229
DataSourceStrategy .normalizeExprs(actualGroupExprs, holder.output)
219
230
} else {
220
231
DataSourceStrategy .normalizeExprs(actualGroupExprs, holder.relation.output)
@@ -459,7 +470,7 @@ object V2ScanRelationPushDown extends Rule[LogicalPlan] with PredicateHelper {
459
470
}
460
471
461
472
def buildScanWithPushedJoin (plan : LogicalPlan ): LogicalPlan = plan.transform {
462
- case holder : ScanBuilderHolder if holder.isJoinPushed && ! holder.isStreaming =>
473
+ case holder : ScanBuilderHolder if holder.joinedRelations.nonEmpty && ! holder.isStreaming =>
463
474
val scan = holder.builder.build()
464
475
val realOutput = toAttributes(scan.readSchema())
465
476
assert(realOutput.length == holder.output.length,
@@ -563,7 +574,7 @@ object V2ScanRelationPushDown extends Rule[LogicalPlan] with PredicateHelper {
563
574
} else {
564
575
aliasReplacedOrder.asInstanceOf [Seq [SortOrder ]]
565
576
}
566
- val normalizedOrders = if (sHolder.isJoinPushed ) {
577
+ val normalizedOrders = if (sHolder.joinedRelations.nonEmpty ) {
567
578
DataSourceStrategy .normalizeExprs(
568
579
newOrder, sHolder.output).asInstanceOf [Seq [SortOrder ]]
569
580
} else {
@@ -704,8 +715,6 @@ case class ScanBuilderHolder(
704
715
705
716
var joinedRelations : Seq [DataSourceV2RelationBase ] = Seq ()
706
717
707
- var isJoinPushed : Boolean = false
708
-
709
718
var exprIdToOriginalName : scala.collection.mutable.Map [ExprId , String ] =
710
719
scala.collection.mutable.Map .empty[ExprId , String ]
711
720
}
0 commit comments