Source file src/pkg/database/sql/convert.go
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 // subsetTypeArgs takes a slice of arguments from callers of the sql 18 // package and converts them into a slice of the driver package's 19 // "subset types". 20 func subsetTypeArgs(args []interface{}) ([]driver.Value, error) { 21 out := make([]driver.Value, len(args)) 22 for n, arg := range args { 23 var err error 24 out[n], err = driver.DefaultParameterConverter.ConvertValue(arg) 25 if err != nil { 26 return nil, fmt.Errorf("sql: converting argument #%d's type: %v", n+1, err) 27 } 28 } 29 return out, nil 30 } 31 32 // convertAssign copies to dest the value in src, converting it if possible. 33 // An error is returned if the copy would result in loss of information. 34 // dest should be a pointer type. 35 func convertAssign(dest, src interface{}) error { 36 // Common cases, without reflect. Fall through. 37 switch s := src.(type) { 38 case string: 39 switch d := dest.(type) { 40 case *string: 41 *d = s 42 return nil 43 case *[]byte: 44 *d = []byte(s) 45 return nil 46 } 47 case []byte: 48 switch d := dest.(type) { 49 case *string: 50 *d = string(s) 51 return nil 52 case *interface{}: 53 bcopy := make([]byte, len(s)) 54 copy(bcopy, s) 55 *d = bcopy 56 return nil 57 case *[]byte: 58 *d = s 59 return nil 60 } 61 case nil: 62 switch d := dest.(type) { 63 case *[]byte: 64 *d = nil 65 return nil 66 } 67 } 68 69 var sv reflect.Value 70 71 switch d := dest.(type) { 72 case *string: 73 sv = reflect.ValueOf(src) 74 switch sv.Kind() { 75 case reflect.Bool, 76 reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, 77 reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, 78 reflect.Float32, reflect.Float64: 79 *d = fmt.Sprintf("%v", src) 80 return nil 81 } 82 case *bool: 83 bv, err := driver.Bool.ConvertValue(src) 84 if err == nil { 85 *d = bv.(bool) 86 } 87 return err 88 case *interface{}: 89 *d = src 90 return nil 91 } 92 93 if scanner, ok := dest.(Scanner); ok { 94 return scanner.Scan(src) 95 } 96 97 dpv := reflect.ValueOf(dest) 98 if dpv.Kind() != reflect.Ptr { 99 return errors.New("destination not a pointer") 100 } 101 102 if !sv.IsValid() { 103 sv = reflect.ValueOf(src) 104 } 105 106 dv := reflect.Indirect(dpv) 107 if dv.Kind() == sv.Kind() { 108 dv.Set(sv) 109 return nil 110 } 111 112 switch dv.Kind() { 113 case reflect.Ptr: 114 if src == nil { 115 dv.Set(reflect.Zero(dv.Type())) 116 return nil 117 } else { 118 dv.Set(reflect.New(dv.Type().Elem())) 119 return convertAssign(dv.Interface(), src) 120 } 121 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 122 s := asString(src) 123 i64, err := strconv.ParseInt(s, 10, dv.Type().Bits()) 124 if err != nil { 125 return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err) 126 } 127 dv.SetInt(i64) 128 return nil 129 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 130 s := asString(src) 131 u64, err := strconv.ParseUint(s, 10, dv.Type().Bits()) 132 if err != nil { 133 return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err) 134 } 135 dv.SetUint(u64) 136 return nil 137 case reflect.Float32, reflect.Float64: 138 s := asString(src) 139 f64, err := strconv.ParseFloat(s, dv.Type().Bits()) 140 if err != nil { 141 return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err) 142 } 143 dv.SetFloat(f64) 144 return nil 145 } 146 147 return fmt.Errorf("unsupported driver -> Scan pair: %T -> %T", src, dest) 148 } 149 150 func asString(src interface{}) string { 151 switch v := src.(type) { 152 case string: 153 return v 154 case []byte: 155 return string(v) 156 } 157 return fmt.Sprintf("%v", src) 158 }