From 59927c5b7d643cdfcbcd4e84d62b42ced437659b Mon Sep 17 00:00:00 2001 From: wjHuang Date: Wed, 8 Feb 2023 12:21:58 +0800 Subject: [PATCH 1/2] This is an automated cherry-pick of #41146 Signed-off-by: ti-chi-bot --- br/pkg/task/backup.go | 10 +++++ ddl/ddl_api.go | 9 ++++- executor/brie.go | 2 +- executor/executor_test.go | 2 +- executor/inspection_result_test.go | 10 ++--- executor/inspection_summary_test.go | 2 +- executor/write.go | 2 +- expression/builtin_cast.go | 47 +++++++++++++++++++++- expression/builtin_cast_vec.go | 52 +++++++++++++++++++++++- expression/builtin_time.go | 14 +++---- expression/builtin_time_vec.go | 4 +- expression/helper.go | 6 +-- expression/helper_test.go | 16 ++++---- planner/core/expression_rewriter.go | 2 +- server/statistics_handler.go | 2 +- server/util_test.go | 2 +- sessionctx/variable/varsutil.go | 4 +- table/column.go | 12 +++--- types/convert.go | 2 +- types/convert_test.go | 7 ++-- types/datum.go | 8 ++-- types/datum_test.go | 27 ++++++++++++- types/format_test.go | 2 +- types/time.go | 62 ++++++++++++++++++----------- types/time_test.go | 53 ++++++++++++++++-------- util/codec/codec_test.go | 2 +- util/dbutil/common.go | 2 +- util/rowcodec/rowcodec_test.go | 2 +- 28 files changed, 265 insertions(+), 100 deletions(-) diff --git a/br/pkg/task/backup.go b/br/pkg/task/backup.go index 1eabae944b46e..cc25ec5edda45 100644 --- a/br/pkg/task/backup.go +++ b/br/pkg/task/backup.go @@ -543,7 +543,17 @@ func ParseTSString(ts string) (uint64, error) { sc := &stmtctx.StatementContext{ TimeZone: loc, } +<<<<<<< HEAD t, err := types.ParseTime(sc, ts, mysql.TypeTimestamp, types.MaxFsp) +======= + if tzCheck { + tzIdx, _, _, _, _ := types.GetTimezone(ts) + if tzIdx < 0 { + return 0, errors.Errorf("must set timezone when using datetime format ts, e.g. '2018-05-11 01:42:23+0800'") + } + } + t, err := types.ParseTime(sc, ts, mysql.TypeTimestamp, types.MaxFsp, nil) +>>>>>>> 8398f0fe098 (*: fix a timezone data race which may cause wrong row data (#41146)) if err != nil { return 0, errors.Trace(err) } diff --git a/ddl/ddl_api.go b/ddl/ddl_api.go index a7af99577e006..4205e452a0f02 100644 --- a/ddl/ddl_api.go +++ b/ddl/ddl_api.go @@ -820,7 +820,7 @@ func checkColumnDefaultValue(ctx sessionctx.Context, col *table.Column, value in if value != nil && ctx.GetSessionVars().SQLMode.HasNoZeroDateMode() && ctx.GetSessionVars().SQLMode.HasStrictMode() && types.IsTypeTime(col.GetType()) { if vv, ok := value.(string); ok { - timeValue, err := expression.GetTimeValue(ctx, vv, col.GetType(), col.GetDecimal()) + timeValue, err := expression.GetTimeValue(ctx, vv, col.GetType(), col.GetDecimal(), nil) if err != nil { return hasDefaultValue, value, errors.Trace(err) } @@ -845,7 +845,7 @@ func convertTimestampDefaultValToUTC(ctx sessionctx.Context, defaultVal interfac } if vv, ok := defaultVal.(string); ok { if vv != types.ZeroDatetimeStr && !strings.EqualFold(vv, ast.CurrentTimestamp) { - t, err := types.ParseTime(ctx.GetSessionVars().StmtCtx, vv, col.GetType(), col.GetDecimal()) + t, err := types.ParseTime(ctx.GetSessionVars().StmtCtx, vv, col.GetType(), col.GetDecimal(), nil) if err != nil { return defaultVal, errors.Trace(err) } @@ -1092,8 +1092,13 @@ func getDefaultValue(ctx sessionctx.Context, col *table.Column, option *ast.Colu // If the function call is ast.CurrentTimestamp, it needs to be continuously processed. } +<<<<<<< HEAD if tp == mysql.TypeTimestamp || tp == mysql.TypeDatetime { vd, err := expression.GetTimeValue(ctx, option.Expr, tp, fsp) +======= + if tp == mysql.TypeTimestamp || tp == mysql.TypeDatetime || tp == mysql.TypeDate { + vd, err := expression.GetTimeValue(ctx, option.Expr, tp, fsp, nil) +>>>>>>> 8398f0fe098 (*: fix a timezone data race which may cause wrong row data (#41146)) value := vd.GetValue() if err != nil { return nil, false, dbterror.ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) diff --git a/executor/brie.go b/executor/brie.go index 9eeb4e48cbdd5..7ca4f10c5da4a 100644 --- a/executor/brie.go +++ b/executor/brie.go @@ -188,7 +188,7 @@ func (bq *brieQueue) clearTask(sc *stmtctx.StatementContext) { func (b *executorBuilder) parseTSString(ts string) (uint64, error) { sc := &stmtctx.StatementContext{TimeZone: b.ctx.GetSessionVars().Location()} - t, err := types.ParseTime(sc, ts, mysql.TypeTimestamp, types.MaxFsp) + t, err := types.ParseTime(sc, ts, mysql.TypeTimestamp, types.MaxFsp, nil) if err != nil { return 0, err } diff --git a/executor/executor_test.go b/executor/executor_test.go index a2826d882bc76..de7903c21664e 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -2497,7 +2497,7 @@ func TestTimestampDefaultValueTimeZone(t *testing.T) { tk.MustExec(`set time_zone = '+00:00'`) timeIn0 := tk.MustQuery("select b from t").Rows()[0][0] require.NotEqual(t, timeIn8, timeIn0) - datumTimeIn8, err := expression.GetTimeValue(tk.Session(), timeIn8, mysql.TypeTimestamp, 0) + datumTimeIn8, err := expression.GetTimeValue(tk.Session(), timeIn8, mysql.TypeTimestamp, 0, nil) require.NoError(t, err) tIn8To0 := datumTimeIn8.GetMysqlTime() timeZoneIn8, err := time.LoadLocation("Asia/Shanghai") diff --git a/executor/inspection_result_test.go b/executor/inspection_result_test.go index d53040dcfff8e..2cd5628cc76ad 100644 --- a/executor/inspection_result_test.go +++ b/executor/inspection_result_test.go @@ -181,7 +181,7 @@ func TestInspectionResult(t *testing.T) { } func parseTime(t *testing.T, se session.Session, str string) types.Time { - time, err := types.ParseTime(se.GetSessionVars().StmtCtx, str, mysql.TypeDatetime, types.MaxFsp) + time, err := types.ParseTime(se.GetSessionVars().StmtCtx, str, mysql.TypeDatetime, types.MaxFsp, nil) require.NoError(t, err) return time } @@ -342,7 +342,7 @@ func TestThresholdCheckInspection2(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") datetime := func(s string) types.Time { - time, err := types.ParseTime(tk.Session().GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp) + time, err := types.ParseTime(tk.Session().GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp, nil) require.NoError(t, err) return time } @@ -427,7 +427,7 @@ func TestThresholdCheckInspection3(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") datetime := func(s string) types.Time { - time, err := types.ParseTime(tk.Session().GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp) + time, err := types.ParseTime(tk.Session().GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp, nil) require.NoError(t, err) return time } @@ -638,7 +638,7 @@ func TestNodeLoadInspection(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") datetime := func(s string) types.Time { - time, err := types.ParseTime(tk.Session().GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp) + time, err := types.ParseTime(tk.Session().GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp, nil) require.NoError(t, err) return time } @@ -716,7 +716,7 @@ func TestConfigCheckOfStorageBlockCacheSize(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") datetime := func(s string) types.Time { - time, err := types.ParseTime(tk.Session().GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp) + time, err := types.ParseTime(tk.Session().GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp, nil) require.NoError(t, err) return time } diff --git a/executor/inspection_summary_test.go b/executor/inspection_summary_test.go index 4b1f1c0819f1c..6a94e8c7dc059 100644 --- a/executor/inspection_summary_test.go +++ b/executor/inspection_summary_test.go @@ -52,7 +52,7 @@ func TestInspectionSummary(t *testing.T) { defer func() { require.NoError(t, failpoint.Disable(fpName)) }() datetime := func(s string) types.Time { - time, err := types.ParseTime(tk.Session().GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp) + time, err := types.ParseTime(tk.Session().GetSessionVars().StmtCtx, s, mysql.TypeDatetime, types.MaxFsp, nil) require.NoError(t, err) return time } diff --git a/executor/write.go b/executor/write.go index 7c9aba9331c4d..5f1fae779cb03 100644 --- a/executor/write.go +++ b/executor/write.go @@ -147,7 +147,7 @@ func updateRecord(ctx context.Context, sctx sessionctx.Context, h kv.Handle, old // Fill values into on-update-now fields, only if they are really changed. for i, col := range t.Cols() { if mysql.HasOnUpdateNowFlag(col.GetFlag()) && !modified[i] && !onUpdateSpecified[i] { - if v, err := expression.GetTimeValue(sctx, strings.ToUpper(ast.CurrentTimestamp), col.GetType(), col.GetDecimal()); err == nil { + if v, err := expression.GetTimeValue(sctx, strings.ToUpper(ast.CurrentTimestamp), col.GetType(), col.GetDecimal(), nil); err == nil { newData[i] = v modified[i] = true } else { diff --git a/expression/builtin_cast.go b/expression/builtin_cast.go index ac580985a8e54..e32de65e3256f 100644 --- a/expression/builtin_cast.go +++ b/expression/builtin_cast.go @@ -1288,7 +1288,7 @@ func (b *builtinCastStringAsTimeSig) evalTime(row chunk.Row) (res types.Time, is return res, isNull, err } sc := b.ctx.GetSessionVars().StmtCtx - res, err = types.ParseTime(sc, val, b.tp.GetType(), b.tp.GetDecimal()) + res, err = types.ParseTime(sc, val, b.tp.GetType(), b.tp.GetDecimal(), nil) if err != nil { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) } @@ -1729,9 +1729,54 @@ func (b *builtinCastJSONAsTimeSig) evalTime(row chunk.Row) (res types.Time, isNu if isNull || err != nil { return res, isNull, err } +<<<<<<< HEAD s, err := val.Unquote() if err != nil { return res, false, err +======= + + switch val.TypeCode { + case types.JSONTypeCodeDate, types.JSONTypeCodeDatetime, types.JSONTypeCodeTimestamp: + res = val.GetTime() + res.SetType(b.tp.GetType()) + if b.tp.GetType() == mysql.TypeDate { + // Truncate hh:mm:ss part if the type is Date. + res.SetCoreTime(types.FromDate(res.Year(), res.Month(), res.Day(), 0, 0, 0, 0)) + } + return res, isNull, err + case types.JSONTypeCodeDuration: + duration := val.GetDuration() + + sc := b.ctx.GetSessionVars().StmtCtx + ts, err := getStmtTimestamp(b.ctx) + if err != nil { + ts = gotime.Now() + } + res, err = duration.ConvertToTimeWithTimestamp(sc, b.tp.GetType(), ts) + if err != nil { + return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) + } + res, err = res.RoundFrac(sc, b.tp.GetDecimal()) + return res, isNull, err + case types.JSONTypeCodeString: + s, err := val.Unquote() + if err != nil { + return res, false, err + } + sc := b.ctx.GetSessionVars().StmtCtx + res, err = types.ParseTime(sc, s, b.tp.GetType(), b.tp.GetDecimal(), nil) + if err != nil { + return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) + } + if b.tp.GetType() == mysql.TypeDate { + // Truncate hh:mm:ss part if the type is Date. + res.SetCoreTime(types.FromDate(res.Year(), res.Month(), res.Day(), 0, 0, 0, 0)) + } + return res, isNull, err + default: + err = types.ErrTruncatedWrongVal.GenWithStackByArgs(types.TypeStr(b.tp.GetType()), val.String()) + return res, true, b.ctx.GetSessionVars().StmtCtx.HandleTruncate(err) +>>>>>>> 8398f0fe098 (*: fix a timezone data race which may cause wrong row data (#41146)) } sc := b.ctx.GetSessionVars().StmtCtx res, err = types.ParseTime(sc, s, b.tp.GetType(), b.tp.GetDecimal()) diff --git a/expression/builtin_cast_vec.go b/expression/builtin_cast_vec.go index ee29a768dd702..b30ef15a1f4a9 100644 --- a/expression/builtin_cast_vec.go +++ b/expression/builtin_cast_vec.go @@ -492,8 +492,58 @@ func (b *builtinCastJSONAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk if err != nil { return err } +<<<<<<< HEAD tm, err := types.ParseTime(stmtCtx, s, b.tp.GetType(), fsp) if err != nil { +======= + + switch val.TypeCode { + case types.JSONTypeCodeDate, types.JSONTypeCodeDatetime, types.JSONTypeCodeTimestamp: + tm := val.GetTime() + times[i] = tm + times[i].SetType(b.tp.GetType()) + if b.tp.GetType() == mysql.TypeDate { + // Truncate hh:mm:ss part if the type is Date. + times[i].SetCoreTime(types.FromDate(tm.Year(), tm.Month(), tm.Day(), 0, 0, 0, 0)) + } + case types.JSONTypeCodeDuration: + duration := val.GetDuration() + + sc := b.ctx.GetSessionVars().StmtCtx + tm, err := duration.ConvertToTimeWithTimestamp(sc, b.tp.GetType(), ts) + if err != nil { + if err = handleInvalidTimeError(b.ctx, err); err != nil { + return err + } + result.SetNull(i, true) + continue + } + tm, err = tm.RoundFrac(stmtCtx, fsp) + if err != nil { + return err + } + times[i] = tm + case types.JSONTypeCodeString: + s, err := val.Unquote() + if err != nil { + return err + } + tm, err := types.ParseTime(stmtCtx, s, b.tp.GetType(), fsp, nil) + if err != nil { + if err = handleInvalidTimeError(b.ctx, err); err != nil { + return err + } + result.SetNull(i, true) + continue + } + times[i] = tm + if b.tp.GetType() == mysql.TypeDate { + // Truncate hh:mm:ss part if the type is Date. + times[i].SetCoreTime(types.FromDate(tm.Year(), tm.Month(), tm.Day(), 0, 0, 0, 0)) + } + default: + err = types.ErrTruncatedWrongVal.GenWithStackByArgs(types.TypeStr(b.tp.GetType()), val.String()) +>>>>>>> 8398f0fe098 (*: fix a timezone data race which may cause wrong row data (#41146)) if err = handleInvalidTimeError(b.ctx, err); err != nil { return err } @@ -1692,7 +1742,7 @@ func (b *builtinCastStringAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chu if result.IsNull(i) { continue } - tm, err := types.ParseTime(stmtCtx, buf.GetString(i), b.tp.GetType(), fsp) + tm, err := types.ParseTime(stmtCtx, buf.GetString(i), b.tp.GetType(), fsp, nil) if err != nil { if err = handleInvalidTimeError(b.ctx, err); err != nil { return err diff --git a/expression/builtin_time.go b/expression/builtin_time.go index e37399b65cf2f..49a426b4d3fb9 100644 --- a/expression/builtin_time.go +++ b/expression/builtin_time.go @@ -2778,7 +2778,7 @@ func (du *baseDateArithmetical) getDateFromString(ctx sessionctx.Context, args [ } sc := ctx.GetSessionVars().StmtCtx - date, err := types.ParseTime(sc, dateStr, dateTp, types.MaxFsp) + date, err := types.ParseTime(sc, dateStr, dateTp, types.MaxFsp, nil) if err != nil { err = handleInvalidTimeError(ctx, err) if err != nil { @@ -3057,7 +3057,7 @@ func (du *baseDateArithmetical) vecGetDateFromString(b *baseBuiltinFunc, input * dateTp = mysql.TypeDatetime } - date, err := types.ParseTime(sc, dateStr, dateTp, types.MaxFsp) + date, err := types.ParseTime(sc, dateStr, dateTp, types.MaxFsp, nil) if err != nil { err = handleInvalidTimeError(b.ctx, err) if err != nil { @@ -5175,7 +5175,7 @@ func (b *builtinTimestamp1ArgSig) evalTime(row chunk.Row) (types.Time, bool, err if b.isFloat { tm, err = types.ParseTimeFromFloatString(sc, s, mysql.TypeDatetime, types.GetFsp(s)) } else { - tm, err = types.ParseTime(sc, s, mysql.TypeDatetime, types.GetFsp(s)) + tm, err = types.ParseTime(sc, s, mysql.TypeDatetime, types.GetFsp(s), nil) } if err != nil { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) @@ -5207,7 +5207,7 @@ func (b *builtinTimestamp2ArgsSig) evalTime(row chunk.Row) (types.Time, bool, er if b.isFloat { tm, err = types.ParseTimeFromFloatString(sc, arg0, mysql.TypeDatetime, types.GetFsp(arg0)) } else { - tm, err = types.ParseTime(sc, arg0, mysql.TypeDatetime, types.GetFsp(arg0)) + tm, err = types.ParseTime(sc, arg0, mysql.TypeDatetime, types.GetFsp(arg0), nil) } if err != nil { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) @@ -5258,7 +5258,7 @@ func (c *timestampLiteralFunctionClass) getFunction(ctx sessionctx.Context, args if !timestampPattern.MatchString(str) { return nil, types.ErrWrongValue.GenWithStackByArgs(types.DateTimeStr, str) } - tm, err := types.ParseTime(ctx.GetSessionVars().StmtCtx, str, mysql.TypeDatetime, types.GetFsp(str)) + tm, err := types.ParseTime(ctx.GetSessionVars().StmtCtx, str, mysql.TypeDatetime, types.GetFsp(str), nil) if err != nil { return nil, err } @@ -5366,7 +5366,7 @@ func isDuration(str string) bool { // strDatetimeAddDuration adds duration to datetime string, returns a string value. func strDatetimeAddDuration(sc *stmtctx.StatementContext, d string, arg1 types.Duration) (result string, isNull bool, err error) { - arg0, err := types.ParseTime(sc, d, mysql.TypeDatetime, types.MaxFsp) + arg0, err := types.ParseTime(sc, d, mysql.TypeDatetime, types.MaxFsp, nil) if err != nil { // Return a warning regardless of the sql_mode, this is compatible with MySQL. sc.AppendWarning(err) @@ -5403,7 +5403,7 @@ func strDurationAddDuration(sc *stmtctx.StatementContext, d string, arg1 types.D // strDatetimeSubDuration subtracts duration from datetime string, returns a string value. func strDatetimeSubDuration(sc *stmtctx.StatementContext, d string, arg1 types.Duration) (result string, isNull bool, err error) { - arg0, err := types.ParseTime(sc, d, mysql.TypeDatetime, types.MaxFsp) + arg0, err := types.ParseTime(sc, d, mysql.TypeDatetime, types.MaxFsp, nil) if err != nil { // Return a warning regardless of the sql_mode, this is compatible with MySQL. sc.AppendWarning(err) diff --git a/expression/builtin_time_vec.go b/expression/builtin_time_vec.go index 80e6db03724d0..685b975011632 100644 --- a/expression/builtin_time_vec.go +++ b/expression/builtin_time_vec.go @@ -2669,7 +2669,7 @@ func (b *builtinTimestamp1ArgSig) vecEvalTime(input *chunk.Chunk, result *chunk. if b.isFloat { tm, err = types.ParseTimeFromFloatString(sc, s, mysql.TypeDatetime, types.GetFsp(s)) } else { - tm, err = types.ParseTime(sc, s, mysql.TypeDatetime, types.GetFsp(s)) + tm, err = types.ParseTime(sc, s, mysql.TypeDatetime, types.GetFsp(s), nil) } if err != nil { if err = handleInvalidTimeError(b.ctx, err); err != nil { @@ -2722,7 +2722,7 @@ func (b *builtinTimestamp2ArgsSig) vecEvalTime(input *chunk.Chunk, result *chunk if b.isFloat { tm, err = types.ParseTimeFromFloatString(sc, arg0, mysql.TypeDatetime, types.GetFsp(arg0)) } else { - tm, err = types.ParseTime(sc, arg0, mysql.TypeDatetime, types.GetFsp(arg0)) + tm, err = types.ParseTime(sc, arg0, mysql.TypeDatetime, types.GetFsp(arg0), nil) } if err != nil { if err = handleInvalidTimeError(b.ctx, err); err != nil { diff --git a/expression/helper.go b/expression/helper.go index b7f06a4ab8b28..cb84b5a4471af 100644 --- a/expression/helper.go +++ b/expression/helper.go @@ -84,7 +84,7 @@ func getTimeCurrentTimeStamp(ctx sessionctx.Context, tp byte, fsp int) (t types. } // GetTimeValue gets the time value with type tp. -func GetTimeValue(ctx sessionctx.Context, v interface{}, tp byte, fsp int) (d types.Datum, err error) { +func GetTimeValue(ctx sessionctx.Context, v interface{}, tp byte, fsp int, explicitTz *time.Location) (d types.Datum, err error) { var value types.Time sc := ctx.GetSessionVars().StmtCtx @@ -99,7 +99,7 @@ func GetTimeValue(ctx sessionctx.Context, v interface{}, tp byte, fsp int) (d ty value, err = types.ParseTimeFromNum(sc, 0, tp, fsp) terror.Log(err) } else { - value, err = types.ParseTime(sc, x, tp, fsp) + value, err = types.ParseTime(sc, x, tp, fsp, explicitTz) if err != nil { return d, err } @@ -107,7 +107,7 @@ func GetTimeValue(ctx sessionctx.Context, v interface{}, tp byte, fsp int) (d ty case *driver.ValueExpr: switch x.Kind() { case types.KindString: - value, err = types.ParseTime(sc, x.GetString(), tp, fsp) + value, err = types.ParseTime(sc, x.GetString(), tp, fsp, nil) if err != nil { return d, err } diff --git a/expression/helper_test.go b/expression/helper_test.go index beb69528b02cf..2f13bca6ef567 100644 --- a/expression/helper_test.go +++ b/expression/helper_test.go @@ -34,7 +34,7 @@ import ( func TestGetTimeValue(t *testing.T) { ctx := mock.NewContext() - v, err := GetTimeValue(ctx, "2012-12-12 00:00:00", mysql.TypeTimestamp, types.MinFsp) + v, err := GetTimeValue(ctx, "2012-12-12 00:00:00", mysql.TypeTimestamp, types.MinFsp, nil) require.NoError(t, err) require.Equal(t, types.KindMysqlTime, v.Kind()) @@ -44,7 +44,7 @@ func TestGetTimeValue(t *testing.T) { sessionVars := ctx.GetSessionVars() err = variable.SetSessionSystemVar(sessionVars, "timestamp", "0") require.NoError(t, err) - v, err = GetTimeValue(ctx, "2012-12-12 00:00:00", mysql.TypeTimestamp, types.MinFsp) + v, err = GetTimeValue(ctx, "2012-12-12 00:00:00", mysql.TypeTimestamp, types.MinFsp, nil) require.NoError(t, err) require.Equal(t, types.KindMysqlTime, v.Kind()) @@ -53,7 +53,7 @@ func TestGetTimeValue(t *testing.T) { err = variable.SetSessionSystemVar(sessionVars, "timestamp", "0") require.NoError(t, err) - v, err = GetTimeValue(ctx, "2012-12-12 00:00:00", mysql.TypeTimestamp, types.MinFsp) + v, err = GetTimeValue(ctx, "2012-12-12 00:00:00", mysql.TypeTimestamp, types.MinFsp, nil) require.NoError(t, err) require.Equal(t, types.KindMysqlTime, v.Kind()) @@ -62,7 +62,7 @@ func TestGetTimeValue(t *testing.T) { err = variable.SetSessionSystemVar(sessionVars, "timestamp", "") require.Error(t, err, "Incorrect argument type to variable 'timestamp'") - v, err = GetTimeValue(ctx, "2012-12-12 00:00:00", mysql.TypeTimestamp, types.MinFsp) + v, err = GetTimeValue(ctx, "2012-12-12 00:00:00", mysql.TypeTimestamp, types.MinFsp, nil) require.NoError(t, err) require.Equal(t, types.KindMysqlTime, v.Kind()) @@ -100,7 +100,7 @@ func TestGetTimeValue(t *testing.T) { for i, tbl := range tbls { comment := fmt.Sprintf("expr: %d", i) - v, err := GetTimeValue(ctx, tbl.Expr, mysql.TypeTimestamp, types.MinFsp) + v, err := GetTimeValue(ctx, tbl.Expr, mysql.TypeTimestamp, types.MinFsp, nil) require.NoError(t, err) switch v.Kind() { @@ -122,7 +122,7 @@ func TestGetTimeValue(t *testing.T) { } for _, tbl := range errTbl { - _, err := GetTimeValue(ctx, tbl.Expr, mysql.TypeTimestamp, types.MinFsp) + _, err := GetTimeValue(ctx, tbl.Expr, mysql.TypeTimestamp, types.MinFsp, nil) require.Error(t, err) } } @@ -165,7 +165,7 @@ func TestCurrentTimestampTimeZone(t *testing.T) { require.NoError(t, err) err = variable.SetSessionSystemVar(sessionVars, "time_zone", "+00:00") require.NoError(t, err) - v, err := GetTimeValue(ctx, ast.CurrentTimestamp, mysql.TypeTimestamp, types.MinFsp) + v, err := GetTimeValue(ctx, ast.CurrentTimestamp, mysql.TypeTimestamp, types.MinFsp, nil) require.NoError(t, err) require.EqualValues(t, types.NewTime( types.FromDate(1970, 1, 1, 0, 20, 34, 0), @@ -176,7 +176,7 @@ func TestCurrentTimestampTimeZone(t *testing.T) { // would get different value. err = variable.SetSessionSystemVar(sessionVars, "time_zone", "+08:00") require.NoError(t, err) - v, err = GetTimeValue(ctx, ast.CurrentTimestamp, mysql.TypeTimestamp, types.MinFsp) + v, err = GetTimeValue(ctx, ast.CurrentTimestamp, mysql.TypeTimestamp, types.MinFsp, nil) require.NoError(t, err) require.EqualValues(t, types.NewTime( types.FromDate(1970, 1, 1, 8, 20, 34, 0), diff --git a/planner/core/expression_rewriter.go b/planner/core/expression_rewriter.go index 3026574d8e424..fa77f3a613d58 100644 --- a/planner/core/expression_rewriter.go +++ b/planner/core/expression_rewriter.go @@ -2051,7 +2051,7 @@ func (er *expressionRewriter) evalDefaultExpr(v *ast.DefaultExpr) { var val *expression.Constant switch { case isCurrentTimestamp && (col.GetType() == mysql.TypeDatetime || col.GetType() == mysql.TypeTimestamp): - t, err := expression.GetTimeValue(er.sctx, ast.CurrentTimestamp, col.GetType(), col.GetDecimal()) + t, err := expression.GetTimeValue(er.sctx, ast.CurrentTimestamp, col.GetType(), col.GetDecimal(), nil) if err != nil { return } diff --git a/server/statistics_handler.go b/server/statistics_handler.go index 8d7818bedac52..6d339706395c4 100644 --- a/server/statistics_handler.go +++ b/server/statistics_handler.go @@ -96,7 +96,7 @@ func (sh StatsHistoryHandler) ServeHTTP(w http.ResponseWriter, req *http.Request defer se.Close() se.GetSessionVars().StmtCtx.TimeZone = time.Local - t, err := types.ParseTime(se.GetSessionVars().StmtCtx, params[pSnapshot], mysql.TypeTimestamp, 6) + t, err := types.ParseTime(se.GetSessionVars().StmtCtx, params[pSnapshot], mysql.TypeTimestamp, 6, nil) if err != nil { writeError(w, err) return diff --git a/server/util_test.go b/server/util_test.go index 889c2512eacad..9ffb8294ff270 100644 --- a/server/util_test.go +++ b/server/util_test.go @@ -186,7 +186,7 @@ func TestDumpTextValue(t *testing.T) { require.NoError(t, err) sc.TimeZone = losAngelesTz - time, err := types.ParseTime(sc, "2017-01-05 23:59:59.575601", mysql.TypeDatetime, 0) + time, err := types.ParseTime(sc, "2017-01-05 23:59:59.575601", mysql.TypeDatetime, 0, nil) require.NoError(t, err) d.SetMysqlTime(time) columns[0].Type = mysql.TypeDatetime diff --git a/sessionctx/variable/varsutil.go b/sessionctx/variable/varsutil.go index 39ec20cbe2fb1..7f0cbb0d33aaf 100644 --- a/sessionctx/variable/varsutil.go +++ b/sessionctx/variable/varsutil.go @@ -445,7 +445,7 @@ func setSnapshotTS(s *SessionVars, sVal string) error { return nil } - t, err := types.ParseTime(s.StmtCtx, sVal, mysql.TypeTimestamp, types.MaxFsp) + t, err := types.ParseTime(s.StmtCtx, sVal, mysql.TypeTimestamp, types.MaxFsp, nil) if err != nil { return err } @@ -463,7 +463,7 @@ func setTxnReadTS(s *SessionVars, sVal string) error { return nil } - t, err := types.ParseTime(s.StmtCtx, sVal, mysql.TypeTimestamp, types.MaxFsp) + t, err := types.ParseTime(s.StmtCtx, sVal, mysql.TypeTimestamp, types.MaxFsp, nil) if err != nil { return err } diff --git a/table/column.go b/table/column.go index 821b7d8d4b368..3be60eede9ba2 100644 --- a/table/column.go +++ b/table/column.go @@ -546,29 +546,27 @@ func getColDefaultValue(ctx sessionctx.Context, col *model.ColumnInfo, defaultVa } // Check and get timestamp/datetime default value. - sc := ctx.GetSessionVars().StmtCtx var needChangeTimeZone bool + var explicitTz *time.Location // If the column's default value is not ZeroDatetimeStr nor CurrentTimestamp, should use the time zone of the default value itself. if col.GetType() == mysql.TypeTimestamp { if vv, ok := defaultVal.(string); ok && vv != types.ZeroDatetimeStr && !strings.EqualFold(vv, ast.CurrentTimestamp) { needChangeTimeZone = true - originalTZ := sc.TimeZone // For col.Version = 0, the timezone information of default value is already lost, so use the system timezone as the default value timezone. - sc.TimeZone = timeutil.SystemLocation() + explicitTz = timeutil.SystemLocation() if col.Version >= model.ColumnInfoVersion1 { - sc.TimeZone = time.UTC + explicitTz = time.UTC } - defer func() { sc.TimeZone = originalTZ }() } } - value, err := expression.GetTimeValue(ctx, defaultVal, col.GetType(), col.GetDecimal()) + value, err := expression.GetTimeValue(ctx, defaultVal, col.GetType(), col.GetDecimal(), explicitTz) if err != nil { return types.Datum{}, errGetDefaultFailed.GenWithStackByArgs(col.Name) } // If the column's default value is not ZeroDatetimeStr or CurrentTimestamp, convert the default value to the current session time zone. if needChangeTimeZone { t := value.GetMysqlTime() - err = t.ConvertTimeZone(sc.TimeZone, ctx.GetSessionVars().Location()) + err = t.ConvertTimeZone(explicitTz, ctx.GetSessionVars().Location()) if err != nil { return value, err } diff --git a/types/convert.go b/types/convert.go index 9433f26dbefc8..408946ab10f25 100644 --- a/types/convert.go +++ b/types/convert.go @@ -302,7 +302,7 @@ func StrToUint(sc *stmtctx.StatementContext, str string, isFuncCast bool) (uint6 // StrToDateTime converts str to MySQL DateTime. func StrToDateTime(sc *stmtctx.StatementContext, str string, fsp int) (Time, error) { - return ParseTime(sc, str, mysql.TypeDatetime, fsp) + return ParseTime(sc, str, mysql.TypeDatetime, fsp, nil) } // StrToDuration converts str to Duration. It returns Duration in normal case, diff --git a/types/convert_test.go b/types/convert_test.go index b6c37e2488ac8..e1d0cd3c7815e 100644 --- a/types/convert_test.go +++ b/types/convert_test.go @@ -151,14 +151,14 @@ func TestConvertType(t *testing.T) { require.NoError(t, err) require.Equal(t, "10:11:12.1", vv.(Duration).String()) sc := &stmtctx.StatementContext{TimeZone: time.UTC} - vd, err := ParseTime(sc, "2010-10-10 10:11:11.12345", mysql.TypeDatetime, 2) + vd, err := ParseTime(sc, "2010-10-10 10:11:11.12345", mysql.TypeDatetime, 2, nil) require.Equal(t, "2010-10-10 10:11:11.12", vd.String()) require.NoError(t, err) v, err = Convert(vd, ft) require.NoError(t, err) require.Equal(t, "10:11:11.1", v.(Duration).String()) - vt, err := ParseTime(sc, "2010-10-10 10:11:11.12345", mysql.TypeTimestamp, 2) + vt, err := ParseTime(sc, "2010-10-10 10:11:11.12345", mysql.TypeTimestamp, 2, nil) require.Equal(t, "2010-10-10 10:11:11.12", vt.String()) require.NoError(t, err) v, err = Convert(vt, ft) @@ -347,8 +347,7 @@ func TestConvertToString(t *testing.T) { testToString(t, Enum{Name: "a", Value: 1}, "a") testToString(t, Set{Name: "a", Value: 1}, "a") - t1, err := ParseTime(&stmtctx.StatementContext{TimeZone: time.UTC}, - "2011-11-10 11:11:11.999999", mysql.TypeTimestamp, 6) + t1, err := ParseTime(&stmtctx.StatementContext{TimeZone: time.UTC}, "2011-11-10 11:11:11.999999", mysql.TypeTimestamp, 6, nil) require.NoError(t, err) testToString(t, t1, "2011-11-10 11:11:11.999999") diff --git a/types/datum.go b/types/datum.go index 2c73068268ee5..f220df6e0e893 100644 --- a/types/datum.go +++ b/types/datum.go @@ -1248,7 +1248,7 @@ func (d *Datum) convertToMysqlTimestamp(sc *stmtctx.StatementContext, target *Fi } t, err = t.RoundFrac(sc, fsp) case KindString, KindBytes: - t, err = ParseTime(sc, d.GetString(), mysql.TypeTimestamp, fsp) + t, err = ParseTime(sc, d.GetString(), mysql.TypeTimestamp, fsp, nil) case KindInt64: t, err = ParseTimeFromNum(sc, d.GetInt64(), mysql.TypeTimestamp, fsp) case KindMysqlDecimal: @@ -1261,7 +1261,7 @@ func (d *Datum) convertToMysqlTimestamp(sc *stmtctx.StatementContext, target *Fi ret.SetMysqlTime(t) return ret, err } - t, err = ParseTime(sc, s, mysql.TypeTimestamp, fsp) + t, err = ParseTime(sc, s, mysql.TypeTimestamp, fsp, nil) default: return invalidConv(d, mysql.TypeTimestamp) } @@ -1302,7 +1302,7 @@ func (d *Datum) convertToMysqlTime(sc *stmtctx.StatementContext, target *FieldTy case KindMysqlDecimal: t, err = ParseTimeFromFloatString(sc, d.GetMysqlDecimal().String(), tp, fsp) case KindString, KindBytes: - t, err = ParseTime(sc, d.GetString(), tp, fsp) + t, err = ParseTime(sc, d.GetString(), tp, fsp, nil) case KindInt64: t, err = ParseTimeFromNum(sc, d.GetInt64(), tp, fsp) case KindUint64: @@ -1321,7 +1321,7 @@ func (d *Datum) convertToMysqlTime(sc *stmtctx.StatementContext, target *FieldTy ret.SetMysqlTime(t) return ret, err } - t, err = ParseTime(sc, s, tp, fsp) + t, err = ParseTime(sc, s, tp, fsp, nil) default: return invalidConv(d, tp) } diff --git a/types/datum_test.go b/types/datum_test.go index fbcafa9b29b04..913bc02290c69 100644 --- a/types/datum_test.go +++ b/types/datum_test.go @@ -76,6 +76,7 @@ func TestToBool(t *testing.T) { testDatumToBool(t, NewBinaryLiteralFromUint(0, -1), 0) testDatumToBool(t, Enum{Name: "a", Value: 1}, 1) testDatumToBool(t, Set{Name: "a", Value: 1}, 1) +<<<<<<< HEAD testDatumToBool(t, json.CreateBinary(int64(1)), 1) testDatumToBool(t, json.CreateBinary(int64(0)), 0) testDatumToBool(t, json.CreateBinary("0"), 1) @@ -93,6 +94,25 @@ func TestToBool(t *testing.T) { testDatumToBool(t, json.CreateBinary(false), 1) testDatumToBool(t, json.CreateBinary(""), 1) t1, err := ParseTime(&stmtctx.StatementContext{TimeZone: time.UTC}, "2011-11-10 11:11:11.999999", mysql.TypeTimestamp, 6) +======= + testDatumToBool(t, CreateBinaryJSON(int64(1)), 1) + testDatumToBool(t, CreateBinaryJSON(int64(0)), 0) + testDatumToBool(t, CreateBinaryJSON("0"), 1) + testDatumToBool(t, CreateBinaryJSON("aaabbb"), 1) + testDatumToBool(t, CreateBinaryJSON(float64(0.0)), 0) + testDatumToBool(t, CreateBinaryJSON(float64(3.1415)), 1) + testDatumToBool(t, CreateBinaryJSON([]interface{}{int64(1), int64(2)}), 1) + testDatumToBool(t, CreateBinaryJSON(map[string]interface{}{"ke": "val"}), 1) + testDatumToBool(t, CreateBinaryJSON("0000-00-00 00:00:00"), 1) + testDatumToBool(t, CreateBinaryJSON("0778"), 1) + testDatumToBool(t, CreateBinaryJSON("0000"), 1) + testDatumToBool(t, CreateBinaryJSON(nil), 1) + testDatumToBool(t, CreateBinaryJSON([]interface{}{nil}), 1) + testDatumToBool(t, CreateBinaryJSON(true), 1) + testDatumToBool(t, CreateBinaryJSON(false), 1) + testDatumToBool(t, CreateBinaryJSON(""), 1) + t1, err := ParseTime(&stmtctx.StatementContext{TimeZone: time.UTC}, "2011-11-10 11:11:11.999999", mysql.TypeTimestamp, 6, nil) +>>>>>>> 8398f0fe098 (*: fix a timezone data race which may cause wrong row data (#41146)) require.NoError(t, err) testDatumToBool(t, t1, 1) @@ -135,7 +155,7 @@ func TestToInt64(t *testing.T) { t1, err := ParseTime(&stmtctx.StatementContext{ TimeZone: time.UTC, - }, "2011-11-10 11:11:11.999999", mysql.TypeTimestamp, 0) + }, "2011-11-10 11:11:11.999999", mysql.TypeTimestamp, 0, nil) require.NoError(t, err) testDatumToInt64(t, t1, int64(20111110111112)) @@ -224,9 +244,14 @@ func TestConvertToFloat(t *testing.T) { } } +<<<<<<< HEAD // mustParseTimeIntoDatum is similar to ParseTime but panic if any error occurs. func mustParseTimeIntoDatum(s string, tp byte, fsp int) (d Datum) { t, err := ParseTime(&stmtctx.StatementContext{TimeZone: time.UTC}, s, tp, fsp) +======= +func mustParseTime(s string, tp byte, fsp int) Time { + t, err := ParseTime(&stmtctx.StatementContext{TimeZone: time.UTC}, s, tp, fsp, nil) +>>>>>>> 8398f0fe098 (*: fix a timezone data race which may cause wrong row data (#41146)) if err != nil { panic("ParseTime fail") } diff --git a/types/format_test.go b/types/format_test.go index 95f20cacb727e..b852fbb678103 100644 --- a/types/format_test.go +++ b/types/format_test.go @@ -69,7 +69,7 @@ func TestTimeFormatMethod(t *testing.T) { }, } for i, tt := range tblDate { - tm, err := types.ParseTime(sc, tt.Input, mysql.TypeDatetime, 6) + tm, err := types.ParseTime(sc, tt.Input, mysql.TypeDatetime, 6, nil) require.NoErrorf(t, err, "Parse time fail: %s", tt.Input) str, err := tm.DateFormat(tt.Format) diff --git a/types/time.go b/types/time.go index c99aba52358e9..db296dac493fa 100644 --- a/types/time.go +++ b/types/time.go @@ -452,7 +452,7 @@ func (t Time) Convert(sc *stmtctx.StatementContext, tp uint8) (Time, error) { } t1.SetType(tp) - err := t1.check(sc) + err := t1.check(sc, nil) return t1, errors.Trace(err) } @@ -483,7 +483,7 @@ func (t Time) Compare(o Time) int { // but parses string to Time then compares. func (t Time) CompareString(sc *stmtctx.StatementContext, str string) (int, error) { // use MaxFsp to parse the string - o, err := ParseTime(sc, str, t.Type(), MaxFsp) + o, err := ParseTime(sc, str, t.Type(), MaxFsp, nil) if err != nil { return 0, errors.Trace(err) } @@ -647,7 +647,7 @@ func (t *Time) FromPackedUint(packed uint64) error { // check whether t matches valid Time format. // If allowZeroInDate is false, it returns ErrZeroDate when month or day is zero. // FIXME: See https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_zero_in_date -func (t Time) check(sc *stmtctx.StatementContext) error { +func (t Time) check(sc *stmtctx.StatementContext, explicitTz *gotime.Location) error { allowZeroInDate := false allowInvalidDate := false // We should avoid passing sc as nil here as far as possible. @@ -658,7 +658,7 @@ func (t Time) check(sc *stmtctx.StatementContext) error { var err error switch t.Type() { case mysql.TypeTimestamp: - err = checkTimestampType(sc, t.coreTime) + err = checkTimestampType(sc, t.coreTime, explicitTz) case mysql.TypeDatetime, mysql.TypeDate: err = checkDatetimeType(t.coreTime, allowZeroInDate, allowInvalidDate) } @@ -667,7 +667,7 @@ func (t Time) check(sc *stmtctx.StatementContext) error { // Check if 't' is valid func (t *Time) Check(sc *stmtctx.StatementContext) error { - return t.check(sc) + return t.check(sc, nil) } // Sub subtracts t1 from t, returns a duration value. @@ -924,7 +924,7 @@ func splitDateTime(format string) (seps []string, fracStr string, hasTZ bool, tz } // See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-literals.html. -func parseDatetime(sc *stmtctx.StatementContext, str string, fsp int, isFloat bool) (Time, error) { +func parseDatetime(sc *stmtctx.StatementContext, str string, fsp int, isFloat bool, explicitTz *gotime.Location) (Time, error) { var ( year, month, day, hour, minute, second, deltaHour, deltaMinute int fracStr string @@ -1160,7 +1160,12 @@ func parseDatetime(sc *stmtctx.StatementContext, str string, fsp int, isFloat bo } if overflow { // Convert to Go time and add 1 second, to handle input like 2017-01-05 08:40:59.575601 - t1, err := tmp.GoTime(sc.TimeZone) + var t1 gotime.Time + if explicitTz != nil { + t1, err = tmp.GoTime(explicitTz) + } else { + t1, err = tmp.GoTime(sc.TimeZone) + } if err != nil { return ZeroDatetime, errors.Trace(err) } @@ -1193,7 +1198,11 @@ func parseDatetime(sc *stmtctx.StatementContext, str string, fsp int, isFloat bo if err != nil { return ZeroDatetime, errors.Trace(err) } - t1 = t1.In(sc.TimeZone) + if explicitTz != nil { + t1 = t1.In(explicitTz) + } else { + t1 = t1.In(sc.TimeZone) + } tmp = FromGoTime(t1) } @@ -1835,7 +1844,7 @@ func getTime(sc *stmtctx.StatementContext, num, originNum int64, tp byte) (Time, return ZeroDatetime, errors.Trace(ErrWrongValue.GenWithStackByArgs(TimeStr, numStr)) } t := NewTime(ct, tp, DefaultFsp) - err := t.check(sc) + err := t.check(sc, nil) return t, errors.Trace(err) } @@ -1927,8 +1936,9 @@ func parseDateTimeFromNum(sc *stmtctx.StatementContext, num int64) (Time, error) // The valid datetime range is from '1000-01-01 00:00:00.000000' to '9999-12-31 23:59:59.999999'. // The valid timestamp range is from '1970-01-01 00:00:01.000000' to '2038-01-19 03:14:07.999999'. // The valid date range is from '1000-01-01' to '9999-12-31' -func ParseTime(sc *stmtctx.StatementContext, str string, tp byte, fsp int) (Time, error) { - return parseTime(sc, str, tp, fsp, false) +// explicitTz is used to handle a data race of timeZone, refer to https://github.com/pingcap/tidb/issues/40710. It only works for timestamp now, be careful to use it! +func ParseTime(sc *stmtctx.StatementContext, str string, tp byte, fsp int, explicitTz *gotime.Location) (Time, error) { + return parseTime(sc, str, tp, fsp, false, explicitTz) } // ParseTimeFromFloatString is similar to ParseTime, except that it's used to parse a float converted string. @@ -1937,22 +1947,22 @@ func ParseTimeFromFloatString(sc *stmtctx.StatementContext, str string, tp byte, if len(str) >= 3 && str[:3] == "0.0" { return NewTime(ZeroCoreTime, tp, DefaultFsp), nil } - return parseTime(sc, str, tp, fsp, true) + return parseTime(sc, str, tp, fsp, true, nil) } -func parseTime(sc *stmtctx.StatementContext, str string, tp byte, fsp int, isFloat bool) (Time, error) { +func parseTime(sc *stmtctx.StatementContext, str string, tp byte, fsp int, isFloat bool, explicitTz *gotime.Location) (Time, error) { fsp, err := CheckFsp(fsp) if err != nil { return NewTime(ZeroCoreTime, tp, DefaultFsp), errors.Trace(err) } - t, err := parseDatetime(sc, str, fsp, isFloat) + t, err := parseDatetime(sc, str, fsp, isFloat, explicitTz) if err != nil { return NewTime(ZeroCoreTime, tp, DefaultFsp), errors.Trace(err) } t.SetType(tp) - if err = t.check(sc); err != nil { + if err = t.check(sc, explicitTz); err != nil { return NewTime(ZeroCoreTime, tp, DefaultFsp), errors.Trace(err) } return t, nil @@ -1960,18 +1970,18 @@ func parseTime(sc *stmtctx.StatementContext, str string, tp byte, fsp int, isFlo // ParseDatetime is a helper function wrapping ParseTime with datetime type and default fsp. func ParseDatetime(sc *stmtctx.StatementContext, str string) (Time, error) { - return ParseTime(sc, str, mysql.TypeDatetime, GetFsp(str)) + return ParseTime(sc, str, mysql.TypeDatetime, GetFsp(str), nil) } // ParseTimestamp is a helper function wrapping ParseTime with timestamp type and default fsp. func ParseTimestamp(sc *stmtctx.StatementContext, str string) (Time, error) { - return ParseTime(sc, str, mysql.TypeTimestamp, GetFsp(str)) + return ParseTime(sc, str, mysql.TypeTimestamp, GetFsp(str), nil) } // ParseDate is a helper function wrapping ParseTime with date type. func ParseDate(sc *stmtctx.StatementContext, str string) (Time, error) { // date has no fractional seconds precision - return ParseTime(sc, str, mysql.TypeDate, MinFsp) + return ParseTime(sc, str, mysql.TypeDate, MinFsp, nil) } // ParseTimeFromYear parse a `YYYY` formed year to corresponded Datetime type. @@ -2015,7 +2025,7 @@ func ParseTimeFromNum(sc *stmtctx.StatementContext, num int64, tp byte, fsp int) t.SetType(tp) t.SetFsp(fsp) - if err := t.check(sc); err != nil { + if err := t.check(sc, nil); err != nil { return NewTime(ZeroCoreTime, tp, DefaultFsp), errors.Trace(err) } return t, nil @@ -2104,7 +2114,7 @@ func checkMonthDay(year, month, day int, allowInvalidDate bool) error { return nil } -func checkTimestampType(sc *stmtctx.StatementContext, t CoreTime) error { +func checkTimestampType(sc *stmtctx.StatementContext, t CoreTime, explicitTz *gotime.Location) error { if compareTime(t, ZeroCoreTime) == 0 { return nil } @@ -2114,9 +2124,13 @@ func checkTimestampType(sc *stmtctx.StatementContext, t CoreTime) error { } var checkTime CoreTime - if sc.TimeZone != BoundTimezone { + tz := sc.TimeZone + if explicitTz != nil { + tz = explicitTz + } + if tz != BoundTimezone { convertTime := NewTime(t, mysql.TypeTimestamp, DefaultFsp) - err := convertTime.ConvertTimeZone(sc.TimeZone, BoundTimezone) + err := convertTime.ConvertTimeZone(tz, BoundTimezone) if err != nil { return err } @@ -2128,7 +2142,7 @@ func checkTimestampType(sc *stmtctx.StatementContext, t CoreTime) error { return errors.Trace(ErrWrongValue.GenWithStackByArgs(TimeStr, t)) } - if _, err := t.GoTime(sc.TimeZone); err != nil { + if _, err := t.GoTime(tz); err != nil { return errors.Trace(err) } @@ -2767,7 +2781,7 @@ func (t *Time) StrToDate(sc *stmtctx.StatementContext, date, format string) bool t.SetCoreTime(tm) t.SetType(mysql.TypeDatetime) - if t.check(sc) != nil { + if t.check(sc, nil) != nil { return false } if warning { diff --git a/types/time_test.go b/types/time_test.go index c575fa730c2b7..5d82777626387 100644 --- a/types/time_test.go +++ b/types/time_test.go @@ -143,12 +143,12 @@ func TestDateTime(t *testing.T) { } for _, test := range fspTbl { - v, err := types.ParseTime(sc, test.Input, mysql.TypeDatetime, test.Fsp) + v, err := types.ParseTime(sc, test.Input, mysql.TypeDatetime, test.Fsp, nil) require.NoError(t, err) require.Equal(t, test.Expect, v.String()) } - v, _ := types.ParseTime(sc, "121231113045.9999999", mysql.TypeDatetime, 6) + v, _ := types.ParseTime(sc, "121231113045.9999999", mysql.TypeDatetime, 6, nil) require.Equal(t, 46, v.Second()) require.Equal(t, 0, v.Microsecond()) @@ -598,7 +598,7 @@ func TestCodec(t *testing.T) { } for _, test := range tbl { - v, err := types.ParseTime(sc, test, mysql.TypeDatetime, types.MaxFsp) + v, err := types.ParseTime(sc, test, mysql.TypeDatetime, types.MaxFsp, nil) require.NoError(t, err) packed, _ = v.ToPackedUint() @@ -706,7 +706,7 @@ func TestToNumber(t *testing.T) { } for _, test := range tblDateTime { - v, err := types.ParseTime(sc, test.Input, mysql.TypeDatetime, test.Fsp) + v, err := types.ParseTime(sc, test.Input, mysql.TypeDatetime, test.Fsp, nil) require.NoError(t, err) require.Equal(t, test.Expect, v.ToNumber().String()) } @@ -729,7 +729,7 @@ func TestToNumber(t *testing.T) { } for _, test := range tblDate { - v, err := types.ParseTime(sc, test.Input, mysql.TypeDate, 0) + v, err := types.ParseTime(sc, test.Input, mysql.TypeDate, 0, nil) require.NoError(t, err) require.Equal(t, test.Expect, v.ToNumber().String()) } @@ -850,7 +850,7 @@ func TestRoundFrac(t *testing.T) { } for _, tt := range tbl { - v, err := types.ParseTime(sc, tt.Input, mysql.TypeDatetime, types.MaxFsp) + v, err := types.ParseTime(sc, tt.Input, mysql.TypeDatetime, types.MaxFsp, nil) require.NoError(t, err) nv, err := v.RoundFrac(sc, tt.Fsp) require.NoError(t, err) @@ -875,7 +875,7 @@ func TestRoundFrac(t *testing.T) { } for _, tt := range tbl { - v, err := types.ParseTime(sc, tt.Input, mysql.TypeDatetime, types.MaxFsp) + v, err := types.ParseTime(sc, tt.Input, mysql.TypeDatetime, types.MaxFsp, nil) require.NoError(t, err) nv, err := v.RoundFrac(sc, tt.Fsp) require.NoError(t, err) @@ -939,7 +939,7 @@ func TestConvert(t *testing.T) { } for _, tt := range tbl { - v, err := types.ParseTime(sc, tt.Input, mysql.TypeDatetime, tt.Fsp) + v, err := types.ParseTime(sc, tt.Input, mysql.TypeDatetime, tt.Fsp, nil) require.NoError(t, err) nv, err := v.ConvertToDuration() require.NoError(t, err) @@ -984,7 +984,7 @@ func TestCompare(t *testing.T) { } for _, tt := range tbl { - v1, err := types.ParseTime(sc, tt.Arg1, mysql.TypeDatetime, types.MaxFsp) + v1, err := types.ParseTime(sc, tt.Arg1, mysql.TypeDatetime, types.MaxFsp, nil) require.NoError(t, err) ret, err := v1.CompareString(nil, tt.Arg2) @@ -992,7 +992,7 @@ func TestCompare(t *testing.T) { require.Equal(t, tt.Ret, ret) } - v1, err := types.ParseTime(sc, "2011-10-10 11:11:11", mysql.TypeDatetime, types.MaxFsp) + v1, err := types.ParseTime(sc, "2011-10-10 11:11:11", mysql.TypeDatetime, types.MaxFsp, nil) require.NoError(t, err) res, err := v1.CompareString(nil, "Test should error") require.Error(t, err) @@ -1148,11 +1148,11 @@ func TestTimeAdd(t *testing.T) { TimeZone: time.UTC, } for _, tt := range tbl { - v1, err := types.ParseTime(sc, tt.Arg1, mysql.TypeDatetime, types.MaxFsp) + v1, err := types.ParseTime(sc, tt.Arg1, mysql.TypeDatetime, types.MaxFsp, nil) require.NoError(t, err) dur, err := types.ParseDuration(sc, tt.Arg2, types.MaxFsp) require.NoError(t, err) - result, err := types.ParseTime(sc, tt.Ret, mysql.TypeDatetime, types.MaxFsp) + result, err := types.ParseTime(sc, tt.Ret, mysql.TypeDatetime, types.MaxFsp, nil) require.NoError(t, err) v2, err := v1.Add(sc, dur) require.NoError(t, err) @@ -1235,7 +1235,7 @@ func TestCheckTimestamp(t *testing.T) { } for _, tt := range tests { - validTimestamp := types.CheckTimestampTypeForTest(&stmtctx.StatementContext{TimeZone: tt.tz}, tt.input) + validTimestamp := types.CheckTimestampTypeForTest(&stmtctx.StatementContext{TimeZone: tt.tz}, tt.input, nil) if tt.expectRetError { require.Errorf(t, validTimestamp, "For %s %s", tt.input, tt.tz) } else { @@ -1292,7 +1292,7 @@ func TestCheckTimestamp(t *testing.T) { } for _, tt := range tests { - validTimestamp := types.CheckTimestampTypeForTest(&stmtctx.StatementContext{TimeZone: tt.tz}, tt.input) + validTimestamp := types.CheckTimestampTypeForTest(&stmtctx.StatementContext{TimeZone: tt.tz}, tt.input, nil) if tt.expectRetError { require.Errorf(t, validTimestamp, "For %s %s", tt.input, tt.tz) } else { @@ -1824,9 +1824,9 @@ func TestTimeSub(t *testing.T) { TimeZone: time.UTC, } for _, tt := range tbl { - v1, err := types.ParseTime(sc, tt.Arg1, mysql.TypeDatetime, types.MaxFsp) + v1, err := types.ParseTime(sc, tt.Arg1, mysql.TypeDatetime, types.MaxFsp, nil) require.NoError(t, err) - v2, err := types.ParseTime(sc, tt.Arg2, mysql.TypeDatetime, types.MaxFsp) + v2, err := types.ParseTime(sc, tt.Arg2, mysql.TypeDatetime, types.MaxFsp, nil) require.NoError(t, err) dur, err := types.ParseDuration(sc, tt.Ret, types.MaxFsp) require.NoError(t, err) @@ -2024,7 +2024,7 @@ func TestParseWithTimezone(t *testing.T) { }, } for ith, ca := range cases { - v, err := types.ParseTime(&stmtctx.StatementContext{TimeZone: ca.sysTZ}, ca.lit, mysql.TypeTimestamp, ca.fsp) + v, err := types.ParseTime(&stmtctx.StatementContext{TimeZone: ca.sysTZ}, ca.lit, mysql.TypeTimestamp, ca.fsp, nil) require.NoErrorf(t, err, "tidb time parse misbehaved on %d", ith) if err != nil { continue @@ -2035,6 +2035,20 @@ func TestParseWithTimezone(t *testing.T) { } } +<<<<<<< HEAD +======= +func TestMarshalTime(t *testing.T) { + sc := mock.NewContext().GetSessionVars().StmtCtx + v1, err := types.ParseTime(sc, "2017-01-18 01:01:01.123456", mysql.TypeDatetime, types.MaxFsp, nil) + require.NoError(t, err) + j, err := json.Marshal(v1) + require.NoError(t, err) + var v2 types.Time + require.NoError(t, json.Unmarshal(j, &v2)) + require.Equal(t, 0, v1.Compare(v2)) +} + +>>>>>>> 8398f0fe098 (*: fix a timezone data race which may cause wrong row data (#41146)) func BenchmarkFormat(b *testing.B) { t1 := types.NewTime(types.FromGoTime(time.Now()), mysql.TypeTimestamp, 0) for i := 0; i < b.N; i++ { @@ -2049,8 +2063,13 @@ func BenchmarkTimeAdd(b *testing.B) { sc := &stmtctx.StatementContext{ TimeZone: time.UTC, } +<<<<<<< HEAD arg1, _ := types.ParseTime(sc, "2017-01-18", mysql.TypeDatetime, types.MaxFsp) arg2, _ := types.ParseDuration(sc, "12:30:59", types.MaxFsp) +======= + arg1, _ := types.ParseTime(sc, "2017-01-18", mysql.TypeDatetime, types.MaxFsp, nil) + arg2, _, _ := types.ParseDuration(sc, "12:30:59", types.MaxFsp) +>>>>>>> 8398f0fe098 (*: fix a timezone data race which may cause wrong row data (#41146)) for i := 0; i < b.N; i++ { _, err := arg1.Add(sc, arg2) if err != nil { diff --git a/util/codec/codec_test.go b/util/codec/codec_test.go index 33af7c59a9840..15f246af0a79d 100644 --- a/util/codec/codec_test.go +++ b/util/codec/codec_test.go @@ -521,7 +521,7 @@ func TestBytes(t *testing.T) { func parseTime(t *testing.T, s string) types.Time { sc := &stmtctx.StatementContext{TimeZone: time.UTC} - m, err := types.ParseTime(sc, s, mysql.TypeDatetime, types.DefaultFsp) + m, err := types.ParseTime(sc, s, mysql.TypeDatetime, types.DefaultFsp, nil) require.NoError(t, err) return m } diff --git a/util/dbutil/common.go b/util/dbutil/common.go index 7ee717f090f19..d30f1791edc82 100644 --- a/util/dbutil/common.go +++ b/util/dbutil/common.go @@ -557,7 +557,7 @@ func AnalyzeValuesFromBuckets(valueString string, cols []*model.ColumnInfo) ([]s if IsTimeTypeAndNeedDecode(col.GetType()) { // check if values[i] is already a time string sc := &stmtctx.StatementContext{TimeZone: time.UTC} - _, err := types.ParseTime(sc, values[i], col.GetType(), types.MinFsp) + _, err := types.ParseTime(sc, values[i], col.GetType(), types.MinFsp, nil) if err == nil { continue } diff --git a/util/rowcodec/rowcodec_test.go b/util/rowcodec/rowcodec_test.go index 51c965f095cd6..6102a4dbc2ef6 100644 --- a/util/rowcodec/rowcodec_test.go +++ b/util/rowcodec/rowcodec_test.go @@ -292,7 +292,7 @@ func TestTypesNewRowCodec(t *testing.T) { return d } getTime := func(value string) types.Time { - d, err := types.ParseTime(&stmtctx.StatementContext{TimeZone: time.UTC}, value, mysql.TypeTimestamp, 6) + d, err := types.ParseTime(&stmtctx.StatementContext{TimeZone: time.UTC}, value, mysql.TypeTimestamp, 6, nil) require.NoError(t, err) return d } From 866cacce91a2a7c0f44a190f1c9b36953b2d0d43 Mon Sep 17 00:00:00 2001 From: wjhuang2016 Date: Wed, 29 Mar 2023 21:40:09 +0800 Subject: [PATCH 2/2] done Signed-off-by: wjhuang2016 --- br/pkg/task/backup.go | 10 ------- ddl/ddl_api.go | 5 ---- expression/builtin_cast.go | 49 ++---------------------------- expression/builtin_cast_vec.go | 54 ++-------------------------------- types/datum_test.go | 25 ---------------- types/time_test.go | 21 +------------ 6 files changed, 5 insertions(+), 159 deletions(-) diff --git a/br/pkg/task/backup.go b/br/pkg/task/backup.go index cc25ec5edda45..61f41a290ef94 100644 --- a/br/pkg/task/backup.go +++ b/br/pkg/task/backup.go @@ -543,17 +543,7 @@ func ParseTSString(ts string) (uint64, error) { sc := &stmtctx.StatementContext{ TimeZone: loc, } -<<<<<<< HEAD - t, err := types.ParseTime(sc, ts, mysql.TypeTimestamp, types.MaxFsp) -======= - if tzCheck { - tzIdx, _, _, _, _ := types.GetTimezone(ts) - if tzIdx < 0 { - return 0, errors.Errorf("must set timezone when using datetime format ts, e.g. '2018-05-11 01:42:23+0800'") - } - } t, err := types.ParseTime(sc, ts, mysql.TypeTimestamp, types.MaxFsp, nil) ->>>>>>> 8398f0fe098 (*: fix a timezone data race which may cause wrong row data (#41146)) if err != nil { return 0, errors.Trace(err) } diff --git a/ddl/ddl_api.go b/ddl/ddl_api.go index 4205e452a0f02..e5f6558716f4e 100644 --- a/ddl/ddl_api.go +++ b/ddl/ddl_api.go @@ -1092,13 +1092,8 @@ func getDefaultValue(ctx sessionctx.Context, col *table.Column, option *ast.Colu // If the function call is ast.CurrentTimestamp, it needs to be continuously processed. } -<<<<<<< HEAD if tp == mysql.TypeTimestamp || tp == mysql.TypeDatetime { - vd, err := expression.GetTimeValue(ctx, option.Expr, tp, fsp) -======= - if tp == mysql.TypeTimestamp || tp == mysql.TypeDatetime || tp == mysql.TypeDate { vd, err := expression.GetTimeValue(ctx, option.Expr, tp, fsp, nil) ->>>>>>> 8398f0fe098 (*: fix a timezone data race which may cause wrong row data (#41146)) value := vd.GetValue() if err != nil { return nil, false, dbterror.ErrInvalidDefaultValue.GenWithStackByArgs(col.Name.O) diff --git a/expression/builtin_cast.go b/expression/builtin_cast.go index e32de65e3256f..8a720f24822f3 100644 --- a/expression/builtin_cast.go +++ b/expression/builtin_cast.go @@ -890,7 +890,7 @@ func (b *builtinCastRealAsTimeSig) evalTime(row chunk.Row) (types.Time, bool, er return types.ZeroTime, false, nil } sc := b.ctx.GetSessionVars().StmtCtx - res, err := types.ParseTime(sc, fv, b.tp.GetType(), b.tp.GetDecimal()) + res, err := types.ParseTime(sc, fv, b.tp.GetType(), b.tp.GetDecimal(), nil) if err != nil { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) } @@ -1729,57 +1729,12 @@ func (b *builtinCastJSONAsTimeSig) evalTime(row chunk.Row) (res types.Time, isNu if isNull || err != nil { return res, isNull, err } -<<<<<<< HEAD s, err := val.Unquote() if err != nil { return res, false, err -======= - - switch val.TypeCode { - case types.JSONTypeCodeDate, types.JSONTypeCodeDatetime, types.JSONTypeCodeTimestamp: - res = val.GetTime() - res.SetType(b.tp.GetType()) - if b.tp.GetType() == mysql.TypeDate { - // Truncate hh:mm:ss part if the type is Date. - res.SetCoreTime(types.FromDate(res.Year(), res.Month(), res.Day(), 0, 0, 0, 0)) - } - return res, isNull, err - case types.JSONTypeCodeDuration: - duration := val.GetDuration() - - sc := b.ctx.GetSessionVars().StmtCtx - ts, err := getStmtTimestamp(b.ctx) - if err != nil { - ts = gotime.Now() - } - res, err = duration.ConvertToTimeWithTimestamp(sc, b.tp.GetType(), ts) - if err != nil { - return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) - } - res, err = res.RoundFrac(sc, b.tp.GetDecimal()) - return res, isNull, err - case types.JSONTypeCodeString: - s, err := val.Unquote() - if err != nil { - return res, false, err - } - sc := b.ctx.GetSessionVars().StmtCtx - res, err = types.ParseTime(sc, s, b.tp.GetType(), b.tp.GetDecimal(), nil) - if err != nil { - return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) - } - if b.tp.GetType() == mysql.TypeDate { - // Truncate hh:mm:ss part if the type is Date. - res.SetCoreTime(types.FromDate(res.Year(), res.Month(), res.Day(), 0, 0, 0, 0)) - } - return res, isNull, err - default: - err = types.ErrTruncatedWrongVal.GenWithStackByArgs(types.TypeStr(b.tp.GetType()), val.String()) - return res, true, b.ctx.GetSessionVars().StmtCtx.HandleTruncate(err) ->>>>>>> 8398f0fe098 (*: fix a timezone data race which may cause wrong row data (#41146)) } sc := b.ctx.GetSessionVars().StmtCtx - res, err = types.ParseTime(sc, s, b.tp.GetType(), b.tp.GetDecimal()) + res, err = types.ParseTime(sc, s, b.tp.GetType(), b.tp.GetDecimal(), nil) if err != nil { return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err) } diff --git a/expression/builtin_cast_vec.go b/expression/builtin_cast_vec.go index b30ef15a1f4a9..aae1dde8a9494 100644 --- a/expression/builtin_cast_vec.go +++ b/expression/builtin_cast_vec.go @@ -492,58 +492,8 @@ func (b *builtinCastJSONAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk if err != nil { return err } -<<<<<<< HEAD - tm, err := types.ParseTime(stmtCtx, s, b.tp.GetType(), fsp) + tm, err := types.ParseTime(stmtCtx, s, b.tp.GetType(), fsp, nil) if err != nil { -======= - - switch val.TypeCode { - case types.JSONTypeCodeDate, types.JSONTypeCodeDatetime, types.JSONTypeCodeTimestamp: - tm := val.GetTime() - times[i] = tm - times[i].SetType(b.tp.GetType()) - if b.tp.GetType() == mysql.TypeDate { - // Truncate hh:mm:ss part if the type is Date. - times[i].SetCoreTime(types.FromDate(tm.Year(), tm.Month(), tm.Day(), 0, 0, 0, 0)) - } - case types.JSONTypeCodeDuration: - duration := val.GetDuration() - - sc := b.ctx.GetSessionVars().StmtCtx - tm, err := duration.ConvertToTimeWithTimestamp(sc, b.tp.GetType(), ts) - if err != nil { - if err = handleInvalidTimeError(b.ctx, err); err != nil { - return err - } - result.SetNull(i, true) - continue - } - tm, err = tm.RoundFrac(stmtCtx, fsp) - if err != nil { - return err - } - times[i] = tm - case types.JSONTypeCodeString: - s, err := val.Unquote() - if err != nil { - return err - } - tm, err := types.ParseTime(stmtCtx, s, b.tp.GetType(), fsp, nil) - if err != nil { - if err = handleInvalidTimeError(b.ctx, err); err != nil { - return err - } - result.SetNull(i, true) - continue - } - times[i] = tm - if b.tp.GetType() == mysql.TypeDate { - // Truncate hh:mm:ss part if the type is Date. - times[i].SetCoreTime(types.FromDate(tm.Year(), tm.Month(), tm.Day(), 0, 0, 0, 0)) - } - default: - err = types.ErrTruncatedWrongVal.GenWithStackByArgs(types.TypeStr(b.tp.GetType()), val.String()) ->>>>>>> 8398f0fe098 (*: fix a timezone data race which may cause wrong row data (#41146)) if err = handleInvalidTimeError(b.ctx, err); err != nil { return err } @@ -589,7 +539,7 @@ func (b *builtinCastRealAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk times[i] = types.ZeroTime continue } - tm, err := types.ParseTime(stmt, fv, b.tp.GetType(), fsp) + tm, err := types.ParseTime(stmt, fv, b.tp.GetType(), fsp, nil) if err != nil { if err = handleInvalidTimeError(b.ctx, err); err != nil { return err diff --git a/types/datum_test.go b/types/datum_test.go index 913bc02290c69..ca6f199629b4e 100644 --- a/types/datum_test.go +++ b/types/datum_test.go @@ -76,7 +76,6 @@ func TestToBool(t *testing.T) { testDatumToBool(t, NewBinaryLiteralFromUint(0, -1), 0) testDatumToBool(t, Enum{Name: "a", Value: 1}, 1) testDatumToBool(t, Set{Name: "a", Value: 1}, 1) -<<<<<<< HEAD testDatumToBool(t, json.CreateBinary(int64(1)), 1) testDatumToBool(t, json.CreateBinary(int64(0)), 0) testDatumToBool(t, json.CreateBinary("0"), 1) @@ -93,26 +92,7 @@ func TestToBool(t *testing.T) { testDatumToBool(t, json.CreateBinary(true), 1) testDatumToBool(t, json.CreateBinary(false), 1) testDatumToBool(t, json.CreateBinary(""), 1) - t1, err := ParseTime(&stmtctx.StatementContext{TimeZone: time.UTC}, "2011-11-10 11:11:11.999999", mysql.TypeTimestamp, 6) -======= - testDatumToBool(t, CreateBinaryJSON(int64(1)), 1) - testDatumToBool(t, CreateBinaryJSON(int64(0)), 0) - testDatumToBool(t, CreateBinaryJSON("0"), 1) - testDatumToBool(t, CreateBinaryJSON("aaabbb"), 1) - testDatumToBool(t, CreateBinaryJSON(float64(0.0)), 0) - testDatumToBool(t, CreateBinaryJSON(float64(3.1415)), 1) - testDatumToBool(t, CreateBinaryJSON([]interface{}{int64(1), int64(2)}), 1) - testDatumToBool(t, CreateBinaryJSON(map[string]interface{}{"ke": "val"}), 1) - testDatumToBool(t, CreateBinaryJSON("0000-00-00 00:00:00"), 1) - testDatumToBool(t, CreateBinaryJSON("0778"), 1) - testDatumToBool(t, CreateBinaryJSON("0000"), 1) - testDatumToBool(t, CreateBinaryJSON(nil), 1) - testDatumToBool(t, CreateBinaryJSON([]interface{}{nil}), 1) - testDatumToBool(t, CreateBinaryJSON(true), 1) - testDatumToBool(t, CreateBinaryJSON(false), 1) - testDatumToBool(t, CreateBinaryJSON(""), 1) t1, err := ParseTime(&stmtctx.StatementContext{TimeZone: time.UTC}, "2011-11-10 11:11:11.999999", mysql.TypeTimestamp, 6, nil) ->>>>>>> 8398f0fe098 (*: fix a timezone data race which may cause wrong row data (#41146)) require.NoError(t, err) testDatumToBool(t, t1, 1) @@ -244,14 +224,9 @@ func TestConvertToFloat(t *testing.T) { } } -<<<<<<< HEAD // mustParseTimeIntoDatum is similar to ParseTime but panic if any error occurs. func mustParseTimeIntoDatum(s string, tp byte, fsp int) (d Datum) { - t, err := ParseTime(&stmtctx.StatementContext{TimeZone: time.UTC}, s, tp, fsp) -======= -func mustParseTime(s string, tp byte, fsp int) Time { t, err := ParseTime(&stmtctx.StatementContext{TimeZone: time.UTC}, s, tp, fsp, nil) ->>>>>>> 8398f0fe098 (*: fix a timezone data race which may cause wrong row data (#41146)) if err != nil { panic("ParseTime fail") } diff --git a/types/time_test.go b/types/time_test.go index 5d82777626387..90d37d64e132b 100644 --- a/types/time_test.go +++ b/types/time_test.go @@ -2035,20 +2035,6 @@ func TestParseWithTimezone(t *testing.T) { } } -<<<<<<< HEAD -======= -func TestMarshalTime(t *testing.T) { - sc := mock.NewContext().GetSessionVars().StmtCtx - v1, err := types.ParseTime(sc, "2017-01-18 01:01:01.123456", mysql.TypeDatetime, types.MaxFsp, nil) - require.NoError(t, err) - j, err := json.Marshal(v1) - require.NoError(t, err) - var v2 types.Time - require.NoError(t, json.Unmarshal(j, &v2)) - require.Equal(t, 0, v1.Compare(v2)) -} - ->>>>>>> 8398f0fe098 (*: fix a timezone data race which may cause wrong row data (#41146)) func BenchmarkFormat(b *testing.B) { t1 := types.NewTime(types.FromGoTime(time.Now()), mysql.TypeTimestamp, 0) for i := 0; i < b.N; i++ { @@ -2063,13 +2049,8 @@ func BenchmarkTimeAdd(b *testing.B) { sc := &stmtctx.StatementContext{ TimeZone: time.UTC, } -<<<<<<< HEAD - arg1, _ := types.ParseTime(sc, "2017-01-18", mysql.TypeDatetime, types.MaxFsp) - arg2, _ := types.ParseDuration(sc, "12:30:59", types.MaxFsp) -======= arg1, _ := types.ParseTime(sc, "2017-01-18", mysql.TypeDatetime, types.MaxFsp, nil) - arg2, _, _ := types.ParseDuration(sc, "12:30:59", types.MaxFsp) ->>>>>>> 8398f0fe098 (*: fix a timezone data race which may cause wrong row data (#41146)) + arg2, _ := types.ParseDuration(sc, "12:30:59", types.MaxFsp) for i := 0; i < b.N; i++ { _, err := arg1.Add(sc, arg2) if err != nil {