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 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  func IsValue(v interface{}) bool {
   176  	if v == nil {
   177  		return true
   178  	}
   179  	switch v.(type) {
   180  	case []byte, bool, float64, int64, string, time.Time:
   181  		return true
   182  	}
   183  	return false
   184  }
   185  
   186  // IsScanValue is equivalent to IsValue.
   187  // It exists for compatibility.
   188  func IsScanValue(v interface{}) bool {
   189  	return IsValue(v)
   190  }
   191  
   192  // DefaultParameterConverter is the default implementation of
   193  // ValueConverter that's used when a Stmt doesn't implement
   194  // ColumnConverter.
   195  //
   196  // DefaultParameterConverter returns its argument directly if
   197  // IsValue(arg). Otherwise, if the argument implements Valuer, its
   198  // Value method is used to return a Value. As a fallback, the provided
   199  // argument's underlying type is used to convert it to a Value:
   200  // underlying integer types are converted to int64, floats to float64,
   201  // bool, string, and []byte to themselves. If the argument is a nil
   202  // pointer, ConvertValue returns a nil Value. If the argument is a
   203  // non-nil pointer, it is dereferenced and ConvertValue is called
   204  // recursively. Other types are an error.
   205  var DefaultParameterConverter defaultConverter
   206  
   207  type defaultConverter struct{}
   208  
   209  var _ ValueConverter = defaultConverter{}
   210  
   211  var valuerReflectType = reflect.TypeOf((*Valuer)(nil)).Elem()
   212  
   213  // callValuerValue returns vr.Value(), with one exception:
   214  // If vr.Value is an auto-generated method on a pointer type and the
   215  // pointer is nil, it would panic at runtime in the panicwrap
   216  // method. Treat it like nil instead.
   217  // Issue 8415.
   218  //
   219  // This is so people can implement driver.Value on value types and
   220  // still use nil pointers to those types to mean nil/NULL, just like
   221  // string/*string.
   222  //
   223  // This function is mirrored in the database/sql package.
   224  func callValuerValue(vr Valuer) (v Value, err error) {
   225  	if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr &&
   226  		rv.IsNil() &&
   227  		rv.Type().Elem().Implements(valuerReflectType) {
   228  		return nil, nil
   229  	}
   230  	return vr.Value()
   231  }
   232  
   233  func (defaultConverter) ConvertValue(v interface{}) (Value, error) {
   234  	if IsValue(v) {
   235  		return v, nil
   236  	}
   237  
   238  	if vr, ok := v.(Valuer); ok {
   239  		sv, err := callValuerValue(vr)
   240  		if err != nil {
   241  			return nil, err
   242  		}
   243  		if !IsValue(sv) {
   244  			return nil, fmt.Errorf("non-Value type %T returned from Value", sv)
   245  		}
   246  		return sv, nil
   247  	}
   248  
   249  	rv := reflect.ValueOf(v)
   250  	switch rv.Kind() {
   251  	case reflect.Ptr:
   252  		// indirect pointers
   253  		if rv.IsNil() {
   254  			return nil, nil
   255  		} else {
   256  			return defaultConverter{}.ConvertValue(rv.Elem().Interface())
   257  		}
   258  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   259  		return rv.Int(), nil
   260  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
   261  		return int64(rv.Uint()), nil
   262  	case reflect.Uint64:
   263  		u64 := rv.Uint()
   264  		if u64 >= 1<<63 {
   265  			return nil, fmt.Errorf("uint64 values with high bit set are not supported")
   266  		}
   267  		return int64(u64), nil
   268  	case reflect.Float32, reflect.Float64:
   269  		return rv.Float(), nil
   270  	case reflect.Bool:
   271  		return rv.Bool(), nil
   272  	case reflect.Slice:
   273  		ek := rv.Type().Elem().Kind()
   274  		if ek == reflect.Uint8 {
   275  			return rv.Bytes(), nil
   276  		}
   277  		return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek)
   278  	case reflect.String:
   279  		return rv.String(), nil
   280  	}
   281  	return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
   282  }
   283  

View as plain text