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 5package driver 6 7import ( 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. 30type 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. 39type 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 54var Bool boolType 55 56type boolType struct{} 57 58var _ ValueConverter = boolType{} 59 60func (boolType) String() string { return "Bool" } 61 62func (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. 101var Int32 int32Type 102 103type int32Type struct{} 104 105var _ ValueConverter = int32Type{} 106 107func (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). 136var String stringType 137 138type stringType struct{} 139 140func (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. 150type Null struct { 151 Converter ValueConverter 152} 153 154func (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. 163type NotNull struct { 164 Converter ValueConverter 165} 166 167func (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. 175func 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. 188func 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. 205var DefaultParameterConverter defaultConverter 206 207type defaultConverter struct{} 208 209var _ ValueConverter = defaultConverter{} 210 211var 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. 224func 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 233func (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