Skip to content

Commit

Permalink
expression, plan: rewrite builtin func get_format (#4422)
Browse files Browse the repository at this point in the history
  • Loading branch information
XuHuaiyu authored and hanfei1991 committed Sep 5, 2017
1 parent 6ad9d35 commit 5f00460
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 23 deletions.
56 changes: 33 additions & 23 deletions expression/builtin_time.go
Expand Up @@ -1199,63 +1199,73 @@ func (c *getFormatFunctionClass) getFunction(ctx context.Context, args []Express
if err := c.verifyArgs(args); err != nil {
return nil, errors.Trace(err)
}
sig := &builtinGetFormatSig{newBaseBuiltinFunc(args, ctx)}
bf := newBaseBuiltinFuncWithTp(args, ctx, tpString, tpString, tpString)
bf.tp.Flen = 17
sig := &builtinGetFormatSig{baseStringBuiltinFunc{bf}}
return sig.setSelf(sig), nil
}

type builtinGetFormatSig struct {
baseBuiltinFunc
baseStringBuiltinFunc
}

// eval evals a builtinGetFormatSig.
// evalString evals a builtinGetFormatSig.
// See https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_get-format
func (b *builtinGetFormatSig) eval(row []types.Datum) (d types.Datum, err error) {
args, err := b.evalArgs(row)
t := args[0].GetString()
l := args[1].GetString()
func (b *builtinGetFormatSig) evalString(row []types.Datum) (string, bool, error) {
sc := b.ctx.GetSessionVars().StmtCtx
t, isNull, err := b.args[0].EvalString(row, sc)
if isNull || err != nil {
return "", isNull, errors.Trace(err)
}
l, isNull, err := b.args[1].EvalString(row, sc)
if isNull || err != nil {
return "", isNull, errors.Trace(err)
}

var res string
switch t {
case dateFormat:
switch l {
case usaLocation:
d.SetString("%m.%d.%Y")
res = "%m.%d.%Y"
case jisLocation:
d.SetString("%Y-%m-%d")
res = "%Y-%m-%d"
case isoLocation:
d.SetString("%Y-%m-%d")
res = "%Y-%m-%d"
case eurLocation:
d.SetString("%d.%m.%Y")
res = "%d.%m.%Y"
case internalLocation:
d.SetString("%Y%m%d")
res = "%Y%m%d"
}
case datetimeFormat, timestampFormat:
switch l {
case usaLocation:
d.SetString("%Y-%m-%d %H.%i.%s")
res = "%Y-%m-%d %H.%i.%s"
case jisLocation:
d.SetString("%Y-%m-%d %H:%i:%s")
res = "%Y-%m-%d %H:%i:%s"
case isoLocation:
d.SetString("%Y-%m-%d %H:%i:%s")
res = "%Y-%m-%d %H:%i:%s"
case eurLocation:
d.SetString("%Y-%m-%d %H.%i.%s")
res = "%Y-%m-%d %H.%i.%s"
case internalLocation:
d.SetString("%Y%m%d%H%i%s")
res = "%Y%m%d%H%i%s"
}
case timeFormat:
switch l {
case usaLocation:
d.SetString("%h:%i:%s %p")
res = "%h:%i:%s %p"
case jisLocation:
d.SetString("%H:%i:%s")
res = "%H:%i:%s"
case isoLocation:
d.SetString("%H:%i:%s")
res = "%H:%i:%s"
case eurLocation:
d.SetString("%H.%i.%s")
res = "%H.%i.%s"
case internalLocation:
d.SetString("%H%i%s")
res = "%H%i%s"
}
}

return
return res, false, nil
}

type strToDateFunctionClass struct {
Expand Down
1 change: 1 addition & 0 deletions expression/builtin_time_test.go
Expand Up @@ -1737,6 +1737,7 @@ func (s *testEvaluatorSuite) TestGetFormat(c *C) {
t := []types.Datum{types.NewStringDatum(test.unit), types.NewStringDatum(test.location)}
f, err := fc.getFunction(s.ctx, datumsToConstants(t))
c.Assert(err, IsNil)
c.Assert(f.canBeFolded(), IsTrue)
d, err := f.eval(nil)
c.Assert(err, IsNil)
result, _ := d.ToString()
Expand Down
7 changes: 7 additions & 0 deletions expression/integration_test.go
Expand Up @@ -1432,6 +1432,13 @@ func (s *testIntegrationSuite) TestTimeBuiltin(c *C) {
// TODO: MySQL returns "<nil> <nil>".
result.Check(testkit.Rows("0000-00-01 <nil>"))
tk.MustQuery("show warnings").Check(testutil.RowsWithSep("|", "Warning|1105|invalid time format"))

// for get_format
result = tk.MustQuery(`select GET_FORMAT(DATE,'USA'), GET_FORMAT(DATE,'JIS'), GET_FORMAT(DATE,'ISO'), GET_FORMAT(DATE,'EUR'),
GET_FORMAT(DATE,'INTERNAL'), GET_FORMAT(DATETIME,'USA') , GET_FORMAT(DATETIME,'JIS'), GET_FORMAT(DATETIME,'ISO'),
GET_FORMAT(DATETIME,'EUR') , GET_FORMAT(DATETIME,'INTERNAL'), GET_FORMAT(TIME,'USA') , GET_FORMAT(TIME,'JIS'),
GET_FORMAT(TIME,'ISO'), GET_FORMAT(TIME,'EUR'), GET_FORMAT(TIME,'INTERNAL')`)
result.Check(testkit.Rows("%m.%d.%Y %Y-%m-%d %Y-%m-%d %d.%m.%Y %Y%m%d %Y-%m-%d %H.%i.%s %Y-%m-%d %H:%i:%s %Y-%m-%d %H:%i:%s %Y-%m-%d %H.%i.%s %Y%m%d%H%i%s %h:%i:%s %p %H:%i:%s %H:%i:%s %H.%i.%s %H%i%s"))
}

func (s *testIntegrationSuite) TestOpBuiltin(c *C) {
Expand Down
2 changes: 2 additions & 0 deletions plan/typeinfer_test.go
Expand Up @@ -1676,6 +1676,8 @@ func (s *testPlanSuite) createTestCase4TimeFuncs() []typeInferTestCase {
{"period_diff(c_blob_d , c_int_d)", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, 6, 0},
{"period_diff(c_set , c_int_d)", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, 6, 0},
{"period_diff(c_enum , c_int_d)", mysql.TypeLonglong, charset.CharsetBin, mysql.BinaryFlag, 6, 0},

{"get_format(DATE, 'USA')", mysql.TypeVarString, charset.CharsetUTF8, 0, 17, types.UnspecifiedLength},
}
}

Expand Down

0 comments on commit 5f00460

Please sign in to comment.