Source file src/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 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 bools.
    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, ConvertValue returns a nil Value. If the argument is a
   206  // non-nil pointer, it is dereferenced and ConvertValue is called
   207  // recursively. Other types are an error.
   208  var DefaultParameterConverter defaultConverter
   209  
   210  type defaultConverter struct{}
   211  
   212  var _ ValueConverter = defaultConverter{}
   213  
   214  var valuerReflectType = reflect.TypeOf((*Valuer)(nil)).Elem()
   215  
   216  // callValuerValue returns vr.Value(), with one exception:
   217  // If vr.Value is an auto-generated method on a pointer type and the
   218  // pointer is nil, it would panic at runtime in the panicwrap
   219  // method. Treat it like nil instead.
   220  // Issue 8415.
   221  //
   222  // This is so people can implement driver.Value on value types and
   223  // still use nil pointers to those types to mean nil/NULL, just like
   224  // string/*string.
   225  //
   226  // This function is mirrored in the database/sql package.
   227  func callValuerValue(vr Valuer) (v Value, err error) {
   228  	if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Pointer &&
   229  		rv.IsNil() &&
   230  		rv.Type().Elem().Implements(valuerReflectType) {
   231  		return nil, nil
   232  	}
   233  	return vr.Value()
   234  }
   235  
   236  func (defaultConverter) ConvertValue(v any) (Value, error) {
   237  	if IsValue(v) {
   238  		return v, nil
   239  	}
   240  
   241  	switch vr := v.(type) {
   242  	case Valuer:
   243  		sv, err := callValuerValue(vr)
   244  		if err != nil {
   245  			return nil, err
   246  		}
   247  		if !IsValue(sv) {
   248  			return nil, fmt.Errorf("non-Value type %T returned from Value", sv)
   249  		}
   250  		return sv, nil
   251  
   252  	// For now, continue to prefer the Valuer interface over the decimal decompose interface.
   253  	case decimalDecompose:
   254  		return vr, nil
   255  	}
   256  
   257  	rv := reflect.ValueOf(v)
   258  	switch rv.Kind() {
   259  	case reflect.Pointer:
   260  		// indirect pointers
   261  		if rv.IsNil() {
   262  			return nil, nil
   263  		} else {
   264  			return defaultConverter{}.ConvertValue(rv.Elem().Interface())
   265  		}
   266  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   267  		return rv.Int(), nil
   268  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
   269  		return int64(rv.Uint()), nil
   270  	case reflect.Uint64:
   271  		u64 := rv.Uint()
   272  		if u64 >= 1<<63 {
   273  			return nil, fmt.Errorf("uint64 values with high bit set are not supported")
   274  		}
   275  		return int64(u64), nil
   276  	case reflect.Float32, reflect.Float64:
   277  		return rv.Float(), nil
   278  	case reflect.Bool:
   279  		return rv.Bool(), nil
   280  	case reflect.Slice:
   281  		ek := rv.Type().Elem().Kind()
   282  		if ek == reflect.Uint8 {
   283  			return rv.Bytes(), nil
   284  		}
   285  		return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek)
   286  	case reflect.String:
   287  		return rv.String(), nil
   288  	}
   289  	return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
   290  }
   291  
   292  type decimalDecompose interface {
   293  	// Decompose returns the internal decimal state into parts.
   294  	// If the provided buf has sufficient capacity, buf may be returned as the coefficient with
   295  	// the value set and length set as appropriate.
   296  	Decompose(buf []byte) (form byte, negative bool, coefficient []byte, exponent int32)
   297  }
   298  

View as plain text