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 // Type conversions for Scan. 6 7 package sql 8 9 import ( 10 "database/sql/driver" 11 "errors" 12 "fmt" 13 "reflect" 14 "strconv" 15 ) 16 17 var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error 18 19 // driverArgs converts arguments from callers of Stmt.Exec and 20 // Stmt.Query into driver Values. 21 // 22 // The statement ds may be nil, if no statement is available. 23 func driverArgs(ds *driverStmt, args []interface{}) ([]driver.Value, error) { 24 dargs := make([]driver.Value, len(args)) 25 var si driver.Stmt 26 if ds != nil { 27 si = ds.si 28 } 29 cc, ok := si.(driver.ColumnConverter) 30 31 // Normal path, for a driver.Stmt that is not a ColumnConverter. 32 if !ok { 33 for n, arg := range args { 34 var err error 35 dargs[n], err = driver.DefaultParameterConverter.ConvertValue(arg) 36 if err != nil { 37 return nil, fmt.Errorf("sql: converting Exec argument #%d's type: %v", n, err) 38 } 39 } 40 return dargs, nil 41 } 42 43 // Let the Stmt convert its own arguments. 44 for n, arg := range args { 45 // First, see if the value itself knows how to convert 46 // itself to a driver type. For example, a NullString 47 // struct changing into a string or nil. 48 if svi, ok := arg.(driver.Valuer); ok { 49 sv, err := svi.Value() 50 if err != nil { 51 return nil, fmt.Errorf("sql: argument index %d from Value: %v", n, err) 52 } 53 if !driver.IsValue(sv) { 54 return nil, fmt.Errorf("sql: argument index %d: non-subset type %T returned from Value", n, sv) 55 } 56 arg = sv 57 } 58 59 // Second, ask the column to sanity check itself. For 60 // example, drivers might use this to make sure that 61 // an int64 values being inserted into a 16-bit 62 // integer field is in range (before getting 63 // truncated), or that a nil can't go into a NOT NULL 64 // column before going across the network to get the 65 // same error. 66 var err error 67 ds.Lock() 68 dargs[n], err = cc.ColumnConverter(n).ConvertValue(arg) 69 ds.Unlock() 70 if err != nil { 71 return nil, fmt.Errorf("sql: converting argument #%d's type: %v", n, err) 72 } 73 if !driver.IsValue(dargs[n]) { 74 return nil, fmt.Errorf("sql: driver ColumnConverter error converted %T to unsupported type %T", 75 arg, dargs[n]) 76 } 77 } 78 79 return dargs, nil 80 } 81 82 // convertAssign copies to dest the value in src, converting it if possible. 83 // An error is returned if the copy would result in loss of information. 84 // dest should be a pointer type. 85 func convertAssign(dest, src interface{}) error { 86 // Common cases, without reflect. 87 switch s := src.(type) { 88 case string: 89 switch d := dest.(type) { 90 case *string: 91 if d == nil { 92 return errNilPtr 93 } 94 *d = s 95 return nil 96 case *[]byte: 97 if d == nil { 98 return errNilPtr 99 } 100 *d = []byte(s) 101 return nil 102 } 103 case []byte: 104 switch d := dest.(type) { 105 case *string: 106 if d == nil { 107 return errNilPtr 108 } 109 *d = string(s) 110 return nil 111 case *interface{}: 112 if d == nil { 113 return errNilPtr 114 } 115 *d = cloneBytes(s) 116 return nil 117 case *[]byte: 118 if d == nil { 119 return errNilPtr 120 } 121 *d = cloneBytes(s) 122 return nil 123 case *RawBytes: 124 if d == nil { 125 return errNilPtr 126 } 127 *d = s 128 return nil 129 } 130 case nil: 131 switch d := dest.(type) { 132 case *interface{}: 133 if d == nil { 134 return errNilPtr 135 } 136 *d = nil 137 return nil 138 case *[]byte: 139 if d == nil { 140 return errNilPtr 141 } 142 *d = nil 143 return nil 144 case *RawBytes: 145 if d == nil { 146 return errNilPtr 147 } 148 *d = nil 149 return nil 150 } 151 } 152 153 var sv reflect.Value 154 155 switch d := dest.(type) { 156 case *string: 157 sv = reflect.ValueOf(src) 158 switch sv.Kind() { 159 case reflect.Bool, 160 reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 161 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, 162 reflect.Float32, reflect.Float64: 163 *d = asString(src) 164 return nil 165 } 166 case *[]byte: 167 sv = reflect.ValueOf(src) 168 if b, ok := asBytes(nil, sv); ok { 169 *d = b 170 return nil 171 } 172 case *RawBytes: 173 sv = reflect.ValueOf(src) 174 if b, ok := asBytes([]byte(*d)[:0], sv); ok { 175 *d = RawBytes(b) 176 return nil 177 } 178 case *bool: 179 bv, err := driver.Bool.ConvertValue(src) 180 if err == nil { 181 *d = bv.(bool) 182 } 183 return err 184 case *interface{}: 185 *d = src 186 return nil 187 } 188 189 if scanner, ok := dest.(Scanner); ok { 190 return scanner.Scan(src) 191 } 192 193 dpv := reflect.ValueOf(dest) 194 if dpv.Kind() != reflect.Ptr { 195 return errors.New("destination not a pointer") 196 } 197 if dpv.IsNil() { 198 return errNilPtr 199 } 200 201 if !sv.IsValid() { 202 sv = reflect.ValueOf(src) 203 } 204 205 dv := reflect.Indirect(dpv) 206 if dv.Kind() == sv.Kind() { 207 dv.Set(sv) 208 return nil 209 } 210 211 switch dv.Kind() { 212 case reflect.Ptr: 213 if src == nil { 214 dv.Set(reflect.Zero(dv.Type())) 215 return nil 216 } else { 217 dv.Set(reflect.New(dv.Type().Elem())) 218 return convertAssign(dv.Interface(), src) 219 } 220 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 221 s := asString(src) 222 i64, err := strconv.ParseInt(s, 10, dv.Type().Bits()) 223 if err != nil { 224 return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err) 225 } 226 dv.SetInt(i64) 227 return nil 228 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 229 s := asString(src) 230 u64, err := strconv.ParseUint(s, 10, dv.Type().Bits()) 231 if err != nil { 232 return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err) 233 } 234 dv.SetUint(u64) 235 return nil 236 case reflect.Float32, reflect.Float64: 237 s := asString(src) 238 f64, err := strconv.ParseFloat(s, dv.Type().Bits()) 239 if err != nil { 240 return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err) 241 } 242 dv.SetFloat(f64) 243 return nil 244 } 245 246 return fmt.Errorf("unsupported driver -> Scan pair: %T -> %T", src, dest) 247 } 248 249 func cloneBytes(b []byte) []byte { 250 if b == nil { 251 return nil 252 } else { 253 c := make([]byte, len(b)) 254 copy(c, b) 255 return c 256 } 257 } 258 259 func asString(src interface{}) string { 260 switch v := src.(type) { 261 case string: 262 return v 263 case []byte: 264 return string(v) 265 } 266 rv := reflect.ValueOf(src) 267 switch rv.Kind() { 268 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 269 return strconv.FormatInt(rv.Int(), 10) 270 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 271 return strconv.FormatUint(rv.Uint(), 10) 272 case reflect.Float64: 273 return strconv.FormatFloat(rv.Float(), 'g', -1, 64) 274 case reflect.Float32: 275 return strconv.FormatFloat(rv.Float(), 'g', -1, 32) 276 case reflect.Bool: 277 return strconv.FormatBool(rv.Bool()) 278 } 279 return fmt.Sprintf("%v", src) 280 } 281 282 func asBytes(buf []byte, rv reflect.Value) (b []byte, ok bool) { 283 switch rv.Kind() { 284 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 285 return strconv.AppendInt(buf, rv.Int(), 10), true 286 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 287 return strconv.AppendUint(buf, rv.Uint(), 10), true 288 case reflect.Float32: 289 return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 32), true 290 case reflect.Float64: 291 return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 64), true 292 case reflect.Bool: 293 return strconv.AppendBool(buf, rv.Bool()), true 294 case reflect.String: 295 s := rv.String() 296 return append(buf, s...), true 297 } 298 return 299 } 300