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 [database/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 any) (Value, error) 33} 34 35// Valuer is the interface providing the Value method. 36// 37// Errors returned by the [Value] method are wrapped by the database/sql package. 38// This allows callers to use [errors.Is] for precise error handling after operations 39// like [database/sql.Query], [database/sql.Exec], or [database/sql.QueryRow]. 40// 41// Types implementing Valuer interface are able to convert 42// themselves to a driver [Value]. 43type Valuer interface { 44 // Value returns a driver Value. 45 // Value must not panic. 46 Value() (Value, error) 47} 48 49// Bool is a [ValueConverter] that converts input values to bool. 50// 51// The conversion rules are: 52// - booleans are returned unchanged 53// - for integer types, 54// 1 is true 55// 0 is false, 56// other integers are an error 57// - for strings and []byte, same rules as [strconv.ParseBool] 58// - all other types are an error 59var Bool boolType 60 61type boolType struct{} 62 63var _ ValueConverter = boolType{} 64 65func (boolType) String() string { return "Bool" } 66 67func (boolType) ConvertValue(src any) (Value, error) { 68 switch s := src.(type) { 69 case bool: 70 return s, nil 71 case string: 72 b, err := strconv.ParseBool(s) 73 if err != nil { 74 return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s) 75 } 76 return b, nil 77 case []byte: 78 b, err := strconv.ParseBool(string(s)) 79 if err != nil { 80 return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s) 81 } 82 return b, nil 83 } 84 85 sv := reflect.ValueOf(src) 86 switch sv.Kind() { 87 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 88 iv := sv.Int() 89 if iv == 1 || iv == 0 { 90 return iv == 1, nil 91 } 92 return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", iv) 93 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 94 uv := sv.Uint() 95 if uv == 1 || uv == 0 { 96 return uv == 1, nil 97 } 98 return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", uv) 99 } 100 101 return nil, fmt.Errorf("sql/driver: couldn't convert %v (%T) into type bool", src, src) 102} 103 104// Int32 is a [ValueConverter] that converts input values to int64, 105// respecting the limits of an int32 value. 106var Int32 int32Type 107 108type int32Type struct{} 109 110var _ ValueConverter = int32Type{} 111 112func (int32Type) ConvertValue(v any) (Value, error) { 113 rv := reflect.ValueOf(v) 114 switch rv.Kind() { 115 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 116 i64 := rv.Int() 117 if i64 > (1<<31)-1 || i64 < -(1<<31) { 118 return nil, fmt.Errorf("sql/driver: value %d overflows int32", v) 119 } 120 return i64, nil 121 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 122 u64 := rv.Uint() 123 if u64 > (1<<31)-1 { 124 return nil, fmt.Errorf("sql/driver: value %d overflows int32", v) 125 } 126 return int64(u64), nil 127 case reflect.String: 128 i, err := strconv.Atoi(rv.String()) 129 if err != nil { 130 return nil, fmt.Errorf("sql/driver: value %q can't be converted to int32", v) 131 } 132 return int64(i), nil 133 } 134 return nil, fmt.Errorf("sql/driver: unsupported value %v (type %T) converting to int32", v, v) 135} 136 137// String is a [ValueConverter] that converts its input to a string. 138// If the value is already a string or []byte, it's unchanged. 139// If the value is of another type, conversion to string is done 140// with fmt.Sprintf("%v", v). 141var String stringType 142 143type stringType struct{} 144 145func (stringType) ConvertValue(v any) (Value, error) { 146 switch v.(type) { 147 case string, []byte: 148 return v, nil 149 } 150 return fmt.Sprintf("%v", v), nil 151} 152 153// Null is a type that implements [ValueConverter] by allowing nil 154// values but otherwise delegating to another [ValueConverter]. 155type Null struct { 156 Converter ValueConverter 157} 158 159func (n Null) ConvertValue(v any) (Value, error) { 160 if v == nil { 161 return nil, nil 162 } 163 return n.Converter.ConvertValue(v) 164} 165 166// NotNull is a type that implements [ValueConverter] by disallowing nil 167// values but otherwise delegating to another [ValueConverter]. 168type NotNull struct { 169 Converter ValueConverter 170} 171 172func (n NotNull) ConvertValue(v any) (Value, error) { 173 if v == nil { 174 return nil, fmt.Errorf("nil value not allowed") 175 } 176 return n.Converter.ConvertValue(v) 177} 178 179// IsValue reports whether v is a valid [Value] parameter type. 180func IsValue(v any) bool { 181 if v == nil { 182 return true 183 } 184 switch v.(type) { 185 case []byte, bool, float64, int64, string, time.Time: 186 return true 187 case decimalDecompose: 188 return true 189 } 190 return false 191} 192 193// IsScanValue is equivalent to [IsValue]. 194// It exists for compatibility. 195func IsScanValue(v any) bool { 196 return IsValue(v) 197} 198 199// DefaultParameterConverter is the default implementation of 200// [ValueConverter] that's used when a [Stmt] doesn't implement 201// [ColumnConverter]. 202// 203// DefaultParameterConverter returns its argument directly if 204// IsValue(arg). Otherwise, if the argument implements [Valuer], its 205// Value method is used to return a [Value]. As a fallback, the provided 206// argument's underlying type is used to convert it to a [Value]: 207// underlying integer types are converted to int64, floats to float64, 208// bool, string, and []byte to themselves. If the argument is a nil 209// pointer, defaultConverter.ConvertValue returns a nil [Value]. 210// If the argument is a non-nil pointer, it is dereferenced and 211// defaultConverter.ConvertValue is called recursively. Other types 212// are an error. 213var DefaultParameterConverter defaultConverter 214 215type defaultConverter struct{} 216 217var _ ValueConverter = defaultConverter{} 218 219var valuerReflectType = reflect.TypeFor[Valuer]() 220 221// callValuerValue returns vr.Value(), with one exception: 222// If vr.Value is an auto-generated method on a pointer type and the 223// pointer is nil, it would panic at runtime in the panicwrap 224// method. Treat it like nil instead. 225// Issue 8415. 226// 227// This is so people can implement driver.Value on value types and 228// still use nil pointers to those types to mean nil/NULL, just like 229// string/*string. 230// 231// This function is mirrored in the database/sql package. 232func callValuerValue(vr Valuer) (v Value, err error) { 233 if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Pointer && 234 rv.IsNil() && 235 rv.Type().Elem().Implements(valuerReflectType) { 236 return nil, nil 237 } 238 return vr.Value() 239} 240 241func (defaultConverter) ConvertValue(v any) (Value, error) { 242 if IsValue(v) { 243 return v, nil 244 } 245 246 switch vr := v.(type) { 247 case Valuer: 248 sv, err := callValuerValue(vr) 249 if err != nil { 250 return nil, err 251 } 252 if !IsValue(sv) { 253 return nil, fmt.Errorf("non-Value type %T returned from Value", sv) 254 } 255 return sv, nil 256 257 // For now, continue to prefer the Valuer interface over the decimal decompose interface. 258 case decimalDecompose: 259 return vr, nil 260 } 261 262 rv := reflect.ValueOf(v) 263 switch rv.Kind() { 264 case reflect.Pointer: 265 // indirect pointers 266 if rv.IsNil() { 267 return nil, nil 268 } else { 269 return defaultConverter{}.ConvertValue(rv.Elem().Interface()) 270 } 271 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 272 return rv.Int(), nil 273 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32: 274 return int64(rv.Uint()), nil 275 case reflect.Uint64: 276 u64 := rv.Uint() 277 if u64 >= 1<<63 { 278 return nil, fmt.Errorf("uint64 values with high bit set are not supported") 279 } 280 return int64(u64), nil 281 case reflect.Float32, reflect.Float64: 282 return rv.Float(), nil 283 case reflect.Bool: 284 return rv.Bool(), nil 285 case reflect.Slice: 286 ek := rv.Type().Elem().Kind() 287 if ek == reflect.Uint8 { 288 return rv.Bytes(), nil 289 } 290 return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek) 291 case reflect.String: 292 return rv.String(), nil 293 } 294 return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind()) 295} 296 297type decimalDecompose interface { 298 // Decompose returns the internal decimal state into parts. 299 // If the provided buf has sufficient capacity, buf may be returned as the coefficient with 300 // the value set and length set as appropriate. 301 Decompose(buf []byte) (form byte, negative bool, coefficient []byte, exponent int32) 302} 303