Merge pull request #23 from pingcap/shenli/builtin-convert

Add convert type function
This commit is contained in:
Shen Li
2015-09-07 11:01:10 +08:00
4 changed files with 46 additions and 6 deletions

View File

@ -29,6 +29,8 @@ type FunctionCast struct {
Expr expression.Expression
// Tp is the conversion type.
Tp *types.FieldType
// Cast and Convert share this struct.
IsConvert bool
}
// Clone implements the Expression Clone interface.
@ -38,8 +40,9 @@ func (f *FunctionCast) Clone() (expression.Expression, error) {
return nil, err
}
nf := &FunctionCast{
Expr: expr,
Tp: f.Tp,
Expr: expr,
Tp: f.Tp,
IsConvert: f.IsConvert,
}
return nf, nil
}
@ -61,6 +64,9 @@ func (f *FunctionCast) String() string {
} else {
tpStr = f.Tp.String()
}
if f.IsConvert {
return fmt.Sprintf("CONVERT(%s, %s)", f.Expr.String(), tpStr)
}
return fmt.Sprintf("CAST(%s AS %s)", f.Expr.String(), tpStr)
}

View File

@ -74,4 +74,16 @@ func (s *testCastSuite) TestCast(c *C) {
_, err = expr.Eval(nil, nil)
c.Assert(err, NotNil)
// For String()
f = types.NewFieldType(mysql.TypeLonglong)
expr = &FunctionCast{
Expr: Value{1},
Tp: f,
}
str := expr.String()
c.Assert(str, Equals, "CAST(1 AS SIGNED)")
expr.IsConvert = true
str = expr.String()
c.Assert(str, Equals, "CONVERT(1, SIGNED)")
}

View File

@ -1808,6 +1808,15 @@ Function:
Charset: $5.(string),
}
}
| "CONVERT" '(' Expression ',' CastType ')'
{
// See: https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_convert
$$ = &expressions.FunctionCast{
Expr: $3.(expression.Expression),
Tp: $5.(*types.FieldType),
IsConvert: true,
}
}
| "SUBSTRING" '(' Expression ',' Expression ')'
{
$$ = &expressions.FunctionSubstring{

View File

@ -18,6 +18,8 @@ import (
"testing"
. "github.com/pingcap/check"
"github.com/pingcap/tidb/expression/expressions"
"github.com/pingcap/tidb/stmt/stmts"
)
func TestT(t *testing.T) {
@ -257,6 +259,8 @@ func (s *testParserSuite) TestParser0(c *C) {
{"SELECT SUBSTRING('Quadratically' FROM 5);", true},
{"SELECT SUBSTRING('Quadratically' FROM 5 FOR 3);", true},
{"SELECT CONVERT('111', SIGNED);", true},
// For delete statement
{"DELETE t1, t2 FROM t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.id=t2.id AND t2.id=t3.id;", true},
{"DELETE FROM t1, t2 USING t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.id=t2.id AND t2.id=t3.id;", true},
@ -284,8 +288,7 @@ func (s *testParserSuite) TestParser0(c *C) {
src := "SELECT id+?, id+? from t;"
l := NewLexer(src)
l.SetPrepare()
ok := yyParse(l) == 0
c.Assert(ok, Equals, true)
c.Assert(yyParse(l), Equals, 0)
c.Assert(len(l.ParamList), Equals, 2)
c.Assert(len(l.Stmts()), Equals, 1)
@ -293,7 +296,17 @@ func (s *testParserSuite) TestParser0(c *C) {
src = "CREATE TABLE foo (a SMALLINT UNSIGNED, b INT UNSIGNED,); -- foo\nSelect --1 from foo;"
l = NewLexer(src)
l.SetPrepare()
ok = yyParse(l) == 0
c.Assert(ok, Equals, true)
c.Assert(yyParse(l), Equals, 0)
c.Assert(len(l.Stmts()), Equals, 2)
// Testcase for CONVERT(expr,type)
src = "SELECT CONVERT('111', SIGNED);"
l = NewLexer(src)
c.Assert(yyParse(l), Equals, 0)
st := l.Stmts()[0]
ss, ok := st.(*stmts.SelectStmt)
c.Assert(ok, IsTrue)
cv, ok := ss.Fields[0].Expr.(*expressions.FunctionCast)
c.Assert(ok, IsTrue)
c.Assert(cv.IsConvert, IsTrue)
}