| // Copyright 2011 The Go Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style | 
 | // license that can be found in the LICENSE file. | 
 |  | 
 | // Type conversions for Scan. | 
 |  | 
 | package sql | 
 |  | 
 | import ( | 
 | 	"database/sql/driver" | 
 | 	"errors" | 
 | 	"fmt" | 
 | 	"reflect" | 
 | 	"strconv" | 
 | ) | 
 |  | 
 | var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error | 
 |  | 
 | // driverArgs converts arguments from callers of Stmt.Exec and | 
 | // Stmt.Query into driver Values. | 
 | // | 
 | // The statement ds may be nil, if no statement is available. | 
 | func driverArgs(ds *driverStmt, args []interface{}) ([]driver.Value, error) { | 
 | 	dargs := make([]driver.Value, len(args)) | 
 | 	var si driver.Stmt | 
 | 	if ds != nil { | 
 | 		si = ds.si | 
 | 	} | 
 | 	cc, ok := si.(driver.ColumnConverter) | 
 |  | 
 | 	// Normal path, for a driver.Stmt that is not a ColumnConverter. | 
 | 	if !ok { | 
 | 		for n, arg := range args { | 
 | 			var err error | 
 | 			dargs[n], err = driver.DefaultParameterConverter.ConvertValue(arg) | 
 | 			if err != nil { | 
 | 				return nil, fmt.Errorf("sql: converting Exec argument #%d's type: %v", n, err) | 
 | 			} | 
 | 		} | 
 | 		return dargs, nil | 
 | 	} | 
 |  | 
 | 	// Let the Stmt convert its own arguments. | 
 | 	for n, arg := range args { | 
 | 		// First, see if the value itself knows how to convert | 
 | 		// itself to a driver type.  For example, a NullString | 
 | 		// struct changing into a string or nil. | 
 | 		if svi, ok := arg.(driver.Valuer); ok { | 
 | 			sv, err := svi.Value() | 
 | 			if err != nil { | 
 | 				return nil, fmt.Errorf("sql: argument index %d from Value: %v", n, err) | 
 | 			} | 
 | 			if !driver.IsValue(sv) { | 
 | 				return nil, fmt.Errorf("sql: argument index %d: non-subset type %T returned from Value", n, sv) | 
 | 			} | 
 | 			arg = sv | 
 | 		} | 
 |  | 
 | 		// Second, ask the column to sanity check itself. For | 
 | 		// example, drivers might use this to make sure that | 
 | 		// an int64 values being inserted into a 16-bit | 
 | 		// integer field is in range (before getting | 
 | 		// truncated), or that a nil can't go into a NOT NULL | 
 | 		// column before going across the network to get the | 
 | 		// same error. | 
 | 		var err error | 
 | 		ds.Lock() | 
 | 		dargs[n], err = cc.ColumnConverter(n).ConvertValue(arg) | 
 | 		ds.Unlock() | 
 | 		if err != nil { | 
 | 			return nil, fmt.Errorf("sql: converting argument #%d's type: %v", n, err) | 
 | 		} | 
 | 		if !driver.IsValue(dargs[n]) { | 
 | 			return nil, fmt.Errorf("sql: driver ColumnConverter error converted %T to unsupported type %T", | 
 | 				arg, dargs[n]) | 
 | 		} | 
 | 	} | 
 |  | 
 | 	return dargs, nil | 
 | } | 
 |  | 
 | // convertAssign copies to dest the value in src, converting it if possible. | 
 | // An error is returned if the copy would result in loss of information. | 
 | // dest should be a pointer type. | 
 | func convertAssign(dest, src interface{}) error { | 
 | 	// Common cases, without reflect. | 
 | 	switch s := src.(type) { | 
 | 	case string: | 
 | 		switch d := dest.(type) { | 
 | 		case *string: | 
 | 			if d == nil { | 
 | 				return errNilPtr | 
 | 			} | 
 | 			*d = s | 
 | 			return nil | 
 | 		case *[]byte: | 
 | 			if d == nil { | 
 | 				return errNilPtr | 
 | 			} | 
 | 			*d = []byte(s) | 
 | 			return nil | 
 | 		} | 
 | 	case []byte: | 
 | 		switch d := dest.(type) { | 
 | 		case *string: | 
 | 			if d == nil { | 
 | 				return errNilPtr | 
 | 			} | 
 | 			*d = string(s) | 
 | 			return nil | 
 | 		case *interface{}: | 
 | 			if d == nil { | 
 | 				return errNilPtr | 
 | 			} | 
 | 			*d = cloneBytes(s) | 
 | 			return nil | 
 | 		case *[]byte: | 
 | 			if d == nil { | 
 | 				return errNilPtr | 
 | 			} | 
 | 			*d = cloneBytes(s) | 
 | 			return nil | 
 | 		case *RawBytes: | 
 | 			if d == nil { | 
 | 				return errNilPtr | 
 | 			} | 
 | 			*d = s | 
 | 			return nil | 
 | 		} | 
 | 	case nil: | 
 | 		switch d := dest.(type) { | 
 | 		case *interface{}: | 
 | 			if d == nil { | 
 | 				return errNilPtr | 
 | 			} | 
 | 			*d = nil | 
 | 			return nil | 
 | 		case *[]byte: | 
 | 			if d == nil { | 
 | 				return errNilPtr | 
 | 			} | 
 | 			*d = nil | 
 | 			return nil | 
 | 		case *RawBytes: | 
 | 			if d == nil { | 
 | 				return errNilPtr | 
 | 			} | 
 | 			*d = nil | 
 | 			return nil | 
 | 		} | 
 | 	} | 
 |  | 
 | 	var sv reflect.Value | 
 |  | 
 | 	switch d := dest.(type) { | 
 | 	case *string: | 
 | 		sv = reflect.ValueOf(src) | 
 | 		switch sv.Kind() { | 
 | 		case reflect.Bool, | 
 | 			reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, | 
 | 			reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, | 
 | 			reflect.Float32, reflect.Float64: | 
 | 			*d = asString(src) | 
 | 			return nil | 
 | 		} | 
 | 	case *[]byte: | 
 | 		sv = reflect.ValueOf(src) | 
 | 		if b, ok := asBytes(nil, sv); ok { | 
 | 			*d = b | 
 | 			return nil | 
 | 		} | 
 | 	case *RawBytes: | 
 | 		sv = reflect.ValueOf(src) | 
 | 		if b, ok := asBytes([]byte(*d)[:0], sv); ok { | 
 | 			*d = RawBytes(b) | 
 | 			return nil | 
 | 		} | 
 | 	case *bool: | 
 | 		bv, err := driver.Bool.ConvertValue(src) | 
 | 		if err == nil { | 
 | 			*d = bv.(bool) | 
 | 		} | 
 | 		return err | 
 | 	case *interface{}: | 
 | 		*d = src | 
 | 		return nil | 
 | 	} | 
 |  | 
 | 	if scanner, ok := dest.(Scanner); ok { | 
 | 		return scanner.Scan(src) | 
 | 	} | 
 |  | 
 | 	dpv := reflect.ValueOf(dest) | 
 | 	if dpv.Kind() != reflect.Ptr { | 
 | 		return errors.New("destination not a pointer") | 
 | 	} | 
 | 	if dpv.IsNil() { | 
 | 		return errNilPtr | 
 | 	} | 
 |  | 
 | 	if !sv.IsValid() { | 
 | 		sv = reflect.ValueOf(src) | 
 | 	} | 
 |  | 
 | 	dv := reflect.Indirect(dpv) | 
 | 	if dv.Kind() == sv.Kind() { | 
 | 		dv.Set(sv) | 
 | 		return nil | 
 | 	} | 
 |  | 
 | 	switch dv.Kind() { | 
 | 	case reflect.Ptr: | 
 | 		if src == nil { | 
 | 			dv.Set(reflect.Zero(dv.Type())) | 
 | 			return nil | 
 | 		} else { | 
 | 			dv.Set(reflect.New(dv.Type().Elem())) | 
 | 			return convertAssign(dv.Interface(), src) | 
 | 		} | 
 | 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | 
 | 		s := asString(src) | 
 | 		i64, err := strconv.ParseInt(s, 10, dv.Type().Bits()) | 
 | 		if err != nil { | 
 | 			return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err) | 
 | 		} | 
 | 		dv.SetInt(i64) | 
 | 		return nil | 
 | 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | 
 | 		s := asString(src) | 
 | 		u64, err := strconv.ParseUint(s, 10, dv.Type().Bits()) | 
 | 		if err != nil { | 
 | 			return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err) | 
 | 		} | 
 | 		dv.SetUint(u64) | 
 | 		return nil | 
 | 	case reflect.Float32, reflect.Float64: | 
 | 		s := asString(src) | 
 | 		f64, err := strconv.ParseFloat(s, dv.Type().Bits()) | 
 | 		if err != nil { | 
 | 			return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err) | 
 | 		} | 
 | 		dv.SetFloat(f64) | 
 | 		return nil | 
 | 	} | 
 |  | 
 | 	return fmt.Errorf("unsupported driver -> Scan pair: %T -> %T", src, dest) | 
 | } | 
 |  | 
 | func cloneBytes(b []byte) []byte { | 
 | 	if b == nil { | 
 | 		return nil | 
 | 	} else { | 
 | 		c := make([]byte, len(b)) | 
 | 		copy(c, b) | 
 | 		return c | 
 | 	} | 
 | } | 
 |  | 
 | func asString(src interface{}) string { | 
 | 	switch v := src.(type) { | 
 | 	case string: | 
 | 		return v | 
 | 	case []byte: | 
 | 		return string(v) | 
 | 	} | 
 | 	rv := reflect.ValueOf(src) | 
 | 	switch rv.Kind() { | 
 | 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | 
 | 		return strconv.FormatInt(rv.Int(), 10) | 
 | 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | 
 | 		return strconv.FormatUint(rv.Uint(), 10) | 
 | 	case reflect.Float64: | 
 | 		return strconv.FormatFloat(rv.Float(), 'g', -1, 64) | 
 | 	case reflect.Float32: | 
 | 		return strconv.FormatFloat(rv.Float(), 'g', -1, 32) | 
 | 	case reflect.Bool: | 
 | 		return strconv.FormatBool(rv.Bool()) | 
 | 	} | 
 | 	return fmt.Sprintf("%v", src) | 
 | } | 
 |  | 
 | func asBytes(buf []byte, rv reflect.Value) (b []byte, ok bool) { | 
 | 	switch rv.Kind() { | 
 | 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | 
 | 		return strconv.AppendInt(buf, rv.Int(), 10), true | 
 | 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | 
 | 		return strconv.AppendUint(buf, rv.Uint(), 10), true | 
 | 	case reflect.Float32: | 
 | 		return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 32), true | 
 | 	case reflect.Float64: | 
 | 		return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 64), true | 
 | 	case reflect.Bool: | 
 | 		return strconv.AppendBool(buf, rv.Bool()), true | 
 | 	case reflect.String: | 
 | 		s := rv.String() | 
 | 		return append(buf, s...), true | 
 | 	} | 
 | 	return | 
 | } |