From 4a32ba54562c16440f417d1a7f8907f4e676dfa5 Mon Sep 17 00:00:00 2001 From: Evan Shaw Date: Mon, 3 Apr 2017 11:13:44 +1200 Subject: [PATCH 1/3] Implement driver.Pinger The Pinger interface was added in Go 1.8. This implementation ignores the context parameter to Ping. --- connection_go18.go | 11 +++++++++++ driver_go18_test.go | 17 +++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 connection_go18.go diff --git a/connection_go18.go b/connection_go18.go new file mode 100644 index 000000000..848d9449f --- /dev/null +++ b/connection_go18.go @@ -0,0 +1,11 @@ +// +build go1.8 + +package mysql + +import ( + "context" +) + +func (mc *mysqlConn) Ping(ctx context.Context) error { + return mc.writeCommandPacket(comPing) +} diff --git a/driver_go18_test.go b/driver_go18_test.go index 93918ad46..3792ead38 100644 --- a/driver_go18_test.go +++ b/driver_go18_test.go @@ -3,7 +3,9 @@ package mysql import ( + "context" "database/sql" + "database/sql/driver" "fmt" "reflect" "testing" @@ -188,3 +190,18 @@ func TestSkipResults(t *testing.T) { } }) } + +func TestPing(t *testing.T) { + runTests(t, dsn, func(dbt *DBTest) { + mysqlDriver := dbt.db.Driver().(driver.Driver) + conn, err := mysqlDriver.Open(dsn) + if err != nil { + dbt.Fatalf("error opening conn: %s", err) + } + pinger := conn.(driver.Pinger) + err = pinger.Ping(context.Background()) + if err != nil { + dbt.Fatalf("error on ping: %s", err) + } + }) +} From 6b890cc94f738cbbfeacfb7e654384209e580142 Mon Sep 17 00:00:00 2001 From: Evan Shaw Date: Tue, 4 Apr 2017 14:48:33 +1200 Subject: [PATCH 2/3] Ping reads its result; obeys the context's Done channel --- connection_go18.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/connection_go18.go b/connection_go18.go index 848d9449f..8dcd7f640 100644 --- a/connection_go18.go +++ b/connection_go18.go @@ -7,5 +7,18 @@ import ( ) func (mc *mysqlConn) Ping(ctx context.Context) error { - return mc.writeCommandPacket(comPing) + err := mc.writeCommandPacket(comPing) + if err != nil { + return err + } + + select { + case <-ctx.Done(): + mc.Close() + return ctx.Err() + default: + } + + _, err = mc.readResultOK() + return err } From 093e4588f001778fdf1543206868cd6a3701ea3c Mon Sep 17 00:00:00 2001 From: Evan Shaw Date: Fri, 7 Apr 2017 13:13:21 +1200 Subject: [PATCH 3/3] Ping can cancel while waiting for a response --- connection_go18.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/connection_go18.go b/connection_go18.go index 8dcd7f640..51e9ce27c 100644 --- a/connection_go18.go +++ b/connection_go18.go @@ -4,6 +4,7 @@ package mysql import ( "context" + "time" ) func (mc *mysqlConn) Ping(ctx context.Context) error { @@ -12,13 +13,16 @@ func (mc *mysqlConn) Ping(ctx context.Context) error { return err } + ch := make(chan error) + go func() { + _, err := mc.readResultOK() + ch <- err + }() select { case <-ctx.Done(): - mc.Close() + mc.netConn.SetReadDeadline(time.Now()) return ctx.Err() - default: + case err := <-ch: + return err } - - _, err = mc.readResultOK() - return err }