Skip to content

Commit fd311c5

Browse files
winorosDefined2014
authored andcommitted
planner: refactor Join and Limit's ResolveIndices (pingcap#45831)
close pingcap#45758, close pingcap#45805
1 parent cf44157 commit fd311c5

File tree

3 files changed

+83
-21
lines changed

3 files changed

+83
-21
lines changed

planner/core/issuetest/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ go_test(
55
timeout = "short",
66
srcs = ["planner_issue_test.go"],
77
flaky = True,
8-
shard_count = 5,
8+
shard_count = 6,
99
deps = ["//testkit"],
1010
)

planner/core/issuetest/planner_issue_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,13 @@ func TestIssue45036(t *testing.T) {
107107
" └─TableReader_9 10000.00 root partition:all data:TableRangeScan_8",
108108
" └─TableRangeScan_8 10000.00 cop[tikv] table:s range:[1,100000], keep order:false, stats:pseudo"))
109109
}
110+
111+
func TestIssue45758(t *testing.T) {
112+
store := testkit.CreateMockStore(t)
113+
tk := testkit.NewTestKit(t, store)
114+
tk.MustExec("use test")
115+
tk.MustExec("CREATE TABLE tb1 (cid INT, code INT, class VARCHAR(10))")
116+
tk.MustExec("CREATE TABLE tb2 (cid INT, code INT, class VARCHAR(10))")
117+
// result ok
118+
tk.MustExec("UPDATE tb1, (SELECT code AS cid, code, MAX(class) AS class FROM tb2 GROUP BY code) tb3 SET tb1.cid = tb3.cid, tb1.code = tb3.code, tb1.class = tb3.class")
119+
}

planner/core/resolve_indices.go

