@@ -181,6 +181,99 @@ func (p *LogicalJoin) Shallow() *LogicalJoin {
181
181
return join .Init (p .ctx , p .blockOffset )
182
182
}
183
183
184
+ // ExtractFD implements the interface LogicalPlan.
185
+ func (p * LogicalJoin ) ExtractFD () * fd.FDSet {
186
+ switch p .JoinType {
187
+ case InnerJoin :
188
+ return p .extractFDForInnerJoin ()
189
+ case LeftOuterJoin , RightOuterJoin :
190
+ return p .extractFDForOuterJoin ()
191
+ case SemiJoin :
192
+ return p .extractFDForSemiJoin ()
193
+ default :
194
+ return & fd.FDSet {HashCodeToUniqueID : make (map [string ]int )}
195
+ }
196
+ }
197
+
198
+ func (p * LogicalJoin ) extractFDForSemiJoin () * fd.FDSet {
199
+ // 1: since semi join will keep the part or all rows of the outer table, it's outer FD can be saved.
200
+ // 2: the un-projected column will be left for the upper layer projection or already be pruned from bottom up.
201
+ outerFD , _ := p .children [0 ].ExtractFD (), p .children [1 ].ExtractFD ()
202
+ fds := outerFD
203
+
204
+ eqCondSlice := expression .ScalarFuncs2Exprs (p .EqualConditions )
205
+ allConds := append (eqCondSlice , p .OtherConditions ... )
206
+ notNullColsFromFilters := extractNotNullFromConds (allConds , p )
207
+
208
+ constUniqueIDs := extractConstantCols (p .LeftConditions , p .SCtx (), fds )
209
+
210
+ fds .MakeNotNull (notNullColsFromFilters )
211
+ fds .AddConstants (constUniqueIDs )
212
+ p .fdSet = fds
213
+ return fds
214
+ }
215
+
216
+ func (p * LogicalJoin ) extractFDForInnerJoin () * fd.FDSet {
217
+ leftFD , rightFD := p .children [0 ].ExtractFD (), p .children [1 ].ExtractFD ()
218
+ fds := leftFD
219
+ fds .MakeCartesianProduct (rightFD )
220
+
221
+ eqCondSlice := expression .ScalarFuncs2Exprs (p .EqualConditions )
222
+ allConds := append (eqCondSlice , p .OtherConditions ... )
223
+ notNullColsFromFilters := extractNotNullFromConds (allConds , p )
224
+
225
+ constUniqueIDs := extractConstantCols (eqCondSlice , p .SCtx (), fds )
226
+
227
+ equivUniqueIDs := extractEquivalenceCols (eqCondSlice , p .SCtx (), fds )
228
+
229
+ fds .MakeNotNull (notNullColsFromFilters )
230
+ fds .AddConstants (constUniqueIDs )
231
+ for _ , equiv := range equivUniqueIDs {
232
+ fds .AddEquivalence (equiv [0 ], equiv [1 ])
233
+ }
234
+ p .fdSet = fds
235
+ return fds
236
+ }
237
+
238
+ func (p * LogicalJoin ) extractFDForOuterJoin () * fd.FDSet {
239
+ outerFD , innerFD := p .children [0 ].ExtractFD (), p .children [1 ].ExtractFD ()
240
+ innerCondition := p .RightConditions
241
+ outerCols , innerCols := fd .NewFastIntSet (), fd .NewFastIntSet ()
242
+ for _ , col := range p .children [0 ].Schema ().Columns {
243
+ outerCols .Insert (int (col .UniqueID ))
244
+ }
245
+ for _ , col := range p .children [1 ].Schema ().Columns {
246
+ innerCols .Insert (int (col .UniqueID ))
247
+ }
248
+ if p .JoinType == RightOuterJoin {
249
+ innerFD , outerFD = outerFD , innerFD
250
+ innerCondition = p .LeftConditions
251
+ innerCols , outerCols = outerCols , innerCols
252
+ }
253
+
254
+ eqCondSlice := expression .ScalarFuncs2Exprs (p .EqualConditions )
255
+ allConds := append (eqCondSlice , p .OtherConditions ... )
256
+ allConds = append (allConds , innerCondition ... )
257
+ notNullColsFromFilters := extractNotNullFromConds (allConds , p )
258
+
259
+ filterFD := & fd.FDSet {HashCodeToUniqueID : make (map [string ]int )}
260
+
261
+ constUniqueIDs := extractConstantCols (eqCondSlice , p .SCtx (), filterFD )
262
+
263
+ equivUniqueIDs := extractEquivalenceCols (eqCondSlice , p .SCtx (), filterFD )
264
+
265
+ filterFD .AddConstants (constUniqueIDs )
266
+ for _ , equiv := range equivUniqueIDs {
267
+ filterFD .AddEquivalence (equiv [0 ], equiv [1 ])
268
+ }
269
+ filterFD .MakeNotNull (notNullColsFromFilters )
270
+
271
+ fds := outerFD
272
+ fds .MakeOuterJoin (innerFD , filterFD , outerCols , innerCols )
273
+ p .fdSet = fds
274
+ return fds
275
+ }
276
+
184
277
// GetJoinKeys extracts join keys(columns) from EqualConditions. It returns left join keys, right
185
278
// join keys and an `isNullEQ` array which means the `joinKey[i]` is a `NullEQ` function. The `hasNullEQ`
186
279
// means whether there is a `NullEQ` of a join key.
@@ -657,34 +750,34 @@ func extractNotNullFromConds(Conditions []expression.Expression, p LogicalPlan)
657
750
return notnullColsUniqueIDs
658
751
}
659
752
660
- func extractConstantCols (Conditions []expression.Expression , p LogicalPlan , fds * fd.FDSet ) fd.FastIntSet {
753
+ func extractConstantCols (Conditions []expression.Expression , sctx sessionctx. Context , fds * fd.FDSet ) fd.FastIntSet {
661
754
// extract constant cols
662
755
// eg: where a=1 and b is null and (1+c)=5.
663
756
// TODO: Some columns can only be determined to be constant from multiple constraints (e.g. x <= 1 AND x >= 1)
664
757
var (
665
758
constObjs []expression.Expression
666
759
constUniqueIDs = fd .NewFastIntSet ()
667
760
)
668
- constObjs = expression .ExtractConstantEqColumnsOrScalar (p . SCtx () , constObjs , Conditions )
761
+ constObjs = expression .ExtractConstantEqColumnsOrScalar (sctx , constObjs , Conditions )
669
762
for _ , constObj := range constObjs {
670
763
switch x := constObj .(type ) {
671
764
case * expression.Column :
672
765
constUniqueIDs .Insert (int (x .UniqueID ))
673
766
case * expression.ScalarFunction :
674
- hashCode := string (x .HashCode (p . SCtx () .GetSessionVars ().StmtCtx ))
767
+ hashCode := string (x .HashCode (sctx .GetSessionVars ().StmtCtx ))
675
768
if uniqueID , ok := fds .IsHashCodeRegistered (hashCode ); ok {
676
769
constUniqueIDs .Insert (uniqueID )
677
770
} else {
678
- scalarUniqueID := int (p . SCtx () .GetSessionVars ().AllocPlanColumnID ())
679
- fds .RegisterUniqueID (string (x .HashCode (p . SCtx () .GetSessionVars ().StmtCtx )), scalarUniqueID )
771
+ scalarUniqueID := int (sctx .GetSessionVars ().AllocPlanColumnID ())
772
+ fds .RegisterUniqueID (string (x .HashCode (sctx .GetSessionVars ().StmtCtx )), scalarUniqueID )
680
773
constUniqueIDs .Insert (scalarUniqueID )
681
774
}
682
775
}
683
776
}
684
777
return constUniqueIDs
685
778
}
686
779
687
- func extractEquivalenceCols (Conditions []expression.Expression , p LogicalPlan , fds * fd.FDSet ) [][]fd.FastIntSet {
780
+ func extractEquivalenceCols (Conditions []expression.Expression , sctx sessionctx. Context , fds * fd.FDSet ) [][]fd.FastIntSet {
688
781
var equivObjsPair [][]expression.Expression
689
782
equivObjsPair = expression .ExtractEquivalenceColumns (equivObjsPair , Conditions )
690
783
equivUniqueIDs := make ([][]fd.FastIntSet , 0 , len (equivObjsPair ))
@@ -698,12 +791,12 @@ func extractEquivalenceCols(Conditions []expression.Expression, p LogicalPlan, f
698
791
case * expression.Column :
699
792
lhsUniqueID = int (x .UniqueID )
700
793
case * expression.ScalarFunction :
701
- hashCode := string (x .HashCode (p . SCtx () .GetSessionVars ().StmtCtx ))
794
+ hashCode := string (x .HashCode (sctx .GetSessionVars ().StmtCtx ))
702
795
if uniqueID , ok := fds .IsHashCodeRegistered (hashCode ); ok {
703
796
lhsUniqueID = uniqueID
704
797
} else {
705
- scalarUniqueID := int (p . SCtx () .GetSessionVars ().AllocPlanColumnID ())
706
- fds .RegisterUniqueID (string (x .HashCode (p . SCtx () .GetSessionVars ().StmtCtx )), scalarUniqueID )
798
+ scalarUniqueID := int (sctx .GetSessionVars ().AllocPlanColumnID ())
799
+ fds .RegisterUniqueID (string (x .HashCode (sctx .GetSessionVars ().StmtCtx )), scalarUniqueID )
707
800
lhsUniqueID = scalarUniqueID
708
801
}
709
802
}
@@ -712,12 +805,12 @@ func extractEquivalenceCols(Conditions []expression.Expression, p LogicalPlan, f
712
805
case * expression.Column :
713
806
rhsUniqueID = int (x .UniqueID )
714
807
case * expression.ScalarFunction :
715
- hashCode := string (x .HashCode (p . SCtx () .GetSessionVars ().StmtCtx ))
808
+ hashCode := string (x .HashCode (sctx .GetSessionVars ().StmtCtx ))
716
809
if uniqueID , ok := fds .IsHashCodeRegistered (hashCode ); ok {
717
810
rhsUniqueID = uniqueID
718
811
} else {
719
- scalarUniqueID := int (p . SCtx () .GetSessionVars ().AllocPlanColumnID ())
720
- fds .RegisterUniqueID (string (x .HashCode (p . SCtx () .GetSessionVars ().StmtCtx )), scalarUniqueID )
812
+ scalarUniqueID := int (sctx .GetSessionVars ().AllocPlanColumnID ())
813
+ fds .RegisterUniqueID (string (x .HashCode (sctx .GetSessionVars ().StmtCtx )), scalarUniqueID )
721
814
rhsUniqueID = scalarUniqueID
722
815
}
723
816
}
@@ -743,10 +836,10 @@ func (p *LogicalSelection) ExtractFD() *fd.FDSet {
743
836
notnullColsUniqueIDs .UnionWith (extractNotNullFromConds (p .Conditions , p ))
744
837
745
838
// extract the constant cols from selection conditions.
746
- constUniqueIDs := extractConstantCols (p .Conditions , p , fds )
839
+ constUniqueIDs := extractConstantCols (p .Conditions , p . SCtx () , fds )
747
840
748
841
// extract equivalence cols.
749
- equivUniqueIDs := extractEquivalenceCols (p .Conditions , p , fds )
842
+ equivUniqueIDs := extractEquivalenceCols (p .Conditions , p . SCtx () , fds )
750
843
751
844
// apply operator's characteristic's FD setting.
752
845
fds .MakeNotNull (notnullColsUniqueIDs )
0 commit comments