package mysql
import (
"context"
"database/sql/driver"
"net"
"os"
"strconv"
"strings"
)
type connector struct {
cfg *Config
encodedAttributes string
}
func encodeConnectionAttributes(cfg *Config ) string {
connAttrsBuf := make ([]byte , 0 )
connAttrsBuf = appendLengthEncodedString (connAttrsBuf , connAttrClientName )
connAttrsBuf = appendLengthEncodedString (connAttrsBuf , connAttrClientNameValue )
connAttrsBuf = appendLengthEncodedString (connAttrsBuf , connAttrOS )
connAttrsBuf = appendLengthEncodedString (connAttrsBuf , connAttrOSValue )
connAttrsBuf = appendLengthEncodedString (connAttrsBuf , connAttrPlatform )
connAttrsBuf = appendLengthEncodedString (connAttrsBuf , connAttrPlatformValue )
connAttrsBuf = appendLengthEncodedString (connAttrsBuf , connAttrPid )
connAttrsBuf = appendLengthEncodedString (connAttrsBuf , strconv .Itoa (os .Getpid ()))
serverHost , _ , _ := net .SplitHostPort (cfg .Addr )
if serverHost != "" {
connAttrsBuf = appendLengthEncodedString (connAttrsBuf , connAttrServerHost )
connAttrsBuf = appendLengthEncodedString (connAttrsBuf , serverHost )
}
for _ , connAttr := range strings .Split (cfg .ConnectionAttributes , "," ) {
k , v , found := strings .Cut (connAttr , ":" )
if !found {
continue
}
connAttrsBuf = appendLengthEncodedString (connAttrsBuf , k )
connAttrsBuf = appendLengthEncodedString (connAttrsBuf , v )
}
return string (connAttrsBuf )
}
func newConnector(cfg *Config ) *connector {
encodedAttributes := encodeConnectionAttributes (cfg )
return &connector {
cfg : cfg ,
encodedAttributes : encodedAttributes ,
}
}
func (c *connector ) Connect (ctx context .Context ) (driver .Conn , error ) {
var err error
cfg := c .cfg
if c .cfg .beforeConnect != nil {
cfg = c .cfg .Clone ()
err = c .cfg .beforeConnect (ctx , cfg )
if err != nil {
return nil , err
}
}
mc := &mysqlConn {
maxAllowedPacket : maxPacketSize ,
maxWriteSize : maxPacketSize - 1 ,
closech : make (chan struct {}),
cfg : cfg ,
connector : c ,
}
mc .parseTime = mc .cfg .ParseTime
dialsLock .RLock ()
dial , ok := dials [mc .cfg .Net ]
dialsLock .RUnlock ()
if ok {
dctx := ctx
if mc .cfg .Timeout > 0 {
var cancel context .CancelFunc
dctx , cancel = context .WithTimeout (ctx , c .cfg .Timeout )
defer cancel ()
}
mc .netConn , err = dial (dctx , mc .cfg .Addr )
} else {
nd := net .Dialer {Timeout : mc .cfg .Timeout }
mc .netConn , err = nd .DialContext (ctx , mc .cfg .Net , mc .cfg .Addr )
}
if err != nil {
return nil , err
}
mc .rawConn = mc .netConn
if tc , ok := mc .netConn .(*net .TCPConn ); ok {
if err := tc .SetKeepAlive (true ); err != nil {
c .cfg .Logger .Print (err )
}
}
mc .startWatcher ()
if err := mc .watchCancel (ctx ); err != nil {
mc .cleanup ()
return nil , err
}
defer mc .finish ()
mc .buf = newBuffer (mc .netConn )
mc .buf .timeout = mc .cfg .ReadTimeout
mc .writeTimeout = mc .cfg .WriteTimeout
authData , plugin , err := mc .readHandshakePacket ()
if err != nil {
mc .cleanup ()
return nil , err
}
if plugin == "" {
plugin = defaultAuthPlugin
}
authResp , err := mc .auth (authData , plugin )
if err != nil {
c .cfg .Logger .Print ("could not use requested auth plugin '" +plugin +"': " , err .Error())
plugin = defaultAuthPlugin
authResp , err = mc .auth (authData , plugin )
if err != nil {
mc .cleanup ()
return nil , err
}
}
if err = mc .writeHandshakeResponsePacket (authResp , plugin ); err != nil {
mc .cleanup ()
return nil , err
}
if err = mc .handleAuthResult (authData , plugin ); err != nil {
mc .cleanup ()
return nil , err
}
if mc .cfg .MaxAllowedPacket > 0 {
mc .maxAllowedPacket = mc .cfg .MaxAllowedPacket
} else {
maxap , err := mc .getSystemVar ("max_allowed_packet" )
if err != nil {
mc .Close ()
return nil , err
}
mc .maxAllowedPacket = stringToInt (maxap ) - 1
}
if mc .maxAllowedPacket < maxPacketSize {
mc .maxWriteSize = mc .maxAllowedPacket
}
err = mc .handleParams ()
if err != nil {
mc .Close ()
return nil , err
}
return mc , nil
}
func (c *connector ) Driver () driver .Driver {
return &MySQLDriver {}
}
The pages are generated with Golds v0.8.2 . (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 .