继续分分析PR。
Pass go vet #16
这个修复了没有指定结构体中变量名的一些测试数据。
mysqldef: fix issue #19 #20
修复了issues#19中提到的make test错误。
原因就是Marshal()中没有使用本地时区导致的。
然后对Timestamp的测试案例修改了两个边界值。
Allow uses to shutdown the pprof #17
谢大对pprof增加了debug开关。
tidb: Add some comments #24
增加了pprof的注释。
mysqldef: save FSP and fix zone offset for codec #29
这个PR对mysqldef.Time的Marshal和UnmarshalInLocation的二进制编码解码增加了FSP信息,然后修复了时区偏移问题,并增加了测试数据。
Add convert type function #23
添加了一个mysql的函数 CONVERT(expr,type),
mysql文档说明了:Discussion of CONVERT(expr, type) syntax here also applies to CAST(expr AS type), which is equivalent。这个函数的具体实现和 CAST(expr AS type)等价(这个CAST已经实现过了),这里加了一个标志来区别是否为Convert,主要用在String()方法。然后对parser.y添加了这个语法。
Pass go tool vet –shadow #31
优化修改了一些变量的重复使用和格式。
Godeps: Update version of boltdb #30
更新boltdb 的版本。
Pass gofmt #32
格式化代码。
cleanup compare #35
把之前零散的不同类型之间的比较统一整合在了util/types/compare.go,并且以前用panic抛出的异常改为返回error。
tidb: update gitignore #38
修改了gitignore。
Update godep packages. #34
更新/改了依赖包。
expressions: operator supports []byte type #39
首先跟着代码跑会发现,select 1 + cast(“123” as binary);这样的语句还不支持,那么原因在这里:
// Operator: DIV / - % MOD + * // See https://dev.mysql.com/doc/refman/5.7/en/arithmetic-functions.html#operator_divide func (o *BinaryOperation) evalArithmeticOp(ctx context.Context, args map[interface{}]interface{}) (interface{}, error) { a, b, err := o.get2(ctx, args) if err != nil { return nil, err } if a == nil || b == nil { // TODO: for <=>, if a and b are both nil, return true return nil, nil } if a, b, err = o.coerceArithmetic2(a, b); err != nil { return nil, o.traceErr(err) } // TODO: support logic division DIV switch o.Op { case opcode.Plus: return o.evalPlus(a, b) case opcode.Minus: return o.evalMinus(a, b) case opcode.Mul: return o.evalMul(a, b) case opcode.Div: return o.evalDiv(a, b) case opcode.Mod: return o.evalMod(a, b) case opcode.IntDiv: return o.evalIntDiv(a, b) default: return nil, o.errorf("invalid op %v in arithmetic operation", o.Op) } }
在a, b, err := o.get2(ctx, args)得到表达式左右两边的值一个是int64一个是[]byte,这个没问题,然后这个o.coerceArithmetic2(a, b)的作用是把需要做算术运算的两边转换成尽量统一的类型,比如一个int64一个float64,则会把两边都转换成float64,然后在coerceArithmetic2()先调用了:
func (o *BinaryOperation) coerceArithmetic(a interface{}) (interface{}, error) { switch x := a.(type) { case string: // MySQL will convert string to float for arithmetic operation f, err := types.StrToFloat(x) if err != nil { return nil, err } return f, err case mysql.Time: // TODO: if time has no precision, return int64 return x.ToNumber(), nil case mysql.Duration: // TODO: if duration has no precision, return int64 return x.ToNumber(), nil default: return x, nil } }
而这里还没定义[]byte的转换,所以这里直接返回的还是[]byte类型,而后面没有定义[]byte类型的加法等:
func (o *BinaryOperation) evalPlus(a interface{}, b interface{}) (interface{}, error) { // TODO: check overflow switch x := a.(type) { case int64: switch y := b.(type) { case int64: return x + y, nil case uint64: // For MySQL, if any is unsigned, return unsigned // TODO: check overflow return uint64(x) + y, nil } case uint64: switch y := b.(type) { case int64: // For MySQL, if any is unsigned, return unsigned // TODO: check overflow return x + uint64(y), nil case uint64: return x + y, nil } case float64: switch y := b.(type) { case float64: return x + y, nil } case mysql.Decimal: switch y := b.(type) { case mysql.Decimal: return x.Add(y), nil } } return types.InvOp2(a, b, opcode.Plus) }
所以只需要这样改coerceArithmetic就解决了。
而这次PR还改了unary.go。这个是为了解决类似:
select + cast("123" as binary);
的,只要跟着跑一下,同理的。
mysqldef: remove fsp codec, set out manually. #40
移除了PR#29中在编码解码中增加的offset,在测试数据改成手动设置offset。