Home | History | Annotate | Download | only in driver
      1 // Copyright 2011 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package driver
      6 
      7 import (
      8 	"fmt"
      9 	"reflect"
     10 	"strconv"
     11 	"time"
     12 )
     13 
     14 // ValueConverter is the interface providing the ConvertValue method.
     15 //
     16 // Various implementations of ValueConverter are provided by the
     17 // driver package to provide consistent implementations of conversions
     18 // between drivers. The ValueConverters have several uses:
     19 //
     20 //  * converting from the Value types as provided by the sql package
     21 //    into a database table's specific column type and making sure it
     22 //    fits, such as making sure a particular int64 fits in a
     23 //    table's uint16 column.
     24 //
     25 //  * converting a value as given from the database into one of the
     26 //    driver Value types.
     27 //
     28 //  * by the sql package, for converting from a driver's Value type
     29 //    to a user's type in a scan.
     30 type ValueConverter interface {
     31 	// ConvertValue converts a value to a driver Value.
     32 	ConvertValue(v interface{}) (Value, error)
     33 }
     34 
     35 // Valuer is the interface providing the Value method.
     36 //
     37 // Types implementing Valuer interface are able to convert
     38 // themselves to a driver Value.
     39 type Valuer interface {
     40 	// Value returns a driver Value.
     41 	Value() (Value, error)
     42 }
     43 
     44 // Bool is a ValueConverter that converts input values to bools.
     45 //
     46 // The conversion rules are:
     47 //  - booleans are returned unchanged
     48 //  - for integer types,
     49 //       1 is true
     50 //       0 is false,
     51 //       other integers are an error
     52 //  - for strings and []byte, same rules as strconv.ParseBool
     53 //  - all other types are an error
     54 var Bool boolType
     55 
     56 type boolType struct{}
     57 
     58 var _ ValueConverter = boolType{}
     59 
     60 func (boolType) String() string { return "Bool" }
     61 
     62 func (boolType) ConvertValue(src interface{}) (Value, error) {
     63 	switch s := src.(type) {
     64 	case bool:
     65 		return s, nil
     66 	case string:
     67 		b, err := strconv.ParseBool(s)
     68 		if err != nil {
     69 			return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
     70 		}
     71 		return b, nil
     72 	case []byte:
     73 		b, err := strconv.ParseBool(string(s))
     74 		if err != nil {
     75 			return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
     76 		}
     77 		return b, nil
     78 	}
     79 
     80 	sv := reflect.ValueOf(src)
     81 	switch sv.Kind() {
     82 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
     83 		iv := sv.Int()
     84 		if iv == 1 || iv == 0 {
     85 			return iv == 1, nil
     86 		}
     87 		return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", iv)
     88 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
     89 		uv := sv.Uint()
     90 		if uv == 1 || uv == 0 {
     91 			return uv == 1, nil
     92 		}
     93 		return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", uv)
     94 	}
     95 
     96 	return nil, fmt.Errorf("sql/driver: couldn't convert %v (%T) into type bool", src, src)
     97 }
     98 
     99 // Int32 is a ValueConverter that converts input values to int64,
    100 // respecting the limits of an int32 value.
    101 var Int32 int32Type
    102 
    103 type int32Type struct{}
    104 
    105 var _ ValueConverter = int32Type{}
    106 
    107 func (int32Type) ConvertValue(v interface{}) (Value, error) {
    108 	rv := reflect.ValueOf(v)
    109 	switch rv.Kind() {
    110 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    111 		i64 := rv.Int()
    112 		if i64 > (1<<31)-1 || i64 < -(1<<31) {
    113 			return nil, fmt.Errorf("sql/driver: value %d overflows int32", v)
    114 		}
    115 		return i64, nil
    116 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
    117 		u64 := rv.Uint()
    118 		if u64 > (1<<31)-1 {
    119 			return nil, fmt.Errorf("sql/driver: value %d overflows int32", v)
    120 		}
    121 		return int64(u64), nil
    122 	case reflect.String:
    123 		i, err := strconv.Atoi(rv.String())
    124 		if err != nil {
    125 			return nil, fmt.Errorf("sql/driver: value %q can't be converted to int32", v)
    126 		}
    127 		return int64(i), nil
    128 	}
    129 	return nil, fmt.Errorf("sql/driver: unsupported value %v (type %T) converting to int32", v, v)
    130 }
    131 
    132 // String is a ValueConverter that converts its input to a string.
    133 // If the value is already a string or []byte, it's unchanged.
    134 // If the value is of another type, conversion to string is done
    135 // with fmt.Sprintf("%v", v).
    136 var String stringType
    137 
    138 type stringType struct{}
    139 
    140 func (stringType) ConvertValue(v interface{}) (Value, error) {
    141 	switch v.(type) {
    142 	case string, []byte:
    143 		return v, nil
    144 	}
    145 	return fmt.Sprintf("%v", v), nil
    146 }
    147 
    148 // Null is a type that implements ValueConverter by allowing nil
    149 // values but otherwise delegating to another ValueConverter.
    150 type Null struct {
    151 	Converter ValueConverter
    152 }
    153 
    154 func (n Null) ConvertValue(v interface{}) (Value, error) {
    155 	if v == nil {
    156 		return nil, nil
    157 	}
    158 	return n.Converter.ConvertValue(v)
    159 }
    160 
    161 // NotNull is a type that implements ValueConverter by disallowing nil
    162 // values but otherwise delegating to another ValueConverter.
    163 type NotNull struct {
    164 	Converter ValueConverter
    165 }
    166 
    167 func (n NotNull) ConvertValue(v interface{}) (Value, error) {
    168 	if v == nil {
    169 		return nil, fmt.Errorf("nil value not allowed")
    170 	}
    171 	return n.Converter.ConvertValue(v)
    172 }
    173 
    174 // IsValue reports whether v is a valid Value parameter type.
    175 func IsValue(v interface{}) bool {
    176 	if v == nil {
    177 		return true
    178 	}
    179 	switch v.(type) {
    180 	case []byte, bool, float64, int64, string, time.Time:
    181 		return true
    182 	}
    183 	return false
    184 }
    185 
    186 // IsScanValue is equivalent to IsValue.
    187 // It exists for compatibility.
    188 func IsScanValue(v interface{}) bool {
    189 	return IsValue(v)
    190 }
    191 
    192 // DefaultParameterConverter is the default implementation of
    193 // ValueConverter that's used when a Stmt doesn't implement
    194 // ColumnConverter.
    195 //
    196 // DefaultParameterConverter returns its argument directly if
    197 // IsValue(arg). Otherwise, if the argument implements Valuer, its
    198 // Value method is used to return a Value. As a fallback, the provided
    199 // argument's underlying type is used to convert it to a Value:
    200 // underlying integer types are converted to int64, floats to float64,
    201 // bool, string, and []byte to themselves. If the argument is a nil
    202 // pointer, ConvertValue returns a nil Value. If the argument is a
    203 // non-nil pointer, it is dereferenced and ConvertValue is called
    204 // recursively. Other types are an error.
    205 var DefaultParameterConverter defaultConverter
    206 
    207 type defaultConverter struct{}
    208 
    209 var _ ValueConverter = defaultConverter{}
    210 
    211 var valuerReflectType = reflect.TypeOf((*Valuer)(nil)).Elem()
    212 
    213 // callValuerValue returns vr.Value(), with one exception:
    214 // If vr.Value is an auto-generated method on a pointer type and the
    215 // pointer is nil, it would panic at runtime in the panicwrap
    216 // method. Treat it like nil instead.
    217 // Issue 8415.
    218 //
    219 // This is so people can implement driver.Value on value types and
    220 // still use nil pointers to those types to mean nil/NULL, just like
    221 // string/*string.
    222 //
    223 // This function is mirrored in the database/sql package.
    224 func callValuerValue(vr Valuer) (v Value, err error) {
    225 	if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr &&
    226 		rv.IsNil() &&
    227 		rv.Type().Elem().Implements(valuerReflectType) {
    228 		return nil, nil
    229 	}
    230 	return vr.Value()
    231 }
    232 
    233 func (defaultConverter) ConvertValue(v interface{}) (Value, error) {
    234 	if IsValue(v) {
    235 		return v, nil
    236 	}
    237 
    238 	if vr, ok := v.(Valuer); ok {
    239 		sv, err := callValuerValue(vr)
    240 		if err != nil {
    241 			return nil, err
    242 		}
    243 		if !IsValue(sv) {
    244 			return nil, fmt.Errorf("non-Value type %T returned from Value", sv)
    245 		}
    246 		return sv, nil
    247 	}
    248 
    249 	rv := reflect.ValueOf(v)
    250 	switch rv.Kind() {
    251 	case reflect.Ptr:
    252 		// indirect pointers
    253 		if rv.IsNil() {
    254 			return nil, nil
    255 		} else {
    256 			return defaultConverter{}.ConvertValue(rv.Elem().Interface())
    257 		}
    258 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    259 		return rv.Int(), nil
    260 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
    261 		return int64(rv.Uint()), nil
    262 	case reflect.Uint64:
    263 		u64 := rv.Uint()
    264 		if u64 >= 1<<63 {
    265 			return nil, fmt.Errorf("uint64 values with high bit set are not supported")
    266 		}
    267 		return int64(u64), nil
    268 	case reflect.Float32, reflect.Float64:
    269 		return rv.Float(), nil
    270 	case reflect.Bool:
    271 		return rv.Bool(), nil
    272 	case reflect.Slice:
    273 		ek := rv.Type().Elem().Kind()
    274 		if ek == reflect.Uint8 {
    275 			return rv.Bytes(), nil
    276 		}
    277 		return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek)
    278 	case reflect.String:
    279 		return rv.String(), nil
    280 	}
    281 	return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
    282 }
    283