src/pkg/database/sql/convert.go - The Go Programming Language

Golang

Source file src/pkg/database/sql/convert.go

     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	// subsetTypeArgs takes a slice of arguments from callers of the sql
    18	// package and converts them into a slice of the driver package's
    19	// "subset types".
    20	func subsetTypeArgs(args []interface{}) ([]driver.Value, error) {
    21		out := make([]driver.Value, len(args))
    22		for n, arg := range args {
    23			var err error
    24			out[n], err = driver.DefaultParameterConverter.ConvertValue(arg)
    25			if err != nil {
    26				return nil, fmt.Errorf("sql: converting argument #%d's type: %v", n+1, err)
    27			}
    28		}
    29		return out, nil
    30	}
    31	
    32	// convertAssign copies to dest the value in src, converting it if possible.
    33	// An error is returned if the copy would result in loss of information.
    34	// dest should be a pointer type.
    35	func convertAssign(dest, src interface{}) error {
    36		// Common cases, without reflect.  Fall through.
    37		switch s := src.(type) {
    38		case string:
    39			switch d := dest.(type) {
    40			case *string:
    41				*d = s
    42				return nil
    43			case *[]byte:
    44				*d = []byte(s)
    45				return nil
    46			}
    47		case []byte:
    48			switch d := dest.(type) {
    49			case *string:
    50				*d = string(s)
    51				return nil
    52			case *interface{}:
    53				bcopy := make([]byte, len(s))
    54				copy(bcopy, s)
    55				*d = bcopy
    56				return nil
    57			case *[]byte:
    58				*d = s
    59				return nil
    60			}
    61		case nil:
    62			switch d := dest.(type) {
    63			case *[]byte:
    64				*d = nil
    65				return nil
    66			}
    67		}
    68	
    69		var sv reflect.Value
    70	
    71		switch d := dest.(type) {
    72		case *string:
    73			sv = reflect.ValueOf(src)
    74			switch sv.Kind() {
    75			case reflect.Bool,
    76				reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
    77				reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
    78				reflect.Float32, reflect.Float64:
    79				*d = fmt.Sprintf("%v", src)
    80				return nil
    81			}
    82		case *bool:
    83			bv, err := driver.Bool.ConvertValue(src)
    84			if err == nil {
    85				*d = bv.(bool)
    86			}
    87			return err
    88		case *interface{}:
    89			*d = src
    90			return nil
    91		}
    92	
    93		if scanner, ok := dest.(Scanner); ok {
    94			return scanner.Scan(src)
    95		}
    96	
    97		dpv := reflect.ValueOf(dest)
    98		if dpv.Kind() != reflect.Ptr {
    99			return errors.New("destination not a pointer")
   100		}
   101	
   102		if !sv.IsValid() {
   103			sv = reflect.ValueOf(src)
   104		}
   105	
   106		dv := reflect.Indirect(dpv)
   107		if dv.Kind() == sv.Kind() {
   108			dv.Set(sv)
   109			return nil
   110		}
   111	
   112		switch dv.Kind() {
   113		case reflect.Ptr:
   114			if src == nil {
   115				dv.Set(reflect.Zero(dv.Type()))
   116				return nil
   117			} else {
   118				dv.Set(reflect.New(dv.Type().Elem()))
   119				return convertAssign(dv.Interface(), src)
   120			}
   121		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   122			s := asString(src)
   123			i64, err := strconv.ParseInt(s, 10, dv.Type().Bits())
   124			if err != nil {
   125				return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
   126			}
   127			dv.SetInt(i64)
   128			return nil
   129		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   130			s := asString(src)
   131			u64, err := strconv.ParseUint(s, 10, dv.Type().Bits())
   132			if err != nil {
   133				return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
   134			}
   135			dv.SetUint(u64)
   136			return nil
   137		case reflect.Float32, reflect.Float64:
   138			s := asString(src)
   139			f64, err := strconv.ParseFloat(s, dv.Type().Bits())
   140			if err != nil {
   141				return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
   142			}
   143			dv.SetFloat(f64)
   144			return nil
   145		}
   146	
   147		return fmt.Errorf("unsupported driver -> Scan pair: %T -> %T", src, dest)
   148	}
   149	
   150	func asString(src interface{}) string {
   151		switch v := src.(type) {
   152		case string:
   153			return v
   154		case []byte:
   155			return string(v)
   156		}
   157		return fmt.Sprintf("%v", src)
   158	}