github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/database/sql/convert.go (about) 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 = fmt.Sprintf("%v", src) 164 return nil 165 } 166 case *[]byte: 167 sv = reflect.ValueOf(src) 168 switch sv.Kind() { 169 case reflect.Bool, 170 reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 171 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, 172 reflect.Float32, reflect.Float64: 173 *d = []byte(fmt.Sprintf("%v", src)) 174 return nil 175 } 176 case *RawBytes: 177 sv = reflect.ValueOf(src) 178 switch sv.Kind() { 179 case reflect.Bool, 180 reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 181 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, 182 reflect.Float32, reflect.Float64: 183 *d = RawBytes(fmt.Sprintf("%v", src)) 184 return nil 185 } 186 case *bool: 187 bv, err := driver.Bool.ConvertValue(src) 188 if err == nil { 189 *d = bv.(bool) 190 } 191 return err 192 case *interface{}: 193 *d = src 194 return nil 195 } 196 197 if scanner, ok := dest.(Scanner); ok { 198 return scanner.Scan(src) 199 } 200 201 dpv := reflect.ValueOf(dest) 202 if dpv.Kind() != reflect.Ptr { 203 return errors.New("destination not a pointer") 204 } 205 if dpv.IsNil() { 206 return errNilPtr 207 } 208 209 if !sv.IsValid() { 210 sv = reflect.ValueOf(src) 211 } 212 213 dv := reflect.Indirect(dpv) 214 if dv.Kind() == sv.Kind() { 215 dv.Set(sv) 216 return nil 217 } 218 219 switch dv.Kind() { 220 case reflect.Ptr: 221 if src == nil { 222 dv.Set(reflect.Zero(dv.Type())) 223 return nil 224 } else { 225 dv.Set(reflect.New(dv.Type().Elem())) 226 return convertAssign(dv.Interface(), src) 227 } 228 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 229 s := asString(src) 230 i64, err := strconv.ParseInt(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.SetInt(i64) 235 return nil 236 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 237 s := asString(src) 238 u64, err := strconv.ParseUint(s, 10, 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.SetUint(u64) 243 return nil 244 case reflect.Float32, reflect.Float64: 245 s := asString(src) 246 f64, err := strconv.ParseFloat(s, dv.Type().Bits()) 247 if err != nil { 248 return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err) 249 } 250 dv.SetFloat(f64) 251 return nil 252 } 253 254 return fmt.Errorf("unsupported driver -> Scan pair: %T -> %T", src, dest) 255 } 256 257 func cloneBytes(b []byte) []byte { 258 if b == nil { 259 return nil 260 } else { 261 c := make([]byte, len(b)) 262 copy(c, b) 263 return c 264 } 265 } 266 267 func asString(src interface{}) string { 268 switch v := src.(type) { 269 case string: 270 return v 271 case []byte: 272 return string(v) 273 } 274 return fmt.Sprintf("%v", src) 275 }