func (t timestampT) SQL(v interface{}) (sqltypes.Value, error) {
	if v == nil {
		return sqltypes.NULL, nil
	}
	v, err := t.Convert(v)
	if err != nil {
		return sqltypes.Value{}, err
	}
	return sqltypes.MakeTrusted(
		sqltypes.Timestamp,
		[]byte(v.(time.Time).Format(TimestampLayout)),
	), nil
}
SQL implements Type interface.
package sql
import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"math"
	"reflect"
	"strconv"
	"strings"
	"time"
	"github.com/spf13/cast"
	"gopkg.in/src-d/go-errors.v1"
	"vitess.io/vitess/go/sqltypes"
	"vitess.io/vitess/go/vt/proto/query"
)
var (
	ErrTypeNotSupported = errors.NewKind("Type not supported: %s")
	ErrUnexpectedType = errors.NewKind("value at %d has unexpected type: %s")
	ErrConvertingToTime = errors.NewKind("value %q can't be converted to time.Time")
	ErrCharTruncation = errors.NewKind("string value of %q is longer than destination capacity %d")
	ErrVarCharTruncation = errors.NewKind("string value of %q is longer than destination capacity %d")
	ErrValueNotNil = errors.NewKind("value not nil: %#v")
	ErrNotTuple = errors.NewKind("value of type %T is not a tuple")
	ErrInvalidColumnNumber = errors.NewKind("tuple should contain %d column(s), but has %d")
	ErrNotArray = errors.NewKind("value of type %T is not an array")
	ErrConvertToSQL = errors.NewKind("incompatible conversion to SQL type: %s")
)
type Schema []*Column
func (s Schema) CheckRow(row Row) error {
	expected := len(s)
	got := len(row)
	if expected != got {
		return ErrUnexpectedRowLength.New(expected, got)
	}
	for idx, f := range s {
		v := row[idx]
		if f.Check(v) {
			continue
		}
		typ := reflect.TypeOf(v).String()
		return ErrUnexpectedType.New(idx, typ)
	}
	return nil
}
func (s Schema) Contains(column string, source string) bool {
	return s.IndexOf(column, source) >= 0
}
func (s Schema) IndexOf(column, source string) int {
	column = strings.ToLower(column)
	source = strings.ToLower(source)
	for i, col := range s {
		if strings.ToLower(col.Name) == column && strings.ToLower(col.Source) == source {
			return i
		}
	}
	return -1
}
func (s Schema) Equals(s2 Schema) bool {
	if len(s) != len(s2) {
		return false
	}
	for i := range s {
		if !s[i].Equals(s2[i]) {
			return false
		}
	}
	return true
}
type Column struct {
	Name string
	Type Type
	Default interface{}
	Nullable bool
	Source string
	PrimaryKey bool
}
func (c *Column) Check(v interface{}) bool {
	if v == nil {
		return c.Nullable
	}
	_, err := c.Type.Convert(v)
	return err == nil
}
func (c *Column) Equals(c2 *Column) bool {
	return c.Name == c2.Name &&
		c.Source == c2.Source &&
		c.Nullable == c2.Nullable &&
		reflect.DeepEqual(c.Default, c2.Default) &&
		reflect.DeepEqual(c.Type, c2.Type)
}
type Type interface {
	Type() query.Type
	Convert(interface{}) (interface{}, error)
	Compare(interface{}, interface{}) (int, error)
	SQL(interface{}) (sqltypes.Value, error)
	fmt.Stringer
}
var maxTime = time.Date(9999, time.December, 31, 23, 59, 59, 0, time.UTC)
func ValidateTime(t time.Time) interface{} {
	if t.After(maxTime) {
		return nil
	}
	return t
}
var (
	Null nullT
	Int8 = numberT{t: sqltypes.Int8}
	Uint8 = numberT{t: sqltypes.Uint8}
	Int16 = numberT{t: sqltypes.Int16}
	Uint16 = numberT{t: sqltypes.Uint16}
	Int24 = numberT{t: sqltypes.Int24}
	Uint24 = numberT{t: sqltypes.Uint24}
	Int32 = numberT{t: sqltypes.Int32}
	Uint32 = numberT{t: sqltypes.Uint32}
	Int64 = numberT{t: sqltypes.Int64}
	Uint64 = numberT{t: sqltypes.Uint64}
	Float32 = numberT{t: sqltypes.Float32}
	Float64 = numberT{t: sqltypes.Float64}
	Timestamp timestampT
	Date dateT
	Datetime datetimeT
	Text textT
	Boolean booleanT
	JSON jsonT
	Blob blobT
)
func Tuple(types ...Type) Type {
	return tupleT(types)
}
func Array(underlying Type) Type {
	return arrayT{underlying}
}
func Char(length int) Type {
	return charT{length: length}
}
func VarChar(length int) Type {
	return varCharT{length: length}
}
func MysqlTypeToType(sql query.Type) (Type, error) {
	switch sql {
	case sqltypes.Null:
		return Null, nil
	case sqltypes.Int8:
		return Int8, nil
	case sqltypes.Uint8:
		return Uint8, nil
	case sqltypes.Int16:
		return Int16, nil
	case sqltypes.Uint16:
		return Uint16, nil
	case sqltypes.Int24:
		return Int24, nil
	case sqltypes.Uint24:
		return Uint24, nil
	case sqltypes.Int32:
		return Int32, nil
	case sqltypes.Uint32:
		return Uint32, nil
	case sqltypes.Int64:
		return Int64, nil
	case sqltypes.Uint64:
		return Uint64, nil
	case sqltypes.Float32:
		return Float32, nil
	case sqltypes.Float64:
		return Float64, nil
	case sqltypes.Timestamp:
		return Timestamp, nil
	case sqltypes.Date:
		return Date, nil
	case sqltypes.Text:
		return Text, nil
	case sqltypes.Char:
		return Text, nil
	case sqltypes.VarChar:
		return Text, nil
	case sqltypes.Datetime:
		return Datetime, nil
	case sqltypes.Bit:
		return Boolean, nil
	case sqltypes.TypeJSON:
		return JSON, nil
	case sqltypes.Blob:
		return Blob, nil
	default:
		return nil, ErrTypeNotSupported.New(sql)
	}
}
type nullT struct{}
func (t nullT) String() string { return "NULL" }
func (t nullT) Type() query.Type {
	return sqltypes.Null
}
func (t nullT) SQL(interface{}) (sqltypes.Value, error) {
	return sqltypes.NULL, nil
}
func (t nullT) Convert(v interface{}) (interface{}, error) {
	if v != nil {
		return nil, ErrValueNotNil.New(v)
	}
	return nil, nil
}
func (t nullT) Compare(a interface{}, b interface{}) (int, error) {
	return 0, nil
}
func IsNull(ex Expression) bool {
	return ex == nil || ex.Type() == Null
}
type numberT struct {
	t query.Type
}
func (t numberT) Type() query.Type {
	return t.t
}
func (t numberT) SQL(v interface{}) (sqltypes.Value, error) {
	if v == nil {
		return sqltypes.NULL, nil
	}
	switch t.t {
	case sqltypes.Int8:
		return sqltypes.MakeTrusted(t.t, strconv.AppendInt(nil, cast.ToInt64(v), 10)), nil
	case sqltypes.Int16:
		return sqltypes.MakeTrusted(t.t, strconv.AppendInt(nil, cast.ToInt64(v), 10)), nil
	case sqltypes.Int32:
		return sqltypes.MakeTrusted(t.t, strconv.AppendInt(nil, cast.ToInt64(v), 10)), nil
	case sqltypes.Int64:
		return sqltypes.MakeTrusted(t.t, strconv.AppendInt(nil, cast.ToInt64(v), 10)), nil
	case sqltypes.Uint8:
		return sqltypes.MakeTrusted(t.t, strconv.AppendUint(nil, cast.ToUint64(v), 10)), nil
	case sqltypes.Uint16:
		return sqltypes.MakeTrusted(t.t, strconv.AppendUint(nil, cast.ToUint64(v), 10)), nil
	case sqltypes.Uint32:
		return sqltypes.MakeTrusted(t.t, strconv.AppendUint(nil, cast.ToUint64(v), 10)), nil
	case sqltypes.Uint64:
		return sqltypes.MakeTrusted(t.t, strconv.AppendUint(nil, cast.ToUint64(v), 10)), nil
	case sqltypes.Float32:
		return sqltypes.MakeTrusted(t.t, strconv.AppendFloat(nil, cast.ToFloat64(v), 'f', -1, 64)), nil
	case sqltypes.Float64:
		return sqltypes.MakeTrusted(t.t, strconv.AppendFloat(nil, cast.ToFloat64(v), 'f', -1, 64)), nil
	default:
		return sqltypes.MakeTrusted(t.t, []byte{}), nil
	}
}
func (t numberT) Convert(v interface{}) (interface{}, error) {
	if ti, ok := v.(time.Time); ok {
		v = ti.Unix()
	}
	switch t.t {
	case sqltypes.Int8:
		return cast.ToInt8E(v)
	case sqltypes.Int16:
		return cast.ToInt16E(v)
	case sqltypes.Int32:
		return cast.ToInt32E(v)
	case sqltypes.Int64:
		return cast.ToInt64E(v)
	case sqltypes.Uint8:
		return cast.ToUint8E(v)
	case sqltypes.Uint16:
		return cast.ToUint16E(v)
	case sqltypes.Uint32:
		return cast.ToUint32E(v)
	case sqltypes.Uint64:
		return cast.ToUint64E(v)
	case sqltypes.Float32:
		return cast.ToFloat32E(v)
	case sqltypes.Float64:
		return cast.ToFloat64E(v)
	default:
		return nil, ErrInvalidType.New(t.t)
	}
}
func (t numberT) Compare(a interface{}, b interface{}) (int, error) {
	if IsUnsigned(t) {
		return compareUnsignedInts(a, b)
	}
	switch t.t {
	case sqltypes.Float64, sqltypes.Float32:
		return compareFloats(a, b)
	default:
		return compareSignedInts(a, b)
	}
}
func (t numberT) String() string { return t.t.String() }
func compareFloats(a interface{}, b interface{}) (int, error) {
	if hasNulls, res := compareNulls(a, b); hasNulls {
		return res, nil
	}
	ca, err := cast.ToFloat64E(a)
	if err != nil {
		return 0, err
	}
	cb, err := cast.ToFloat64E(b)
	if err != nil {
		return 0, err
	}
	if ca == cb {
		return 0, nil
	}
	if ca < cb {
		return -1, nil
	}
	return +1, nil
}
func compareSignedInts(a interface{}, b interface{}) (int, error) {
	if hasNulls, res := compareNulls(a, b); hasNulls {
		return res, nil
	}
	ca, err := cast.ToInt64E(a)
	if err != nil {
		return 0, err
	}
	cb, err := cast.ToInt64E(b)
	if err != nil {
		return 0, err
	}
	if ca == cb {
		return 0, nil
	}
	if ca < cb {
		return -1, nil
	}
	return +1, nil
}
func compareUnsignedInts(a interface{}, b interface{}) (int, error) {
	if hasNulls, res := compareNulls(a, b); hasNulls {
		return res, nil
	}
	ca, err := cast.ToUint64E(a)
	if err != nil {
		return 0, err
	}
	cb, err := cast.ToUint64E(b)
	if err != nil {
		return 0, err
	}
	if ca == cb {
		return 0, nil
	}
	if ca < cb {
		return -1, nil
	}
	return +1, nil
}
type timestampT struct{}
func (t timestampT) String() string { return "TIMESTAMP" }
func (t timestampT) Type() query.Type {
	return sqltypes.Timestamp
}
const TimestampLayout = "2006-01-02 15:04:05"
var TimestampLayouts = []string{
	"2006-01-02",
	time.RFC3339,
	"20060102150405",
	"20060102",
}