OSDN Git Service

Merge pull request #201 from Bytom/v0.1
[bytom/vapor.git] / vendor / github.com / go-sql-driver / mysql / driver.go
diff --git a/vendor/github.com/go-sql-driver/mysql/driver.go b/vendor/github.com/go-sql-driver/mysql/driver.go
new file mode 100644 (file)
index 0000000..ba12978
--- /dev/null
@@ -0,0 +1,165 @@
+// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// Package mysql provides a MySQL driver for Go's database/sql package.
+//
+// The driver should be used via the database/sql package:
+//
+//  import "database/sql"
+//  import _ "github.com/go-sql-driver/mysql"
+//
+//  db, err := sql.Open("mysql", "user:password@/dbname")
+//
+// See https://github.com/go-sql-driver/mysql#usage for details
+package mysql
+
+import (
+       "database/sql"
+       "database/sql/driver"
+       "net"
+       "sync"
+)
+
+// MySQLDriver is exported to make the driver directly accessible.
+// In general the driver is used via the database/sql package.
+type MySQLDriver struct{}
+
+// DialFunc is a function which can be used to establish the network connection.
+// Custom dial functions must be registered with RegisterDial
+type DialFunc func(addr string) (net.Conn, error)
+
+var (
+       dialsLock sync.RWMutex
+       dials     map[string]DialFunc
+)
+
+// RegisterDial registers a custom dial function. It can then be used by the
+// network address mynet(addr), where mynet is the registered new network.
+// addr is passed as a parameter to the dial function.
+func RegisterDial(net string, dial DialFunc) {
+       dialsLock.Lock()
+       defer dialsLock.Unlock()
+       if dials == nil {
+               dials = make(map[string]DialFunc)
+       }
+       dials[net] = dial
+}
+
+// Open new Connection.
+// See https://github.com/go-sql-driver/mysql#dsn-data-source-name for how
+// the DSN string is formated
+func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
+       var err error
+
+       // New mysqlConn
+       mc := &mysqlConn{
+               maxAllowedPacket: maxPacketSize,
+               maxWriteSize:     maxPacketSize - 1,
+               closech:          make(chan struct{}),
+       }
+       mc.cfg, err = ParseDSN(dsn)
+       if err != nil {
+               return nil, err
+       }
+       mc.parseTime = mc.cfg.ParseTime
+
+       // Connect to Server
+       dialsLock.RLock()
+       dial, ok := dials[mc.cfg.Net]
+       dialsLock.RUnlock()
+       if ok {
+               mc.netConn, err = dial(mc.cfg.Addr)
+       } else {
+               nd := net.Dialer{Timeout: mc.cfg.Timeout}
+               mc.netConn, err = nd.Dial(mc.cfg.Net, mc.cfg.Addr)
+       }
+       if err != nil {
+               return nil, err
+       }
+
+       // Enable TCP Keepalives on TCP connections
+       if tc, ok := mc.netConn.(*net.TCPConn); ok {
+               if err := tc.SetKeepAlive(true); err != nil {
+                       // Don't send COM_QUIT before handshake.
+                       mc.netConn.Close()
+                       mc.netConn = nil
+                       return nil, err
+               }
+       }
+
+       // Call startWatcher for context support (From Go 1.8)
+       mc.startWatcher()
+
+       mc.buf = newBuffer(mc.netConn)
+
+       // Set I/O timeouts
+       mc.buf.timeout = mc.cfg.ReadTimeout
+       mc.writeTimeout = mc.cfg.WriteTimeout
+
+       // Reading Handshake Initialization Packet
+       authData, plugin, err := mc.readHandshakePacket()
+       if err != nil {
+               mc.cleanup()
+               return nil, err
+       }
+       if plugin == "" {
+               plugin = defaultAuthPlugin
+       }
+
+       // Send Client Authentication Packet
+       authResp, addNUL, err := mc.auth(authData, plugin)
+       if err != nil {
+               // try the default auth plugin, if using the requested plugin failed
+               errLog.Print("could not use requested auth plugin '"+plugin+"': ", err.Error())
+               plugin = defaultAuthPlugin
+               authResp, addNUL, err = mc.auth(authData, plugin)
+               if err != nil {
+                       mc.cleanup()
+                       return nil, err
+               }
+       }
+       if err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin); err != nil {
+               mc.cleanup()
+               return nil, err
+       }
+
+       // Handle response to auth packet, switch methods if possible
+       if err = mc.handleAuthResult(authData, plugin); err != nil {
+               // Authentication failed and MySQL has already closed the connection
+               // (https://dev.mysql.com/doc/internals/en/authentication-fails.html).
+               // Do not send COM_QUIT, just cleanup and return the error.
+               mc.cleanup()
+               return nil, err
+       }
+
+       if mc.cfg.MaxAllowedPacket > 0 {
+               mc.maxAllowedPacket = mc.cfg.MaxAllowedPacket
+       } else {
+               // Get max allowed packet size
+               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
+       }
+
+       // Handle DSN Params
+       err = mc.handleParams()
+       if err != nil {
+               mc.Close()
+               return nil, err
+       }
+
+       return mc, nil
+}
+
+func init() {
+       sql.Register("mysql", &MySQLDriver{})
+}