From ca1671a04ab68fe914ebf0f77c28feba14886b5d Mon Sep 17 00:00:00 2001
From: Ichinose Shogo <shogo82148@gmail.com>
Date: Sat, 7 Apr 2018 15:38:14 +0900
Subject: [PATCH 01/14] Implement Connector and DriverContext interface

---
 connector.go         | 126 +++++++++++++++++++++++++++++++++++++++++++
 driver_go110.go      |  27 ++++++++++
 driver_go110_test.go |  15 ++++++
 3 files changed, 168 insertions(+)
 create mode 100644 connector.go
 create mode 100644 driver_go110.go
 create mode 100644 driver_go110_test.go

diff --git a/connector.go b/connector.go
new file mode 100644
index 000000000..d96edcf32
--- /dev/null
+++ b/connector.go
@@ -0,0 +1,126 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// 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/.
+
+// +build go1.10
+
+package mysql
+
+import (
+	"context"
+	"database/sql/driver"
+	"net"
+)
+
+// Connector is a driver in a fixed configuration.
+type Connector struct {
+	Config *Config
+}
+
+// Connect implements driver.Connector interface.
+// Connect returns a connection to the database.
+func (c Connector) Connect(ctx context.Context) (driver.Conn, error) {
+	var err error
+
+	// New mysqlConn
+	mc := &mysqlConn{
+		maxAllowedPacket: maxPacketSize,
+		maxWriteSize:     maxPacketSize - 1,
+		closech:          make(chan struct{}),
+		cfg:              c.Config,
+	}
+	mc.parseTime = mc.cfg.ParseTime
+
+	// Connect to Server
+	// TODO: needs RegisterDialContext
+	if dial, ok := dials[mc.cfg.Net]; ok {
+		mc.netConn, err = dial(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
+	}
+
+	// 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)
+	if s, ok := interface{}(mc).(watcher); ok {
+		s.startWatcher()
+	}
+	if err := mc.watchCancel(ctx); err != nil {
+		return nil, err
+	}
+	defer mc.finish()
+
+	mc.buf = newBuffer(mc.netConn)
+
+	// Set I/O timeouts
+	mc.buf.timeout = mc.cfg.ReadTimeout
+	mc.writeTimeout = mc.cfg.WriteTimeout
+
+	// Reading Handshake Initialization Packet
+	cipher, err := mc.readInitPacket()
+	if err != nil {
+		mc.cleanup()
+		return nil, err
+	}
+
+	// Send Client Authentication Packet
+	if err = mc.writeAuthPacket(cipher); err != nil {
+		mc.cleanup()
+		return nil, err
+	}
+
+	// Handle response to auth packet, switch methods if possible
+	if err = handleAuthResult(mc, cipher); 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
+}
+
+// Driver implements driver.Connector interface.
+// Driver returns &MySQLDriver{}.
+func (c Connector) Driver() driver.Driver {
+	return &MySQLDriver{}
+}
diff --git a/driver_go110.go b/driver_go110.go
new file mode 100644
index 000000000..5389e3107
--- /dev/null
+++ b/driver_go110.go
@@ -0,0 +1,27 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// 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/.
+
+// +build go1.10
+
+package mysql
+
+import (
+	"database/sql/driver"
+)
+
+// OpenConnector implements driver.DriverContext.
+func (d MySQLDriver) OpenConnector(dsn string) (driver.Connector, error) {
+	c, err := ParseDSN(dsn)
+	if err != nil {
+		return nil, err
+	}
+
+	return Connector{
+		Config: c,
+	}, nil
+}
diff --git a/driver_go110_test.go b/driver_go110_test.go
new file mode 100644
index 000000000..daa47bae6
--- /dev/null
+++ b/driver_go110_test.go
@@ -0,0 +1,15 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2013 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
+
+import (
+	"database/sql/driver"
+)
+
+var _ driver.DriverContext = &MySQLDriver{}

From ccd26221cb6abfc712c15d479695faa8684b7b61 Mon Sep 17 00:00:00 2001
From: Ichinose Shogo <shogo82148@gmail.com>
Date: Sat, 7 Apr 2018 15:48:34 +0900
Subject: [PATCH 02/14] no need to check the driver implements the watcher
 interface.

because Connector.Connect is built with Go1.10 or higher.
---
 connector.go | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/connector.go b/connector.go
index d96edcf32..95af2faf7 100644
--- a/connector.go
+++ b/connector.go
@@ -58,9 +58,7 @@ func (c Connector) Connect(ctx context.Context) (driver.Conn, error) {
 	}
 
 	// Call startWatcher for context support (From Go 1.8)
-	if s, ok := interface{}(mc).(watcher); ok {
-		s.startWatcher()
-	}
+	mc.startWatcher()
 	if err := mc.watchCancel(ctx); err != nil {
 		return nil, err
 	}

From cc53a93b7a7352ab0561a5803fc21ca5f5ee4f5b Mon Sep 17 00:00:00 2001
From: Ichinose Shogo <shogo82148@gmail.com>
Date: Sat, 7 Apr 2018 15:51:25 +0900
Subject: [PATCH 03/14] add missing build tag.

---
 driver_go110_test.go | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/driver_go110_test.go b/driver_go110_test.go
index daa47bae6..8ac834f33 100644
--- a/driver_go110_test.go
+++ b/driver_go110_test.go
@@ -6,6 +6,8 @@
 // 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/.
 
+// +build go1.10
+
 package mysql
 
 import (

From 877ae16b36f6e6dd6fcd710960e951fb76130f05 Mon Sep 17 00:00:00 2001
From: Ichinose Shogo <shogo82148@gmail.com>
Date: Sat, 16 Jun 2018 19:07:53 +0900
Subject: [PATCH 04/14] Rename new files.

because the Go toolchain has special support for this naming scheme.
---
 connector.go => connector_go1.10.go           | 9 +++++----
 driver_go110_test.go => driver_go1.10_test.go | 4 +---
 2 files changed, 6 insertions(+), 7 deletions(-)
 rename connector.go => connector_go1.10.go (95%)
 rename driver_go110_test.go => driver_go1.10_test.go (81%)

diff --git a/connector.go b/connector_go1.10.go
similarity index 95%
rename from connector.go
rename to connector_go1.10.go
index 95af2faf7..4357ec3d9 100644
--- a/connector.go
+++ b/connector_go1.10.go
@@ -1,13 +1,11 @@
 // Go MySQL Driver - A MySQL-Driver for Go's database/sql package
 //
-// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
+// Copyright 2018 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/.
 
-// +build go1.10
-
 package mysql
 
 import (
@@ -37,7 +35,10 @@ func (c Connector) Connect(ctx context.Context) (driver.Conn, error) {
 
 	// Connect to Server
 	// TODO: needs RegisterDialContext
-	if dial, ok := dials[mc.cfg.Net]; ok {
+	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}
diff --git a/driver_go110_test.go b/driver_go1.10_test.go
similarity index 81%
rename from driver_go110_test.go
rename to driver_go1.10_test.go
index 8ac834f33..7641e4b61 100644
--- a/driver_go110_test.go
+++ b/driver_go1.10_test.go
@@ -1,13 +1,11 @@
 // Go MySQL Driver - A MySQL-Driver for Go's database/sql package
 //
-// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
+// Copyright 2018 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/.
 
-// +build go1.10
-
 package mysql
 
 import (

From 0aca26bcac8989a02fe2f484b99325cd2f4a0a70 Mon Sep 17 00:00:00 2001
From: Ichinose Shogo <shogo82148@gmail.com>
Date: Sat, 16 Jun 2018 19:12:11 +0900
Subject: [PATCH 05/14] move Connect to Config from Connector.

---
 connector_go1.10.go | 11 +++--------
 driver_go110.go     |  4 +---
 2 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/connector_go1.10.go b/connector_go1.10.go
index 4357ec3d9..90b1a86d6 100644
--- a/connector_go1.10.go
+++ b/connector_go1.10.go
@@ -14,14 +14,9 @@ import (
 	"net"
 )
 
-// Connector is a driver in a fixed configuration.
-type Connector struct {
-	Config *Config
-}
-
 // Connect implements driver.Connector interface.
 // Connect returns a connection to the database.
-func (c Connector) Connect(ctx context.Context) (driver.Conn, error) {
+func (c *Config) Connect(ctx context.Context) (driver.Conn, error) {
 	var err error
 
 	// New mysqlConn
@@ -29,7 +24,7 @@ func (c Connector) Connect(ctx context.Context) (driver.Conn, error) {
 		maxAllowedPacket: maxPacketSize,
 		maxWriteSize:     maxPacketSize - 1,
 		closech:          make(chan struct{}),
-		cfg:              c.Config,
+		cfg:              c,
 	}
 	mc.parseTime = mc.cfg.ParseTime
 
@@ -120,6 +115,6 @@ func (c Connector) Connect(ctx context.Context) (driver.Conn, error) {
 
 // Driver implements driver.Connector interface.
 // Driver returns &MySQLDriver{}.
-func (c Connector) Driver() driver.Driver {
+func (c *Config) Driver() driver.Driver {
 	return &MySQLDriver{}
 }
diff --git a/driver_go110.go b/driver_go110.go
index 5389e3107..4b2eff96d 100644
--- a/driver_go110.go
+++ b/driver_go110.go
@@ -21,7 +21,5 @@ func (d MySQLDriver) OpenConnector(dsn string) (driver.Connector, error) {
 		return nil, err
 	}
 
-	return Connector{
-		Config: c,
-	}, nil
+	return c, nil
 }

From cfaf043ea7a44f589a7501ccbc267187b312291b Mon Sep 17 00:00:00 2001
From: Ichinose Shogo <shogo82148@gmail.com>
Date: Sat, 16 Jun 2018 19:15:52 +0900
Subject: [PATCH 06/14] rename driver_go110.go

---
 driver_go110.go => driver_go1.10.go | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
 rename driver_go110.go => driver_go1.10.go (86%)

diff --git a/driver_go110.go b/driver_go1.10.go
similarity index 86%
rename from driver_go110.go
rename to driver_go1.10.go
index 4b2eff96d..ef3392dc0 100644
--- a/driver_go110.go
+++ b/driver_go1.10.go
@@ -1,13 +1,11 @@
 // Go MySQL Driver - A MySQL-Driver for Go's database/sql package
 //
-// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
+// Copyright 2018 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/.
 
-// +build go1.10
-
 package mysql
 
 import (

From 49e248029a3ed1958a80ae7dfd199851e0447652 Mon Sep 17 00:00:00 2001
From: Ichinose Shogo <shogo82148@gmail.com>
Date: Sat, 16 Jun 2018 19:31:12 +0900
Subject: [PATCH 07/14] fix broken build.

---
 connector_go1.10.go => connector_go1.8.go | 19 ++++++++++++++++---
 driver_go1.10.go                          |  2 ++
 driver_go1.10_test.go                     |  2 ++
 3 files changed, 20 insertions(+), 3 deletions(-)
 rename connector_go1.10.go => connector_go1.8.go (82%)

diff --git a/connector_go1.10.go b/connector_go1.8.go
similarity index 82%
rename from connector_go1.10.go
rename to connector_go1.8.go
index 90b1a86d6..a74642e80 100644
--- a/connector_go1.10.go
+++ b/connector_go1.8.go
@@ -6,6 +6,8 @@
 // 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/.
 
+// +build go1.8
+
 package mysql
 
 import (
@@ -67,20 +69,31 @@ func (c *Config) Connect(ctx context.Context) (driver.Conn, error) {
 	mc.writeTimeout = mc.cfg.WriteTimeout
 
 	// Reading Handshake Initialization Packet
-	cipher, err := mc.readInitPacket()
+	authData, plugin, err := mc.readHandshakePacket()
 	if err != nil {
 		mc.cleanup()
 		return nil, err
 	}
 
 	// Send Client Authentication Packet
-	if err = mc.writeAuthPacket(cipher); err != nil {
+	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 = handleAuthResult(mc, cipher); err != nil {
+	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.
diff --git a/driver_go1.10.go b/driver_go1.10.go
index ef3392dc0..2008df7a6 100644
--- a/driver_go1.10.go
+++ b/driver_go1.10.go
@@ -6,6 +6,8 @@
 // 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/.
 
+// +build go1.10
+
 package mysql
 
 import (
diff --git a/driver_go1.10_test.go b/driver_go1.10_test.go
index 7641e4b61..a9d784c52 100644
--- a/driver_go1.10_test.go
+++ b/driver_go1.10_test.go
@@ -6,6 +6,8 @@
 // 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/.
 
+// +build go1.10
+
 package mysql
 
 import (

From 82898e3c84ecb5c9618fa16a3264c5e897854083 Mon Sep 17 00:00:00 2001
From: Ichinose Shogo <shogo82148@gmail.com>
Date: Sat, 16 Jun 2018 20:04:25 +0900
Subject: [PATCH 08/14] simplify OpenConnector

---
 driver_go1.10.go | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/driver_go1.10.go b/driver_go1.10.go
index 2008df7a6..11b863a11 100644
--- a/driver_go1.10.go
+++ b/driver_go1.10.go
@@ -16,10 +16,5 @@ import (
 
 // OpenConnector implements driver.DriverContext.
 func (d MySQLDriver) OpenConnector(dsn string) (driver.Connector, error) {
-	c, err := ParseDSN(dsn)
-	if err != nil {
-		return nil, err
-	}
-
-	return c, nil
+	return ParseDSN(dsn)
 }

From ee66ae64098e2c98654d22574e54c3f278e3bed0 Mon Sep 17 00:00:00 2001
From: Ichinose Shogo <shogo82148@gmail.com>
Date: Sat, 16 Jun 2018 20:15:04 +0900
Subject: [PATCH 09/14] make `MySQLDriver.Open` more simple.

---
 connector_go1.8.go => connector.go |   6 +-
 driver.go                          | 105 +----------------------------
 2 files changed, 6 insertions(+), 105 deletions(-)
 rename connector_go1.8.go => connector.go (98%)

diff --git a/connector_go1.8.go b/connector.go
similarity index 98%
rename from connector_go1.8.go
rename to connector.go
index a74642e80..89c6cf7f0 100644
--- a/connector_go1.8.go
+++ b/connector.go
@@ -6,8 +6,6 @@
 // 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/.
 
-// +build go1.8
-
 package mysql
 
 import (
@@ -56,7 +54,9 @@ func (c *Config) Connect(ctx context.Context) (driver.Conn, error) {
 	}
 
 	// Call startWatcher for context support (From Go 1.8)
-	mc.startWatcher()
+	if s, ok := interface{}(mc).(watcher); ok {
+		s.startWatcher()
+	}
 	if err := mc.watchCancel(ctx); err != nil {
 		return nil, err
 	}
diff --git a/driver.go b/driver.go
index 1a75a16ec..b6063fef4 100644
--- a/driver.go
+++ b/driver.go
@@ -17,6 +17,7 @@
 package mysql
 
 import (
+	"context"
 	"database/sql"
 	"database/sql/driver"
 	"net"
@@ -57,111 +58,11 @@ func RegisterDial(net string, dial DialFunc) {
 // 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)
-	if s, ok := interface{}(mc).(watcher); ok {
-		s.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()
+	c, err := ParseDSN(dsn)
 	if err != nil {
-		mc.cleanup()
 		return nil, err
 	}
-
-	// 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
+	return c.Connect(context.Background())
 }
 
 func init() {

From 069b52996568a9c28916402d41ccc5f03399a3af Mon Sep 17 00:00:00 2001
From: Ichinose Shogo <shogo82148@gmail.com>
Date: Sat, 16 Jun 2018 20:23:56 +0900
Subject: [PATCH 10/14] fix broken build with Go 1.7

---
 connector.go | 8 ++++----
 driver.go    | 1 +
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/connector.go b/connector.go
index 89c6cf7f0..daa180734 100644
--- a/connector.go
+++ b/connector.go
@@ -56,11 +56,11 @@ func (c *Config) Connect(ctx context.Context) (driver.Conn, error) {
 	// Call startWatcher for context support (From Go 1.8)
 	if s, ok := interface{}(mc).(watcher); ok {
 		s.startWatcher()
+		if err := s.watchCancel(ctx); err != nil {
+			return nil, err
+		}
+		defer mc.finish()
 	}
-	if err := mc.watchCancel(ctx); err != nil {
-		return nil, err
-	}
-	defer mc.finish()
 
 	mc.buf = newBuffer(mc.netConn)
 
diff --git a/driver.go b/driver.go
index b6063fef4..7739ab584 100644
--- a/driver.go
+++ b/driver.go
@@ -27,6 +27,7 @@ import (
 // watcher interface is used for context support (From Go 1.8)
 type watcher interface {
 	startWatcher()
+	watchCancel(ctx context.Context) error
 }
 
 // MySQLDriver is exported to make the driver directly accessible.

From d081e4e80200d1bdfffe0c737789ebd2e18d2384 Mon Sep 17 00:00:00 2001
From: Ichinose Shogo <shogo82148@gmail.com>
Date: Wed, 20 Jun 2018 09:21:02 +0900
Subject: [PATCH 11/14] remove the watcher interface

---
 connector.go | 10 ++++------
 driver.go    |  6 ------
 2 files changed, 4 insertions(+), 12 deletions(-)

diff --git a/connector.go b/connector.go
index daa180734..a7d5b3f3f 100644
--- a/connector.go
+++ b/connector.go
@@ -54,13 +54,11 @@ func (c *Config) Connect(ctx context.Context) (driver.Conn, error) {
 	}
 
 	// Call startWatcher for context support (From Go 1.8)
-	if s, ok := interface{}(mc).(watcher); ok {
-		s.startWatcher()
-		if err := s.watchCancel(ctx); err != nil {
-			return nil, err
-		}
-		defer mc.finish()
+	mc.startWatcher()
+	if err := mc.watchCancel(ctx); err != nil {
+		return nil, err
 	}
+	defer mc.finish()
 
 	mc.buf = newBuffer(mc.netConn)
 
diff --git a/driver.go b/driver.go
index 7739ab584..9f1e486cb 100644
--- a/driver.go
+++ b/driver.go
@@ -24,12 +24,6 @@ import (
 	"sync"
 )
 
-// watcher interface is used for context support (From Go 1.8)
-type watcher interface {
-	startWatcher()
-	watchCancel(ctx context.Context) error
-}
-
 // MySQLDriver is exported to make the driver directly accessible.
 // In general the driver is used via the database/sql package.
 type MySQLDriver struct{}

From 40d78d5360212fe55f0c0807acc20c99c48a98a1 Mon Sep 17 00:00:00 2001
From: Ichinose Shogo <shogo82148@gmail.com>
Date: Mon, 29 Oct 2018 00:14:59 +0900
Subject: [PATCH 12/14] apply the chages of 7ac0064e

---
 connector.go | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/connector.go b/connector.go
index a7d5b3f3f..e4fd76f63 100644
--- a/connector.go
+++ b/connector.go
@@ -73,6 +73,10 @@ func (c *Config) Connect(ctx context.Context) (driver.Conn, error) {
 		return nil, err
 	}
 
+	if plugin == "" {
+		plugin = defaultAuthPlugin
+	}
+
 	// Send Client Authentication Packet
 	authResp, addNUL, err := mc.auth(authData, plugin)
 	if err != nil {

From 1b00bed8a76846fdd80bea1dd2d649448aa1cfdc Mon Sep 17 00:00:00 2001
From: Ichinose Shogo <shogo82148@gmail.com>
Date: Tue, 30 Oct 2018 08:23:46 +0900
Subject: [PATCH 13/14] add the connetor struct

---
 connector.go     | 10 +++++++---
 driver.go        |  5 ++++-
 driver_go1.10.go |  8 +++++++-
 3 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/connector.go b/connector.go
index e4fd76f63..876ad976d 100644
--- a/connector.go
+++ b/connector.go
@@ -14,9 +14,13 @@ import (
 	"net"
 )
 
+type connector struct {
+	cfg *Config // immutable private copy.
+}
+
 // Connect implements driver.Connector interface.
 // Connect returns a connection to the database.
-func (c *Config) Connect(ctx context.Context) (driver.Conn, error) {
+func (c *connector) Connect(ctx context.Context) (driver.Conn, error) {
 	var err error
 
 	// New mysqlConn
@@ -24,7 +28,7 @@ func (c *Config) Connect(ctx context.Context) (driver.Conn, error) {
 		maxAllowedPacket: maxPacketSize,
 		maxWriteSize:     maxPacketSize - 1,
 		closech:          make(chan struct{}),
-		cfg:              c,
+		cfg:              c.cfg,
 	}
 	mc.parseTime = mc.cfg.ParseTime
 
@@ -130,6 +134,6 @@ func (c *Config) Connect(ctx context.Context) (driver.Conn, error) {
 
 // Driver implements driver.Connector interface.
 // Driver returns &MySQLDriver{}.
-func (c *Config) Driver() driver.Driver {
+func (c *connector) Driver() driver.Driver {
 	return &MySQLDriver{}
 }
diff --git a/driver.go b/driver.go
index 9f1e486cb..c986f1052 100644
--- a/driver.go
+++ b/driver.go
@@ -53,10 +53,13 @@ func RegisterDial(net string, dial DialFunc) {
 // 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) {
-	c, err := ParseDSN(dsn)
+	cfg, err := ParseDSN(dsn)
 	if err != nil {
 		return nil, err
 	}
+	c := &connector{
+		cfg: cfg,
+	}
 	return c.Connect(context.Background())
 }
 
diff --git a/driver_go1.10.go b/driver_go1.10.go
index 11b863a11..9669a4f01 100644
--- a/driver_go1.10.go
+++ b/driver_go1.10.go
@@ -16,5 +16,11 @@ import (
 
 // OpenConnector implements driver.DriverContext.
 func (d MySQLDriver) OpenConnector(dsn string) (driver.Connector, error) {
-	return ParseDSN(dsn)
+	cfg, err := ParseDSN(dsn)
+	if err != nil {
+		return nil, err
+	}
+	return &connector{
+		cfg: cfg,
+	}, nil
 }

From 255f9886a5b8e006949d618de10bba07f6055722 Mon Sep 17 00:00:00 2001
From: Ichinose Shogo <shogo82148@gmail.com>
Date: Tue, 30 Oct 2018 08:41:14 +0900
Subject: [PATCH 14/14] add NewConnector

---
 driver_go1.10.go | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/driver_go1.10.go b/driver_go1.10.go
index 9669a4f01..b0ee134bd 100644
--- a/driver_go1.10.go
+++ b/driver_go1.10.go
@@ -11,9 +11,28 @@
 package mysql
 
 import (
+	"crypto/rsa"
 	"database/sql/driver"
+	"math/big"
 )
 
+// NewConnector returns new driver.Connector.
+func NewConnector(cfg *Config) driver.Connector {
+	copyCfg := *cfg
+	copyCfg.tls = cfg.tls.Clone()
+	copyCfg.Params = make(map[string]string, len(cfg.Params))
+	for k, v := range cfg.Params {
+		copyCfg.Params[k] = v
+	}
+	if cfg.pubKey != nil {
+		copyCfg.pubKey = &rsa.PublicKey{
+			N: new(big.Int).Set(cfg.pubKey.N),
+			E: cfg.pubKey.E,
+		}
+	}
+	return &connector{cfg: &copyCfg}
+}
+
 // OpenConnector implements driver.DriverContext.
 func (d MySQLDriver) OpenConnector(dsn string) (driver.Connector, error) {
 	cfg, err := ParseDSN(dsn)