// See https://dev.mysql.com/doc/refman/5.7/en/string-comparison-functions.html func builtinStrcmp(args []types.Datum, _ context.Context) (d types.Datum, err error) { if args[0].IsNull() || args[1].IsNull() { return d, nil } left, err := args[0].ToString() if err != nil { return d, errors.Trace(err) } right, err := args[1].ToString() if err != nil { return d, errors.Trace(err) } res := types.CompareString(left, right) d.SetInt64(int64(res)) return d, nil }
// See https://dev.mysql.com/doc/refman/5.7/en/type-conversion.html func evalCompare(a interface{}, b interface{}) (int, error) { // TODO: support compare time type with other types switch x := a.(type) { case float64: switch y := b.(type) { case float64: return types.CompareFloat64(x, y), nil case string: return compareFloatString(x, y) } case int64: switch y := b.(type) { case int64: return types.CompareInt64(x, y), nil case uint64: return types.CompareInteger(x, y), nil case string: return compareFloatString(float64(x), y) } case uint64: switch y := b.(type) { case uint64: return types.CompareUint64(x, y), nil case int64: return -types.CompareInteger(y, x), nil case string: return compareFloatString(float64(x), y) } case mysql.Decimal: switch y := b.(type) { case mysql.Decimal: return x.Cmp(y), nil case string: f, err := mysql.ConvertToDecimal(y) if err != nil { return 0, err } return x.Cmp(f), nil } case string: switch y := b.(type) { case string: return types.CompareString(x, y), nil case int64: return compareStringFloat(x, float64(y)) case uint64: return compareStringFloat(x, float64(y)) case float64: return compareStringFloat(x, y) case mysql.Decimal: f, err := mysql.ConvertToDecimal(x) if err != nil { return 0, err } return f.Cmp(y), nil case mysql.Time: n, err := y.CompareString(x) return -n, err case mysql.Duration: n, err := y.CompareString(x) return -n, err } case mysql.Time: switch y := b.(type) { case mysql.Time: return x.Compare(y), nil case string: return x.CompareString(y) } case mysql.Duration: switch y := b.(type) { case mysql.Duration: return x.Compare(y), nil case string: return x.CompareString(y) } } return 0, errors.Errorf("invalid compare type %T cmp %T", a, b) }