1// Extracted from Go database/sql source code 2 3// Copyright 2011 The Go Authors. All rights reserved. 4// Use of this source code is governed by a BSD-style 5// license that can be found in the LICENSE file. 6 7// Type conversions for Scan. 8 9package sqlite3 10 11import ( 12 "database/sql" 13 "database/sql/driver" 14 "errors" 15 "fmt" 16 "reflect" 17 "strconv" 18 "time" 19) 20 21var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error 22 23// convertAssign copies to dest the value in src, converting it if possible. 24// An error is returned if the copy would result in loss of information. 25// dest should be a pointer type. 26func convertAssign(dest, src interface{}) error { 27 // Common cases, without reflect. 28 switch s := src.(type) { 29 case string: 30 switch d := dest.(type) { 31 case *string: 32 if d == nil { 33 return errNilPtr 34 } 35 *d = s 36 return nil 37 case *[]byte: 38 if d == nil { 39 return errNilPtr 40 } 41 *d = []byte(s) 42 return nil 43 case *sql.RawBytes: 44 if d == nil { 45 return errNilPtr 46 } 47 *d = append((*d)[:0], s...) 48 return nil 49 } 50 case []byte: 51 switch d := dest.(type) { 52 case *string: 53 if d == nil { 54 return errNilPtr 55 } 56 *d = string(s) 57 return nil 58 case *interface{}: 59 if d == nil { 60 return errNilPtr 61 } 62 *d = cloneBytes(s) 63 return nil 64 case *[]byte: 65 if d == nil { 66 return errNilPtr 67 } 68 *d = cloneBytes(s) 69 return nil 70 case *sql.RawBytes: 71 if d == nil { 72 return errNilPtr 73 } 74 *d = s 75 return nil 76 } 77 case time.Time: 78 switch d := dest.(type) { 79 case *time.Time: 80 *d = s 81 return nil 82 case *string: 83 *d = s.Format(time.RFC3339Nano) 84 return nil 85 case *[]byte: 86 if d == nil { 87 return errNilPtr 88 } 89 *d = []byte(s.Format(time.RFC3339Nano)) 90 return nil 91 case *sql.RawBytes: 92 if d == nil { 93 return errNilPtr 94 } 95 *d = s.AppendFormat((*d)[:0], time.RFC3339Nano) 96 return nil 97 } 98 case nil: 99 switch d := dest.(type) { 100 case *interface{}: 101 if d == nil { 102 return errNilPtr 103 } 104 *d = nil 105 return nil 106 case *[]byte: 107 if d == nil { 108 return errNilPtr 109 } 110 *d = nil 111 return nil 112 case *sql.RawBytes: 113 if d == nil { 114 return errNilPtr 115 } 116 *d = nil 117 return nil 118 } 119 } 120 121 var sv reflect.Value 122 123 switch d := dest.(type) { 124 case *string: 125 sv = reflect.ValueOf(src) 126 switch sv.Kind() { 127 case reflect.Bool, 128 reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 129 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, 130 reflect.Float32, reflect.Float64: 131 *d = asString(src) 132 return nil 133 } 134 case *[]byte: 135 sv = reflect.ValueOf(src) 136 if b, ok := asBytes(nil, sv); ok { 137 *d = b 138 return nil 139 } 140 case *sql.RawBytes: 141 sv = reflect.ValueOf(src) 142 if b, ok := asBytes([]byte(*d)[:0], sv); ok { 143 *d = sql.RawBytes(b) 144 return nil 145 } 146 case *bool: 147 bv, err := driver.Bool.ConvertValue(src) 148 if err == nil { 149 *d = bv.(bool) 150 } 151 return err 152 case *interface{}: 153 *d = src 154 return nil 155 } 156 157 if scanner, ok := dest.(sql.Scanner); ok { 158 return scanner.Scan(src) 159 } 160 161 dpv := reflect.ValueOf(dest) 162 if dpv.Kind() != reflect.Ptr { 163 return errors.New("destination not a pointer") 164 } 165 if dpv.IsNil() { 166 return errNilPtr 167 } 168 169 if !sv.IsValid() { 170 sv = reflect.ValueOf(src) 171 } 172 173 dv := reflect.Indirect(dpv) 174 if sv.IsValid() && sv.Type().AssignableTo(dv.Type()) { 175 switch b := src.(type) { 176 case []byte: 177 dv.Set(reflect.ValueOf(cloneBytes(b))) 178 default: 179 dv.Set(sv) 180 } 181 return nil 182 } 183 184 if dv.Kind() == sv.Kind() && sv.Type().ConvertibleTo(dv.Type()) { 185 dv.Set(sv.Convert(dv.Type())) 186 return nil 187 } 188 189 // The following conversions use a string value as an intermediate representation 190 // to convert between various numeric types. 191 // 192 // This also allows scanning into user defined types such as "type Int int64". 193 // For symmetry, also check for string destination types. 194 switch dv.Kind() { 195 case reflect.Ptr: 196 if src == nil { 197 dv.Set(reflect.Zero(dv.Type())) 198 return nil 199 } 200 dv.Set(reflect.New(dv.Type().Elem())) 201 return convertAssign(dv.Interface(), src) 202 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 203 s := asString(src) 204 i64, err := strconv.ParseInt(s, 10, dv.Type().Bits()) 205 if err != nil { 206 err = strconvErr(err) 207 return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err) 208 } 209 dv.SetInt(i64) 210 return nil 211 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 212 s := asString(src) 213 u64, err := strconv.ParseUint(s, 10, dv.Type().Bits()) 214 if err != nil { 215 err = strconvErr(err) 216 return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err) 217 } 218 dv.SetUint(u64) 219 return nil 220 case reflect.Float32, reflect.Float64: 221 s := asString(src) 222 f64, err := strconv.ParseFloat(s, dv.Type().Bits()) 223 if err != nil { 224 err = strconvErr(err) 225 return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err) 226 } 227 dv.SetFloat(f64) 228 return nil 229 case reflect.String: 230 switch v := src.(type) { 231 case string: 232 dv.SetString(v) 233 return nil 234 case []byte: 235 dv.SetString(string(v)) 236 return nil 237 } 238 } 239 240 return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest) 241} 242 243func strconvErr(err error) error { 244 if ne, ok := err.(*strconv.NumError); ok { 245 return ne.Err 246 } 247 return err 248} 249 250func cloneBytes(b []byte) []byte { 251 if b == nil { 252 return nil 253 } 254 c := make([]byte, len(b)) 255 copy(c, b) 256 return c 257} 258 259func 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 282func 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