func convertValue(val interface{}, castTo string) (interface{}, error) {
	switch strings.ToLower(castTo) {
	case ConvertToBinary:
		b, err := sql.LongBlob.Convert(val)
		if err != nil {
			return nil, nil
		}
		return b, nil
	case ConvertToChar, ConvertToNChar:
		s, err := sql.LongText.Convert(val)
		if err != nil {
			return nil, nil
		}
		return s, nil
	case ConvertToDate:
		_, isTime := val.(time.Time)
		_, isString := val.(string)
		if !(isTime || isString) {
			return nil, nil
		}
		d, err := sql.Date.Convert(val)
		if err != nil {
			return nil, nil
		}
		return d, nil
	case ConvertToDatetime:
		_, isTime := val.(time.Time)
		_, isString := val.(string)
		if !(isTime || isString) {
			return nil, nil
		}
		d, err := sql.Datetime.Convert(val)
		if err != nil {
			return nil, nil
		}
		return d, nil
	case ConvertToDecimal:
		typ := sql.MustCreateDecimalType(65, 10)
		d, err := typ.Convert(val)
		if err != nil {
			return typ.Zero(), nil
		}
		return d, nil
	case ConvertToDouble, ConvertToReal:
		d, err := sql.Float64.Convert(val)
		if err != nil {
			return sql.Float64.Zero(), nil
		}
		return d, nil
	case ConvertToJSON:
		js, err := sql.JSON.Convert(val)
		if err != nil {
			return nil, err
		}
		return js, nil
	case ConvertToSigned:
		num, err := sql.Int64.Convert(val)
		if err != nil {
			return sql.Int64.Zero(), nil
		}
		return num, nil
	case ConvertToTime:
		t, err := sql.Time.Convert(val)
		if err != nil {
			return nil, nil
		}
		return t, nil
	case ConvertToUnsigned:
		num, err := sql.Uint64.Convert(val)
		if err != nil {
			num, err = sql.Int64.Convert(val)
			if err != nil {
				return sql.Uint64.Zero(), nil
			}
			return uint64(num.(int64)), nil
		}
		return num, nil
	default:
		return nil, nil
	}
}
convertValue only returns an error if converting to JSON, and returns the zero value for float types.
Nil is returned in all other cases.
package expression
import (
	"fmt"
	"strings"
	"time"
	"gopkg.in/src-d/go-errors.v1"
	"github.com/dolthub/go-mysql-server/sql"
)
var ErrConvertExpression = errors.NewKind("expression '%v': couldn't convert to %v")
const (
	ConvertToBinary = "binary"
	ConvertToChar = "char"
	ConvertToNChar = "nchar"
	ConvertToDate = "date"
	ConvertToDatetime = "datetime"
	ConvertToDecimal = "decimal"
	ConvertToDouble = "double"
	ConvertToJSON = "json"
	ConvertToReal = "real"
	ConvertToSigned = "signed"
	ConvertToTime = "time"
	ConvertToUnsigned = "unsigned"
)
type Convert struct {
	UnaryExpression
	castToType string
}
func NewConvert(expr sql.Expression, castToType string) *Convert {
	return &Convert{
		UnaryExpression: UnaryExpression{Child: expr},
		castToType:      strings.ToLower(castToType),
	}
}
func (c *Convert) IsNullable() bool {
	switch c.castToType {
	case ConvertToDate, ConvertToDatetime:
		return true
	default:
		return c.Child.IsNullable()
	}
}
func (c *Convert) Type() sql.Type {
	switch c.castToType {
	case ConvertToBinary:
		return sql.LongBlob
	case ConvertToChar, ConvertToNChar:
		return sql.LongText
	case ConvertToDate:
		return sql.Date
	case ConvertToDatetime:
		return sql.Datetime
	case ConvertToDecimal:
		return sql.MustCreateDecimalType(65, 10)
	case ConvertToDouble, ConvertToReal:
		return sql.Float64
	case ConvertToJSON:
		return sql.JSON
	case ConvertToSigned:
		return sql.Int64
	case ConvertToTime:
		return sql.Time
	case ConvertToUnsigned:
		return sql.Uint64
	default:
		return sql.Null
	}
}
func (c *Convert) String() string {
	return fmt.Sprintf("convert(%v, %v)", c.Child, c.castToType)
}
func (c *Convert) WithChildren(children ...sql.Expression) (sql.Expression, error) {
	if len(children) != 1 {
		return nil, sql.ErrInvalidChildrenNumber.New(c, len(children), 1)
	}
	return NewConvert(children[0], c.castToType), nil
}
func (c *Convert) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
	val, err := c.Child.Eval(ctx, row)
	if err != nil {
		return nil, err
	}
	if val == nil {
		return nil, nil
	}
	casted, err := convertValue(val, c.castToType)
	if err != nil {
		return nil, ErrConvertExpression.Wrap(err, c.String(), c.castToType)
	}
	return casted, nil
}