// 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 (
	
	
	
	
	
	
	
	
	
	_  // for linkname
)

var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error

func describeNamedValue( *driver.NamedValue) string {
	if len(.Name) == 0 {
		return fmt.Sprintf("$%d", .Ordinal)
	}
	return fmt.Sprintf("with name %q", .Name)
}

func validateNamedValueName( string) error {
	if len() == 0 {
		return nil
	}
	,  := utf8.DecodeRuneInString()
	if unicode.IsLetter() {
		return nil
	}
	return fmt.Errorf("name %q does not begin with a letter", )
}

// ccChecker wraps the driver.ColumnConverter and allows it to be used
// as if it were a NamedValueChecker. If the driver ColumnConverter
// is not present then the NamedValueChecker will return driver.ErrSkip.
type ccChecker struct {
	cci  driver.ColumnConverter
	want int
}

func ( ccChecker) ( *driver.NamedValue) error {
	if .cci == nil {
		return driver.ErrSkip
	}
	// The column converter shouldn't be called on any index
	// it isn't expecting. The final error will be thrown
	// in the argument converter loop.
	 := .Ordinal - 1
	if .want <=  {
		return nil
	}

	// 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 ,  := .Value.(driver.Valuer);  {
		,  := callValuerValue()
		if  != nil {
			return 
		}
		if !driver.IsValue() {
			return fmt.Errorf("non-subset type %T returned from Value", )
		}
		.Value = 
	}

	// 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  error
	 := .Value
	.Value,  = .cci.ColumnConverter().ConvertValue()
	if  != nil {
		return 
	}
	if !driver.IsValue(.Value) {
		return fmt.Errorf("driver ColumnConverter error converted %T to unsupported type %T", , .Value)
	}
	return nil
}

// defaultCheckNamedValue wraps the default ColumnConverter to have the same
// function signature as the CheckNamedValue in the driver.NamedValueChecker
// interface.
func defaultCheckNamedValue( *driver.NamedValue) ( error) {
	.Value,  = driver.DefaultParameterConverter.ConvertValue(.Value)
	return 
}

// driverArgsConnLocked converts arguments from callers of Stmt.Exec and
// Stmt.Query into driver Values.
//
// The statement ds may be nil, if no statement is available.
//
// ci must be locked.
func driverArgsConnLocked( driver.Conn,  *driverStmt,  []any) ([]driver.NamedValue, error) {
	 := make([]driver.NamedValue, len())

	// -1 means the driver doesn't know how to count the number of
	// placeholders, so we won't sanity check input here and instead let the
	// driver deal with errors.
	 := -1

	var  driver.Stmt
	var  ccChecker
	if  != nil {
		 = .si
		 = .si.NumInput()
		.want = 
	}

	// Check all types of interfaces from the start.
	// Drivers may opt to use the NamedValueChecker for special
	// argument types, then return driver.ErrSkip to pass it along
	// to the column converter.
	,  := .(driver.NamedValueChecker)
	if ! {
		, _ = .(driver.NamedValueChecker)
	}
	,  := .(driver.ColumnConverter)
	if  {
		.cci = 
	}

	// Loop through all the arguments, checking each one.
	// If no error is returned simply increment the index
	// and continue. However, if driver.ErrRemoveArgument
	// is returned the argument is not included in the query
	// argument list.
	var  error
	var  int
	for ,  := range  {
		 := &[]
		if ,  := .(NamedArg);  {
			if  = validateNamedValueName(.Name);  != nil {
				return nil, 
			}
			 = .Value
			.Name = .Name
		}
		.Ordinal =  + 1
		.Value = 

		// Checking sequence has four routes:
		// A: 1. Default
		// B: 1. NamedValueChecker 2. Column Converter 3. Default
		// C: 1. NamedValueChecker 3. Default
		// D: 1. Column Converter 2. Default
		//
		// The only time a Column Converter is called is first
		// or after NamedValueConverter. If first it is handled before
		// the nextCheck label. Thus for repeats tries only when the
		// NamedValueConverter is selected should the Column Converter
		// be used in the retry.
		 := defaultCheckNamedValue
		 := false
		switch {
		case  != nil:
			 =  != nil
			 = .CheckNamedValue
		case  != nil:
			 = .CheckNamedValue
		}

	:
		 = ()
		switch  {
		case nil:
			++
			continue
		case driver.ErrRemoveArgument:
			 = [:len()-1]
			continue
		case driver.ErrSkip:
			if  {
				 = false
				 = .CheckNamedValue
			} else {
				 = defaultCheckNamedValue
			}
			goto 
		default:
			return nil, fmt.Errorf("sql: converting argument %s type: %w", describeNamedValue(), )
		}
	}

	// Check the length of arguments after conversion to allow for omitted
	// arguments.
	if  != -1 && len() !=  {
		return nil, fmt.Errorf("sql: expected %d arguments, got %d", , len())
	}

	return , nil
}

