github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/go-sql-driver/mysql/connector.go (about) 1 // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 // 3 // Copyright 2018 The Go-MySQL-Driver Authors. All rights reserved. 4 // 5 // This Source Code Form is subject to the terms of the Mozilla Public 6 // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 // You can obtain one at http://mozilla.org/MPL/2.0/. 8 9 package mysql 10 11 import ( 12 "context" 13 "database/sql/driver" 14 "net" 15 ) 16 17 type connector struct { 18 cfg *Config // immutable private copy. 19 } 20 21 // Connect implements driver.Connector interface. 22 // Connect returns a connection to the database. 23 func (c *connector) Connect(ctx context.Context) (driver.Conn, error) { 24 var err error 25 26 // New mysqlConn 27 mc := &mysqlConn{ 28 maxAllowedPacket: maxPacketSize, 29 maxWriteSize: maxPacketSize - 1, 30 closech: make(chan struct{}), 31 cfg: c.cfg, 32 } 33 mc.parseTime = mc.cfg.ParseTime 34 35 // Connect to Server 36 dialsLock.RLock() 37 dial, ok := dials[mc.cfg.Net] 38 dialsLock.RUnlock() 39 if ok { 40 mc.netConn, err = dial(ctx, mc.cfg.Addr) 41 } else { 42 nd := net.Dialer{Timeout: mc.cfg.Timeout} 43 mc.netConn, err = nd.DialContext(ctx, mc.cfg.Net, mc.cfg.Addr) 44 } 45 46 if err != nil { 47 if nerr, ok := err.(net.Error); ok && nerr.Temporary() { 48 errLog.Print("net.Error from Dial()': ", nerr.Error()) 49 return nil, driver.ErrBadConn 50 } 51 return nil, err 52 } 53 54 // Enable TCP Keepalives on TCP connections 55 if tc, ok := mc.netConn.(*net.TCPConn); ok { 56 if err := tc.SetKeepAlive(true); err != nil { 57 // Don't send COM_QUIT before handshake. 58 mc.netConn.Close() 59 mc.netConn = nil 60 return nil, err 61 } 62 } 63 64 // Call startWatcher for context support (From Go 1.8) 65 mc.startWatcher() 66 if err := mc.watchCancel(ctx); err != nil { 67 return nil, err 68 } 69 defer mc.finish() 70 71 mc.buf = newBuffer(mc.netConn) 72 73 // Set I/O timeouts 74 mc.buf.timeout = mc.cfg.ReadTimeout 75 mc.writeTimeout = mc.cfg.WriteTimeout 76 77 // Reading Handshake Initialization Packet 78 authData, plugin, err := mc.readHandshakePacket() 79 if err != nil { 80 mc.cleanup() 81 return nil, err 82 } 83 84 if plugin == "" { 85 plugin = defaultAuthPlugin 86 } 87 88 // Send Client Authentication Packet 89 authResp, err := mc.auth(authData, plugin) 90 if err != nil { 91 // try the default auth plugin, if using the requested plugin failed 92 errLog.Print("could not use requested auth plugin '"+plugin+"': ", err.Error()) 93 plugin = defaultAuthPlugin 94 authResp, err = mc.auth(authData, plugin) 95 if err != nil { 96 mc.cleanup() 97 return nil, err 98 } 99 } 100 if err = mc.writeHandshakeResponsePacket(authResp, plugin); err != nil { 101 mc.cleanup() 102 return nil, err 103 } 104 105 // Handle response to auth packet, switch methods if possible 106 if err = mc.handleAuthResult(authData, plugin); err != nil { 107 // Authentication failed and MySQL has already closed the connection 108 // (https://dev.mysql.com/doc/internals/en/authentication-fails.html). 109 // Do not send COM_QUIT, just cleanup and return the error. 110 mc.cleanup() 111 return nil, err 112 } 113 114 if mc.cfg.MaxAllowedPacket > 0 { 115 mc.maxAllowedPacket = mc.cfg.MaxAllowedPacket 116 } else { 117 // Get max allowed packet size 118 maxap, err := mc.getSystemVar("max_allowed_packet") 119 if err != nil { 120 mc.Close() 121 return nil, err 122 } 123 mc.maxAllowedPacket = stringToInt(maxap) - 1 124 } 125 if mc.maxAllowedPacket < maxPacketSize { 126 mc.maxWriteSize = mc.maxAllowedPacket 127 } 128 129 // Handle DSN Params 130 err = mc.handleParams() 131 if err != nil { 132 mc.Close() 133 return nil, err 134 } 135 136 return mc, nil 137 } 138 139 // Driver implements driver.Connector interface. 140 // Driver returns &MySQLDriver{}. 141 func (c *connector) Driver() driver.Driver { 142 return &MySQLDriver{} 143 }