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  }