github.com/sbinet/go@v0.0.0-20160827155028-54d7de7dd62b/src/database/sql/convert.go (about)

     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  // Type conversions for Scan.
     6  
     7  package sql
     8  
     9  import (
    10  	"database/sql/driver"
    11  	"errors"
    12  	"fmt"
    13  	"reflect"
    14  	"strconv"
    15  	"time"
    16  )
    17  
    18  var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error
    19  
    20  // driverArgs converts arguments from callers of Stmt.Exec and
    21  // Stmt.Query into driver Values.
    22  //
    23  // The statement ds may be nil, if no statement is available.
    24  func driverArgs(ds *driverStmt, args []interface{}) ([]driver.Value, error) {
    25  	dargs := make([]driver.Value, len(args))
    26  	var si driver.Stmt
    27  	if ds != nil {
    28  		si = ds.si
    29  	}
    30  	cc, ok := si.(driver.ColumnConverter)
    31  
    32  	// Normal path, for a driver.Stmt that is not a ColumnConverter.
    33  	if !ok {
    34  		for n, arg := range args {
    35  			var err error
    36  			dargs[n], err = driver.DefaultParameterConverter.ConvertValue(arg)
    37  			if err != nil {
    38  				return nil, fmt.Errorf("sql: converting Exec argument #%d's type: %v", n, err)
    39  			}
    40  		}
    41  		return dargs, nil
    42  	}
    43  
    44  	// Let the Stmt convert its own arguments.
    45  	for n, arg := range args {
    46  		// First, see if the value itself knows how to convert
    47  		// itself to a driver type. For example, a NullString
    48  		// struct changing into a string or nil.
    49  		if svi, ok := arg.(driver.Valuer); ok {
    50  			sv, err := svi.Value()
    51  			if err != nil {
    52  				return nil, fmt.Errorf("sql: argument index %d from Value: %v", n, err)
    53  			}
    54  			if !driver.IsValue(sv) {
    55  				return nil, fmt.Errorf("sql: argument index %d: non-subset type %T returned from Value", n, sv)
    56  			}
    57  			arg = sv
    58  		}
    59  
    60  		// Second, ask the column to sanity check itself. For
    61  		// example, drivers might use this to make sure that
    62  		// an int64 values being inserted into a 16-bit
    63  		// integer field is in range (before getting
    64  		// truncated), or that a nil can't go into a NOT NULL
    65  		// column before going across the network to get the
    66  		// same error.
    67  		var err error
    68  		ds.Lock()
    69  		dargs[n], err = cc.ColumnConverter(n).ConvertValue(arg)
    70  		ds.Unlock()
    71  		if err != nil {
    72  			return nil, fmt.Errorf("sql: converting argument #%d's type: %v", n, err)
    73  		}
    74  		if !driver.IsValue(dargs[n]) {
    75  			return nil, fmt.Errorf("sql: driver ColumnConverter error converted %T to unsupported type %T",
    76  				arg, dargs[n])
    77  		}
    78  	}
    79  
    80  	return dargs, nil
    81  }
    82  
    83  // convertAssign copies to dest the value in src, converting it if possible.
    84  // An error is returned if the copy would result in loss of information.
    85  // dest should be a pointer type.
    86  func convertAssign(dest, src interface{}) error {
    87  	// Common cases, without reflect.
    88  	switch s := src.(type) {
    89  	case string:
    90  		switch d := dest.(type) {
    91  		case *string:
    92  			if d == nil {
    93  				return errNilPtr
    94  			}
    95  			*d = s
    96  			return nil
    97  		case *[]byte:
    98  			if d == nil {
    99  				return errNilPtr
   100  			}
   101  			*d = []byte(s)
   102  			return nil
   103  		}
   104  	case []byte:
   105  		switch d := dest.(type) {
   106  		case *string:
   107  			if d == nil {
   108  				return errNilPtr
   109  			}
   110  			*d = string(s)
   111  			return nil
   112  		case *interface{}:
   113  			if d == nil {
   114  				return errNilPtr
   115  			}
   116  			*d = cloneBytes(s)
   117  			return nil
   118  		case *[]byte:
   119  			if d == nil {
   120  				return errNilPtr
   121  			}
   122  			*d = cloneBytes(s)
   123  			return nil
   124  		case *RawBytes:
   125  			if d == nil {
   126  				return errNilPtr
   127  			}
   128  			*d = s
   129  			return nil
   130  		}
   131  	case time.Time:
   132  		switch d := dest.(type) {
   133  		case *string:
   134  			*d = s.Format(time.RFC3339Nano)
   135  			return nil
   136  		case *[]byte:
   137  			if d == nil {
   138  				return errNilPtr
   139  			}
   140  			*d = []byte(s.Format(time.RFC3339Nano))
   141  			return nil
   142  		}
   143  	case nil:
   144  		switch d := dest.(type) {
   145  		case *interface{}:
   146  			if d == nil {
   147  				return errNilPtr
   148  			}
   149  			*d = nil
   150  			return nil
   151  		case *[]byte:
   152  			if d == nil {
   153  				return errNilPtr
   154  			}
   155  			*d = nil
   156  			return nil
   157  		case *RawBytes:
   158  			if d == nil {
   159  				return errNilPtr
   160  			}
   161  			*d = nil
   162  			return nil
   163  		}
   164  	}
   165  
   166  	var sv reflect.Value
   167  
   168  	switch d := dest.(type) {
   169  	case *string:
   170  		sv = reflect.ValueOf(src)
   171  		switch sv.Kind() {
   172  		case reflect.Bool,
   173  			reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
   174  			reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
   175  			reflect.Float32, reflect.Float64:
   176  			*d = asString(src)
   177  			return nil
   178  		}
   179  	case *[]byte:
   180  		sv = reflect.ValueOf(src)
   181  		if b, ok := asBytes(nil, sv); ok {
   182  			*d = b
   183  			return nil
   184  		}
   185  	case *RawBytes:
   186  		sv = reflect.ValueOf(src)
   187  		if b, ok := asBytes([]byte(*d)[:0], sv); ok {
   188  			*d = RawBytes(b)
   189  			return nil
   190  		}
   191  	case *bool:
   192  		bv, err := driver.Bool.ConvertValue(src)
   193  		if err == nil {
   194  			*d = bv.(bool)
   195  		}
   196  		return err
   197  	case *interface{}:
   198  		*d = src
   199  		return nil
   200  	}
   201  
   202  	if scanner, ok := dest.(Scanner); ok {
   203  		return scanner.Scan(src)
   204  	}
   205  
   206  	dpv := reflect.ValueOf(dest)
   207  	if dpv.Kind() != reflect.Ptr {
   208  		return errors.New("destination not a pointer")
   209  	}
   210  	if dpv.IsNil() {
   211  		return errNilPtr
   212  	}
   213  
   214  	if !sv.IsValid() {
   215  		sv = reflect.ValueOf(src)
   216  	}
   217  
   218  	dv := reflect.Indirect(dpv)
   219  	if sv.IsValid() && sv.Type().AssignableTo(dv.Type()) {
   220  		switch b := src.(type) {
   221  		case []byte:
   222  			dv.Set(reflect.ValueOf(cloneBytes(b)))
   223  		default:
   224  			dv.Set(sv)
   225  		}
   226  		return nil
   227  	}
   228  
   229  	if dv.Kind() == sv.Kind() && sv.Type().ConvertibleTo(dv.Type()) {
   230  		dv.Set(sv.Convert(dv.Type()))
   231  		return nil
   232  	}
   233  
   234  	switch dv.Kind() {
   235  	case reflect.Ptr:
   236  		if src == nil {
   237  			dv.Set(reflect.Zero(dv.Type()))
   238  			return nil
   239  		} else {
   240  			dv.Set(reflect.New(dv.Type().Elem()))
   241  			return convertAssign(dv.Interface(), src)
   242  		}
   243  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   244  		s := asString(src)
   245  		i64, err := strconv.ParseInt(s, 10, dv.Type().Bits())
   246  		if err != nil {
   247  			err = strconvErr(err)
   248  			return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
   249  		}
   250  		dv.SetInt(i64)
   251  		return nil
   252  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   253  		s := asString(src)
   254  		u64, err := strconv.ParseUint(s, 10, dv.Type().Bits())
   255  		if err != nil {
   256  			err = strconvErr(err)
   257  			return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
   258  		}
   259  		dv.SetUint(u64)
   260  		return nil
   261  	case reflect.Float32, reflect.Float64:
   262  		s := asString(src)
   263  		f64, err := strconv.ParseFloat(s, dv.Type().Bits())
   264  		if err != nil {
   265  			err = strconvErr(err)
   266  			return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
   267  		}
   268  		dv.SetFloat(f64)
   269  		return nil
   270  	}
   271  
   272  	return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest)
   273  }
   274  
   275  func strconvErr(err error) error {
   276  	if ne, ok := err.(*strconv.NumError); ok {
   277  		return ne.Err
   278  	}
   279  	return err
   280  }
   281  
   282  func cloneBytes(b []byte) []byte {
   283  	if b == nil {
   284  		return nil
   285  	} else {
   286  		c := make([]byte, len(b))
   287  		copy(c, b)
   288  		return c
   289  	}
   290  }
   291  
   292  func asString(src interface{}) string {
   293  	switch v := src.(type) {
   294  	case string:
   295  		return v
   296  	case []byte:
   297  		return string(v)
   298  	}
   299  	rv := reflect.ValueOf(src)
   300  	switch rv.Kind() {
   301  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   302  		return strconv.FormatInt(rv.Int(), 10)
   303  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   304  		return strconv.FormatUint(rv.Uint(), 10)
   305  	case reflect.Float64:
   306  		return strconv.FormatFloat(rv.Float(), 'g', -1, 64)
   307  	case reflect.Float32:
   308  		return strconv.FormatFloat(rv.Float(), 'g', -1, 32)
   309  	case reflect.Bool:
   310  		return strconv.FormatBool(rv.Bool())
   311  	}
   312  	return fmt.Sprintf("%v", src)
   313  }
   314  
   315  func asBytes(buf []byte, rv reflect.Value) (b []byte, ok bool) {
   316  	switch rv.Kind() {
   317  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   318  		return strconv.AppendInt(buf, rv.Int(), 10), true
   319  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   320  		return strconv.AppendUint(buf, rv.Uint(), 10), true
   321  	case reflect.Float32:
   322  		return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 32), true
   323  	case reflect.Float64:
   324  		return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 64), true
   325  	case reflect.Bool:
   326  		return strconv.AppendBool(buf, rv.Bool()), true
   327  	case reflect.String:
   328  		s := rv.String()
   329  		return append(buf, s...), true
   330  	}
   331  	return
   332  }