Skip to content

Commit

Permalink
expression: fix that the result of expression castRealAsTime is incon…
Browse files Browse the repository at this point in the history
…sistent with mysql (#37461)

close #37462
  • Loading branch information
mengxin9014 authored Sep 2, 2022
1 parent 36ff60d commit 0482b2e
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 17 deletions.
2 changes: 1 addition & 1 deletion expression/builtin_cast.go
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,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.ParseTimeFromFloatString(sc, fv, b.tp.GetType(), b.tp.GetDecimal())
if err != nil {
return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err)
}
Expand Down
2 changes: 1 addition & 1 deletion expression/builtin_cast_vec.go
Original file line number Diff line number Diff line change
Expand Up @@ -539,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.ParseTimeFromFloatString(stmt, fv, b.tp.GetType(), fsp)
if err != nil {
if err = handleInvalidTimeError(b.ctx, err); err != nil {
return err
Expand Down
75 changes: 60 additions & 15 deletions expression/builtin_cast_vec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,9 @@ func TestVectorizedCastRealAsTime(t *testing.T) {
}
cast := &builtinCastRealAsTimeSig{baseFunc}

inputChunk, expect := genCastRealAsTime()
inputs := []*chunk.Chunk{
genCastRealAsTime(),
inputChunk,
}

for _, input := range inputs {
Expand All @@ -175,27 +176,71 @@ func TestVectorizedCastRealAsTime(t *testing.T) {
for i := 0; i < input.NumRows(); i++ {
res, isNull, err := cast.evalTime(input.GetRow(i))
require.NoError(t, err)
if isNull {
if expect[i] == nil {
require.True(t, result.IsNull(i))
require.True(t, isNull)
continue
}
require.False(t, result.IsNull(i))
require.Zero(t, result.GetTime(i).Compare(res))
require.Equal(t, result.GetTime(i), *expect[i])
require.Equal(t, res, *expect[i])
}
}
}

func genCastRealAsTime() *chunk.Chunk {
input := chunk.NewChunkWithCapacity([]*types.FieldType{types.NewFieldType(mysql.TypeDouble)}, 10)
gen := newDefaultRandGen()
for i := 0; i < 10; i++ {
if i < 5 {
input.AppendFloat64(0, 0)
} else {
input.AppendFloat64(0, gen.Float64()*100000)
}
}
return input
func getTime(year int, month int, day int, hour int, minute int, second int) *types.Time {
retTime := types.NewTime(types.FromDate(year, month, day, hour, minute, second, 0), mysql.TypeDatetime, types.DefaultFsp)
return &retTime
}

func genCastRealAsTime() (*chunk.Chunk, []*types.Time) {
input := chunk.NewChunkWithCapacity([]*types.FieldType{types.NewFieldType(mysql.TypeDouble)}, 20)
expect := make([]*types.Time, 0, 20)

// valid
input.AppendFloat64(0, 0)
input.AppendFloat64(0, 101.1)
input.AppendFloat64(0, 111.1)
input.AppendFloat64(0, 1122.1)
input.AppendFloat64(0, 31212.111)
input.AppendFloat64(0, 121212.1111)
input.AppendFloat64(0, 1121212.111111)
input.AppendFloat64(0, 11121212.111111)
input.AppendFloat64(0, 99991111.1111111)
input.AppendFloat64(0, 201212121212.1111111)
input.AppendFloat64(0, 20121212121212.1111111)
// invalid
input.AppendFloat64(0, 1.1)
input.AppendFloat64(0, 48.1)
input.AppendFloat64(0, 100.1)
input.AppendFloat64(0, 1301.11)
input.AppendFloat64(0, 1131.111)
input.AppendFloat64(0, 100001111.111)
input.AppendFloat64(0, 20121212121260.1111111)
input.AppendFloat64(0, 20121212126012.1111111)
input.AppendFloat64(0, 20121212241212.1111111)

expect = append(expect, getTime(0, 0, 0, 0, 0, 0))
expect = append(expect, getTime(2000, 1, 1, 0, 0, 0))
expect = append(expect, getTime(2000, 1, 11, 0, 0, 0))
expect = append(expect, getTime(2000, 11, 22, 0, 0, 0))
expect = append(expect, getTime(2003, 12, 12, 0, 0, 0))
expect = append(expect, getTime(2012, 12, 12, 0, 0, 0))
expect = append(expect, getTime(112, 12, 12, 0, 0, 0))
expect = append(expect, getTime(1112, 12, 12, 0, 0, 0))
expect = append(expect, getTime(9999, 11, 11, 0, 0, 0))
expect = append(expect, getTime(2020, 12, 12, 12, 12, 12))
expect = append(expect, getTime(2012, 12, 12, 12, 12, 12))
expect = append(expect, nil)
expect = append(expect, nil)
expect = append(expect, nil)
expect = append(expect, nil)
expect = append(expect, nil)
expect = append(expect, nil)
expect = append(expect, nil)
expect = append(expect, nil)
expect = append(expect, nil)

return input, expect
}

// for issue https://github.com/pingcap/tidb/issues/16825
Expand Down
35 changes: 35 additions & 0 deletions expression/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7471,3 +7471,38 @@ func TestCompareJSONWithOtherType(t *testing.T) {
tk.MustQuery("select * from t where a < 6;").Check(testkit.Rows("5"))
tk.MustQuery("select * from t where a > 5;").Check(testkit.Rows("{}", "true"))
}

func TestCastRealAsTime(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t(d1 double, f float, d2 decimal(24,8))")

// zero input
tk.MustExec("insert into t values(0, 0, 0)")

// const
tk.MustQuery("select cast(111.1 as datetime) from t").Check(testkit.Rows("2000-01-11 00:00:00"))
tk.MustQuery("select cast(1311.1 as datetime) from t").Check(testkit.Rows("<nil>"))

// vec
// valid input
tk.MustExec("insert into t values(111.1, 1122.1, 31212.111)")
tk.MustExec("insert into t values(121212.1111, 1121212.111111, 11121212.111111)")
tk.MustExec("insert into t values(99991111.1111111, 101.1111111, 20121212121212.1111111)")
// null input
tk.MustExec("insert into t values(NULL, NULL, NULL)")
// invalid input
tk.MustExec("insert into t values(1.1, 48.1, 100.1)")
tk.MustExec("insert into t values(1301.11, 1131.111, 100001111.111)")
tk.MustExec("insert into t values(20121212121260.1111111, 20121212126012.1111111, 20121212241212.1111111)")
tk.MustQuery("select cast(d1 as datetime), cast(f as datetime), cast(d2 as datetime) from t").Check(testkit.Rows(
"0000-00-00 00:00:00 0000-00-00 00:00:00 0000-00-00 00:00:00",
"2000-01-11 00:00:00 2000-11-22 00:00:00 2003-12-12 00:00:00",
"2012-12-12 00:00:00 0112-12-12 00:00:00 1112-12-12 00:00:00",
"9999-11-11 00:00:00 2000-01-01 00:00:00 2012-12-12 12:12:12",
"<nil> <nil> <nil>",
"<nil> <nil> <nil>",
"<nil> <nil> <nil>",
"<nil> <nil> <nil>"))
}

0 comments on commit 0482b2e

Please sign in to comment.