Skip to content

Commit 7b3025b

Browse files
committed
expression: fix issue that timestampadd is not compatible with Mysql (pingcap#10314)
1 parent 570a315 commit 7b3025b

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

expression/builtin_time.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5649,13 +5649,30 @@ func (b *builtinTimestampAddSig) evalString(row chunk.Row) (string, bool, error)
56495649
default:
56505650
return "", true, errors.Trace(types.ErrInvalidTimeFormat.GenWithStackByArgs(unit))
56515651
}
5652-
r := types.Time{Time: types.FromGoTime(tb), Type: mysql.TypeDatetime, Fsp: fsp}
5652+
r := types.Time{Time: types.FromGoTime(tb), Type: b.resolveType(arg.Type, unit), Fsp: fsp}
56535653
if err = r.Check(b.ctx.GetSessionVars().StmtCtx); err != nil {
56545654
return "", true, errors.Trace(handleInvalidTimeError(b.ctx, err))
56555655
}
56565656
return r.String(), false, nil
56575657
}
56585658

5659+
func (b *builtinTimestampAddSig) resolveType(typ uint8, unit string) uint8 {
5660+
// The approach below is from MySQL.
5661+
// The field type for the result of an Item_date function is defined as
5662+
// follows:
5663+
//
5664+
//- If first arg is a MYSQL_TYPE_DATETIME result is MYSQL_TYPE_DATETIME
5665+
//- If first arg is a MYSQL_TYPE_DATE and the interval type uses hours,
5666+
// minutes, seconds or microsecond then type is MYSQL_TYPE_DATETIME.
5667+
//- Otherwise the result is MYSQL_TYPE_STRING
5668+
// (This is because you can't know if the string contains a DATE, MYSQL_TIME
5669+
// or DATETIME argument)
5670+
if typ == mysql.TypeDate && (unit == "HOUR" || unit == "MINUTE" || unit == "SECOND" || unit == "MICROSECOND") {
5671+
return mysql.TypeDatetime
5672+
}
5673+
return typ
5674+
}
5675+
56595676
type toDaysFunctionClass struct {
56605677
baseFunctionClass
56615678
}

expression/integration_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,6 +1300,18 @@ func (s *testIntegrationSuite) TestTimeBuiltin(c *C) {
13001300
result.Check(testkit.Rows("2017-01-18 12:39:50.123 2017-01-18 12:39:50.999"))
13011301
result = tk.MustQuery("select timestamp('2003-12-31', '01:01:01.01'), timestamp('2003-12-31 12:34', '01:01:01.01')," +
13021302
" timestamp('2008-12-31','00:00:00.0'), timestamp('2008-12-31 00:00:00.000');")
1303+
1304+
tk.MustQuery(`select timestampadd(second, 1, cast("2001-01-01" as date))`).Check(testkit.Rows("2001-01-01 00:00:01"))
1305+
tk.MustQuery(`select timestampadd(hour, 1, cast("2001-01-01" as date))`).Check(testkit.Rows("2001-01-01 01:00:00"))
1306+
tk.MustQuery(`select timestampadd(day, 1, cast("2001-01-01" as date))`).Check(testkit.Rows("2001-01-02"))
1307+
tk.MustQuery(`select timestampadd(month, 1, cast("2001-01-01" as date))`).Check(testkit.Rows("2001-02-01"))
1308+
tk.MustQuery(`select timestampadd(year, 1, cast("2001-01-01" as date))`).Check(testkit.Rows("2002-01-01"))
1309+
tk.MustQuery(`select timestampadd(second, 1, cast("2001-01-01" as datetime))`).Check(testkit.Rows("2001-01-01 00:00:01"))
1310+
tk.MustQuery(`select timestampadd(hour, 1, cast("2001-01-01" as datetime))`).Check(testkit.Rows("2001-01-01 01:00:00"))
1311+
tk.MustQuery(`select timestampadd(day, 1, cast("2001-01-01" as datetime))`).Check(testkit.Rows("2001-01-02 00:00:00"))
1312+
tk.MustQuery(`select timestampadd(month, 1, cast("2001-01-01" as datetime))`).Check(testkit.Rows("2001-02-01 00:00:00"))
1313+
tk.MustQuery(`select timestampadd(year, 1, cast("2001-01-01" as datetime))`).Check(testkit.Rows("2002-01-01 00:00:00"))
1314+
13031315
result.Check(testkit.Rows("2003-12-31 01:01:01.01 2003-12-31 13:35:01.01 2008-12-31 00:00:00.0 2008-12-31 00:00:00.000"))
13041316
result = tk.MustQuery("select timestamp('2003-12-31', 1), timestamp('2003-12-31', -1);")
13051317
result.Check(testkit.Rows("2003-12-31 00:00:01 2003-12-30 23:59:59"))

0 commit comments

Comments
 (0)