package mysql
import (
"database/sql/driver"
"encoding/json"
"fmt"
"io"
"reflect"
)
type mysqlStmt struct {
mc *mysqlConn
id uint32
paramCount int
}
func (stmt *mysqlStmt ) Close () error {
if stmt .mc == nil || stmt .mc .closed .Load () {
return driver .ErrBadConn
}
err := stmt .mc .writeCommandPacketUint32 (comStmtClose , stmt .id )
stmt .mc = nil
return err
}
func (stmt *mysqlStmt ) NumInput () int {
return stmt .paramCount
}
func (stmt *mysqlStmt ) ColumnConverter (idx int ) driver .ValueConverter {
return converter {}
}
func (stmt *mysqlStmt ) CheckNamedValue (nv *driver .NamedValue ) (err error ) {
nv .Value , err = converter {}.ConvertValue (nv .Value )
return
}
func (stmt *mysqlStmt ) Exec (args []driver .Value ) (driver .Result , error ) {
if stmt .mc .closed .Load () {
errLog .Print (ErrInvalidConn )
return nil , driver .ErrBadConn
}
err := stmt .writeExecutePacket (args )
if err != nil {
return nil , stmt .mc .markBadConn (err )
}
mc := stmt .mc
mc .affectedRows = 0
mc .insertId = 0
resLen , err := mc .readResultSetHeaderPacket ()
if err != nil {
return nil , err
}
if resLen > 0 {
if err = mc .readUntilEOF (); err != nil {
return nil , err
}
if err := mc .readUntilEOF (); err != nil {
return nil , err
}
}
if err := mc .discardResults (); err != nil {
return nil , err
}
return &mysqlResult {
affectedRows : int64 (mc .affectedRows ),
insertId : int64 (mc .insertId ),
}, nil
}
func (stmt *mysqlStmt ) Query (args []driver .Value ) (driver .Rows , error ) {
return stmt .query (args )
}
func (stmt *mysqlStmt ) query (args []driver .Value ) (*binaryRows , error ) {
if stmt .mc .closed .Load () {
errLog .Print (ErrInvalidConn )
return nil , driver .ErrBadConn
}
err := stmt .writeExecutePacket (args )
if err != nil {
return nil , stmt .mc .markBadConn (err )
}
mc := stmt .mc
resLen , err := mc .readResultSetHeaderPacket ()
if err != nil {
return nil , err
}
rows := new (binaryRows )
if resLen > 0 {
rows .mc = mc
rows .rs .columns , err = mc .readColumns (resLen )
} else {
rows .rs .done = true
switch err := rows .NextResultSet (); err {
case nil , io .EOF :
return rows , nil
default :
return nil , err
}
}
return rows , err
}
var jsonType = reflect .TypeOf (json .RawMessage {})
type converter struct {}
func (c converter ) ConvertValue (v interface {}) (driver .Value , error ) {
if driver .IsValue (v ) {
return v , nil
}
if vr , ok := v .(driver .Valuer ); ok {
sv , err := callValuerValue (vr )
if err != nil {
return nil , err
}
if driver .IsValue (sv ) {
return sv , nil
}
if u , ok := sv .(uint64 ); ok {
return u , nil
}
return nil , fmt .Errorf ("non-Value type %T returned from Value" , sv )
}
rv := reflect .ValueOf (v )
switch rv .Kind () {
case reflect .Ptr :
if rv .IsNil () {
return nil , nil
} else {
return c .ConvertValue (rv .Elem ().Interface ())
}
case reflect .Int , reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 :
return rv .Int (), nil
case reflect .Uint , reflect .Uint8 , reflect .Uint16 , reflect .Uint32 , reflect .Uint64 :
return rv .Uint (), nil
case reflect .Float32 , reflect .Float64 :
return rv .Float (), nil
case reflect .Bool :
return rv .Bool (), nil
case reflect .Slice :
switch t := rv .Type (); {
case t == jsonType :
return v , nil
case t .Elem ().Kind () == reflect .Uint8 :
return rv .Bytes (), nil
default :
return nil , fmt .Errorf ("unsupported type %T, a slice of %s" , v , t .Elem ().Kind ())
}
case reflect .String :
return rv .String (), nil
}
return nil , fmt .Errorf ("unsupported type %T, a %s" , v , rv .Kind ())
}
var valuerReflectType = reflect .TypeOf ((*driver .Valuer )(nil )).Elem ()
func callValuerValue(vr driver .Valuer ) (v driver .Value , err error ) {
if rv := reflect .ValueOf (vr ); rv .Kind () == reflect .Ptr &&
rv .IsNil () &&
rv .Type ().Elem ().Implements (valuerReflectType ) {
return nil , nil
}
return vr .Value ()
}
The pages are generated with Golds v0.6.7 . (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 @Go100and1 (reachable from the left QR code) to get the latest news of Golds .