github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/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 = fmt.Sprintf("%v", src)
   164  			return nil
   165  		}
   166  	case *[]byte:
   167  		sv = reflect.ValueOf(src)
   168  		switch sv.Kind() {
   169  		case reflect.Bool,
   170  			reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
   171  			reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
   172  			reflect.Float32, reflect.Float64:
   173  			*d = []byte(fmt.Sprintf("%v", src))
   174  			return nil
   175  		}
   176  	case *RawBytes:
   177  		sv = reflect.ValueOf(src)
   178  		switch sv.Kind() {
   179  		case reflect.Bool,
   180  			reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
   181  			reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
   182  			reflect.Float32, reflect.Float64:
   183  			*d = RawBytes(fmt.Sprintf("%v", src))
   184  			return nil
   185  		}
   186  	case *bool:
   187  		bv, err := driver.Bool.ConvertValue(src)
   188  		if err == nil {
   189  			*d = bv.(bool)
   190  		}
   191  		return err
   192  	case *interface{}:
   193  		*d = src
   194  		return nil
   195  	}
   196  
   197  	if scanner, ok := dest.(Scanner); ok {
   198  		return scanner.Scan(src)
   199  	}
   200  
   201  	dpv := reflect.ValueOf(dest)
   202  	if dpv.Kind() != reflect.Ptr {
   203  		return errors.New("destination not a pointer")
   204  	}
   205  	if dpv.IsNil() {
   206  		return errNilPtr
   207  	}
   208  
   209  	if !sv.IsValid() {
   210  		sv = reflect.ValueOf(src)
   211  	}
   212  
   213  	dv := reflect.Indirect(dpv)
   214  	if dv.Kind() == sv.Kind() {
   215  		dv.Set(sv)
   216  		return nil
   217  	}
   218  
   219  	switch dv.Kind() {
   220  	case reflect.Ptr:
   221  		if src == nil {
   222  			dv.Set(reflect.Zero(dv.Type()))
   223  			return nil
   224  		} else {
   225  			dv.Set(reflect.New(dv.Type().Elem()))
   226  			return convertAssign(dv.Interface(), src)
   227  		}
   228  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   229  		s := asString(src)
   230  		i64, err := strconv.ParseInt(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.SetInt(i64)
   235  		return nil
   236  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   237  		s := asString(src)
   238  		u64, err := strconv.ParseUint(s, 10, 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.SetUint(u64)
   243  		return nil
   244  	case reflect.Float32, reflect.Float64:
   245  		s := asString(src)
   246  		f64, err := strconv.ParseFloat(s, dv.Type().Bits())
   247  		if err != nil {
   248  			return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
   249  		}
   250  		dv.SetFloat(f64)
   251  		return nil
   252  	}
   253  
   254  	return fmt.Errorf("unsupported driver -> Scan pair: %T -> %T", src, dest)
   255  }
   256  
   257  func cloneBytes(b []byte) []byte {
   258  	if b == nil {
   259  		return nil
   260  	} else {
   261  		c := make([]byte, len(b))
   262  		copy(c, b)
   263  		return c
   264  	}
   265  }
   266  
   267  func asString(src interface{}) string {
   268  	switch v := src.(type) {
   269  	case string:
   270  		return v
   271  	case []byte:
   272  		return string(v)
   273  	}
   274  	return fmt.Sprintf("%v", src)
   275  }