Lines changed: 72 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,25 @@ func (p *PhysicalHashJoin) ResolveIndicesItself() (err error) {
140140
shallowColSlice := make([]*expression.Column, p.schema.Len())
141141
copy(shallowColSlice, p.schema.Columns)
142142
p.schema = expression.NewSchema(shallowColSlice...)
143-
for i := 0; i < colsNeedResolving; i++ {
144-
newCol, err := p.schema.Columns[i].ResolveIndices(mergedSchema)
145-
if err != nil {
146-
return err
143+
foundCnt := 0
144+
// The two column sets are all ordered. And the colsNeedResolving is the subset of the mergedSchema.
145+
// So we can just move forward j if there's no matching is found.
146+
// We don't use the normal ResolvIndices here since there might be duplicate columns in the schema.
147+
// e.g. The schema of child_0 is [col0, col0, col1]
148+
// ResolveIndices will only resolve all col0 reference of the current plan to the first col0.
149+
for i, j := 0, 0; i < colsNeedResolving && j < len(mergedSchema.Columns); {
150+
if !p.schema.Columns[i].Equal(nil, mergedSchema.Columns[j]) {
151+
j++
152+
continue
147153
}
148-
p.schema.Columns[i] = newCol.(*expression.Column)
154+
p.schema.Columns[i] = p.schema.Columns[i].Clone().(*expression.Column)
155+
p.schema.Columns[i].Index = j
156+
i++
157+
j++
158+
foundCnt++
159+
}
160+
if foundCnt < colsNeedResolving {
161+
return errors.Errorf("Some columns of %v cannot find the reference from its child(ren)", p.ExplainID().String())
149162
}
150163

151164
return
@@ -213,12 +226,25 @@ func (p *PhysicalMergeJoin) ResolveIndices() (err error) {
213226
shallowColSlice := make([]*expression.Column, p.schema.Len())
214227
copy(shallowColSlice, p.schema.Columns)
215228
p.schema = expression.NewSchema(shallowColSlice...)
216-
for i := 0; i < colsNeedResolving; i++ {
217-
newCol, err := p.schema.Columns[i].ResolveIndices(mergedSchema)
218-
if err != nil {
219-
return err
229+
foundCnt := 0
230+
// The two column sets are all ordered. And the colsNeedResolving is the subset of the mergedSchema.
231+
// So we can just move forward j if there's no matching is found.
232+
// We don't use the normal ResolvIndices here since there might be duplicate columns in the schema.
233+
// e.g. The schema of child_0 is [col0, col0, col1]
234+
// ResolveIndices will only resolve all col0 reference of the current plan to the first col0.
235+
for i, j := 0, 0; i < colsNeedResolving && j < len(mergedSchema.Columns); {
236+
if !p.schema.Columns[i].Equal(nil, mergedSchema.Columns[j]) {
237+
j++
238+
continue
220239
}
221-
p.schema.Columns[i] = newCol.(*expression.Column)
240+
p.schema.Columns[i] = p.schema.Columns[i].Clone().(*expression.Column)
241+
p.schema.Columns[i].Index = j
242+
i++
243+
j++
244+
foundCnt++
245+
}
246+
if foundCnt < colsNeedResolving {
247+
return errors.Errorf("Some columns of %v cannot find the reference from its child(ren)", p.ExplainID().String())
222248
}
223249
return
224250
}
@@ -296,12 +322,25 @@ func (p *PhysicalIndexJoin) ResolveIndices() (err error) {
296322
shallowColSlice := make([]*expression.Column, p.schema.Len())
297323
copy(shallowColSlice, p.schema.Columns)
298324
p.schema = expression.NewSchema(shallowColSlice...)
299-
for i := 0; i < colsNeedResolving; i++ {
300-
newCol, err := p.schema.Columns[i].ResolveIndices(mergedSchema)
301-
if err != nil {
302-
return err
325+
foundCnt := 0
326+
// The two column sets are all ordered. And the colsNeedResolving is the subset of the mergedSchema.
327+
// So we can just move forward j if there's no matching is found.
328+
// We don't use the normal ResolvIndices here since there might be duplicate columns in the schema.
329+
// e.g. The schema of child_0 is [col0, col0, col1]
330+
// ResolveIndices will only resolve all col0 reference of the current plan to the first col0.
331+
for i, j := 0, 0; i < colsNeedResolving && j < len(mergedSchema.Columns); {
332+
if !p.schema.Columns[i].Equal(nil, mergedSchema.Columns[j]) {
333+
j++
334+
continue
303335
}
304-
p.schema.Columns[i] = newCol.(*expression.Column)
336+
p.schema.Columns[i] = p.schema.Columns[i].Clone().(*expression.Column)
337+
p.schema.Columns[i].Index = j
338+
i++
339+
j++
340+
foundCnt++
341+
}
342+
if foundCnt < colsNeedResolving {
343+
return errors.Errorf("Some columns of %v cannot find the reference from its child(ren)", p.ExplainID().String())
305344
}
306345

307346
return
@@ -670,12 +709,25 @@ func (p *PhysicalLimit) ResolveIndices() (err error) {
670709
shallowColSlice := make([]*expression.Column, p.schema.Len())
671710
copy(shallowColSlice, p.schema.Columns)
672711
p.schema = expression.NewSchema(shallowColSlice...)
673-
for i, col := range p.schema.Columns {
674-
newCol, err := col.ResolveIndices(p.children[0].Schema())
675-
if err != nil {
676-
return err
712+
foundCnt := 0
713+
// The two column sets are all ordered. And the colsNeedResolving is the subset of the mergedSchema.
714+
// So we can just move forward j if there's no matching is found.
715+
// We don't use the normal ResolvIndices here since there might be duplicate columns in the schema.
716+
// e.g. The schema of child_0 is [col0, col0, col1]
717+
// ResolveIndices will only resolve all col0 reference of the current plan to the first col0.
718+
for i, j := 0, 0; i < p.schema.Len() && j < p.children[0].Schema().Len(); {
719+
if !p.schema.Columns[i].Equal(nil, p.children[0].Schema().Columns[j]) {
720+
j++
721+
continue
677722
}
678-
p.schema.Columns[i] = newCol.(*expression.Column)
723+
p.schema.Columns[i] = p.schema.Columns[i].Clone().(*expression.Column)
724+
p.schema.Columns[i].Index = j
725+
i++
726+
j++
727+
foundCnt++
728+
}
729+
if foundCnt < p.schema.Len() {
730+
return errors.Errorf("Some columns of %v cannot find the reference from its child(ren)", p.ExplainID().String())
679731
}
680732
return
681733
}

0 commit comments

Comments
 (0)