• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
5package driver
6
7import (
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 [database/sql] package, for converting from a driver's [Value] type
29//     to a user's type in a scan.
30type ValueConverter interface {
31	// ConvertValue converts a value to a driver Value.
32	ConvertValue(v any) (Value, error)
33}
34
35// Valuer is the interface providing the Value method.
36//
37// Errors returned by the [Value] method are wrapped by the database/sql package.
38// This allows callers to use [errors.Is] for precise error handling after operations
39// like [database/sql.Query], [database/sql.Exec], or [database/sql.QueryRow].
40//
41// Types implementing Valuer interface are able to convert
42// themselves to a driver [Value].
43type Valuer interface {
44	// Value returns a driver Value.
45	// Value must not panic.
46	Value() (Value, error)
47}
48
49// Bool is a [ValueConverter] that converts input values to bool.
50//
51// The conversion rules are:
52//   - booleans are returned unchanged
53//   - for integer types,
54//     1 is true
55//     0 is false,
56//     other integers are an error
57//   - for strings and []byte, same rules as [strconv.ParseBool]
58//   - all other types are an error
59var Bool boolType
60
61type boolType struct{}
62
63var _ ValueConverter = boolType{}
64
65func (boolType) String() string { return "Bool" }
66
67func (boolType) ConvertValue(src any) (Value, error) {
68	switch s := src.(type) {
69	case bool:
70		return s, nil
71	case string:
72		b, err := strconv.ParseBool(s)
73		if err != nil {
74			return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
75		}
76		return b, nil
77	case []byte:
78		b, err := strconv.ParseBool(string(s))
79		if err != nil {
80			return nil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", s)
81		}
82		return b, nil
83	}
84
85	sv := reflect.ValueOf(src)
86	switch sv.Kind() {
87	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
88		iv := sv.Int()
89		if iv == 1 || iv == 0 {
90			return iv == 1, nil
91		}
92		return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", iv)
93	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
94		uv := sv.Uint()
95		if uv == 1 || uv == 0 {
96			return uv == 1, nil
97		}
98		return nil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", uv)
99	}
100
101	return nil, fmt.Errorf("sql/driver: couldn't convert %v (%T) into type bool", src, src)
102}
103
104// Int32 is a [ValueConverter] that converts input values to int64,
105// respecting the limits of an int32 value.
106var Int32 int32Type
107
108type int32Type struct{}
109
110var _ ValueConverter = int32Type{}
111
112func (int32Type) ConvertValue(v any) (Value, error) {
113	rv := reflect.ValueOf(v)
114	switch rv.Kind() {
115	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
116		i64 := rv.Int()
117		if i64 > (1<<31)-1 || i64 < -(1<<31) {
118			return nil, fmt.Errorf("sql/driver: value %d overflows int32", v)
119		}
120		return i64, nil
121	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
122		u64 := rv.Uint()
123		if u64 > (1<<31)-1 {
124			return nil, fmt.Errorf("sql/driver: value %d overflows int32", v)
125		}
126		return int64(u64), nil
127	case reflect.String:
128		i, err := strconv.Atoi(rv.String())
129		if err != nil {
130			return nil, fmt.Errorf("sql/driver: value %q can't be converted to int32", v)
131		}
132		return int64(i), nil
133	}
134	return nil, fmt.Errorf("sql/driver: unsupported value %v (type %T) converting to int32", v, v)
135}
136
137// String is a [ValueConverter] that converts its input to a string.
138// If the value is already a string or []byte, it's unchanged.
139// If the value is of another type, conversion to string is done
140// with fmt.Sprintf("%v", v).
141var String stringType
142
143type stringType struct{}
144
145func (stringType) ConvertValue(v any) (Value, error) {
146	switch v.(type) {
147	case string, []byte:
148		return v, nil
149	}
150	return fmt.Sprintf("%v", v), nil
151}
152
153// Null is a type that implements [ValueConverter] by allowing nil
154// values but otherwise delegating to another [ValueConverter].
155type Null struct {
156	Converter ValueConverter
157}
158
159func (n Null) ConvertValue(v any) (Value, error) {
160	if v == nil {
161		return nil, nil
162	}
163	return n.Converter.ConvertValue(v)
164}
165
166// NotNull is a type that implements [ValueConverter] by disallowing nil
167// values but otherwise delegating to another [ValueConverter].
168type NotNull struct {
169	Converter ValueConverter
170}
171
172func (n NotNull) ConvertValue(v any) (Value, error) {
173	if v == nil {
174		return nil, fmt.Errorf("nil value not allowed")
175	}
176	return n.Converter.ConvertValue(v)
177}
178
179// IsValue reports whether v is a valid [Value] parameter type.
180func IsValue(v any) bool {
181	if v == nil {
182		return true
183	}
184	switch v.(type) {
185	case []byte, bool, float64, int64, string, time.Time:
186		return true
187	case decimalDecompose:
188		return true
189	}
190	return false
191}
192
193// IsScanValue is equivalent to [IsValue].
194// It exists for compatibility.
195func IsScanValue(v any) bool {
196	return IsValue(v)
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 its argument directly if
204// IsValue(arg). Otherwise, if the argument implements [Valuer], its
205// Value method is used to return a [Value]. As a fallback, the provided
206// argument's underlying type is used to convert it to a [Value]:
207// underlying integer types are converted to int64, floats to float64,
208// bool, string, and []byte to themselves. If the argument is a nil
209// pointer, defaultConverter.ConvertValue returns a nil [Value].
210// If the argument is a non-nil pointer, it is dereferenced and
211// defaultConverter.ConvertValue is called recursively. Other types
212// are an error.
213var DefaultParameterConverter defaultConverter
214
215type defaultConverter struct{}
216
217var _ ValueConverter = defaultConverter{}
218
219var valuerReflectType = reflect.TypeFor[Valuer]()
220
221// callValuerValue returns vr.Value(), with one exception:
222// If vr.Value is an auto-generated method on a pointer type and the
223// pointer is nil, it would panic at runtime in the panicwrap
224// method. Treat it like nil instead.
225// Issue 8415.
226//
227// This is so people can implement driver.Value on value types and
228// still use nil pointers to those types to mean nil/NULL, just like
229// string/*string.
230//
231// This function is mirrored in the database/sql package.
232func callValuerValue(vr Valuer) (v Value, err error) {
233	if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Pointer &&
234		rv.IsNil() &&
235		rv.Type().Elem().Implements(valuerReflectType) {
236		return nil, nil
237	}
238	return vr.Value()
239}
240
241func (defaultConverter) ConvertValue(v any) (Value, error) {
242	if IsValue(v) {
243		return v, nil
244	}
245
246	switch vr := v.(type) {
247	case Valuer:
248		sv, err := callValuerValue(vr)
249		if err != nil {
250			return nil, err
251		}
252		if !IsValue(sv) {
253			return nil, fmt.Errorf("non-Value type %T returned from Value", sv)
254		}
255		return sv, nil
256
257	// For now, continue to prefer the Valuer interface over the decimal decompose interface.
258	case decimalDecompose:
259		return vr, nil
260	}
261
262	rv := reflect.ValueOf(v)
263	switch rv.Kind() {
264	case reflect.Pointer:
265		// indirect pointers
266		if rv.IsNil() {
267			return nil, nil
268		} else {
269			return defaultConverter{}.ConvertValue(rv.Elem().Interface())
270		}
271	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
272		return rv.Int(), nil
273	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
274		return int64(rv.Uint()), nil
275	case reflect.Uint64:
276		u64 := rv.Uint()
277		if u64 >= 1<<63 {
278			return nil, fmt.Errorf("uint64 values with high bit set are not supported")
279		}
280		return int64(u64), nil
281	case reflect.Float32, reflect.Float64:
282		return rv.Float(), nil
283	case reflect.Bool:
284		return rv.Bool(), nil
285	case reflect.Slice:
286		ek := rv.Type().Elem().Kind()
287		if ek == reflect.Uint8 {
288			return rv.Bytes(), nil
289		}
290		return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek)
291	case reflect.String:
292		return rv.String(), nil
293	}
294	return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
295}
296
297type decimalDecompose interface {
298	// Decompose returns the internal decimal state into parts.
299	// If the provided buf has sufficient capacity, buf may be returned as the coefficient with
300	// the value set and length set as appropriate.
301	Decompose(buf []byte) (form byte, negative bool, coefficient []byte, exponent int32)
302}
303