Skip to content

Commit 3950070

Browse files
XuHuaiyuzz-jason
authored andcommitted
util: refine chunk.SwapColumn to rebuild the column reference (#7841) (#7849)
1 parent fbdcf63 commit 3950070

File tree

2 files changed

+85
-1
lines changed

2 files changed

+85
-1
lines changed

util/chunk/chunk.go

+39-1
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,47 @@ func (c *Chunk) MakeRef(srcColIdx, dstColIdx int) {
137137
c.columns[dstColIdx] = c.columns[srcColIdx]
138138
}
139139

140-
// SwapColumn swaps column "c.columns[colIdx]" with column "other.columns[otherIdx]".
140+
// SwapColumn swaps column "c.columns[colIdx]" with column
141+
// "other.columns[otherIdx]". If there exists columns refer to the column to be
142+
// swapped, we need to re-build the reference.
141143
func (c *Chunk) SwapColumn(colIdx int, other *Chunk, otherIdx int) {
144+
// Find the leftmost column of the reference which is the actual column to
145+
// be swapped.
146+
for i := 0; i < colIdx; i++ {
147+
if c.columns[i] == c.columns[colIdx] {
148+
colIdx = i
149+
}
150+
}
151+
for i := 0; i < otherIdx; i++ {
152+
if other.columns[i] == other.columns[otherIdx] {
153+
otherIdx = i
154+
}
155+
}
156+
157+
// Find the columns which refer to the actual column to be swapped.
158+
refColsIdx := make([]int, 0, len(c.columns)-colIdx)
159+
for i := colIdx; i < len(c.columns); i++ {
160+
if c.columns[i] == c.columns[colIdx] {
161+
refColsIdx = append(refColsIdx, i)
162+
}
163+
}
164+
refColsIdx4Other := make([]int, 0, len(other.columns)-otherIdx)
165+
for i := otherIdx; i < len(other.columns); i++ {
166+
if other.columns[i] == other.columns[otherIdx] {
167+
refColsIdx4Other = append(refColsIdx4Other, i)
168+
}
169+
}
170+
171+
// Swap columns from two chunks.
142172
c.columns[colIdx], other.columns[otherIdx] = other.columns[otherIdx], c.columns[colIdx]
173+
174+
// Rebuild the reference.
175+
for _, i := range refColsIdx {
176+
c.MakeRef(colIdx, i)
177+
}
178+
for _, i := range refColsIdx4Other {
179+
other.MakeRef(otherIdx, i)
180+
}
143181
}
144182

145183
// SwapColumns swaps columns with another Chunk.

util/chunk/chunk_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,52 @@ func (s *testChunkSuite) TestChunkMemoryUsage(c *check.C) {
471471
c.Assert(memUsage, check.Equals, int64(expectedUsage))
472472
}
473473

474+
func (s *testChunkSuite) TestSwapColumn(c *check.C) {
475+
fieldTypes := make([]*types.FieldType, 0, 2)
476+
fieldTypes = append(fieldTypes, &types.FieldType{Tp: mysql.TypeFloat})
477+
fieldTypes = append(fieldTypes, &types.FieldType{Tp: mysql.TypeFloat})
478+
fieldTypes = append(fieldTypes, &types.FieldType{Tp: mysql.TypeFloat})
479+
480+
// chk1: column1 refers to column0
481+
chk1 := NewChunkWithCapacity(fieldTypes, 1)
482+
chk1.AppendFloat64(0, 1)
483+
chk1.MakeRef(0, 1)
484+
chk1.AppendFloat64(2, 3)
485+
486+
// chk2: column1 refers to column0
487+
chk2 := NewChunkWithCapacity(fieldTypes, 1)
488+
chk2.AppendFloat64(0, 1)
489+
chk2.MakeRef(0, 1)
490+
chk2.AppendFloat64(2, 3)
491+
492+
c.Assert(chk1.columns[0] == chk1.columns[1], check.IsTrue)
493+
c.Assert(chk2.columns[0] == chk2.columns[1], check.IsTrue)
494+
495+
checkRef := func() {
496+
c.Assert(chk1.columns[0] == chk1.columns[1], check.IsTrue)
497+
c.Assert(chk1.columns[0] == chk2.columns[0], check.IsFalse)
498+
c.Assert(chk2.columns[0] == chk2.columns[1], check.IsTrue)
499+
}
500+
501+
chk1.SwapColumn(0, chk2, 0)
502+
checkRef()
503+
504+
chk1.SwapColumn(0, chk2, 1)
505+
checkRef()
506+
507+
chk2.SwapColumn(1, chk2, 0)
508+
checkRef()
509+
510+
chk2.SwapColumn(1, chk2, 1)
511+
checkRef()
512+
513+
chk2.SwapColumn(1, chk2, 2)
514+
checkRef()
515+
516+
chk2.SwapColumn(2, chk2, 0)
517+
checkRef()
518+
}
519+
474520
func BenchmarkAppendInt(b *testing.B) {
475521
b.ReportAllocs()
476522
chk := newChunk(8)

0 commit comments

Comments
 (0)