Skip to content

Commit 660c384

Browse files
committed
added AntiJoinIncludingNulls join type
1 parent 6b61b7d commit 660c384

File tree

5 files changed

+73
-47
lines changed

5 files changed

+73
-47
lines changed

sql/analyzer/indexed_joins.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,11 @@ func convertAntiToLeftJoin(m *memo.Memo) error {
561561
rightGrp := m.MemoizeProject(nil, anti.Right, projectExpressions)
562562

563563
// join is a new group
564-
joinGrp := m.MemoizeLeftJoin(nil, anti.Left, rightGrp, plan.JoinTypeLeftOuterExcludeNulls, anti.Filter)
564+
joinType := plan.JoinTypeLeftOuter
565+
if anti.Op.IsExcludeNulls() {
566+
joinType = plan.JoinTypeLeftOuterExcludeNulls
567+
}
568+
joinGrp := m.MemoizeLeftJoin(nil, anti.Left, rightGrp, joinType, anti.Filter)
565569

566570
// drop null projected columns on right table
567571
nullFilters := make([]sql.Expression, len(nullify))

sql/analyzer/unnest_exists_subqueries.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ func unnestExistSubqueries(ctx *sql.Context, scope *plan.Scope, a *Analyzer, fil
190190
switch joinType {
191191
case plan.JoinTypeAnti:
192192
cond := expression.NewLiteral(true, types.Boolean)
193-
ret = plan.NewAntiJoin(ret, s.inner, cond).WithComment(comment)
193+
ret = plan.NewAntiJoinIncludingNulls(ret, s.inner, cond).WithComment(comment)
194194
qFlags.Set(sql.QFlagInnerJoin)
195195
case plan.JoinTypeSemi:
196196
ret = plan.NewCrossJoin(ret, s.inner).WithComment(comment)
@@ -209,7 +209,7 @@ func unnestExistSubqueries(ctx *sql.Context, scope *plan.Scope, a *Analyzer, fil
209209

210210
switch joinType {
211211
case plan.JoinTypeAnti:
212-
ret = plan.NewAntiJoin(ret, s.inner, expression.JoinAnd(outerFilters...)).WithComment(comment)
212+
ret = plan.NewAntiJoinIncludingNulls(ret, s.inner, expression.JoinAnd(outerFilters...)).WithComment(comment)
213213
qFlags.Set(sql.QFlagInnerJoin)
214214
case plan.JoinTypeSemi:
215215
ret = plan.NewSemiJoin(ret, s.inner, expression.JoinAnd(outerFilters...)).WithComment(comment)

sql/memo/join_order_builder.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,7 @@ func (j *joinOrderBuilder) constructJoin(
811811
rel = &LeftJoin{b}
812812
case plan.JoinTypeSemi:
813813
rel = &SemiJoin{b}
814-
case plan.JoinTypeAnti:
814+
case plan.JoinTypeAnti, plan.JoinTypeAntiIncludeNulls:
815815
rel = &AntiJoin{b}
816816
case plan.JoinTypeLateralInner, plan.JoinTypeLateralCross,
817817
plan.JoinTypeLateralRight, plan.JoinTypeLateralLeft:
@@ -1428,7 +1428,7 @@ func getOpIdx(e *edge) int {
14281428
return 1
14291429
case plan.JoinTypeSemi:
14301430
return 2
1431-
case plan.JoinTypeAnti:
1431+
case plan.JoinTypeAnti, plan.JoinTypeAntiIncludeNulls:
14321432
return 3
14331433
case plan.JoinTypeLeftOuter:
14341434
return 4

sql/plan/join.go

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const (
3333
JoinTypeInner // InnerJoin
3434
JoinTypeSemi // SemiJoin
3535
JoinTypeAnti // AntiJoin
36+
JoinTypeAntiIncludeNulls // AntiJoinIncludingNulls
3637
JoinTypeLeftOuter // LeftOuterJoin
3738
JoinTypeLeftOuterExcludeNulls // LeftOuterJoinExcludingNulls
3839
JoinTypeFullOuter // FullOuterJoin
@@ -49,10 +50,13 @@ const (
4950
JoinTypeLeftOuterRangeHeap // LeftOuterRangeHeapJoin
5051
JoinTypeSemiHash // SemiHashJoin
5152
JoinTypeAntiHash // AntiHashJoin
53+
JoinTypeAntiHashIncludeNulls // AntiHashJoinIncludeNulls
5254
JoinTypeSemiLookup // SemiLookupJoin
5355
JoinTypeAntiLookup // AntiLookupJoin
56+
JoinTypeAntiLookupIncludeNulls // AntiLookupIncludeNulls
5457
JoinTypeSemiMerge // SemiMergeJoin
5558
JoinTypeAntiMerge // AntiMergeJoin
59+
JoinTypeAntiMergeIncludeNulls // AntiMergeIncludeNulls
5660
JoinTypeUsing // NaturalJoin
5761
JoinTypeUsingLeft // NaturalLeftJoin
5862
JoinTypeUsingRight // NaturalRightJoin
@@ -98,7 +102,10 @@ func (i JoinType) IsPhysical() bool {
98102
JoinTypeSemiLookup, JoinTypeSemiMerge, JoinTypeSemiHash,
99103
JoinTypeHash, JoinTypeLeftOuterHash, JoinTypeLeftOuterHashExcludeNulls,
100104
JoinTypeMerge, JoinTypeLeftOuterMerge,
101-
JoinTypeAntiLookup, JoinTypeAntiMerge, JoinTypeAntiHash, JoinTypeRangeHeap, JoinTypeLeftOuterRangeHeap:
105+
JoinTypeAntiLookup, JoinTypeAntiLookupIncludeNulls,
106+
JoinTypeAntiMerge, JoinTypeAntiMergeIncludeNulls,
107+
JoinTypeAntiHash, JoinTypeAntiHashIncludeNulls,
108+
JoinTypeRangeHeap, JoinTypeLeftOuterRangeHeap:
102109
return true
103110
default:
104111
return false
@@ -129,7 +136,7 @@ func (i JoinType) IsDegenerate() bool {
129136

130137
func (i JoinType) IsMerge() bool {
131138
switch i {
132-
case JoinTypeMerge, JoinTypeSemiMerge, JoinTypeAntiMerge, JoinTypeLeftOuterMerge:
139+
case JoinTypeMerge, JoinTypeSemiMerge, JoinTypeAntiMerge, JoinTypeAntiMergeIncludeNulls, JoinTypeLeftOuterMerge:
133140
return true
134141
default:
135142
return false
@@ -138,7 +145,8 @@ func (i JoinType) IsMerge() bool {
138145

139146
func (i JoinType) IsHash() bool {
140147
switch i {
141-
case JoinTypeHash, JoinTypeSemiHash, JoinTypeAntiHash, JoinTypeLeftOuterHash, JoinTypeLeftOuterHashExcludeNulls, JoinTypeCrossHash:
148+
case JoinTypeHash, JoinTypeSemiHash, JoinTypeAntiHash, JoinTypeAntiHashIncludeNulls,
149+
JoinTypeLeftOuterHash, JoinTypeLeftOuterHashExcludeNulls, JoinTypeCrossHash:
142150
return true
143151
default:
144152
return false
@@ -157,20 +165,23 @@ func (i JoinType) IsSemi() bool {
157165

158166
func (i JoinType) IsAnti() bool {
159167
switch i {
160-
case JoinTypeAnti, JoinTypeAntiLookup, JoinTypeAntiMerge, JoinTypeAntiHash:
168+
case JoinTypeAnti, JoinTypeAntiIncludeNulls, JoinTypeAntiLookup, JoinTypeAntiLookupIncludeNulls,
169+
JoinTypeAntiMerge, JoinTypeAntiMergeIncludeNulls, JoinTypeAntiHash, JoinTypeAntiHashIncludeNulls:
161170
return true
162171
default:
163172
return false
164173
}
165174
}
166175

167176
func (i JoinType) IsPartial() bool {
168-
return i == JoinTypeSemi ||
169-
i == JoinTypeAnti ||
170-
i == JoinTypeSemiHash ||
171-
i == JoinTypeAntiHash ||
172-
i == JoinTypeAntiLookup ||
173-
i == JoinTypeSemiLookup
177+
switch i {
178+
case JoinTypeSemi, JoinTypeAnti, JoinTypeAntiIncludeNulls, JoinTypeSemiHash,
179+
JoinTypeAntiHash, JoinTypeAntiHashIncludeNulls, JoinTypeAntiLookup, JoinTypeAntiLookupIncludeNulls,
180+
JoinTypeSemiLookup:
181+
return true
182+
default:
183+
return false
184+
}
174185
}
175186

176187
func (i JoinType) IsPlaceholder() bool {
@@ -180,7 +191,8 @@ func (i JoinType) IsPlaceholder() bool {
180191

181192
func (i JoinType) IsLookup() bool {
182193
switch i {
183-
case JoinTypeLookup, JoinTypeLeftOuterLookup, JoinTypeAntiLookup, JoinTypeSemiLookup:
194+
case JoinTypeLookup, JoinTypeLeftOuterLookup,
195+
JoinTypeAntiLookup, JoinTypeAntiLookupIncludeNulls, JoinTypeSemiLookup:
184196
return true
185197
default:
186198
return false
@@ -221,6 +233,8 @@ func (i JoinType) AsHash() JoinType {
221233
return JoinTypeSemiHash
222234
case JoinTypeAnti:
223235
return JoinTypeAntiHash
236+
case JoinTypeAntiIncludeNulls:
237+
return JoinTypeAntiHashIncludeNulls
224238
case JoinTypeCross:
225239
return JoinTypeCrossHash
226240
default:
@@ -249,6 +263,8 @@ func (i JoinType) AsMerge() JoinType {
249263
return JoinTypeSemiMerge
250264
case JoinTypeAnti:
251265
return JoinTypeAntiMerge
266+
case JoinTypeAntiIncludeNulls:
267+
return JoinTypeAntiMergeIncludeNulls
252268
default:
253269
return i
254270
}
@@ -264,6 +280,8 @@ func (i JoinType) AsLookup() JoinType {
264280
return JoinTypeSemiLookup
265281
case JoinTypeAnti:
266282
return JoinTypeAntiLookup
283+
case JoinTypeAntiIncludeNulls:
284+
return JoinTypeAntiLookupIncludeNulls
267285
default:
268286
return i
269287
}
@@ -521,8 +539,8 @@ func NewLookupJoin(left, right sql.Node, cond sql.Expression) *JoinNode {
521539
return NewJoin(left, right, JoinTypeLookup, cond)
522540
}
523541

524-
func NewAntiJoin(left, right sql.Node, cond sql.Expression) *JoinNode {
525-
return NewJoin(left, right, JoinTypeAnti, cond)
542+
func NewAntiJoinIncludingNulls(left, right sql.Node, cond sql.Expression) *JoinNode {
543+
return NewJoin(left, right, JoinTypeAntiIncludeNulls, cond)
526544
}
527545

528546
func NewSemiJoin(left, right sql.Node, cond sql.Expression) *JoinNode {

sql/plan/jointype_string.go

Lines changed: 33 additions & 29 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)