...

Source file src/database/sql/driver/types.go

Documentation: database/sql/driver

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

View as plain text