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