Home | History | Annotate | Download | only in sql
      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 }
    300