// convertAssign is the same as convertAssignRows, but without the optional
// rows argument.
//
// convertAssign should be an internal detail,
// but widely used packages access it using linkname.
// Notable members of the hall of shame include:
//   - ariga.io/entcache
//
// Do not remove or change the type signature.
// See go.dev/issue/67401.
//
//go:linkname convertAssign
func convertAssign(,  any) error {
	return convertAssignRows(, , nil)
}

// convertAssignRows 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. If rows is passed in, the rows will
// be used as the parent for any cursor values converted from a
// driver.Rows to a *Rows.
func convertAssignRows(,  any,  *Rows) error {
	// Common cases, without reflect.
	switch s := .(type) {
	case string:
		switch d := .(type) {
		case *string:
			if  == nil {
				return errNilPtr
			}
			* = 
			return nil
		case *[]byte:
			if  == nil {
				return errNilPtr
			}
			* = []byte()
			return nil
		case *RawBytes:
			if  == nil {
				return errNilPtr
			}
			* = .setrawbuf(append(.rawbuf(), ...))
			return nil
		}
	case []byte:
		switch d := .(type) {
		case *string:
			if  == nil {
				return errNilPtr
			}
			* = string()
			return nil
		case *any:
			if  == nil {
				return errNilPtr
			}
			* = bytes.Clone()
			return nil
		case *[]byte:
			if  == nil {
				return errNilPtr
			}
			* = bytes.Clone()
			return nil
		case *RawBytes:
			if  == nil {
				return errNilPtr
			}
			* = 
			return nil
		}
	case time.Time:
		switch d := .(type) {
		case *time.Time:
			* = 
			return nil
		case *string:
			* = .Format(time.RFC3339Nano)
			return nil
		case *[]byte:
			if  == nil {
				return errNilPtr
			}
			* = []byte(.Format(time.RFC3339Nano))
			return nil
		case *RawBytes:
			if  == nil {
				return errNilPtr
			}
			* = .setrawbuf(.AppendFormat(.rawbuf(), time.RFC3339Nano))
			return nil
		}
	case decimalDecompose:
		switch d := .(type) {
		case decimalCompose:
			return .Compose(.Decompose(nil))
		}
	case nil:
		switch d := .(type) {
		case *any:
			if  == nil {
				return errNilPtr
			}
			* = nil
			return nil
		case *[]byte:
			if  == nil {
				return errNilPtr
			}
			* = nil
			return nil
		case *RawBytes:
			if  == nil {
				return errNilPtr
			}
			* = nil
			return nil
		}
	// The driver is returning a cursor the client may iterate over.
	case driver.Rows:
		switch d := .(type) {
		case *Rows:
			if  == nil {
				return errNilPtr
			}
			if  == nil {
				return errors.New("invalid context to convert cursor rows, missing parent *Rows")
			}
			.closemu.Lock()
			* = Rows{
				dc:          .dc,
				releaseConn: func(error) {},
				rowsi:       ,
			}
			// Chain the cancel function.
			 := .cancel
			.cancel = func() {
				// When Rows.cancel is called, the closemu will be locked as well.
				// So we can access rs.lasterr.
				.close(.lasterr)
				if  != nil {
					()
				}
			}
			.closemu.Unlock()
			return nil
		}
	}

	var  reflect.Value

	switch d := .(type) {
	case *string:
		 = reflect.ValueOf()
		switch .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:
			* = asString()
			return nil
		}
	case *[]byte:
		 = reflect.ValueOf()
		if ,  := asBytes(nil, );  {
			* = 
			return nil
		}
	case *RawBytes:
		 = reflect.ValueOf()
		if ,  := asBytes(.rawbuf(), );  {
			* = .setrawbuf()
			return nil
		}
	case *bool:
		,  := driver.Bool.ConvertValue()
		if  == nil {
			* = .(bool)
		}
		return 
	case *any:
		* = 
		return nil
	}

	if ,  := .(Scanner);  {
		return .Scan()
	}

	 := reflect.ValueOf()
	if .Kind() != reflect.Pointer {
		return errors.New("destination not a pointer")
	}
	if .IsNil() {
		return errNilPtr
	}

	if !.IsValid() {
		 = reflect.ValueOf()
	}

	 := reflect.Indirect()
	if .IsValid() && .Type().AssignableTo(.Type()) {
		switch b := .(type) {
		case []byte:
			.Set(reflect.ValueOf(bytes.Clone()))
		default:
			.Set()
		}
		return nil
	}

	if .Kind() == .Kind() && .Type().ConvertibleTo(.Type()) {
		.Set(.Convert(.Type()))
		return nil
	}

	// The following conversions use a string value as an intermediate representation
	// to convert between various numeric types.
	//
	// This also allows scanning into user defined types such as "type Int int64".
	// For symmetry, also check for string destination types.
	switch .Kind() {
	case reflect.Pointer:
		if  == nil {
			.SetZero()
			return nil
		}
		.Set(reflect.New(.Type().Elem()))
		return (.Interface(), , )
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if  == nil {
			return fmt.Errorf("converting NULL to %s is unsupported", .Kind())
		}
		 := asString()
		,  := strconv.ParseInt(, 10, .Type().Bits())
		if  != nil {
			 = strconvErr()
			return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", , , .Kind(), )
		}
		.SetInt()
		return nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		if  == nil {
			return fmt.Errorf("converting NULL to %s is unsupported", .Kind())
		}
		 := asString()
		,  := strconv.ParseUint(, 10, .Type().Bits())
		if  != nil {
			 = strconvErr()
			return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", , , .Kind(), )
		}
		.SetUint()
		return nil
	case reflect.Float32, reflect.Float64:
		if  == nil {
			return fmt.Errorf("converting NULL to %s is unsupported", .Kind())
		}
		 := asString()
		,  := strconv.ParseFloat(, .Type().Bits())
		if  != nil {
			 = strconvErr()
			return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", , , .Kind(), )
		}
		.SetFloat()
		return nil
	case reflect.String:
		if  == nil {
			return fmt.Errorf("converting NULL to %s is unsupported", .Kind())
		}
		switch v := .(type) {
		case string:
			.SetString()
			return nil
		case []byte:
			.SetString(string())
			return nil
		}
	}

	return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", , )
}

