func (t decimalType) String() string {
	return fmt.Sprintf("DECIMAL(%v,%v)", t.precision, t.scale)
}
String implements Type interface.
package sql
import (
	"fmt"
	"math/big"
	"github.com/dolthub/vitess/go/sqltypes"
	"github.com/dolthub/vitess/go/vt/proto/query"
	"github.com/shopspring/decimal"
	"gopkg.in/src-d/go-errors.v1"
)
const (
	DecimalTypeMaxPrecision = 65
	DecimalTypeMaxScale = 30
)
var (
	ErrConvertingToDecimal   = errors.NewKind("value %v is not a valid Decimal")
	ErrConvertToDecimalLimit = errors.NewKind("value of Decimal is too large for type")
	ErrMarshalNullDecimal    = errors.NewKind("Decimal cannot marshal a null value")
)
type DecimalType interface {
	Type
	ConvertToDecimal(v interface{}) (decimal.NullDecimal, error)
	ExclusiveUpperBound() decimal.Decimal
	MaximumScale() uint8
	Precision() uint8
	Scale() uint8
}
type decimalType struct {
	exclusiveUpperBound decimal.Decimal
	precision           uint8
	scale               uint8
}
func CreateDecimalType(precision uint8, scale uint8) (DecimalType, error) {
	if precision > DecimalTypeMaxPrecision {
		return nil, fmt.Errorf("%v is beyond the max precision", precision)
	}
	if scale > precision {
		return nil, fmt.Errorf("%v cannot be larger than the precision %v", scale, precision)
	}
	if scale > DecimalTypeMaxScale {
		return nil, fmt.Errorf("%v is beyond the max scale", scale)
	}
	if precision == 0 {
		precision = 10
	}
	return decimalType{
		exclusiveUpperBound: decimal.New(1, int32(precision-scale)),
		precision:           precision,
		scale:               scale,
	}, nil
}
func MustCreateDecimalType(precision uint8, scale uint8) DecimalType {
	dt, err := CreateDecimalType(precision, scale)
	if err != nil {
		panic(err)
	}
	return dt
}
func (t decimalType) Type() query.Type {
	return sqltypes.Decimal
}
func (t decimalType) Compare(a interface{}, b interface{}) (int, error) {
	if hasNulls, res := compareNulls(a, b); hasNulls {
		return res, nil
	}
	af, err := t.ConvertToDecimal(a)
	if err != nil {
		return 0, err
	}
	bf, err := t.ConvertToDecimal(b)
	if err != nil {
		return 0, err
	}
	return af.Decimal.Cmp(bf.Decimal), nil
}
func (t decimalType) Convert(v interface{}) (interface{}, error) {
	dec, err := t.ConvertToDecimal(v)
	if err != nil {
		return nil, err
	}
	if !dec.Valid {
		return nil, nil
	}
	return dec.Decimal.StringFixed(int32(t.scale)), nil
}
func (t decimalType) ConvertToDecimal(v interface{}) (decimal.NullDecimal, error) {
	if v == nil {
		return decimal.NullDecimal{}, nil
	}
	var res decimal.Decimal
	switch value := v.(type) {
	case int:
		return t.ConvertToDecimal(int64(value))
	case uint:
		return t.ConvertToDecimal(uint64(value))
	case int8:
		return t.ConvertToDecimal(int64(value))
	case uint8:
		return t.ConvertToDecimal(uint64(value))
	case int16:
		return t.ConvertToDecimal(int64(value))
	case uint16:
		return t.ConvertToDecimal(uint64(value))
	case int32:
		res = decimal.NewFromInt32(value)
	case uint32:
		return t.ConvertToDecimal(uint64(value))
	case int64:
		res = decimal.NewFromInt(value)
	case uint64:
		res = decimal.NewFromBigInt(new(big.Int).SetUint64(value), 0)
	case float32:
		res = decimal.NewFromFloat32(value)
	case float64:
		res = decimal.NewFromFloat(value)
	case string:
		var err error
		res, err = decimal.NewFromString(value)
		if err != nil {
			bf, _, err := new(big.Float).SetPrec(217).Parse(value, 0)
			if err != nil {
				return decimal.NullDecimal{}, err
			}
			res, err = decimal.NewFromString(bf.Text('f', -1))
			if err != nil {
				return decimal.NullDecimal{}, err
			}
		}
	case *big.Float:
		return t.ConvertToDecimal(value.Text('f', -1))
	case *big.Int:
		return t.ConvertToDecimal(value.Text(10))
	case *big.Rat:
		return t.ConvertToDecimal(new(big.Float).SetRat(value))
	case decimal.Decimal:
		res = value
	case decimal.NullDecimal:
		if !value.Valid {
			return decimal.NullDecimal{}, nil
		}
		res = value.Decimal
	default:
		return decimal.NullDecimal{}, ErrConvertingToDecimal.New(v)
	}
	res = res.Round(int32(t.scale))
	if !res.Abs().LessThan(t.exclusiveUpperBound) {
		return decimal.NullDecimal{}, ErrConvertToDecimalLimit.New()
	}
	return decimal.NullDecimal{Decimal: res, Valid: true}, nil
}
func (t decimalType) MustConvert(v interface{}) interface{} {
	value, err := t.Convert(v)
	if err != nil {
		panic(err)
	}
	return value
}
func (t decimalType) Promote() Type {
	return MustCreateDecimalType(DecimalTypeMaxPrecision, t.scale)
}
func (t decimalType) SQL(v interface{}) (sqltypes.Value, error) {
	if v == nil {
		return sqltypes.NULL, nil
	}
	value, err := t.Convert(v)
	if err != nil {
		return sqltypes.Value{}, err
	}
	return sqltypes.MakeTrusted(sqltypes.Decimal, []byte(value.(string))), nil
}