Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expression: fix that the result of expression castRealAsTime is inconsistent with mysql (#37461) #37560

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions expression/builtin_cast.go
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,11 @@ func (b *builtinCastRealAsTimeSig) evalTime(row chunk.Row) (types.Time, bool, er
return types.ZeroTime, false, nil
}
sc := b.ctx.GetSessionVars().StmtCtx
<<<<<<< HEAD
res, err := types.ParseTime(sc, fv, b.tp.Tp, int8(b.tp.Decimal))
=======
res, err := types.ParseTimeFromFloatString(sc, fv, b.tp.GetType(), b.tp.GetDecimal())
>>>>>>> 0482b2e83... expression: fix that the result of expression castRealAsTime is inconsistent with mysql (#37461)
if err != nil {
return types.ZeroTime, true, handleInvalidTimeError(b.ctx, err)
}
Expand Down
4 changes: 4 additions & 0 deletions expression/builtin_cast_vec.go
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,11 @@ func (b *builtinCastRealAsTimeSig) vecEvalTime(input *chunk.Chunk, result *chunk
times[i] = types.ZeroTime
continue
}
<<<<<<< HEAD
tm, err := types.ParseTime(stmt, fv, b.tp.Tp, fsp)
=======
tm, err := types.ParseTimeFromFloatString(stmt, fv, b.tp.GetType(), fsp)
>>>>>>> 0482b2e83... expression: fix that the result of expression castRealAsTime is inconsistent with mysql (#37461)
if err != nil {
if err = handleInvalidTimeError(b.ctx, err); err != nil {
return err
Expand Down
79 changes: 67 additions & 12 deletions expression/builtin_cast_vec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,37 +164,92 @@ func (s *testEvaluatorSuite) TestVectorizedCastRealAsTime(c *C) {
}
cast := &builtinCastRealAsTimeSig{baseFunc}

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

for _, input := range inputs {
result := chunk.NewColumn(types.NewFieldType(mysql.TypeDatetime), input.NumRows())
c.Assert(cast.vecEvalTime(input, result), IsNil)
for i := 0; i < input.NumRows(); i++ {
res, isNull, err := cast.evalTime(input.GetRow(i))
<<<<<<< HEAD
c.Assert(err, IsNil)
if isNull {
c.Assert(result.IsNull(i), IsTrue)
continue
}
c.Assert(result.IsNull(i), IsFalse)
c.Assert(result.GetTime(i).Compare(res), Equals, 0)
=======
require.NoError(t, err)
if expect[i] == nil {
require.True(t, result.IsNull(i))
require.True(t, isNull)
continue
}
require.Equal(t, result.GetTime(i), *expect[i])
require.Equal(t, res, *expect[i])
>>>>>>> 0482b2e83... expression: fix that the result of expression castRealAsTime is inconsistent with mysql (#37461)
}
}
}

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 @@ -9986,3 +9986,38 @@ func (s *testIntegrationSuite) TestIssue29244(c *C) {
tk.MustExec("set tidb_enable_vectorized_expression = off;")
tk.MustQuery("select microsecond(a) from t;").Check(testkit.Rows("123500", "123500"))
}

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>"))
}