Source file src/pkg/database/sql/driver/types.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 package driver
6
7 import (
8 "fmt"
9 "reflect"
10 "strconv"
11 "time"
12 )
13
14 // ValueConverter is the interface providing the ConvertValue method.
15 //
16 // Various implementations of ValueConverter are provided by the
17 // driver package to provide consistent implementations of conversions
18 // between drivers. The ValueConverters have several uses:
19 //
20 // * converting from the Value types as provided by the sql package
21 // into a database table's specific column type and making sure it
22 // fits, such as making sure a particular int64 fits in a
23 // table's uint16 column.
24 //
25 // * converting a value as given from the database into one of the
26 // driver Value types.
27 //
28 // * by the sql package, for converting from a driver's Value type
29 // to a user's type in a scan.
30 type ValueConverter interface {
31 // ConvertValue converts a value to a driver Value.
32 ConvertValue(v interface{}) (Value, error)
33 }
34
35 // Valuer is the interface providing the Value method.
36 //
37 // Types implementing Valuer interface are able to convert
38 // themselves to a driver Value.
39 type Valuer interface {
40 // Value returns a driver Value.
41 Value() (Value, error)
42 }
43
44 // Bool is a ValueConverter that converts input values to bools.
45 //
46 // The conversion rules are:
47 // - booleans are returned unchanged
48 // - for integer types,
49 // 1 is true
50 // 0 is false,
51 // other integers are an error
52 // - for strings and []byte, same rules as strconv.ParseBool
53 // - all other types are an error
54 var Bool boolType
55
56 type boolType struct{}
57
58 var _ ValueConverter = boolType{}
59
60 func (boolType) String() string { return "Bool" }
61
62 func (boolType) ConvertValue(src interface{}) (Value, error) {
63 switch s := src.(type) {
64 case bool:
65 return s, nil
66 case string:
67 b, err := strconv.ParseBool(s)
68 if err != nil {
69 return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
70 }
71 return b, nil
72 case []byte:
73 b, err := strconv.ParseBool(string(s))
74 if err != nil {
75 return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
76 }
77 return b, nil
78 }
79
80 sv := reflect.ValueOf(src)
81 switch sv.Kind() {
82 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
83 iv := sv.Int()
84 if iv == 1 || iv == 0 {
85 return iv == 1, nil
86 }
87 return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", iv)
88 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
89 uv := sv.Uint()
90 if uv == 1 || uv == 0 {
91 return uv == 1, nil
92 }
93 return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", uv)
94 }
95
96 return nil, fmt.Errorf("sql/driver: couldn't convert %v (%T) into type bool", src, src)
97 }
98
99 // Int32 is a ValueConverter that converts input values to int64,
100 // respecting the limits of an int32 value.
101 var Int32 int32Type
102
103 type int32Type struct{}
104
105 var _ ValueConverter = int32Type{}
106
107 func (int32Type) ConvertValue(v interface{}) (Value, error) {
108 rv := reflect.ValueOf(v)
109 switch rv.Kind() {
110 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
111 i64 := rv.Int()
112 if i64 > (1<<31)-1 || i64 < -(1<<31) {
113 return nil, fmt.Errorf("sql/driver: value %d overflows int32", v)
114 }
115 return i64, nil
116 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
117 u64 := rv.Uint()
118 if u64 > (1<<31)-1 {
119 return nil, fmt.Errorf("sql/driver: value %d overflows int32", v)
120 }
121 return int64(u64), nil
122 case reflect.String:
123 i, err := strconv.Atoi(rv.String())
124 if err != nil {
125 return nil, fmt.Errorf("sql/driver: value %q can't be converted to int32", v)
126 }
127 return int64(i), nil
128 }
129 return nil, fmt.Errorf("sql/driver: unsupported value %v (type %T) converting to int32", v, v)
130 }
131
132 // String is a ValueConverter that converts its input to a string.
133 // If the value is already a string or []byte, it's unchanged.
134 // If the value is of another type, conversion to string is done
135 // with fmt.Sprintf("%v", v).
136 var String stringType
137
138 type stringType struct{}
139
140 func (stringType) ConvertValue(v interface{}) (Value, error) {
141 switch v.(type) {
142 case string, []byte:
143 return v, nil
144 }
145 return fmt.Sprintf("%v", v), nil
146 }
147
148 // Null is a type that implements ValueConverter by allowing nil
149 // values but otherwise delegating to another ValueConverter.
150 type Null struct {
151 Converter ValueConverter
152 }
153
154 func (n Null) ConvertValue(v interface{}) (Value, error) {
155 if v == nil {
156 return nil, nil
157 }
158 return n.Converter.ConvertValue(v)
159 }
160
161 // NotNull is a type that implements ValueConverter by disallowing nil
162 // values but otherwise delegating to another ValueConverter.
163 type NotNull struct {
164 Converter ValueConverter
165 }
166
167 func (n NotNull) ConvertValue(v interface{}) (Value, error) {
168 if v == nil {
169 return nil, fmt.Errorf("nil value not allowed")
170 }
171 return n.Converter.ConvertValue(v)
172 }
173
174 // IsValue reports whether v is a valid Value parameter type.
175 // Unlike IsScanValue, IsValue permits the string type.
176 func IsValue(v interface{}) bool {
177 if IsScanValue(v) {
178 return true
179 }
180 if _, ok := v.(string); ok {
181 return true
182 }
183 return false
184 }
185
186 // IsScanValue reports whether v is a valid Value scan type.
187 // Unlike IsValue, IsScanValue does not permit the string type.
188 func IsScanValue(v interface{}) bool {
189 if v == nil {
190 return true
191 }
192 switch v.(type) {
193 case int64, float64, []byte, bool, time.Time:
194 return true
195 }
196 return false
197 }
198
199 // DefaultParameterConverter is the default implementation of
200 // ValueConverter that's used when a Stmt doesn't implement
201 // ColumnConverter.
202 //
203 // DefaultParameterConverter returns the given value directly if
204 // IsValue(value). Otherwise integer type are converted to
205 // int64, floats to float64, and strings to []byte. Other types are
206 // an error.
207 var DefaultParameterConverter defaultConverter
208
209 type defaultConverter struct{}
210
211 var _ ValueConverter = defaultConverter{}
212
213 func (defaultConverter) ConvertValue(v interface{}) (Value, error) {
214 if IsValue(v) {
215 return v, nil
216 }
217
218 if svi, ok := v.(Valuer); ok {
219 sv, err := svi.Value()
220 if err != nil {
221 return nil, err
222 }
223 if !IsValue(sv) {
224 return nil, fmt.Errorf("non-Value type %T returned from Value", sv)
225 }
226 return sv, nil
227 }
228
229 rv := reflect.ValueOf(v)
230 switch rv.Kind() {
231 case reflect.Ptr:
232 // indirect pointers
233 if rv.IsNil() {
234 return nil, nil
235 } else {
236 return defaultConverter{}.ConvertValue(rv.Elem().Interface())
237 }
238 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
239 return rv.Int(), nil
240 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
241 return int64(rv.Uint()), nil
242 case reflect.Uint64:
243 u64 := rv.Uint()
244 if u64 >= 1<<63 {
245 return nil, fmt.Errorf("uint64 values with high bit set are not supported")
246 }
247 return int64(u64), nil
248 case reflect.Float32, reflect.Float64:
249 return rv.Float(), nil
250 }
251 return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
252 }