diff --git a/expression/builtin_other.go b/expression/builtin_other.go index 4b8ff8d79c343..2be110ea0b3a8 100644 --- a/expression/builtin_other.go +++ b/expression/builtin_other.go @@ -22,6 +22,7 @@ import ( "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/types/json" "github.com/pingcap/tidb/util/chunk" + "github.com/pingcap/tidb/util/stringutil" "github.com/pingcap/tipb/go-tipb" ) @@ -420,7 +421,7 @@ func (b *builtinSetVarSig) evalString(row chunk.Row) (res string, isNull bool, e } varName = strings.ToLower(varName) sessionVars.UsersLock.Lock() - sessionVars.Users[varName] = res + sessionVars.Users[varName] = stringutil.Copy(res) sessionVars.UsersLock.Unlock() return res, false, nil } diff --git a/expression/builtin_other_test.go b/expression/builtin_other_test.go index 713965ce81f03..cd9660e13a7d5 100644 --- a/expression/builtin_other_test.go +++ b/expression/builtin_other_test.go @@ -234,3 +234,46 @@ func (s *testEvaluatorSuite) TestValues(c *C) { c.Assert(err, IsNil) c.Assert(cmp, Equals, 0) } + +func (s *testEvaluatorSuite) TestSetVarFromColumn(c *C) { + defer testleak.AfterTest(c)() + + // Construct arguments. + argVarName := &Constant{ + Value: types.NewStringDatum("a"), + RetType: &types.FieldType{Tp: mysql.TypeVarString, Flen: 20}, + } + argCol := &Column{ + RetType: &types.FieldType{Tp: mysql.TypeVarString, Flen: 20}, + Index: 0, + } + + // Construct SetVar function. + funcSetVar, err := NewFunction( + s.ctx, + ast.SetVar, + &types.FieldType{Tp: mysql.TypeVarString, Flen: 20}, + []Expression{argVarName, argCol}..., + ) + c.Assert(err, IsNil) + + // Construct input and output Chunks. + inputChunk := chunk.NewChunkWithCapacity([]*types.FieldType{argCol.RetType}, 1) + inputChunk.AppendString(0, "a") + outputChunk := chunk.NewChunkWithCapacity([]*types.FieldType{argCol.RetType}, 1) + + // Evaluate the SetVar function. + err = evalOneCell(s.ctx, funcSetVar, inputChunk.GetRow(0), outputChunk, 0) + c.Assert(err, IsNil) + c.Assert(outputChunk.GetRow(0).GetString(0), Equals, "a") + + // Change the content of the underlying Chunk. + inputChunk.Reset() + inputChunk.AppendString(0, "b") + + // Check whether the user variable changed. + sessionVars := s.ctx.GetSessionVars() + sessionVars.UsersLock.RLock() + defer sessionVars.UsersLock.RUnlock() + c.Assert(sessionVars.Users["a"], Equals, "a") +}