...
Run Format

Source file src/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		"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	}
   333	

View as plain text