// 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.package driverimport ()// ValueConverter is the interface providing the ConvertValue method.//// Various implementations of ValueConverter are provided by the// driver package to provide consistent implementations of conversions// between drivers. The ValueConverters have several uses://// - converting from the [Value] types as provided by the sql package// into a database table's specific column type and making sure it// fits, such as making sure a particular int64 fits in a// table's uint16 column.//// - converting a value as given from the database into one of the// driver [Value] types.//// - by the [database/sql] package, for converting from a driver's [Value] type// to a user's type in a scan.typeValueConverterinterface {// ConvertValue converts a value to a driver Value.ConvertValue(v any) (Value, error)}// Valuer is the interface providing the Value method.//// Errors returned by the [Value] method are wrapped by the database/sql package.// This allows callers to use [errors.Is] for precise error handling after operations// like [database/sql.Query], [database/sql.Exec], or [database/sql.QueryRow].//// Types implementing Valuer interface are able to convert// themselves to a driver [Value].typeValuerinterface {// Value returns a driver Value. // Value must not panic.Value() (Value, error)}// Bool is a [ValueConverter] that converts input values to bool.//// The conversion rules are:// - booleans are returned unchanged// - for integer types,// 1 is true// 0 is false,// other integers are an error// - for strings and []byte, same rules as [strconv.ParseBool]// - all other types are an errorvarBoolboolTypetype boolType struct{}var _ ValueConverter = boolType{}func (boolType) () string { return"Bool" }func (boolType) ( any) (Value, error) {switch s := .(type) {casebool:return , nilcasestring: , := strconv.ParseBool()if != nil {returnnil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", ) }return , nilcase []byte: , := strconv.ParseBool(string())if != nil {returnnil, fmt.Errorf("sql/driver: couldn't convert %q into type bool", ) }return , nil } := reflect.ValueOf()switch .Kind() {casereflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: := .Int()if == 1 || == 0 {return == 1, nil }returnnil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", )casereflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: := .Uint()if == 1 || == 0 {return == 1, nil }returnnil, fmt.Errorf("sql/driver: couldn't convert %d into type bool", ) }returnnil, fmt.Errorf("sql/driver: couldn't convert %v (%T) into type bool", , )}// Int32 is a [ValueConverter] that converts input values to int64,// respecting the limits of an int32 value.varInt32int32Typetype int32Type struct{}var _ ValueConverter = int32Type{}func (int32Type) ( any) (Value, error) { := reflect.ValueOf()switch .Kind() {casereflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: := .Int()if > (1<<31)-1 || < -(1<<31) {returnnil, fmt.Errorf("sql/driver: value %d overflows int32", ) }return , nilcasereflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: := .Uint()if > (1<<31)-1 {returnnil, fmt.Errorf("sql/driver: value %d overflows int32", ) }returnint64(), nilcasereflect.String: , := strconv.Atoi(.String())if != nil {returnnil, fmt.Errorf("sql/driver: value %q can't be converted to int32", ) }returnint64(), nil }returnnil, fmt.Errorf("sql/driver: unsupported value %v (type %T) converting to int32", , )}// String is a [ValueConverter] that converts its input to a string.// If the value is already a string or []byte, it's unchanged.// If the value is of another type, conversion to string is done// with fmt.Sprintf("%v", v).varStringstringTypetype stringType struct{}func (stringType) ( any) (Value, error) {switch .(type) {casestring, []byte:return , nil }returnfmt.Sprintf("%v", ), nil}// Null is a type that implements [ValueConverter] by allowing nil// values but otherwise delegating to another [ValueConverter].typeNullstruct { Converter ValueConverter}func ( Null) ( any) (Value, error) {if == nil {returnnil, nil }return .Converter.ConvertValue()}// NotNull is a type that implements [ValueConverter] by disallowing nil// values but otherwise delegating to another [ValueConverter].typeNotNullstruct { Converter ValueConverter}func ( NotNull) ( any) (Value, error) {if == nil {returnnil, fmt.Errorf("nil value not allowed") }return .Converter.ConvertValue()}// IsValue reports whether v is a valid [Value] parameter type.func ( any) bool {if == nil {returntrue }switch .(type) {case []byte, bool, float64, int64, string, time.Time:returntruecasedecimalDecompose:returntrue }returnfalse}// IsScanValue is equivalent to [IsValue].// It exists for compatibility.func ( any) bool {returnIsValue()}// DefaultParameterConverter is the default implementation of// [ValueConverter] that's used when a [Stmt] doesn't implement// [ColumnConverter].//// DefaultParameterConverter returns its argument directly if// IsValue(arg). Otherwise, if the argument implements [Valuer], its// Value method is used to return a [Value]. As a fallback, the provided// argument's underlying type is used to convert it to a [Value]:// underlying integer types are converted to int64, floats to float64,// bool, string, and []byte to themselves. If the argument is a nil// pointer, defaultConverter.ConvertValue returns a nil [Value].// If the argument is a non-nil pointer, it is dereferenced and// defaultConverter.ConvertValue is called recursively. Other types// are an error.varDefaultParameterConverterdefaultConvertertype defaultConverter struct{}var _ ValueConverter = defaultConverter{}var valuerReflectType = reflect.TypeFor[Valuer]()// callValuerValue returns vr.Value(), with one exception:// If vr.Value is an auto-generated method on a pointer type and the// pointer is nil, it would panic at runtime in the panicwrap// method. Treat it like nil instead.// Issue 8415.//// This is so people can implement driver.Value on value types and// still use nil pointers to those types to mean nil/NULL, just like// string/*string.//// This function is mirrored in the database/sql package.func callValuerValue( Valuer) ( Value, error) {if := reflect.ValueOf(); .Kind() == reflect.Pointer && .IsNil() && .Type().Elem().Implements(valuerReflectType) {returnnil, nil }return .Value()}func (defaultConverter) ( any) (Value, error) {ifIsValue() {return , nil }switch vr := .(type) {caseValuer: , := callValuerValue()if != nil {returnnil, }if !IsValue() {returnnil, fmt.Errorf("non-Value type %T returned from Value", ) }return , nil// For now, continue to prefer the Valuer interface over the decimal decompose interface.casedecimalDecompose:return , nil } := reflect.ValueOf()switch .Kind() {casereflect.Pointer:// indirect pointersif .IsNil() {returnnil, nil } else {returndefaultConverter{}.(.Elem().Interface()) }casereflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:return .Int(), nilcasereflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:returnint64(.Uint()), nilcasereflect.Uint64: := .Uint()if >= 1<<63 {returnnil, fmt.Errorf("uint64 values with high bit set are not supported") }returnint64(), nilcasereflect.Float32, reflect.Float64:return .Float(), nilcasereflect.Bool:return .Bool(), nilcasereflect.Slice: := .Type().Elem().Kind()if == reflect.Uint8 {return .Bytes(), nil }returnnil, fmt.Errorf("unsupported type %T, a slice of %s", , )casereflect.String:return .String(), nil }returnnil, fmt.Errorf("unsupported type %T, a %s", , .Kind())}type decimalDecompose interface {// Decompose returns the internal decimal state into parts. // If the provided buf has sufficient capacity, buf may be returned as the coefficient with // the value set and length set as appropriate. Decompose(buf []byte) (form byte, negative bool, coefficient []byte, exponent int32)}
The pages are generated with Goldsv0.7.0-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.