1001 lines
31 KiB
Go
1001 lines
31 KiB
Go
// Copyright 2015 PingCAP, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package expression
|
|
|
|
import (
|
|
"math"
|
|
"strings"
|
|
"time"
|
|
|
|
. "github.com/pingcap/check"
|
|
"github.com/pingcap/tidb/ast"
|
|
"github.com/pingcap/tidb/util/mock"
|
|
"github.com/pingcap/tidb/util/testleak"
|
|
"github.com/pingcap/tidb/util/testutil"
|
|
"github.com/pingcap/tidb/util/types"
|
|
)
|
|
|
|
func (s *testEvaluatorSuite) TestDate(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
tblDate := []struct {
|
|
Input interface{}
|
|
Expect interface{}
|
|
}{
|
|
{"2011-11-11", "2011-11-11"},
|
|
{nil, nil},
|
|
{"2011-11-11 10:10:10", "2011-11-11"},
|
|
}
|
|
dtblDate := tblToDtbl(tblDate)
|
|
for _, t := range dtblDate {
|
|
fc := funcs[ast.Date]
|
|
f, err := fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
if v.Kind() != types.KindMysqlTime {
|
|
c.Assert(v, testutil.DatumEquals, t["Expect"][0])
|
|
} else {
|
|
c.Assert(v.GetMysqlTime().String(), Equals, t["Expect"][0].GetString())
|
|
}
|
|
}
|
|
|
|
// test year, month and day
|
|
tbl := []struct {
|
|
Input string
|
|
Year int64
|
|
Month int64
|
|
MonthName string
|
|
DayOfMonth int64
|
|
DayOfWeek int64
|
|
DayOfYear int64
|
|
WeekDay int64
|
|
DayName string
|
|
Week int64
|
|
WeekOfYear int64
|
|
YearWeek int64
|
|
}{
|
|
{"2000-01-01", 2000, 1, "January", 1, 7, 1, 5, "Saturday", 0, 52, 199952},
|
|
{"2011-11-11", 2011, 11, "November", 11, 6, 315, 4, "Friday", 45, 45, 201145},
|
|
{"0000-01-01", int64(0), 1, "January", 1, 7, 1, 5, "Saturday", 1, 52, 1},
|
|
}
|
|
|
|
dtbl := tblToDtbl(tbl)
|
|
for ith, t := range dtbl {
|
|
fc := funcs[ast.Year]
|
|
f, err := fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["Year"][0])
|
|
|
|
fc = funcs[ast.Month]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["Month"][0])
|
|
|
|
fc = funcs[ast.MonthName]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["MonthName"][0])
|
|
|
|
fc = funcs[ast.DayOfMonth]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["DayOfMonth"][0])
|
|
|
|
fc = funcs[ast.DayOfWeek]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["DayOfWeek"][0])
|
|
|
|
fc = funcs[ast.DayOfYear]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["DayOfYear"][0])
|
|
|
|
fc = funcs[ast.Weekday]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["WeekDay"][0])
|
|
|
|
fc = funcs[ast.DayName]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["DayName"][0])
|
|
|
|
fc = funcs[ast.Week]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["Week"][0], Commentf("no.%d", ith))
|
|
|
|
fc = funcs[ast.WeekOfYear]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["WeekOfYear"][0])
|
|
|
|
fc = funcs[ast.YearWeek]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["YearWeek"][0], Commentf("no.%d", ith))
|
|
}
|
|
|
|
// test nil
|
|
tblNil := []struct {
|
|
Input interface{}
|
|
Year interface{}
|
|
Month interface{}
|
|
MonthName interface{}
|
|
DayOfMonth interface{}
|
|
DayOfWeek interface{}
|
|
DayOfYear interface{}
|
|
WeekDay interface{}
|
|
DayName interface{}
|
|
Week interface{}
|
|
WeekOfYear interface{}
|
|
YearWeek interface{}
|
|
}{
|
|
{nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil},
|
|
{"0000-00-00", int64(0), int64(0), nil, int64(0), nil, nil, nil, nil, nil, nil, nil},
|
|
}
|
|
|
|
dtblNil := tblToDtbl(tblNil)
|
|
for _, t := range dtblNil {
|
|
fc := funcs[ast.Year]
|
|
f, err := fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["Year"][0])
|
|
|
|
fc = funcs[ast.Month]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["Month"][0])
|
|
|
|
fc = funcs[ast.MonthName]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["MonthName"][0])
|
|
|
|
fc = funcs[ast.DayOfMonth]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["DayOfMonth"][0])
|
|
|
|
fc = funcs[ast.DayOfWeek]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["DayOfWeek"][0])
|
|
|
|
fc = funcs[ast.DayOfYear]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["DayOfYear"][0])
|
|
|
|
fc = funcs[ast.Weekday]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["WeekDay"][0])
|
|
|
|
fc = funcs[ast.DayName]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["DayName"][0])
|
|
|
|
fc = funcs[ast.Week]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["Week"][0])
|
|
|
|
fc = funcs[ast.WeekOfYear]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["WeekOfYear"][0])
|
|
|
|
fc = funcs[ast.YearWeek]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["YearWeek"][0])
|
|
}
|
|
}
|
|
|
|
func (s *testEvaluatorSuite) TestDateFormat(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
|
|
tblDate := []struct {
|
|
Input []string
|
|
Expect interface{}
|
|
}{
|
|
{[]string{"2010-01-07 23:12:34.12345",
|
|
"%b %M %m %c %D %d %e %j %k %h %i %p %r %T %s %f %U %u %V %v %a %W %w %X %x %Y %y %%"},
|
|
"Jan January 01 1 7th 07 7 007 23 11 12 PM 11:12:34 PM 23:12:34 34 123450 01 01 01 01 Thu Thursday 4 2010 2010 2010 10 %"},
|
|
{[]string{"2012-12-21 23:12:34.123456",
|
|
"%b %M %m %c %D %d %e %j %k %h %i %p %r %T %s %f %U %u %V %v %a %W %w %X %x %Y %y %%"},
|
|
"Dec December 12 12 21st 21 21 356 23 11 12 PM 11:12:34 PM 23:12:34 34 123456 51 51 51 51 Fri Friday 5 2012 2012 2012 12 %"},
|
|
{[]string{"0000-01-01 00:00:00.123456",
|
|
// Functions week() and yearweek() don't support multi mode,
|
|
// so the result of "%U %u %V %Y" is different from MySQL.
|
|
"%b %M %m %c %D %d %e %j %k %h %i %p %r %T %s %f %v %x %Y %y %%"},
|
|
"Jan January 01 1 1st 01 1 001 0 12 00 AM 12:00:00 AM 00:00:00 00 123456 52 4294967295 0000 00 %"},
|
|
{[]string{"2016-09-3 00:59:59.123456",
|
|
"abc%b %M %m %c %D %d %e %j %k %h %i %p %r %T %s %f %U %u %V %v %a %W %w %X %x %Y %y!123 %%xyz %z"},
|
|
"abcSep September 09 9 3rd 03 3 247 0 12 59 AM 12:59:59 AM 00:59:59 59 123456 35 35 35 35 Sat Saturday 6 2016 2016 2016 16!123 %xyz z"},
|
|
{[]string{"2012-10-01 00:00:00",
|
|
"%b %M %m %c %D %d %e %j %k %H %i %p %r %T %s %f %v %x %Y %y %%"},
|
|
"Oct October 10 10 1st 01 1 275 0 00 00 AM 12:00:00 AM 00:00:00 00 000000 40 2012 2012 12 %"},
|
|
}
|
|
dtblDate := tblToDtbl(tblDate)
|
|
for i, t := range dtblDate {
|
|
fc := funcs[ast.DateFormat]
|
|
f, err := fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["Expect"][0], Commentf("no.%d \nobtain:%v \nexpect:%v\n", i,
|
|
v.GetValue(), t["Expect"][0].GetValue()))
|
|
}
|
|
}
|
|
|
|
func (s *testEvaluatorSuite) TestClock(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
// test hour, minute, second, micro second
|
|
|
|
tbl := []struct {
|
|
Input string
|
|
Hour int64
|
|
Minute int64
|
|
Second int64
|
|
MicroSecond int64
|
|
Time string
|
|
}{
|
|
{"10:10:10.123456", 10, 10, 10, 123456, "10:10:10.123456"},
|
|
{"11:11:11.11", 11, 11, 11, 110000, "11:11:11.11"},
|
|
{"2010-10-10 11:11:11.11", 11, 11, 11, 110000, "11:11:11.11"},
|
|
}
|
|
|
|
dtbl := tblToDtbl(tbl)
|
|
for _, t := range dtbl {
|
|
fc := funcs[ast.Hour]
|
|
f, err := fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["Hour"][0])
|
|
|
|
fc = funcs[ast.Minute]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["Minute"][0])
|
|
|
|
fc = funcs[ast.Second]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["Second"][0])
|
|
|
|
fc = funcs[ast.MicroSecond]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["MicroSecond"][0])
|
|
|
|
fc = funcs[ast.Time]
|
|
f, err = fc.getFunction(datumsToConstants(t["Input"]), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v, testutil.DatumEquals, t["Time"][0])
|
|
}
|
|
|
|
// nil
|
|
fc := funcs[ast.Hour]
|
|
f, err := fc.getFunction(datumsToConstants(types.MakeDatums(nil)), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v.Kind(), Equals, types.KindNull)
|
|
|
|
fc = funcs[ast.Minute]
|
|
f, err = fc.getFunction(datumsToConstants(types.MakeDatums(nil)), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v.Kind(), Equals, types.KindNull)
|
|
|
|
fc = funcs[ast.Second]
|
|
f, err = fc.getFunction(datumsToConstants(types.MakeDatums(nil)), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v.Kind(), Equals, types.KindNull)
|
|
|
|
fc = funcs[ast.MicroSecond]
|
|
f, err = fc.getFunction(datumsToConstants(types.MakeDatums(nil)), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v.Kind(), Equals, types.KindNull)
|
|
|
|
fc = funcs[ast.Time]
|
|
f, err = fc.getFunction(datumsToConstants(types.MakeDatums(nil)), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v.Kind(), Equals, types.KindNull)
|
|
|
|
// test error
|
|
errTbl := []string{
|
|
"2011-11-11T10:10:10.11",
|
|
"2011-11-11 10:10:10.11.12",
|
|
}
|
|
|
|
for _, t := range errTbl {
|
|
td := types.MakeDatums(t)
|
|
fc := funcs[ast.Hour]
|
|
f, err := fc.getFunction(datumsToConstants(td), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
_, err = f.eval(nil)
|
|
c.Assert(err, NotNil)
|
|
|
|
fc = funcs[ast.Minute]
|
|
f, err = fc.getFunction(datumsToConstants(td), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
_, err = f.eval(nil)
|
|
c.Assert(err, NotNil)
|
|
|
|
fc = funcs[ast.Second]
|
|
f, err = fc.getFunction(datumsToConstants(td), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
_, err = f.eval(nil)
|
|
c.Assert(err, NotNil)
|
|
|
|
fc = funcs[ast.MicroSecond]
|
|
f, err = fc.getFunction(datumsToConstants(td), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
_, err = f.eval(nil)
|
|
c.Assert(err, NotNil)
|
|
|
|
fc = funcs[ast.Time]
|
|
f, err = fc.getFunction(datumsToConstants(td), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
_, err = f.eval(nil)
|
|
c.Assert(err, NotNil)
|
|
}
|
|
}
|
|
|
|
func (s *testEvaluatorSuite) TestNowAndUTCTimestamp(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
|
|
gotime := func(t types.Time, l *time.Location) time.Time {
|
|
tt, err := t.Time.GoTime(l)
|
|
c.Assert(err, IsNil)
|
|
return tt
|
|
}
|
|
|
|
for _, x := range []struct {
|
|
fc functionClass
|
|
now func() time.Time
|
|
}{
|
|
{funcs[ast.Now], func() time.Time { return time.Now() }},
|
|
{funcs[ast.UTCTimestamp], func() time.Time { return time.Now().UTC() }},
|
|
} {
|
|
f, err := x.fc.getFunction(datumsToConstants(nil), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err := f.eval(nil)
|
|
ts := x.now()
|
|
c.Assert(err, IsNil)
|
|
t := v.GetMysqlTime()
|
|
// we canot use a constant value to check timestamp funcs, so here
|
|
// just to check the fractional seconds part and the time delta.
|
|
c.Assert(strings.Contains(t.String(), "."), IsFalse)
|
|
c.Assert(ts.Sub(gotime(t, ts.Location())), LessEqual, time.Second)
|
|
|
|
f, err = x.fc.getFunction(datumsToConstants(types.MakeDatums(6)), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
ts = x.now()
|
|
c.Assert(err, IsNil)
|
|
t = v.GetMysqlTime()
|
|
c.Assert(strings.Contains(t.String(), "."), IsTrue)
|
|
c.Assert(ts.Sub(gotime(t, ts.Location())), LessEqual, time.Millisecond)
|
|
|
|
f, err = x.fc.getFunction(datumsToConstants(types.MakeDatums(8)), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
_, err = f.eval(nil)
|
|
c.Assert(err, NotNil)
|
|
|
|
f, err = x.fc.getFunction(datumsToConstants(types.MakeDatums(-2)), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
_, err = f.eval(nil)
|
|
c.Assert(err, NotNil)
|
|
}
|
|
}
|
|
|
|
func (s *testEvaluatorSuite) TestSysDate(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
fc := funcs[ast.Sysdate]
|
|
f, err := fc.getFunction(datumsToConstants(nil), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err := f.eval(nil)
|
|
last := time.Now()
|
|
c.Assert(err, IsNil)
|
|
n := v.GetMysqlTime()
|
|
c.Assert(n.String(), GreaterEqual, last.Format(types.TimeFormat))
|
|
|
|
f, err = fc.getFunction(datumsToConstants(types.MakeDatums(6)), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
n = v.GetMysqlTime()
|
|
c.Assert(n.String(), GreaterEqual, last.Format(types.TimeFormat))
|
|
|
|
f, err = fc.getFunction(datumsToConstants(types.MakeDatums(-2)), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
_, err = f.eval(nil)
|
|
c.Assert(err, NotNil)
|
|
}
|
|
|
|
func (s *testEvaluatorSuite) TestFromUnixTime(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
|
|
tbl := []struct {
|
|
isDecimal bool
|
|
integralPart int64
|
|
fractionalPart int64
|
|
decimal float64
|
|
format string
|
|
ansLen int
|
|
}{
|
|
{false, 1451606400, 0, 0, "", 19},
|
|
{true, 1451606400, 123456000, 1451606400.123456, "", 26},
|
|
{true, 1451606400, 999999000, 1451606400.999999, "", 26},
|
|
{true, 1451606400, 999999900, 1451606400.9999999, "", 19},
|
|
{false, 1451606400, 0, 0, "%Y %D %M %h:%i:%s %x", 19},
|
|
{true, 1451606400, 123456000, 1451606400.123456, "%Y %D %M %h:%i:%s %x", 26},
|
|
{true, 1451606400, 999999000, 1451606400.999999, "%Y %D %M %h:%i:%s %x", 26},
|
|
{true, 1451606400, 999999900, 1451606400.9999999, "%Y %D %M %h:%i:%s %x", 19},
|
|
}
|
|
fc := funcs[ast.FromUnixTime]
|
|
for _, t := range tbl {
|
|
var timestamp types.Datum
|
|
if !t.isDecimal {
|
|
timestamp.SetInt64(t.integralPart)
|
|
} else {
|
|
timestamp.SetFloat64(t.decimal)
|
|
}
|
|
// result of from_unixtime() is dependent on specific time zone.
|
|
unixTime := time.Unix(t.integralPart, t.fractionalPart).Round(time.Microsecond).String()[:t.ansLen]
|
|
if len(t.format) == 0 {
|
|
f, err := fc.getFunction(datumsToConstants([]types.Datum{timestamp}), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
ans := v.GetMysqlTime()
|
|
c.Assert(ans.String(), Equals, unixTime)
|
|
} else {
|
|
format := types.NewStringDatum(t.format)
|
|
f, err := fc.getFunction(datumsToConstants([]types.Datum{timestamp, format}), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
result, err := builtinDateFormat([]types.Datum{types.NewStringDatum(unixTime), format}, s.ctx)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v.GetString(), Equals, result.GetString())
|
|
}
|
|
}
|
|
|
|
f, err := fc.getFunction(datumsToConstants(types.MakeDatums(-12345)), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v.Kind(), Equals, types.KindNull)
|
|
|
|
f, err = fc.getFunction(datumsToConstants(types.MakeDatums(math.MaxInt32+1)), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
_, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v.Kind(), Equals, types.KindNull)
|
|
}
|
|
|
|
func (s *testEvaluatorSuite) TestCurrentDate(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
last := time.Now()
|
|
fc := funcs[ast.CurrentDate]
|
|
f, err := fc.getFunction(datumsToConstants(nil), mock.NewContext())
|
|
c.Assert(err, IsNil)
|
|
v, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
n := v.GetMysqlTime()
|
|
c.Assert(n.String(), GreaterEqual, last.Format(types.DateFormat))
|
|
}
|
|
|
|
func (s *testEvaluatorSuite) TestCurrentTime(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
tfStr := "15:04:05"
|
|
|
|
last := time.Now()
|
|
fc := funcs[ast.CurrentTime]
|
|
f, err := fc.getFunction(datumsToConstants(types.MakeDatums(nil)), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
n := v.GetMysqlDuration()
|
|
c.Assert(n.String(), HasLen, 8)
|
|
c.Assert(n.String(), GreaterEqual, last.Format(tfStr))
|
|
|
|
f, err = fc.getFunction(datumsToConstants(types.MakeDatums(3)), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
n = v.GetMysqlDuration()
|
|
c.Assert(n.String(), HasLen, 12)
|
|
c.Assert(n.String(), GreaterEqual, last.Format(tfStr))
|
|
|
|
f, err = fc.getFunction(datumsToConstants(types.MakeDatums(6)), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
n = v.GetMysqlDuration()
|
|
c.Assert(n.String(), HasLen, 15)
|
|
c.Assert(n.String(), GreaterEqual, last.Format(tfStr))
|
|
|
|
f, err = fc.getFunction(datumsToConstants(types.MakeDatums(-1)), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
_, err = f.eval(nil)
|
|
c.Assert(err, NotNil)
|
|
|
|
f, err = fc.getFunction(datumsToConstants(types.MakeDatums(7)), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
_, err = f.eval(nil)
|
|
c.Assert(err, NotNil)
|
|
}
|
|
|
|
func (s *testEvaluatorSuite) TestUTCDate(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
last := time.Now().UTC()
|
|
fc := funcs[ast.UTCDate]
|
|
f, err := fc.getFunction(datumsToConstants(nil), mock.NewContext())
|
|
c.Assert(err, IsNil)
|
|
v, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
n := v.GetMysqlTime()
|
|
c.Assert(n.String(), GreaterEqual, last.Format(types.DateFormat))
|
|
}
|
|
|
|
func (s *testEvaluatorSuite) TestStrToDate(c *C) {
|
|
tests := []struct {
|
|
Date string
|
|
Format string
|
|
Success bool
|
|
Expect time.Time
|
|
}{
|
|
{"20161122165022", "%Y%m%d%H%i%s", true, time.Date(2016, 11, 22, 16, 50, 22, 0, time.Local)},
|
|
{"2016 11 22 16 50 22", "%Y%m%d%H%i%s", true, time.Date(2016, 11, 22, 16, 50, 22, 0, time.Local)},
|
|
{"16-50-22 2016 11 22", "%H-%i-%s%Y%m%d", true, time.Date(2016, 11, 22, 16, 50, 22, 0, time.Local)},
|
|
{"16-50 2016 11 22", "%H-%i-%s%Y%m%d", false, time.Time{}},
|
|
}
|
|
|
|
fc := funcs[ast.StrToDate]
|
|
for _, test := range tests {
|
|
date := types.NewStringDatum(test.Date)
|
|
format := types.NewStringDatum(test.Format)
|
|
f, err := fc.getFunction(datumsToConstants([]types.Datum{date, format}), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
result, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
if !test.Success {
|
|
c.Assert(err, IsNil)
|
|
c.Assert(result.IsNull(), IsTrue)
|
|
continue
|
|
}
|
|
c.Assert(result.Kind(), Equals, types.KindMysqlTime)
|
|
value := result.GetMysqlTime()
|
|
t1, _ := value.Time.GoTime(time.Local)
|
|
c.Assert(t1, Equals, test.Expect)
|
|
}
|
|
}
|
|
|
|
func (s *testEvaluatorSuite) TestFromDays(c *C) {
|
|
tests := []struct {
|
|
day int64
|
|
expect string
|
|
}{
|
|
{-140, "0000-00-00"}, // mysql FROM_DAYS returns 0000-00-00 for any day <= 365.
|
|
{140, "0000-00-00"}, // mysql FROM_DAYS returns 0000-00-00 for any day <= 365.
|
|
{735000, "2012-05-12"}, // Leap year.
|
|
{735030, "2012-06-11"},
|
|
{735130, "2012-09-19"},
|
|
{734909, "2012-02-11"},
|
|
{734878, "2012-01-11"},
|
|
{734927, "2012-02-29"},
|
|
{734634, "2011-05-12"}, // Non Leap year.
|
|
{734664, "2011-06-11"},
|
|
{734764, "2011-09-19"},
|
|
{734544, "2011-02-11"},
|
|
{734513, "2011-01-11"},
|
|
}
|
|
|
|
fc := funcs[ast.FromDays]
|
|
for _, test := range tests {
|
|
t1 := types.NewIntDatum(test.day)
|
|
|
|
f, err := fc.getFunction(datumsToConstants([]types.Datum{t1}), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
result, err := f.eval(nil)
|
|
|
|
c.Assert(err, IsNil)
|
|
c.Assert(result.GetMysqlTime().String(), Equals, test.expect)
|
|
}
|
|
|
|
stringTests := []struct {
|
|
day string
|
|
expect string
|
|
}{
|
|
{"z550z", "0000-00-00"},
|
|
{"6500z", "0017-10-18"},
|
|
{"440", "0001-03-16"},
|
|
}
|
|
|
|
for _, test := range stringTests {
|
|
t1 := types.NewStringDatum(test.day)
|
|
|
|
f, err := fc.getFunction(datumsToConstants([]types.Datum{t1}), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
result, err := f.eval(nil)
|
|
|
|
c.Assert(err, IsNil)
|
|
c.Assert(result.GetMysqlTime().String(), Equals, test.expect)
|
|
}
|
|
}
|
|
|
|
func (s *testEvaluatorSuite) TestDateDiff(c *C) {
|
|
// Test cases from https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_datediff
|
|
tests := []struct {
|
|
t1 string
|
|
t2 string
|
|
expect int64
|
|
}{
|
|
{"2004-05-21", "2004:01:02", 140},
|
|
{"2004-04-21", "2000:01:02", 1571},
|
|
{"2008-12-31 23:59:59.000001", "2008-12-30 01:01:01.000002", 1},
|
|
{"1010-11-30 23:59:59", "2010-12-31", -365274},
|
|
{"1010-11-30", "2210-11-01", -438262},
|
|
}
|
|
|
|
fc := funcs[ast.DateDiff]
|
|
for _, test := range tests {
|
|
t1 := types.NewStringDatum(test.t1)
|
|
t2 := types.NewStringDatum(test.t2)
|
|
|
|
f, err := fc.getFunction(datumsToConstants([]types.Datum{t1, t2}), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
result, err := f.eval(nil)
|
|
|
|
c.Assert(err, IsNil)
|
|
c.Assert(result.GetInt64(), Equals, test.expect)
|
|
}
|
|
|
|
// Check if month is 0.
|
|
t1 := types.NewStringDatum("2016-00-01")
|
|
t2 := types.NewStringDatum("2016-01-13")
|
|
|
|
f, err := fc.getFunction(datumsToConstants([]types.Datum{t1, t2}), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
result, err := f.eval(nil)
|
|
|
|
c.Assert(err, IsNil)
|
|
c.Assert(result.IsNull(), Equals, true)
|
|
|
|
f, err = fc.getFunction(datumsToConstants([]types.Datum{{}, types.NewStringDatum("2017-01-01")}), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
d, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(d.IsNull(), IsTrue)
|
|
}
|
|
|
|
func (s *testEvaluatorSuite) TestTimeDiff(c *C) {
|
|
// Test cases from https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_timediff
|
|
tests := []struct {
|
|
t1 string
|
|
t2 string
|
|
expectStr string
|
|
}{
|
|
{"2000:01:01 00:00:00", "2000:01:01 00:00:00.000001", "-00:00:00.000001"},
|
|
{"2008-12-31 23:59:59.000001", "2008-12-30 01:01:01.000002", "46:58:57.999999"},
|
|
{"2016-12-00 12:00:00", "2016-12-01 12:00:00", "-24:00:00.000000"},
|
|
}
|
|
fc := funcs[ast.TimeDiff]
|
|
for _, test := range tests {
|
|
t1 := types.NewStringDatum(test.t1)
|
|
t2 := types.NewStringDatum(test.t2)
|
|
f, err := fc.getFunction(datumsToConstants([]types.Datum{t1, t2}), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
result, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(result.GetMysqlDuration().String(), Equals, test.expectStr)
|
|
}
|
|
f, err := fc.getFunction(datumsToConstants([]types.Datum{{}, types.NewStringDatum("2017-01-01")}), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
d, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(d.IsNull(), IsTrue)
|
|
}
|
|
|
|
func (s *testEvaluatorSuite) TestWeek(c *C) {
|
|
// Test cases from https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_week
|
|
tests := []struct {
|
|
t string
|
|
mode int64
|
|
expect int64
|
|
}{
|
|
{"2008-02-20", 0, 7},
|
|
{"2008-02-20", 1, 8},
|
|
{"2008-12-31", 1, 53},
|
|
}
|
|
fc := funcs[ast.Week]
|
|
for _, test := range tests {
|
|
arg1 := types.NewStringDatum(test.t)
|
|
arg2 := types.NewIntDatum(test.mode)
|
|
f, err := fc.getFunction(datumsToConstants([]types.Datum{arg1, arg2}), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
result, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(result.GetInt64(), Equals, test.expect)
|
|
}
|
|
|
|
}
|
|
|
|
func (s *testEvaluatorSuite) TestYearWeek(c *C) {
|
|
// Test cases from https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_yearweek
|
|
tests := []struct {
|
|
t string
|
|
mode int64
|
|
expect int64
|
|
}{
|
|
{"1987-01-01", 0, 198652},
|
|
{"2000-01-01", 0, 199952},
|
|
}
|
|
fc := funcs[ast.YearWeek]
|
|
for _, test := range tests {
|
|
arg1 := types.NewStringDatum(test.t)
|
|
arg2 := types.NewIntDatum(test.mode)
|
|
f, err := fc.getFunction(datumsToConstants([]types.Datum{arg1, arg2}), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
result, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(result.GetInt64(), Equals, test.expect)
|
|
}
|
|
|
|
f, err := fc.getFunction(datumsToConstants(types.MakeDatums("2016-00-05")), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
result, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(result.IsNull(), IsTrue)
|
|
}
|
|
|
|
func (s *testEvaluatorSuite) TestTimestampDiff(c *C) {
|
|
tests := []struct {
|
|
unit string
|
|
t1 string
|
|
t2 string
|
|
expect int64
|
|
}{
|
|
{"MONTH", "2003-02-01", "2003-05-01", 3},
|
|
{"YEAR", "2002-05-01", "2001-01-01", -1},
|
|
{"MINUTE", "2003-02-01", "2003-05-01 12:05:55", 128885},
|
|
}
|
|
|
|
fc := funcs[ast.TimestampDiff]
|
|
for _, test := range tests {
|
|
args := []types.Datum{
|
|
types.NewStringDatum(test.unit),
|
|
types.NewStringDatum(test.t1),
|
|
types.NewStringDatum(test.t2),
|
|
}
|
|
f, err := fc.getFunction(datumsToConstants(args), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
d, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(d.GetInt64(), Equals, test.expect)
|
|
}
|
|
s.ctx.GetSessionVars().StmtCtx.IgnoreTruncate = true
|
|
f, err := fc.getFunction(datumsToConstants([]types.Datum{types.NewStringDatum("DAY"),
|
|
types.NewStringDatum("2017-01-00"),
|
|
types.NewStringDatum("2017-01-01")}), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
d, err := f.eval(nil)
|
|
c.Assert(d.Kind(), Equals, types.KindNull)
|
|
|
|
f, err = fc.getFunction(datumsToConstants([]types.Datum{types.NewStringDatum("DAY"),
|
|
{}, types.NewStringDatum("2017-01-01")}), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
d, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(d.IsNull(), IsTrue)
|
|
}
|
|
|
|
func (s *testEvaluatorSuite) TestUnixTimestamp(c *C) {
|
|
fc := funcs[ast.UnixTimestamp]
|
|
f, err := fc.getFunction(nil, s.ctx)
|
|
c.Assert(err, IsNil)
|
|
d, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(d.GetInt64()-time.Now().Unix(), GreaterEqual, int64(-1))
|
|
c.Assert(d.GetInt64()-time.Now().Unix(), LessEqual, int64(1))
|
|
|
|
// Test case for https://github.com/pingcap/tidb/issues/2496
|
|
// select unix_timestamp(now());
|
|
n, err := builtinNow(nil, s.ctx)
|
|
c.Assert(err, IsNil)
|
|
args := []types.Datum{n}
|
|
f, err = fc.getFunction(datumsToConstants(args), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
d, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(d.GetInt64()-time.Now().Unix(), GreaterEqual, int64(-1))
|
|
c.Assert(d.GetInt64()-time.Now().Unix(), LessEqual, int64(1))
|
|
|
|
// Set the time_zone variable, because UnixTimestamp() result depends on it.
|
|
s.ctx.GetSessionVars().TimeZone = time.UTC
|
|
tests := []struct {
|
|
input types.Datum
|
|
expect string
|
|
}{
|
|
{types.NewIntDatum(20151113102019), "1447410019"},
|
|
{types.NewStringDatum("2015-11-13 10:20:19"), "1447410019"},
|
|
{types.NewStringDatum("2015-11-13 10:20:19.012"), "1447410019.012"},
|
|
{types.NewStringDatum("2017-00-02"), "0"},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
f, err := fc.getFunction(datumsToConstants([]types.Datum{test.input}), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
d, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
str, err := d.ToString()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(str, Equals, test.expect)
|
|
}
|
|
}
|
|
|
|
func (s *testEvaluatorSuite) TestDateArithFuncs(c *C) {
|
|
defer testleak.AfterTest(c)()
|
|
|
|
date := []string{"2016-12-31", "2017-01-01"}
|
|
fcAdd := funcs[ast.DateAdd]
|
|
fcSub := funcs[ast.DateSub]
|
|
|
|
args := types.MakeDatums(date[0], 1, "DAY")
|
|
f, err := fcAdd.getFunction(datumsToConstants(args), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v.GetMysqlTime().String(), Equals, date[1])
|
|
|
|
args = types.MakeDatums(date[1], 1, "DAY")
|
|
f, err = fcSub.getFunction(datumsToConstants(args), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v.GetMysqlTime().String(), Equals, date[0])
|
|
|
|
args = types.MakeDatums(date[0], nil, "DAY")
|
|
f, err = fcAdd.getFunction(datumsToConstants(args), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v.IsNull(), IsTrue)
|
|
|
|
args = types.MakeDatums(date[1], nil, "DAY")
|
|
f, err = fcSub.getFunction(datumsToConstants(args), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
v, err = f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(v.IsNull(), IsTrue)
|
|
}
|
|
|
|
func (s *testEvaluatorSuite) TestTimestamp(c *C) {
|
|
tests := []struct {
|
|
t []types.Datum
|
|
expect string
|
|
}{
|
|
// one argument
|
|
{[]types.Datum{types.NewStringDatum("2017-01-18")}, "2017-01-18 00:00:00"},
|
|
{[]types.Datum{types.NewStringDatum("20170118")}, "2017-01-18 00:00:00"},
|
|
{[]types.Datum{types.NewStringDatum("170118")}, "2017-01-18 00:00:00"},
|
|
{[]types.Datum{types.NewStringDatum("20170118123056")}, "2017-01-18 12:30:56"},
|
|
{[]types.Datum{types.NewStringDatum("2017-01-18 12:30:56")}, "2017-01-18 12:30:56"},
|
|
{[]types.Datum{types.NewIntDatum(170118)}, "2017-01-18 00:00:00"},
|
|
{[]types.Datum{types.NewFloat64Datum(20170118)}, "2017-01-18 00:00:00"},
|
|
{[]types.Datum{types.NewStringDatum("20170118123050.999")}, "2017-01-18 12:30:50.999"},
|
|
{[]types.Datum{types.NewStringDatum("20170118123050.1234567")}, "2017-01-18 12:30:50.123457"},
|
|
|
|
// two arguments
|
|
{[]types.Datum{types.NewStringDatum("2017-01-18"), types.NewStringDatum("12:30:59")}, "2017-01-18 12:30:59"},
|
|
{[]types.Datum{types.NewStringDatum("2017-01-18"), types.NewStringDatum("12:30:59")}, "2017-01-18 12:30:59"},
|
|
{[]types.Datum{types.NewStringDatum("2017-01-18 01:01:01"), types.NewStringDatum("12:30:50")}, "2017-01-18 13:31:51"},
|
|
{[]types.Datum{types.NewStringDatum("2017-01-18 01:01:01"), types.NewStringDatum("838:59:59")}, "2017-02-22 00:01:00"},
|
|
|
|
// TODO: the following test cases exists precision problems.
|
|
//{[]types.Datum{types.NewFloat64Datum(20170118123950.123)}, "2017-01-18 12:30:50.123"},
|
|
//{[]types.Datum{types.NewFloat64Datum(20170118123950.999)}, "2017-01-18 12:30:50.999"},
|
|
//{[]types.Datum{types.NewFloat32Datum(float32(20170118123950.999))}, "2017-01-18 12:30:50.699"},
|
|
|
|
// TODO: the following test cases will cause time format error.
|
|
//{[]types.Datum{types.NewFloat64Datum(20170118.999)}, "2017-01-18 00:00:00.000"},
|
|
//{[]types.Datum{types.NewStringDatum("11111111111")}, "2011-11-11 11:11:01"},
|
|
|
|
}
|
|
fc := funcs[ast.Timestamp]
|
|
for _, test := range tests {
|
|
f, err := fc.getFunction(datumsToConstants(test.t), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
d, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
result, _ := d.ToString()
|
|
c.Assert(result, Equals, test.expect)
|
|
}
|
|
|
|
nilDatum := types.NewDatum(nil)
|
|
f, err := fc.getFunction(datumsToConstants([]types.Datum{nilDatum}), s.ctx)
|
|
c.Assert(err, IsNil)
|
|
d, err := f.eval(nil)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(d.Kind(), Equals, types.KindNull)
|
|
}
|