func strconvErr( error) error {
	if ,  := .(*strconv.NumError);  {
		return .Err
	}
	return 
}

func asString( any) string {
	switch v := .(type) {
	case string:
		return 
	case []byte:
		return string()
	}
	 := reflect.ValueOf()
	switch .Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return strconv.FormatInt(.Int(), 10)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return strconv.FormatUint(.Uint(), 10)
	case reflect.Float64:
		return strconv.FormatFloat(.Float(), 'g', -1, 64)
	case reflect.Float32:
		return strconv.FormatFloat(.Float(), 'g', -1, 32)
	case reflect.Bool:
		return strconv.FormatBool(.Bool())
	}
	return fmt.Sprintf("%v", )
}

func asBytes( []byte,  reflect.Value) ( []byte,  bool) {
	switch .Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return strconv.AppendInt(, .Int(), 10), true
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return strconv.AppendUint(, .Uint(), 10), true
	case reflect.Float32:
		return strconv.AppendFloat(, .Float(), 'g', -1, 32), true
	case reflect.Float64:
		return strconv.AppendFloat(, .Float(), 'g', -1, 64), true
	case reflect.Bool:
		return strconv.AppendBool(, .Bool()), true
	case reflect.String:
		 := .String()
		return append(, ...), true
	}
	return
}

var valuerReflectType = reflect.TypeFor[driver.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/driver package.
func callValuerValue( driver.Valuer) ( driver.Value,  error) {
	if  := reflect.ValueOf(); .Kind() == reflect.Pointer &&
		.IsNil() &&
		.Type().Elem().Implements(valuerReflectType) {
		return nil, nil
	}
	return .Value()
}

// decimal composes or decomposes a decimal value to and from individual parts.
// There are four parts: a boolean negative flag, a form byte with three possible states
// (finite=0, infinite=1, NaN=2), a base-2 big-endian integer
// coefficient (also known as a significand) as a []byte, and an int32 exponent.
// These are composed into a final value as "decimal = (neg) (form=finite) coefficient * 10 ^ exponent".
// A zero length coefficient is a zero value.
// The big-endian integer coefficient stores the most significant byte first (at coefficient[0]).
// If the form is not finite the coefficient and exponent should be ignored.
// The negative parameter may be set to true for any form, although implementations are not required
// to respect the negative parameter in the non-finite form.
//
// Implementations may choose to set the negative parameter to true on a zero or NaN value,
// but implementations that do not differentiate between negative and positive
// zero or NaN values should ignore the negative parameter without error.
// If an implementation does not support Infinity it may be converted into a NaN without error.
// If a value is set that is larger than what is supported by an implementation,
// an error must be returned.
// Implementations must return an error if a NaN or Infinity is attempted to be set while neither
// are supported.
//
// NOTE(kardianos): This is an experimental interface. See https://golang.org/issue/30870
type decimal interface {
	decimalDecompose
	decimalCompose
}

type decimalDecompose interface {
	// Decompose returns the internal decimal state in 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)
}

type decimalCompose interface {
	// Compose sets the internal decimal value from parts. If the value cannot be
	// represented then an error should be returned.
	Compose(form byte, negative bool, coefficient []byte, exponent int32) error
}