Skip to content

Commit

Permalink
*: remove CorrelatedCol.HashCode to avoid potential bug (#45034)
Browse files Browse the repository at this point in the history
close #45033
  • Loading branch information
guo-shaoge authored Jun 30, 2023
1 parent ebcb9b8 commit 8d6071a
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 57 deletions.
2 changes: 1 addition & 1 deletion executor/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -5458,7 +5458,7 @@ func (b *executorBuilder) buildCTE(v *plannercore.PhysicalCTE) Executor {

var corColHashCodes [][]byte
for _, corCol := range corCols {
corColHashCodes = append(corColHashCodes, corCol.HashCode(b.ctx.GetSessionVars().StmtCtx))
corColHashCodes = append(corColHashCodes, getCorColHashCode(corCol))
}

producer = &cteProducer{
Expand Down
7 changes: 5 additions & 2 deletions executor/cte.go
Original file line number Diff line number Diff line change
Expand Up @@ -661,12 +661,15 @@ func (p *cteProducer) checkHasDup(probeKey uint64,
return false, nil
}

func getCorColHashCode(corCol *expression.CorrelatedColumn) (res []byte) {
return codec.HashCode(res, *corCol.Data)
}

// Return true if cor col has changed.
func (p *cteProducer) checkAndUpdateCorColHashCode() bool {
var changed bool
for i, corCol := range p.corCols {
corCol.CleanHashCode()
newHashCode := corCol.HashCode(p.ctx.GetSessionVars().StmtCtx)
newHashCode := getCorColHashCode(corCol)
if !bytes.Equal(newHashCode, p.corColHashCodes[i]) {
changed = true
p.corColHashCodes[i] = newHashCode
Expand Down
27 changes: 1 addition & 26 deletions expression/column.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ import (
type CorrelatedColumn struct {
Column

Data *types.Datum
columnHashCode []byte
Data *types.Datum
}

// Clone implements Expression interface.
Expand Down Expand Up @@ -224,30 +223,6 @@ func (col *CorrelatedColumn) RemapColumn(m map[int64]*Column) (Expression, error
}, nil
}

// HashCode implements Expression interface.
func (col *CorrelatedColumn) HashCode(sc *stmtctx.StatementContext) []byte {
if len(col.columnHashCode) == 0 {
col.columnHashCode = make([]byte, 0, 9)
col.columnHashCode = append(col.columnHashCode, columnFlag)
col.columnHashCode = codec.EncodeInt(col.columnHashCode, col.UniqueID)
}

if len(col.hashcode) < len(col.columnHashCode) {
if len(col.hashcode) == 0 {
col.hashcode = make([]byte, 0, len(col.columnHashCode))
} else {
col.hashcode = col.hashcode[:0]
}
col.hashcode = append(col.hashcode, col.columnHashCode...)
}

// Because col.Data can be changed anytime, so always use newest Datum to calc hash code.
if col.Data != nil {
col.hashcode = codec.HashCode(col.hashcode, *col.Data)
}
return col.hashcode
}

// Column represents a column.
type Column struct {
RetType *types.FieldType
Expand Down
28 changes: 0 additions & 28 deletions expression/column_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package expression

import (
"bytes"
"fmt"
"testing"

Expand Down Expand Up @@ -264,30 +263,3 @@ func TestGcColumnExprIsTidbShard(t *testing.T) {
shardExpr := NewFunctionInternal(ctx, ast.TiDBShard, ft, col)
require.True(t, GcColumnExprIsTidbShard(shardExpr))
}

func TestCorColHashCode(t *testing.T) {
ctx := mock.NewContext()
sc := ctx.GetSessionVars().StmtCtx
col := &Column{UniqueID: 0, ID: 0, RetType: types.NewFieldType(mysql.TypeLonglong)}

corCol := CorrelatedColumn{
Column: *col,
}

oriCorColHashCode := corCol.HashCode(sc)
oriColHashCode := col.HashCode(sc)
// hash code is same when Data is not set.
require.True(t, bytes.Equal(oriColHashCode, oriCorColHashCode))

// corCol.hashcode changes after datum changed.
d1 := types.NewDatum(1)
corCol.Data = &d1
require.False(t, bytes.Equal(col.HashCode(sc), corCol.HashCode(sc)))
d1HashCode := corCol.HashCode(sc)
d2 := types.NewFloat64Datum(1.1)
corCol.Data = &d2
require.False(t, bytes.Equal(d1HashCode, corCol.HashCode(sc)))

// col.hashcode doesn't change.
require.True(t, bytes.Equal(oriColHashCode, col.HashCode(sc)))
}
29 changes: 29 additions & 0 deletions planner/core/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5303,3 +5303,32 @@ func TestIssue43116(t *testing.T) {
" └─TableFullScan 10000.00 cop[tikv] table:a keep order:false, stats:pseudo"))
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 Memory capacity of 111 bytes for 'tidb_opt_range_max_size' exceeded when building ranges. Less accurate ranges such as full range are chosen"))
}

func TestIssue45033(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1, t2, t3, t4;")
tk.MustExec("create table t1 (c1 int, c2 int, c3 int, primary key(c1, c2));")
tk.MustExec("create table t2 (c2 int, c1 int, primary key(c2, c1));")
tk.MustExec("create table t3 (c4 int, key(c4));")
tk.MustExec("create table t4 (c2 varchar(20) , test_col varchar(50), gen_col varchar(50) generated always as(concat(test_col,'')) virtual not null, unique key(gen_col));")
tk.MustQuery(`select count(1)
from (select ( case
when count(1)
over(
partition by a.c2) >= 50 then 1
else 0
end ) alias1,
b.c2 as alias_col1
from t1 a
left join (select c2
from t4 f) k
on k.c2 = a.c2
inner join t2 b
on b.c1 = a.c3) alias2
where exists (select 1
from (select distinct alias3.c4 as c2
from t3 alias3) alias4
where alias4.c2 = alias2.alias_col1);`).Check(testkit.Rows("0"))
}

0 comments on commit 8d6071a

Please sign in to comment.