From 20e588de45c77a8efcf5f51edf989f7e0a01f459 Mon Sep 17 00:00:00 2001 From: Jason Mo Date: Fri, 19 Nov 2021 13:48:31 +0800 Subject: [PATCH 1/8] first edition --- expression/builtin_math.go | 6 +++++- expression/builtin_math_vec.go | 4 ++++ expression/rand.go | 12 +++++++++--- sessionctx/variable/noop.go | 2 -- sessionctx/variable/session.go | 5 +++++ sessionctx/variable/sysvar.go | 12 ++++++++++++ 6 files changed, 35 insertions(+), 6 deletions(-) diff --git a/expression/builtin_math.go b/expression/builtin_math.go index d179ddcfc0bc8..03796d1c8f147 100644 --- a/expression/builtin_math.go +++ b/expression/builtin_math.go @@ -1014,7 +1014,7 @@ func (c *randFunctionClass) getFunction(ctx sessionctx.Context, args []Expressio } bt := bf if len(args) == 0 { - sig = &builtinRandSig{bt, &sync.Mutex{}, NewWithTime()} + sig = &builtinRandSig{bt, &sync.Mutex{}, NewWithSeeds(ctx.GetSessionVars().RandSeed1, ctx.GetSessionVars().RandSeed2)} sig.setPbCode(tipb.ScalarFuncSig_Rand) } else if _, isConstant := args[0].(*Constant); isConstant { // According to MySQL manual: @@ -1056,6 +1056,10 @@ func (b *builtinRandSig) Clone() builtinFunc { func (b *builtinRandSig) evalReal(row chunk.Row) (float64, bool, error) { b.mu.Lock() res := b.mysqlRng.Gen() + if b.mysqlRng.needUpdate { + b.ctx.GetSessionVars().RandSeed1 = int64(b.mysqlRng.seed1) + b.ctx.GetSessionVars().RandSeed2 = int64(b.mysqlRng.seed2) + } b.mu.Unlock() return res, false, nil } diff --git a/expression/builtin_math_vec.go b/expression/builtin_math_vec.go index de1b6886d51cc..7347b79670279 100644 --- a/expression/builtin_math_vec.go +++ b/expression/builtin_math_vec.go @@ -712,6 +712,10 @@ func (b *builtinRandSig) vecEvalReal(input *chunk.Chunk, result *chunk.Column) e b.mu.Lock() for i := range f64s { f64s[i] = b.mysqlRng.Gen() + if b.mysqlRng.needUpdate { + b.ctx.GetSessionVars().RandSeed1 = int64(b.mysqlRng.seed1) + b.ctx.GetSessionVars().RandSeed2 = int64(b.mysqlRng.seed2) + } } b.mu.Unlock() return nil diff --git a/expression/rand.go b/expression/rand.go index f33331374f197..4c54a374b46e2 100644 --- a/expression/rand.go +++ b/expression/rand.go @@ -21,15 +21,21 @@ const maxRandValue = 0x3FFFFFFF // MysqlRng is random number generator and this implementation is ported from MySQL. // See https://github.com/tikv/tikv/pull/6117#issuecomment-562489078. type MysqlRng struct { - seed1 uint32 - seed2 uint32 + seed1 uint32 + seed2 uint32 + needUpdate bool } // NewWithSeed create a rng with random seed. func NewWithSeed(seed int64) *MysqlRng { seed1 := uint32(seed*0x10001+55555555) % maxRandValue seed2 := uint32(seed*0x10000001) % maxRandValue - return &MysqlRng{seed1: seed1, seed2: seed2} + return &MysqlRng{seed1: seed1, seed2: seed2, needUpdate: false} +} + +// NewWithSeeds create a rng with random seeds. +func NewWithSeeds(seed1 int64, seed2 int64) *MysqlRng { + return &MysqlRng{uint32(seed1) % maxRandValue, uint32(seed2) % maxRandValue, true} } // NewWithTime create a rng with time stamp. diff --git a/sessionctx/variable/noop.go b/sessionctx/variable/noop.go index fbec3e758c910..8eb9a9c7670e6 100644 --- a/sessionctx/variable/noop.go +++ b/sessionctx/variable/noop.go @@ -59,7 +59,6 @@ var noopSysVars = []*SysVar{ {Scope: ScopeGlobal | ScopeSession, Name: BigTables, Value: Off, Type: TypeBool}, {Scope: ScopeNone, Name: "skip_external_locking", Value: "1"}, {Scope: ScopeNone, Name: "innodb_sync_array_size", Value: "1"}, - {Scope: ScopeSession, Name: "rand_seed2", Value: ""}, {Scope: ScopeGlobal, Name: ValidatePasswordCheckUserName, Value: Off, Type: TypeBool}, {Scope: ScopeGlobal, Name: ValidatePasswordNumberCount, Value: "1", Type: TypeUnsigned, MinValue: 0, MaxValue: math.MaxUint64}, {Scope: ScopeSession, Name: "gtid_next", Value: ""}, @@ -275,7 +274,6 @@ var noopSysVars = []*SysVar{ {Scope: ScopeNone, Name: "binlog_gtid_simple_recovery", Value: "1"}, {Scope: ScopeNone, Name: "performance_schema_digests_size", Value: "10000"}, {Scope: ScopeGlobal | ScopeSession, Name: Profiling, Value: Off, Type: TypeBool}, - {Scope: ScopeSession, Name: "rand_seed1", Value: ""}, {Scope: ScopeGlobal, Name: "sha256_password_proxy_users", Value: ""}, {Scope: ScopeGlobal | ScopeSession, Name: SQLQuoteShowCreate, Value: On, Type: TypeBool}, {Scope: ScopeGlobal | ScopeSession, Name: "binlogging_impossible_mode", Value: "IGNORE_ERROR"}, diff --git a/sessionctx/variable/session.go b/sessionctx/variable/session.go index c395d98c85356..e8e3510afb86c 100644 --- a/sessionctx/variable/session.go +++ b/sessionctx/variable/session.go @@ -955,6 +955,11 @@ type SessionVars struct { curr int8 data [2]stmtctx.StatementContext } + + // RandSeed1 stores the value of rand_seed1 + RandSeed1 int64 + // RandSeed2 stores the value of rand_seed2 + RandSeed2 int64 } // InitStatementContext initializes a StatementContext, the object is reused to reduce allocation. diff --git a/sessionctx/variable/sysvar.go b/sessionctx/variable/sysvar.go index 52006bf44f9ce..824a401fdf3e0 100644 --- a/sessionctx/variable/sysvar.go +++ b/sessionctx/variable/sysvar.go @@ -1861,6 +1861,18 @@ var defaultSysVars = []*SysVar{ {Scope: ScopeNone, Name: "version_compile_os", Value: runtime.GOOS}, {Scope: ScopeNone, Name: "version_compile_machine", Value: runtime.GOARCH}, {Scope: ScopeNone, Name: TiDBAllowFunctionForExpressionIndex, ReadOnly: true, Value: collectAllowFuncName4ExpressionIndex()}, + {Scope: ScopeSession, Name: "rand_seed1", Type: TypeInt, Value: strconv.Itoa(int(time.Now().UnixNano() % math.MaxInt32)), MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { + s.RandSeed1 = int64(tidbOptPositiveInt32(val, 0)) + return nil + }, GetSession: func(s *SessionVars) (string, error) { + return "0", nil + }}, + {Scope: ScopeSession, Name: "rand_seed2", Type: TypeInt, Value: strconv.Itoa(int(time.Now().UnixNano() % math.MaxInt32)), MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { + s.RandSeed2 = int64(tidbOptPositiveInt32(val, 0)) + return nil + }, GetSession: func(s *SessionVars) (string, error) { + return "0", nil + }}, } func collectAllowFuncName4ExpressionIndex() string { From d0af7f22f61975c5c9c8c2e1119b4b49d7461719 Mon Sep 17 00:00:00 2001 From: Jason Mo Date: Fri, 19 Nov 2021 15:48:39 +0800 Subject: [PATCH 2/8] move rand.go to util --- expression/builtin_math.go | 23 ++++++---------- expression/builtin_math_vec.go | 11 ++------ sessionctx/variable/session.go | 9 +++--- sessionctx/variable/sysvar.go | 8 +++--- {expression => util/math}/rand.go | 38 ++++++++++++++++++-------- {expression => util/math}/rand_test.go | 2 +- 6 files changed, 48 insertions(+), 43 deletions(-) rename {expression => util/math}/rand.go (77%) rename {expression => util/math}/rand_test.go (98%) diff --git a/expression/builtin_math.go b/expression/builtin_math.go index 03796d1c8f147..569d04b57cc69 100644 --- a/expression/builtin_math.go +++ b/expression/builtin_math.go @@ -24,7 +24,6 @@ import ( "math" "strconv" "strings" - "sync" "github.com/cznic/mathutil" "github.com/pingcap/tidb/parser/ast" @@ -32,6 +31,7 @@ import ( "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" + utilMath "github.com/pingcap/tidb/util/math" "github.com/pingcap/tipb/go-tipb" ) @@ -1014,7 +1014,7 @@ func (c *randFunctionClass) getFunction(ctx sessionctx.Context, args []Expressio } bt := bf if len(args) == 0 { - sig = &builtinRandSig{bt, &sync.Mutex{}, NewWithSeeds(ctx.GetSessionVars().RandSeed1, ctx.GetSessionVars().RandSeed2)} + sig = &builtinRandSig{bt, ctx.GetSessionVars().Rng} sig.setPbCode(tipb.ScalarFuncSig_Rand) } else if _, isConstant := args[0].(*Constant); isConstant { // According to MySQL manual: @@ -1030,7 +1030,7 @@ func (c *randFunctionClass) getFunction(ctx sessionctx.Context, args []Expressio // The behavior same as MySQL. seed = 0 } - sig = &builtinRandSig{bt, &sync.Mutex{}, NewWithSeed(seed)} + sig = &builtinRandSig{bt, utilMath.NewWithSeed(seed)} sig.setPbCode(tipb.ScalarFuncSig_Rand) } else { sig = &builtinRandWithSeedFirstGenSig{bt} @@ -1041,12 +1041,11 @@ func (c *randFunctionClass) getFunction(ctx sessionctx.Context, args []Expressio type builtinRandSig struct { baseBuiltinFunc - mu *sync.Mutex - mysqlRng *MysqlRng + mysqlRng *utilMath.MysqlRng } func (b *builtinRandSig) Clone() builtinFunc { - newSig := &builtinRandSig{mysqlRng: b.mysqlRng, mu: b.mu} + newSig := &builtinRandSig{mysqlRng: b.mysqlRng} newSig.cloneFrom(&b.baseBuiltinFunc) return newSig } @@ -1054,13 +1053,7 @@ func (b *builtinRandSig) Clone() builtinFunc { // evalReal evals RAND(). // See https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_rand func (b *builtinRandSig) evalReal(row chunk.Row) (float64, bool, error) { - b.mu.Lock() res := b.mysqlRng.Gen() - if b.mysqlRng.needUpdate { - b.ctx.GetSessionVars().RandSeed1 = int64(b.mysqlRng.seed1) - b.ctx.GetSessionVars().RandSeed2 = int64(b.mysqlRng.seed2) - } - b.mu.Unlock() return res, false, nil } @@ -1084,11 +1077,11 @@ func (b *builtinRandWithSeedFirstGenSig) evalReal(row chunk.Row) (float64, bool, // b.args[0] is promised to be a non-constant(such as a column name) in // builtinRandWithSeedFirstGenSig, the seed is initialized with the value for each // invocation of RAND(). - var rng *MysqlRng + var rng *utilMath.MysqlRng if !isNull { - rng = NewWithSeed(seed) + rng = utilMath.NewWithSeed(seed) } else { - rng = NewWithSeed(0) + rng = utilMath.NewWithSeed(0) } return rng.Gen(), false, nil } diff --git a/expression/builtin_math_vec.go b/expression/builtin_math_vec.go index 7347b79670279..91ea97980036a 100644 --- a/expression/builtin_math_vec.go +++ b/expression/builtin_math_vec.go @@ -16,6 +16,7 @@ package expression import ( "fmt" + utilMath "github.com/pingcap/tidb/util/math" "hash/crc32" "math" "strconv" @@ -709,15 +710,9 @@ func (b *builtinRandSig) vecEvalReal(input *chunk.Chunk, result *chunk.Column) e n := input.NumRows() result.ResizeFloat64(n, false) f64s := result.Float64s() - b.mu.Lock() for i := range f64s { f64s[i] = b.mysqlRng.Gen() - if b.mysqlRng.needUpdate { - b.ctx.GetSessionVars().RandSeed1 = int64(b.mysqlRng.seed1) - b.ctx.GetSessionVars().RandSeed2 = int64(b.mysqlRng.seed2) - } } - b.mu.Unlock() return nil } @@ -742,9 +737,9 @@ func (b *builtinRandWithSeedFirstGenSig) vecEvalReal(input *chunk.Chunk, result for i := 0; i < n; i++ { // When the seed is null we need to use 0 as the seed. // The behavior same as MySQL. - rng := NewWithSeed(0) + rng := utilMath.NewWithSeed(0) if !buf.IsNull(i) { - rng = NewWithSeed(i64s[i]) + rng = utilMath.NewWithSeed(i64s[i]) } f64s[i] = rng.Gen() } diff --git a/sessionctx/variable/session.go b/sessionctx/variable/session.go index e8e3510afb86c..b239a45bfcaed 100644 --- a/sessionctx/variable/session.go +++ b/sessionctx/variable/session.go @@ -29,6 +29,8 @@ import ( "sync/atomic" "time" + utilMath "github.com/pingcap/tidb/util/math" + "github.com/pingcap/errors" pumpcli "github.com/pingcap/tidb-tools/tidb-binlog/pump_client" "github.com/pingcap/tidb/config" @@ -956,10 +958,8 @@ type SessionVars struct { data [2]stmtctx.StatementContext } - // RandSeed1 stores the value of rand_seed1 - RandSeed1 int64 - // RandSeed2 stores the value of rand_seed2 - RandSeed2 int64 + // Rng stores the rand_seed1 and rand_seed2 for Rand() function + Rng *utilMath.MysqlRng } // InitStatementContext initializes a StatementContext, the object is reused to reduce allocation. @@ -1193,6 +1193,7 @@ func NewSessionVars() *SessionVars { MPPStoreLastFailTime: make(map[string]time.Time), MPPStoreFailTTL: DefTiDBMPPStoreFailTTL, EnablePlacementChecks: DefEnablePlacementCheck, + Rng: utilMath.NewWithTime(), } vars.KVVars = tikvstore.NewVariables(&vars.Killed) vars.Concurrency = Concurrency{ diff --git a/sessionctx/variable/sysvar.go b/sessionctx/variable/sysvar.go index 824a401fdf3e0..bb89b7053bd08 100644 --- a/sessionctx/variable/sysvar.go +++ b/sessionctx/variable/sysvar.go @@ -1861,14 +1861,14 @@ var defaultSysVars = []*SysVar{ {Scope: ScopeNone, Name: "version_compile_os", Value: runtime.GOOS}, {Scope: ScopeNone, Name: "version_compile_machine", Value: runtime.GOARCH}, {Scope: ScopeNone, Name: TiDBAllowFunctionForExpressionIndex, ReadOnly: true, Value: collectAllowFuncName4ExpressionIndex()}, - {Scope: ScopeSession, Name: "rand_seed1", Type: TypeInt, Value: strconv.Itoa(int(time.Now().UnixNano() % math.MaxInt32)), MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { - s.RandSeed1 = int64(tidbOptPositiveInt32(val, 0)) + {Scope: ScopeSession, Name: "rand_seed1", Type: TypeInt, Value: "0", skipInit: true, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { + s.Rng.SetSeed1(uint32(tidbOptPositiveInt32(val, 0))) return nil }, GetSession: func(s *SessionVars) (string, error) { return "0", nil }}, - {Scope: ScopeSession, Name: "rand_seed2", Type: TypeInt, Value: strconv.Itoa(int(time.Now().UnixNano() % math.MaxInt32)), MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { - s.RandSeed2 = int64(tidbOptPositiveInt32(val, 0)) + {Scope: ScopeSession, Name: "rand_seed2", Type: TypeInt, Value: "0", skipInit: true, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { + s.Rng.SetSeed2(uint32(tidbOptPositiveInt32(val, 0))) return nil }, GetSession: func(s *SessionVars) (string, error) { return "0", nil diff --git a/expression/rand.go b/util/math/rand.go similarity index 77% rename from expression/rand.go rename to util/math/rand.go index 4c54a374b46e2..64187442f1e22 100644 --- a/expression/rand.go +++ b/util/math/rand.go @@ -12,30 +12,32 @@ // See the License for the specific language governing permissions and // limitations under the License. -package expression +package math -import "time" +import ( + "sync" + "time" +) const maxRandValue = 0x3FFFFFFF // MysqlRng is random number generator and this implementation is ported from MySQL. // See https://github.com/tikv/tikv/pull/6117#issuecomment-562489078. type MysqlRng struct { - seed1 uint32 - seed2 uint32 - needUpdate bool + seed1 uint32 + seed2 uint32 + mu *sync.Mutex } // NewWithSeed create a rng with random seed. func NewWithSeed(seed int64) *MysqlRng { seed1 := uint32(seed*0x10001+55555555) % maxRandValue seed2 := uint32(seed*0x10000001) % maxRandValue - return &MysqlRng{seed1: seed1, seed2: seed2, needUpdate: false} -} - -// NewWithSeeds create a rng with random seeds. -func NewWithSeeds(seed1 int64, seed2 int64) *MysqlRng { - return &MysqlRng{uint32(seed1) % maxRandValue, uint32(seed2) % maxRandValue, true} + return &MysqlRng{ + seed1: seed1, + seed2: seed2, + mu: &sync.Mutex{}, + } } // NewWithTime create a rng with time stamp. @@ -45,7 +47,21 @@ func NewWithTime() *MysqlRng { // Gen will generate random number. func (rng *MysqlRng) Gen() float64 { + rng.mu.Lock() + defer rng.mu.Unlock() rng.seed1 = (rng.seed1*3 + rng.seed2) % maxRandValue rng.seed2 = (rng.seed1 + rng.seed2 + 33) % maxRandValue return float64(rng.seed1) / float64(maxRandValue) } + +func (rng *MysqlRng) SetSeed1(seed uint32) { + rng.mu.Lock() + defer rng.mu.Unlock() + rng.seed1 = seed +} + +func (rng *MysqlRng) SetSeed2(seed uint32) { + rng.mu.Lock() + defer rng.mu.Unlock() + rng.seed2 = seed +} diff --git a/expression/rand_test.go b/util/math/rand_test.go similarity index 98% rename from expression/rand_test.go rename to util/math/rand_test.go index 8a6f18b824718..5a6c8bdbd9ad2 100644 --- a/expression/rand_test.go +++ b/util/math/rand_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package expression +package math import ( "testing" From a553b787beaf42e4a5c572d7dc0831b2bc8caabc Mon Sep 17 00:00:00 2001 From: Jason Mo Date: Fri, 19 Nov 2021 16:11:51 +0800 Subject: [PATCH 3/8] add test --- expression/builtin_math_test.go | 3 ++- expression/integration_test.go | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/expression/builtin_math_test.go b/expression/builtin_math_test.go index 5a3d5f4cd6068..88d2985f10c17 100644 --- a/expression/builtin_math_test.go +++ b/expression/builtin_math_test.go @@ -26,6 +26,7 @@ import ( "github.com/pingcap/tidb/testkit/trequire" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/chunk" + utilMath "github.com/pingcap/tidb/util/math" "github.com/pingcap/tipb/go-tipb" "github.com/stretchr/testify/require" ) @@ -382,7 +383,7 @@ func TestRand(t *testing.T) { // issue 3211 f2, err := fc.getFunction(ctx, []Expression{&Constant{Value: types.NewIntDatum(20160101), RetType: types.NewFieldType(mysql.TypeLonglong)}}) require.NoError(t, err) - randGen := NewWithSeed(20160101) + randGen := utilMath.NewWithSeed(20160101) for i := 0; i < 3; i++ { v, err = evalBuiltinFunc(f2, chunk.Row{}) require.NoError(t, err) diff --git a/expression/integration_test.go b/expression/integration_test.go index 96b7b10fe901d..c27a6823b8016 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -794,6 +794,10 @@ func (s *testIntegrationSuite2) TestMathBuiltin(c *C) { tk.MustQuery("select rand(1) from t").Sort().Check(testkit.Rows("0.1418603212962489", "0.40540353712197724", "0.8716141803857071")) tk.MustQuery("select rand(a) from t").Check(testkit.Rows("0.40540353712197724", "0.6555866465490187", "0.9057697559760601")) tk.MustQuery("select rand(1), rand(2), rand(3)").Check(testkit.Rows("0.40540353712197724 0.6555866465490187 0.9057697559760601")) + tk.MustQuery("set @@rand_seed1=10000000,@@rand_seed2=1000000") + tk.MustQuery("select rand()").Check(testkit.Rows("0.028870999839968048")) + tk.MustQuery("select rand(1)").Check(testkit.Rows("0.40540353712197724")) + tk.MustQuery("select rand()").Check(testkit.Rows("0.11641535266900002")) } func (s *testIntegrationSuite2) TestStringBuiltin(c *C) { From 70f05e211e3387b292c3f1c8d1e48b82a6b6729a Mon Sep 17 00:00:00 2001 From: Jason Mo Date: Fri, 19 Nov 2021 16:33:49 +0800 Subject: [PATCH 4/8] add tests --- util/math/rand_test.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/util/math/rand_test.go b/util/math/rand_test.go index 5a6c8bdbd9ad2..70f6bac105e10 100644 --- a/util/math/rand_test.go +++ b/util/math/rand_test.go @@ -55,8 +55,23 @@ func TestRandWithSeed(t *testing.T) { for _, test := range tests { rng := NewWithSeed(test.seed) got1 := rng.Gen() - require.True(t, got1 == test.once) + require.Equal(t, got1, test.once) got2 := rng.Gen() - require.True(t, got2 == test.twice) + require.Equal(t, got2, test.twice) } } + +func TestRandWithSeed1AndSeed2(t *testing.T) { + t.Parallel() + + seed1 := uint32(10000000) + seed2 := uint32(1000000) + + rng := NewWithTime() + rng.SetSeed1(seed1) + rng.SetSeed2(seed2) + + require.Equal(t, rng.Gen(), 0.028870999839968048) + require.Equal(t, rng.Gen(), 0.11641535266900002) + require.Equal(t, rng.Gen(), 0.49546379455874096) +} From 6a81f399d49b7ccf7cd0cd827f28a3644f0cb2b2 Mon Sep 17 00:00:00 2001 From: Jason Mo Date: Fri, 19 Nov 2021 16:35:59 +0800 Subject: [PATCH 5/8] go fmt --- sessionctx/variable/session.go | 2 +- util/math/rand.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sessionctx/variable/session.go b/sessionctx/variable/session.go index b239a45bfcaed..57d6f75c25902 100644 --- a/sessionctx/variable/session.go +++ b/sessionctx/variable/session.go @@ -1193,7 +1193,7 @@ func NewSessionVars() *SessionVars { MPPStoreLastFailTime: make(map[string]time.Time), MPPStoreFailTTL: DefTiDBMPPStoreFailTTL, EnablePlacementChecks: DefEnablePlacementCheck, - Rng: utilMath.NewWithTime(), + Rng: utilMath.NewWithTime(), } vars.KVVars = tikvstore.NewVariables(&vars.Killed) vars.Concurrency = Concurrency{ diff --git a/util/math/rand.go b/util/math/rand.go index 64187442f1e22..82e33591d822b 100644 --- a/util/math/rand.go +++ b/util/math/rand.go @@ -26,7 +26,7 @@ const maxRandValue = 0x3FFFFFFF type MysqlRng struct { seed1 uint32 seed2 uint32 - mu *sync.Mutex + mu *sync.Mutex } // NewWithSeed create a rng with random seed. @@ -36,7 +36,7 @@ func NewWithSeed(seed int64) *MysqlRng { return &MysqlRng{ seed1: seed1, seed2: seed2, - mu: &sync.Mutex{}, + mu: &sync.Mutex{}, } } From eb846129979bf1fae1f4084d56fa41bda85262d1 Mon Sep 17 00:00:00 2001 From: Jason Mo Date: Fri, 19 Nov 2021 16:51:14 +0800 Subject: [PATCH 6/8] fix fmt --- util/math/rand.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/util/math/rand.go b/util/math/rand.go index 82e33591d822b..25b111e72788b 100644 --- a/util/math/rand.go +++ b/util/math/rand.go @@ -54,12 +54,14 @@ func (rng *MysqlRng) Gen() float64 { return float64(rng.seed1) / float64(maxRandValue) } +// SetSeed1 is a interface to set seed1 func (rng *MysqlRng) SetSeed1(seed uint32) { rng.mu.Lock() defer rng.mu.Unlock() rng.seed1 = seed } +// SetSeed2 is a interface to set seed2 func (rng *MysqlRng) SetSeed2(seed uint32) { rng.mu.Lock() defer rng.mu.Unlock() From bd141a6d4b43c14d65273d2ef4634495017178fb Mon Sep 17 00:00:00 2001 From: Jason Mo Date: Fri, 19 Nov 2021 17:01:57 +0800 Subject: [PATCH 7/8] go fmt --- expression/builtin_math_vec.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/expression/builtin_math_vec.go b/expression/builtin_math_vec.go index 91ea97980036a..13b6a701d5d8e 100644 --- a/expression/builtin_math_vec.go +++ b/expression/builtin_math_vec.go @@ -16,11 +16,12 @@ package expression import ( "fmt" - utilMath "github.com/pingcap/tidb/util/math" "hash/crc32" "math" "strconv" + utilMath "github.com/pingcap/tidb/util/math" + "github.com/cznic/mathutil" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/types" From e0618dfc6949da9565754a5bc5cc6976f01feff3 Mon Sep 17 00:00:00 2001 From: Jason Mo Date: Tue, 23 Nov 2021 18:09:30 +0800 Subject: [PATCH 8/8] follow comments --- sessionctx/variable/sysvar.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sessionctx/variable/sysvar.go b/sessionctx/variable/sysvar.go index bb89b7053bd08..d66eb6c88096f 100644 --- a/sessionctx/variable/sysvar.go +++ b/sessionctx/variable/sysvar.go @@ -1861,13 +1861,13 @@ var defaultSysVars = []*SysVar{ {Scope: ScopeNone, Name: "version_compile_os", Value: runtime.GOOS}, {Scope: ScopeNone, Name: "version_compile_machine", Value: runtime.GOARCH}, {Scope: ScopeNone, Name: TiDBAllowFunctionForExpressionIndex, ReadOnly: true, Value: collectAllowFuncName4ExpressionIndex()}, - {Scope: ScopeSession, Name: "rand_seed1", Type: TypeInt, Value: "0", skipInit: true, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { + {Scope: ScopeSession, Name: RandSeed1, Type: TypeInt, Value: "0", skipInit: true, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { s.Rng.SetSeed1(uint32(tidbOptPositiveInt32(val, 0))) return nil }, GetSession: func(s *SessionVars) (string, error) { return "0", nil }}, - {Scope: ScopeSession, Name: "rand_seed2", Type: TypeInt, Value: "0", skipInit: true, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { + {Scope: ScopeSession, Name: RandSeed2, Type: TypeInt, Value: "0", skipInit: true, MaxValue: math.MaxInt32, SetSession: func(s *SessionVars, val string) error { s.Rng.SetSeed2(uint32(tidbOptPositiveInt32(val, 0))) return nil }, GetSession: func(s *SessionVars) (string, error) { @@ -2195,6 +2195,10 @@ const ( Identity = "identity" // TiDBAllowFunctionForExpressionIndex is the name of `TiDBAllowFunctionForExpressionIndex` system variable. TiDBAllowFunctionForExpressionIndex = "tidb_allow_function_for_expression_index" + // RandSeed1 is the name of 'rand_seed1' system variable. + RandSeed1 = "rand_seed1" + // RandSeed2 is the name of 'rand_seed2' system variable. + RandSeed2 = "rand_seed2" ) // GlobalVarAccessor is the interface for accessing global scope system and status variables.