diff --git a/ddl/column_test.go b/ddl/column_test.go index fd784eed231ef..0b9ffc1b6e2ca 100644 --- a/ddl/column_test.go +++ b/ddl/column_test.go @@ -275,7 +275,7 @@ func (s *testColumnSuite) checkColumnKVExist(ctx sessionctx.Context, t table.Tab } colMap := make(map[int64]*types.FieldType) colMap[col.ID] = &col.FieldType - rowMap, err := tablecodec.DecodeRow(data, colMap, ctx.GetSessionVars().GetTimeZone()) + rowMap, err := tablecodec.DecodeRow(data, colMap, ctx.GetSessionVars().Location()) if err != nil { return errors.Trace(err) } diff --git a/distsql/select_result.go b/distsql/select_result.go index ba3fa490ce164..835104090594a 100644 --- a/distsql/select_result.go +++ b/distsql/select_result.go @@ -174,7 +174,7 @@ func (r *selectResult) getSelectResp() error { func (r *selectResult) readRowsData(chk *chunk.Chunk) (err error) { rowsData := r.selectResp.Chunks[r.respChkIdx].RowsData maxChunkSize := r.ctx.GetSessionVars().MaxChunkSize - decoder := codec.NewDecoder(chk, r.ctx.GetSessionVars().GetTimeZone()) + decoder := codec.NewDecoder(chk, r.ctx.GetSessionVars().Location()) for chk.NumRows() < maxChunkSize && len(rowsData) > 0 { for i := 0; i < r.rowLen; i++ { rowsData, err = decoder.DecodeOne(rowsData, i, r.fieldTypes[i]) diff --git a/distsql/stream.go b/distsql/stream.go index 240d15d670a24..b6411ab9064f7 100644 --- a/distsql/stream.go +++ b/distsql/stream.go @@ -115,7 +115,7 @@ func (r *streamResult) readDataIfNecessary(ctx context.Context) error { func (r *streamResult) flushToChunk(chk *chunk.Chunk) (err error) { remainRowsData := r.curr.RowsData maxChunkSize := r.ctx.GetSessionVars().MaxChunkSize - decoder := codec.NewDecoder(chk, r.ctx.GetSessionVars().GetTimeZone()) + decoder := codec.NewDecoder(chk, r.ctx.GetSessionVars().Location()) for chk.NumRows() < maxChunkSize && len(remainRowsData) > 0 { for i := 0; i < r.rowLen; i++ { remainRowsData, err = decoder.DecodeOne(remainRowsData, i, r.fieldTypes[i]) diff --git a/executor/admin.go b/executor/admin.go index d6c3f4889e513..bb9da124d9259 100644 --- a/executor/admin.go +++ b/executor/admin.go @@ -121,7 +121,7 @@ func (e *CheckIndexRangeExec) Open(ctx context.Context) error { func (e *CheckIndexRangeExec) buildDAGPB() (*tipb.DAGRequest, error) { dagReq := &tipb.DAGRequest{} dagReq.StartTs = e.ctx.Txn().StartTS() - dagReq.TimeZoneOffset = timeZoneOffset(e.ctx) + dagReq.TimeZoneName, dagReq.TimeZoneOffset = zone(e.ctx) sc := e.ctx.GetSessionVars().StmtCtx dagReq.Flags = statementContextToFlags(sc) for i := range e.schema.Columns { @@ -219,7 +219,7 @@ func (e *RecoverIndexExec) constructLimitPB(count uint64) *tipb.Executor { func (e *RecoverIndexExec) buildDAGPB(txn kv.Transaction, limitCnt uint64) (*tipb.DAGRequest, error) { dagReq := &tipb.DAGRequest{} dagReq.StartTs = txn.StartTS() - dagReq.TimeZoneOffset = timeZoneOffset(e.ctx) + dagReq.TimeZoneName, dagReq.TimeZoneOffset = zone(e.ctx) sc := e.ctx.GetSessionVars().StmtCtx dagReq.Flags = statementContextToFlags(sc) for i := range e.columns { @@ -646,7 +646,7 @@ func (e *CleanupIndexExec) Open(ctx context.Context) error { func (e *CleanupIndexExec) buildIdxDAGPB(txn kv.Transaction) (*tipb.DAGRequest, error) { dagReq := &tipb.DAGRequest{} dagReq.StartTs = txn.StartTS() - dagReq.TimeZoneOffset = timeZoneOffset(e.ctx) + dagReq.TimeZoneName, dagReq.TimeZoneOffset = zone(e.ctx) sc := e.ctx.GetSessionVars().StmtCtx dagReq.Flags = statementContextToFlags(sc) for i := range e.idxCols { diff --git a/executor/analyze.go b/executor/analyze.go index f6c8b965537db..92981466f3518 100644 --- a/executor/analyze.go +++ b/executor/analyze.go @@ -331,7 +331,7 @@ func (e *AnalyzeColumnsExec) buildStats() (hists []*statistics.Histogram, cms [] collectors[i].MergeSampleCollector(sc, statistics.SampleCollectorFromProto(rc)) } } - timeZone := e.ctx.GetSessionVars().GetTimeZone() + timeZone := e.ctx.GetSessionVars().Location() if e.pkInfo != nil { pkHist.ID = e.pkInfo.ID err = pkHist.DecodeTo(&e.pkInfo.FieldType, timeZone) diff --git a/executor/builder.go b/executor/builder.go index f794ef02838cb..332615e8d6002 100644 --- a/executor/builder.go +++ b/executor/builder.go @@ -1231,6 +1231,7 @@ func (b *executorBuilder) buildDelete(v *plan.Delete) Executor { } func (b *executorBuilder) buildAnalyzeIndexPushdown(task plan.AnalyzeIndexTask) *AnalyzeIndexExec { + _, offset := zone(b.ctx) e := &AnalyzeIndexExec{ ctx: b.ctx, tblInfo: task.TableInfo, @@ -1240,7 +1241,7 @@ func (b *executorBuilder) buildAnalyzeIndexPushdown(task plan.AnalyzeIndexTask) Tp: tipb.AnalyzeType_TypeIndex, StartTs: math.MaxUint64, Flags: statementContextToFlags(b.ctx.GetSessionVars().StmtCtx), - TimeZoneOffset: timeZoneOffset(b.ctx), + TimeZoneOffset: offset, }, } e.analyzePB.IdxReq = &tipb.AnalyzeIndexReq{ @@ -1261,6 +1262,8 @@ func (b *executorBuilder) buildAnalyzeColumnsPushdown(task plan.AnalyzeColumnsTa keepOrder = true cols = append([]*model.ColumnInfo{task.PKInfo}, cols...) } + + _, offset := zone(b.ctx) e := &AnalyzeColumnsExec{ ctx: b.ctx, tblInfo: task.TableInfo, @@ -1272,7 +1275,7 @@ func (b *executorBuilder) buildAnalyzeColumnsPushdown(task plan.AnalyzeColumnsTa Tp: tipb.AnalyzeType_TypeColumn, StartTs: math.MaxUint64, Flags: statementContextToFlags(b.ctx.GetSessionVars().StmtCtx), - TimeZoneOffset: timeZoneOffset(b.ctx), + TimeZoneOffset: offset, }, } depth := int32(defaultCMSketchDepth) @@ -1336,7 +1339,7 @@ func constructDistExec(sctx sessionctx.Context, plans []plan.PhysicalPlan) ([]*t func (b *executorBuilder) constructDAGReq(plans []plan.PhysicalPlan) (dagReq *tipb.DAGRequest, streaming bool, err error) { dagReq = &tipb.DAGRequest{} dagReq.StartTs = b.getStartTS() - dagReq.TimeZoneOffset = timeZoneOffset(b.ctx) + dagReq.TimeZoneName, dagReq.TimeZoneOffset = zone(b.ctx) sc := b.ctx.GetSessionVars().StmtCtx dagReq.Flags = statementContextToFlags(sc) dagReq.Executors, streaming, err = constructDistExec(b.ctx, plans) diff --git a/executor/distsql.go b/executor/distsql.go index 03020f500b145..4a237bf2c73c5 100644 --- a/executor/distsql.go +++ b/executor/distsql.go @@ -118,11 +118,20 @@ func closeAll(objs ...Closeable) error { return errors.Trace(err) } -// timeZoneOffset returns the local time zone offset in seconds. -func timeZoneOffset(ctx sessionctx.Context) int64 { - loc := ctx.GetSessionVars().GetTimeZone() +// zone returns the current timezone name and timezone offset in seconds. +// In compatible with MySQL, we change `Local` to `System`. +// TODO: Golang team plan to return system timezone name intead of +// returning `Local` when `loc` is `time.Local`. We need keep an eye on this. +func zone(sctx sessionctx.Context) (string, int64) { + loc := sctx.GetSessionVars().Location() _, offset := time.Now().In(loc).Zone() - return int64(offset) + var name string + name = loc.String() + if name == "Local" { + name = "System" + } + + return name, int64(offset) } // statementContextToFlags converts StatementContext to tipb.SelectRequest.Flags. diff --git a/executor/executor_test.go b/executor/executor_test.go index 3b8cd21c326e5..6f14d5cc3242b 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -1938,6 +1938,7 @@ func (s *testSuite) TestTimestampTimeZone(c *C) { r.Check(testkit.Rows("123381351 1734 2014-03-31 08:57:10 127.0.0.1")) // Cover IndexLookupExec // For issue https://github.com/pingcap/tidb/issues/3485 + tk.MustExec("set time_zone = 'Asia/Shanghai'") tk.MustExec("drop table if exists t1") tk.MustExec(`CREATE TABLE t1 ( id bigint(20) NOT NULL AUTO_INCREMENT, diff --git a/executor/prepared.go b/executor/prepared.go index 4a25584cc5fa3..08e2caa7691d4 100644 --- a/executor/prepared.go +++ b/executor/prepared.go @@ -264,7 +264,7 @@ func CompileExecutePreparedStmt(ctx sessionctx.Context, ID uint32, args ...inter func ResetStmtCtx(ctx sessionctx.Context, s ast.StmtNode) (err error) { sessVars := ctx.GetSessionVars() sc := new(stmtctx.StatementContext) - sc.TimeZone = sessVars.GetTimeZone() + sc.TimeZone = sessVars.Location() sc.MemTracker = memory.NewTracker(s.Text(), sessVars.MemQuotaQuery) switch config.GetGlobalConfig().OOMAction { case config.OOMActionCancel: diff --git a/expression/builtin_time.go b/expression/builtin_time.go index e9d191c472020..c6f92266fd5a7 100644 --- a/expression/builtin_time.go +++ b/expression/builtin_time.go @@ -1889,8 +1889,8 @@ func (b *builtinSysDateWithFspSig) evalTime(row types.Row) (d types.Time, isNull return types.Time{}, isNull, errors.Trace(err) } - tz := b.ctx.GetSessionVars().GetTimeZone() - now := time.Now().In(tz) + loc := b.ctx.GetSessionVars().Location() + now := time.Now().In(loc) result, err := convertTimeToMysqlTime(now, int(fsp)) if err != nil { return types.Time{}, true, errors.Trace(err) @@ -1911,7 +1911,7 @@ func (b *builtinSysDateWithoutFspSig) Clone() builtinFunc { // evalTime evals SYSDATE(). // See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_sysdate func (b *builtinSysDateWithoutFspSig) evalTime(row types.Row) (d types.Time, isNull bool, err error) { - tz := b.ctx.GetSessionVars().GetTimeZone() + tz := b.ctx.GetSessionVars().Location() now := time.Now().In(tz) result, err := convertTimeToMysqlTime(now, 0) if err != nil { @@ -1947,7 +1947,7 @@ func (b *builtinCurrentDateSig) Clone() builtinFunc { // evalTime evals CURDATE(). // See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_curdate func (b *builtinCurrentDateSig) evalTime(row types.Row) (d types.Time, isNull bool, err error) { - tz := b.ctx.GetSessionVars().GetTimeZone() + tz := b.ctx.GetSessionVars().Location() year, month, day := time.Now().In(tz).Date() result := types.Time{ Time: types.FromDate(year, int(month), day, 0, 0, 0, 0), @@ -2002,7 +2002,7 @@ func (b *builtinCurrentTime0ArgSig) Clone() builtinFunc { } func (b *builtinCurrentTime0ArgSig) evalDuration(row types.Row) (types.Duration, bool, error) { - tz := b.ctx.GetSessionVars().GetTimeZone() + tz := b.ctx.GetSessionVars().Location() dur := time.Now().In(tz).Format(types.TimeFormat) res, err := types.ParseDuration(dur, types.MinFsp) if err != nil { @@ -2026,7 +2026,7 @@ func (b *builtinCurrentTime1ArgSig) evalDuration(row types.Row) (types.Duration, if err != nil { return types.Duration{}, true, errors.Trace(err) } - tz := b.ctx.GetSessionVars().GetTimeZone() + tz := b.ctx.GetSessionVars().Location() dur := time.Now().In(tz).Format(types.TimeFSPFormat) res, err := types.ParseDuration(dur, int(fsp)) if err != nil { @@ -2310,7 +2310,7 @@ func evalNowWithFsp(ctx sessionctx.Context, fsp int) (types.Time, bool, error) { return types.Time{}, true, errors.Trace(err) } - err = result.ConvertTimeZone(time.Local, ctx.GetSessionVars().GetTimeZone()) + err = result.ConvertTimeZone(time.Local, ctx.GetSessionVars().Location()) if err != nil { return types.Time{}, true, errors.Trace(err) } diff --git a/expression/builtin_time_test.go b/expression/builtin_time_test.go index b74f41ed6874e..381a69aff0721 100644 --- a/expression/builtin_time_test.go +++ b/expression/builtin_time_test.go @@ -2212,7 +2212,7 @@ func (s *testEvaluatorSuite) TestLastDay(c *C) { func (s *testEvaluatorSuite) TestWithTimeZone(c *C) { sv := s.ctx.GetSessionVars() - originTZ := sv.GetTimeZone() + originTZ := sv.Location() sv.TimeZone, _ = time.LoadLocation("Asia/Tokyo") defer func() { sv.TimeZone = originTZ diff --git a/expression/helper.go b/expression/helper.go index 9210cf47dbafe..a7bc83fcb7770 100644 --- a/expression/helper.go +++ b/expression/helper.go @@ -59,7 +59,7 @@ func GetTimeValue(ctx sessionctx.Context, v interface{}, tp byte, fsp int) (d ty if upperX == strings.ToUpper(ast.CurrentTimestamp) { value.Time = types.FromGoTime(defaultTime) if tp == mysql.TypeTimestamp { - err = value.ConvertTimeZone(time.Local, ctx.GetSessionVars().GetTimeZone()) + err = value.ConvertTimeZone(time.Local, ctx.GetSessionVars().Location()) if err != nil { return d, errors.Trace(err) } diff --git a/expression/integration_test.go b/expression/integration_test.go index 6d86f04e9f8d5..26239df23b86f 100644 --- a/expression/integration_test.go +++ b/expression/integration_test.go @@ -2663,7 +2663,7 @@ func (s *testIntegrationSuite) TestCompareBuiltin(c *C) { tk.MustExec(`insert into t2 values(1, 1.1, "2017-08-01 12:01:01", "12:01:01", "abcdef", 0b10101)`) result = tk.MustQuery("select coalesce(NULL, a), coalesce(NULL, b, a), coalesce(c, NULL, a, b), coalesce(d, NULL), coalesce(d, c), coalesce(NULL, NULL, e, 1), coalesce(f), coalesce(1, a, b, c, d, e, f) from t2") - result.Check(testkit.Rows(fmt.Sprintf("1 1.1 2017-08-01 12:01:01 12:01:01 %s 12:01:01 abcdef 21 1", time.Now().In(tk.Se.GetSessionVars().GetTimeZone()).Format("2006-01-02")))) + result.Check(testkit.Rows(fmt.Sprintf("1 1.1 2017-08-01 12:01:01 12:01:01 %s 12:01:01 abcdef 21 1", time.Now().In(tk.Se.GetSessionVars().Location()).Format("2006-01-02")))) // nullif result = tk.MustQuery(`SELECT NULLIF(NULL, 1), NULLIF(1, NULL), NULLIF(1, 1), NULLIF(NULL, NULL);`) @@ -2727,9 +2727,24 @@ func (s *testIntegrationSuite) TestCompareBuiltin(c *C) { result = tk.MustQuery(`select least(cast("2017-01-01" as datetime), "123", "234", cast("2018-01-01" as date)), least(cast("2017-01-01" as date), "123", null)`) result.Check(testkit.Rows("123 ")) tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1292|invalid time format: '123'", "Warning|1292|invalid time format: '234'", "Warning|1292|invalid time format: '123'")) - tk.MustQuery(`select 1 < 17666000000000000000, 1 > 17666000000000000000, 1 = 17666000000000000000`).Check(testkit.Rows("1 0 0")) + tk.MustExec("drop table if exists t") + // insert value at utc timezone + tk.MustExec("set time_zone = '+00:00'") + tk.MustExec("create table t(a timestamp)") + tk.MustExec("insert into t value('1991-05-06 04:59:28')") + // check daylight saving time in Asia/Shanghai + tk.MustExec("set time_zone='Asia/Shanghai'") + tk.MustQuery("select * from t").Check(testkit.Rows("1991-05-06 13:59:28")) + // insert an nonexistent time + tk.MustExec("set time_zone = 'America/Los_Angeles'") + _, err := tk.Exec("insert into t value('2011-03-13 02:00:00')") + c.Assert(err, NotNil) + // reset timezone to a +8 offset + tk.MustExec("set time_zone = '+08:00'") + tk.MustQuery("select * from t").Check(testkit.Rows("1991-05-06 12:59:28")) + tk.MustExec("drop table if exists t") tk.MustExec("create table t(a bigint unsigned)") tk.MustExec("insert into t value(17666000000000000000)") diff --git a/sessionctx/variable/session.go b/sessionctx/variable/session.go index daa5a456a3fe3..05bbd02b538bf 100644 --- a/sessionctx/variable/session.go +++ b/sessionctx/variable/session.go @@ -407,8 +407,8 @@ func (s *SessionVars) GetNextPreparedStmtID() uint32 { return s.preparedStmtID } -// GetTimeZone returns the value of time_zone session variable. -func (s *SessionVars) GetTimeZone() *time.Location { +// Location returns the value of time_zone session variable. If it is nil, then return time.Local. +func (s *SessionVars) Location() *time.Location { loc := s.TimeZone if loc == nil { loc = time.Local diff --git a/store/mockstore/mocktikv/cop_handler_dag.go b/store/mockstore/mocktikv/cop_handler_dag.go index a6f06f14ac06b..74c7848f79a11 100644 --- a/store/mockstore/mocktikv/cop_handler_dag.go +++ b/store/mockstore/mocktikv/cop_handler_dag.go @@ -15,7 +15,9 @@ package mocktikv import ( "bytes" + "fmt" "io" + "sync" "time" "github.com/golang/protobuf/proto" @@ -43,6 +45,50 @@ import ( var dummySlice = make([]byte, 0) +// locCache is a simple map with lock. It stores all used timezone during the lifetime of tidb instance. +// Talked with Golang team about whether they can have some forms of cache policy available for programmer, +// they suggests that only programmers knows which one is best for their use case. +// For detail, please refer to: https://github.com/golang/go/issues/26106 +type locCache struct { + sync.RWMutex + // locMap stores locations used in past and can be retrieved by a timezone's name. + locMap map[string]*time.Location +} + +// init initializes `locCache`. +func init() { + LocCache = &locCache{} + LocCache.locMap = make(map[string]*time.Location) +} + +// LocCache is a simple cache policy to improve the performance of 'time.LoadLocation'. +var LocCache *locCache + +// getLoc first trying to load location from a cache map. If nothing found in such map, then call +// `time.LocadLocation` to get a timezone location. After trying both way, an error wil be returned +// if valid Location is not found. +func (lm *locCache) getLoc(name string) (*time.Location, error) { + if name == "System" { + name = "Local" + } + lm.RLock() + if v, ok := lm.locMap[name]; ok { + lm.RUnlock() + return v, nil + } + + if loc, err := time.LoadLocation(name); err == nil { + lm.RUnlock() + lm.Lock() + lm.locMap[name] = loc + lm.Unlock() + return loc, nil + } + + lm.RUnlock() + return nil, errors.New(fmt.Sprintf("invalid name for timezone %s", name)) +} + type dagContext struct { dagReq *tipb.DAGRequest keyRanges []*coprocessor.KeyRange @@ -100,7 +146,17 @@ func (h *rpcHandler) buildDAGExecutor(req *coprocessor.Request) (*dagContext, ex return nil, nil, nil, errors.Trace(err) } sc := flagsToStatementContext(dagReq.Flags) - sc.TimeZone = time.FixedZone("UTC", int(dagReq.TimeZoneOffset)) + + // retrieving timezone by name first. When name is set, it means we need + // consider daylight saving time. If it is not, we can use offset. + if dagReq.TimeZoneName != "" { + if sc.TimeZone, err = LocCache.getLoc(dagReq.TimeZoneName); err != nil { + return nil, nil, nil, errors.Trace(err) + } + dagReq.TimeZoneName = sc.TimeZone.String() + } else { + sc.TimeZone = time.FixedZone("UTC", int(dagReq.TimeZoneOffset)) + } ctx := &dagContext{ dagReq: dagReq, keyRanges: req.Ranges, diff --git a/store/tikv/gcworker/gc_worker.go b/store/tikv/gcworker/gc_worker.go index bcf1709fc57df..d29c4b91b6022 100644 --- a/store/tikv/gcworker/gc_worker.go +++ b/store/tikv/gcworker/gc_worker.go @@ -240,7 +240,7 @@ func (w *GCWorker) leaderTick(ctx context.Context) error { return nil } -// prepare checks required conditions for starting a GC job. It returns a bool +// prepare checks preconditions for starting a GC job. It returns a bool // that indicates whether the GC job should start and the new safePoint. func (w *GCWorker) prepare() (bool, uint64, error) { now, err := w.getOracleTime() @@ -255,11 +255,11 @@ func (w *GCWorker) prepare() (bool, uint64, error) { if err != nil || newSafePoint == nil { return false, 0, errors.Trace(err) } - err = w.saveTime(gcLastRunTimeKey, now, w.session) + err = w.saveTime(gcLastRunTimeKey, now) if err != nil { return false, 0, errors.Trace(err) } - err = w.saveTime(gcSafePointKey, *newSafePoint, w.session) + err = w.saveTime(gcSafePointKey, *newSafePoint) if err != nil { return false, 0, errors.Trace(err) } @@ -282,7 +282,7 @@ func (w *GCWorker) checkGCInterval(now time.Time) (bool, error) { return false, errors.Trace(err) } gcConfigGauge.WithLabelValues(gcRunIntervalKey).Set(runInterval.Seconds()) - lastRun, err := w.loadTime(gcLastRunTimeKey, w.session) + lastRun, err := w.loadTime(gcLastRunTimeKey) if err != nil { return false, errors.Trace(err) } @@ -300,7 +300,7 @@ func (w *GCWorker) calculateNewSafePoint(now time.Time) (*time.Time, error) { return nil, errors.Trace(err) } gcConfigGauge.WithLabelValues(gcLifeTimeKey).Set(lifeTime.Seconds()) - lastSafePoint, err := w.loadTime(gcSafePointKey, w.session) + lastSafePoint, err := w.loadTime(gcSafePointKey) if err != nil { return nil, errors.Trace(err) } @@ -379,12 +379,12 @@ func (w *GCWorker) deleteRanges(ctx context.Context, safePoint uint64) error { } func (w *GCWorker) loadGCConcurrencyWithDefault() (int, error) { - str, err := w.loadValueFromSysTable(gcConcurrencyKey, w.session) + str, err := w.loadValueFromSysTable(gcConcurrencyKey) if err != nil { return gcDefaultConcurrency, errors.Trace(err) } if str == "" { - err = w.saveValueToSysTable(gcConcurrencyKey, strconv.Itoa(gcDefaultConcurrency), w.session) + err = w.saveValueToSysTable(gcConcurrencyKey, strconv.Itoa(gcDefaultConcurrency)) if err != nil { return gcDefaultConcurrency, errors.Trace(err) } @@ -711,7 +711,8 @@ func (w *GCWorker) checkLeader() (bool, error) { if err != nil { return false, errors.Trace(err) } - leader, err := w.loadValueFromSysTable(gcLeaderUUIDKey, se) + w.session = se + leader, err := w.loadValueFromSysTable(gcLeaderUUIDKey) if err != nil { _, err1 := se.Execute(ctx, "ROLLBACK") terror.Log(errors.Trace(err1)) @@ -719,7 +720,7 @@ func (w *GCWorker) checkLeader() (bool, error) { } log.Debugf("[gc worker] got leader: %s", leader) if leader == w.uuid { - err = w.saveTime(gcLeaderLeaseKey, time.Now().Add(gcWorkerLease), se) + err = w.saveTime(gcLeaderLeaseKey, time.Now().Add(gcWorkerLease)) if err != nil { _, err1 := se.Execute(ctx, "ROLLBACK") terror.Log(errors.Trace(err1)) @@ -739,7 +740,7 @@ func (w *GCWorker) checkLeader() (bool, error) { if err != nil { return false, errors.Trace(err) } - lease, err := w.loadTime(gcLeaderLeaseKey, se) + lease, err := w.loadTime(gcLeaderLeaseKey) if err != nil { return false, errors.Trace(err) } @@ -747,19 +748,19 @@ func (w *GCWorker) checkLeader() (bool, error) { log.Debugf("[gc worker] register %s as leader", w.uuid) gcWorkerCounter.WithLabelValues("register_leader").Inc() - err = w.saveValueToSysTable(gcLeaderUUIDKey, w.uuid, se) + err = w.saveValueToSysTable(gcLeaderUUIDKey, w.uuid) if err != nil { _, err1 := se.Execute(ctx, "ROLLBACK") terror.Log(errors.Trace(err1)) return false, errors.Trace(err) } - err = w.saveValueToSysTable(gcLeaderDescKey, w.desc, se) + err = w.saveValueToSysTable(gcLeaderDescKey, w.desc) if err != nil { _, err1 := se.Execute(ctx, "ROLLBACK") terror.Log(errors.Trace(err1)) return false, errors.Trace(err) } - err = w.saveTime(gcLeaderLeaseKey, time.Now().Add(gcWorkerLease), se) + err = w.saveTime(gcLeaderLeaseKey, time.Now().Add(gcWorkerLease)) if err != nil { _, err1 := se.Execute(ctx, "ROLLBACK") terror.Log(errors.Trace(err1)) @@ -786,13 +787,13 @@ func (w *GCWorker) saveSafePoint(kv tikv.SafePointKV, key string, t uint64) erro return nil } -func (w *GCWorker) saveTime(key string, t time.Time, s session.Session) error { - err := w.saveValueToSysTable(key, t.Format(gcTimeFormat), s) +func (w *GCWorker) saveTime(key string, t time.Time) error { + err := w.saveValueToSysTable(key, t.Format(gcTimeFormat)) return errors.Trace(err) } -func (w *GCWorker) loadTime(key string, s session.Session) (*time.Time, error) { - str, err := w.loadValueFromSysTable(key, s) +func (w *GCWorker) loadTime(key string) (*time.Time, error) { + str, err := w.loadValueFromSysTable(key) if err != nil { return nil, errors.Trace(err) } @@ -807,12 +808,12 @@ func (w *GCWorker) loadTime(key string, s session.Session) (*time.Time, error) { } func (w *GCWorker) saveDuration(key string, d time.Duration) error { - err := w.saveValueToSysTable(key, d.String(), w.session) + err := w.saveValueToSysTable(key, d.String()) return errors.Trace(err) } func (w *GCWorker) loadDuration(key string) (*time.Duration, error) { - str, err := w.loadValueFromSysTable(key, w.session) + str, err := w.loadValueFromSysTable(key) if err != nil { return nil, errors.Trace(err) } @@ -841,10 +842,10 @@ func (w *GCWorker) loadDurationWithDefault(key string, def time.Duration) (*time return d, nil } -func (w *GCWorker) loadValueFromSysTable(key string, s session.Session) (string, error) { +func (w *GCWorker) loadValueFromSysTable(key string) (string, error) { ctx := context.Background() stmt := fmt.Sprintf(`SELECT HIGH_PRIORITY (variable_value) FROM mysql.tidb WHERE variable_name='%s' FOR UPDATE`, key) - rs, err := s.Execute(ctx, stmt) + rs, err := w.session.Execute(ctx, stmt) if len(rs) > 0 { defer terror.Call(rs[0].Close) } @@ -865,15 +866,15 @@ func (w *GCWorker) loadValueFromSysTable(key string, s session.Session) (string, return value, nil } -func (w *GCWorker) saveValueToSysTable(key, value string, s session.Session) error { +func (w *GCWorker) saveValueToSysTable(key, value string) error { stmt := fmt.Sprintf(`INSERT INTO mysql.tidb VALUES ('%[1]s', '%[2]s', '%[3]s') ON DUPLICATE KEY UPDATE variable_value = '%[2]s', comment = '%[3]s'`, key, value, gcVariableComments[key]) - if s == nil { + if w.session == nil { return errors.New("[saveValueToSysTable session is nil]") } - _, err := s.Execute(context.Background(), stmt) + _, err := w.session.Execute(context.Background(), stmt) log.Debugf("[gc worker] save kv, %s:%s %v", key, value, err) return errors.Trace(err) } diff --git a/store/tikv/gcworker/gc_worker_test.go b/store/tikv/gcworker/gc_worker_test.go index 2197fb5d77300..f2d7da9b70600 100644 --- a/store/tikv/gcworker/gc_worker_test.go +++ b/store/tikv/gcworker/gc_worker_test.go @@ -86,10 +86,10 @@ func (s *testGCWorkerSuite) TestPrepareGC(c *C) { close(s.gcWorker.done) ok, _, err := s.gcWorker.prepare() c.Assert(err, IsNil) - lastRun, err := s.gcWorker.loadTime(gcLastRunTimeKey, s.gcWorker.session) + lastRun, err := s.gcWorker.loadTime(gcLastRunTimeKey) c.Assert(err, IsNil) c.Assert(lastRun, NotNil) - safePoint, err := s.gcWorker.loadTime(gcSafePointKey, s.gcWorker.session) + safePoint, err := s.gcWorker.loadTime(gcSafePointKey) c.Assert(err, IsNil) s.timeEqual(c, safePoint.Add(gcDefaultLifeTime), now, 2*time.Second) @@ -118,7 +118,7 @@ func (s *testGCWorkerSuite) TestPrepareGC(c *C) { ok, _, err = s.gcWorker.prepare() c.Assert(err, IsNil) c.Assert(ok, IsTrue) - safePoint, err = s.gcWorker.loadTime(gcSafePointKey, s.gcWorker.session) + safePoint, err = s.gcWorker.loadTime(gcSafePointKey) c.Assert(err, IsNil) s.timeEqual(c, safePoint.Add(time.Minute*30), now, 2*time.Second) @@ -127,19 +127,19 @@ func (s *testGCWorkerSuite) TestPrepareGC(c *C) { c.Assert(err, IsNil) c.Assert(concurrency, Equals, gcDefaultConcurrency) - err = s.gcWorker.saveValueToSysTable(gcConcurrencyKey, strconv.Itoa(gcMinConcurrency), s.gcWorker.session) + err = s.gcWorker.saveValueToSysTable(gcConcurrencyKey, strconv.Itoa(gcMinConcurrency)) c.Assert(err, IsNil) concurrency, err = s.gcWorker.loadGCConcurrencyWithDefault() c.Assert(err, IsNil) c.Assert(concurrency, Equals, gcMinConcurrency) - err = s.gcWorker.saveValueToSysTable(gcConcurrencyKey, strconv.Itoa(-1), s.gcWorker.session) + err = s.gcWorker.saveValueToSysTable(gcConcurrencyKey, strconv.Itoa(-1)) c.Assert(err, IsNil) concurrency, err = s.gcWorker.loadGCConcurrencyWithDefault() c.Assert(err, IsNil) c.Assert(concurrency, Equals, gcMinConcurrency) - err = s.gcWorker.saveValueToSysTable(gcConcurrencyKey, strconv.Itoa(1000000), s.gcWorker.session) + err = s.gcWorker.saveValueToSysTable(gcConcurrencyKey, strconv.Itoa(1000000)) c.Assert(err, IsNil) concurrency, err = s.gcWorker.loadGCConcurrencyWithDefault() c.Assert(err, IsNil) @@ -185,17 +185,17 @@ func (s *testGCWorkerSuite) TestDoGC(c *C) { gcSafePointCacheInterval = 1 - err = s.gcWorker.saveValueToSysTable(gcConcurrencyKey, strconv.Itoa(gcDefaultConcurrency), s.gcWorker.session) + err = s.gcWorker.saveValueToSysTable(gcConcurrencyKey, strconv.Itoa(gcDefaultConcurrency)) c.Assert(err, IsNil) err = s.gcWorker.doGC(ctx, 20) c.Assert(err, IsNil) - err = s.gcWorker.saveValueToSysTable(gcConcurrencyKey, strconv.Itoa(gcMinConcurrency), s.gcWorker.session) + err = s.gcWorker.saveValueToSysTable(gcConcurrencyKey, strconv.Itoa(gcMinConcurrency)) c.Assert(err, IsNil) err = s.gcWorker.doGC(ctx, 20) c.Assert(err, IsNil) - err = s.gcWorker.saveValueToSysTable(gcConcurrencyKey, strconv.Itoa(gcMaxConcurrency), s.gcWorker.session) + err = s.gcWorker.saveValueToSysTable(gcConcurrencyKey, strconv.Itoa(gcMaxConcurrency)) c.Assert(err, IsNil) err = s.gcWorker.doGC(ctx, 20) c.Assert(err, IsNil) diff --git a/table/tables/tables.go b/table/tables/tables.go index 6777c117cffd4..39050fc3424b6 100644 --- a/table/tables/tables.go +++ b/table/tables/tables.go @@ -583,7 +583,7 @@ func DecodeRawRowData(ctx sessionctx.Context, meta *model.TableInfo, h int64, co } colTps[col.ID] = &col.FieldType } - rowMap, err := tablecodec.DecodeRow(value, colTps, ctx.GetSessionVars().GetTimeZone()) + rowMap, err := tablecodec.DecodeRow(value, colTps, ctx.GetSessionVars().Location()) if err != nil { return nil, rowMap, errors.Trace(err) } @@ -765,7 +765,7 @@ func (t *tableCommon) IterRecords(ctx sessionctx.Context, startKey kv.Key, cols if err != nil { return errors.Trace(err) } - rowMap, err := tablecodec.DecodeRow(it.Value(), colMap, ctx.GetSessionVars().GetTimeZone()) + rowMap, err := tablecodec.DecodeRow(it.Value(), colMap, ctx.GetSessionVars().Location()) if err != nil { return errors.Trace(err) } diff --git a/util/admin/admin.go b/util/admin/admin.go index da1b8e5d48785..5517b84f628ac 100644 --- a/util/admin/admin.go +++ b/util/admin/admin.go @@ -295,7 +295,7 @@ func checkIndexAndRecord(sessCtx sessionctx.Context, txn kv.Transaction, t table return errors.Trace(err) } - vals1, err = tablecodec.UnflattenDatums(vals1, fieldTypes, sessCtx.GetSessionVars().GetTimeZone()) + vals1, err = tablecodec.UnflattenDatums(vals1, fieldTypes, sessCtx.GetSessionVars().Location()) if err != nil { return errors.Trace(err) } @@ -495,7 +495,7 @@ func rowWithCols(sessCtx sessionctx.Context, txn kv.Retriever, t table.Table, h } colTps[col.ID] = &col.FieldType } - row, err := tablecodec.DecodeRow(value, colTps, sessCtx.GetSessionVars().GetTimeZone()) + row, err := tablecodec.DecodeRow(value, colTps, sessCtx.GetSessionVars().Location()) if err != nil { return nil, errors.Trace(err) } @@ -556,7 +556,7 @@ func iterRecords(sessCtx sessionctx.Context, retriever kv.Retriever, t table.Tab return errors.Trace(err) } - rowMap, err := tablecodec.DecodeRow(it.Value(), colMap, sessCtx.GetSessionVars().GetTimeZone()) + rowMap, err := tablecodec.DecodeRow(it.Value(), colMap, sessCtx.GetSessionVars().Location()) if err != nil { return errors.Trace(err) }