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 }