@@ -17,6 +17,7 @@ import (
1717 "net"
1818 "strconv"
1919 "strings"
20+ "sync/atomic"
2021 "time"
2122)
2223
@@ -45,7 +46,12 @@ type mysqlConn struct {
4546 closech chan struct {}
4647 finished chan <- struct {}
4748 canceled atomicError // set non-nil if conn is canceled
48- closed atomicBool // set when conn is closed, before closech is closed
49+ closed atomic.Bool // set when conn is closed, before closech is closed
50+ }
51+
52+ // Helper function to call per-connection logger.
53+ func (mc * mysqlConn ) log (v ... any ) {
54+ mc .cfg .Logger .Print (v ... )
4955}
5056
5157type packetReader interface {
@@ -133,6 +139,7 @@ func (mc *mysqlConn) Begin() (driver.Tx, error) {
133139
134140func (mc * mysqlConn ) begin (readOnly bool ) (driver.Tx , error ) {
135141 if mc .closed .Load () {
142+ mc .log (ErrInvalidConn )
136143 return nil , driver .ErrBadConn
137144 }
138145 var q string
@@ -155,6 +162,7 @@ func (mc *mysqlConn) Close() (err error) {
155162 }
156163
157164 mc .cleanup ()
165+ mc .clearResult ()
158166 return
159167}
160168
@@ -169,13 +177,16 @@ func (mc *mysqlConn) cleanup() {
169177
170178 // Makes cleanup idempotent
171179 close (mc .closech )
172- if mc .netConn == nil {
180+ conn := mc .rawConn
181+ if conn == nil {
173182 return
174183 }
175- if err := mc . netConn .Close (); err != nil {
184+ if err := conn .Close (); err != nil {
176185 mc .log ("closing connection:" , err )
177186 }
178- mc .clearResult ()
187+ // This function can be called from multiple goroutines.
188+ // So we can not mc.clearResult() here.
189+ // Caller should do it if they are in safe goroutine.
179190}
180191
181192func (mc * mysqlConn ) error () error {
@@ -190,14 +201,14 @@ func (mc *mysqlConn) error() error {
190201
191202func (mc * mysqlConn ) Prepare (query string ) (driver.Stmt , error ) {
192203 if mc .closed .Load () {
193- mc .cfg . Logger . Print (ErrInvalidConn )
204+ mc .log (ErrInvalidConn )
194205 return nil , driver .ErrBadConn
195206 }
196207 // Send command
197208 err := mc .writeCommandPacketStr (comStmtPrepare , query )
198209 if err != nil {
199210 // STMT_PREPARE is safe to retry. So we can return ErrBadConn here.
200- mc .cfg . Logger . Print (err )
211+ mc .log (err )
201212 return nil , driver .ErrBadConn
202213 }
203214
@@ -231,7 +242,7 @@ func (mc *mysqlConn) interpolateParams(query string, args []driver.Value) (strin
231242 buf , err := mc .buf .takeCompleteBuffer ()
232243 if err != nil {
233244 // can not take the buffer. Something must be wrong with the connection
234- mc .cfg . Logger . Print (err )
245+ mc .log (err )
235246 return "" , ErrInvalidConn
236247 }
237248 buf = buf [:0 ]
@@ -323,7 +334,7 @@ func (mc *mysqlConn) interpolateParams(query string, args []driver.Value) (strin
323334
324335func (mc * mysqlConn ) Exec (query string , args []driver.Value ) (driver.Result , error ) {
325336 if mc .closed .Load () {
326- mc .cfg . Logger . Print (ErrInvalidConn )
337+ mc .log (ErrInvalidConn )
327338 return nil , driver .ErrBadConn
328339 }
329340 if len (args ) != 0 {
@@ -383,7 +394,7 @@ func (mc *mysqlConn) query(query string, args []driver.Value) (*textRows, error)
383394 handleOk := mc .clearResult ()
384395
385396 if mc .closed .Load () {
386- mc .cfg . Logger . Print (ErrInvalidConn )
397+ mc .log (ErrInvalidConn )
387398 return nil , driver .ErrBadConn
388399 }
389400 if len (args ) != 0 {
@@ -478,7 +489,7 @@ func (mc *mysqlConn) finish() {
478489// Ping implements driver.Pinger interface
479490func (mc * mysqlConn ) Ping (ctx context.Context ) (err error ) {
480491 if mc .closed .Load () {
481- mc .cfg . Logger . Print (ErrInvalidConn )
492+ mc .log (ErrInvalidConn )
482493 return driver .ErrBadConn
483494 }
484495
@@ -687,7 +698,7 @@ func (mc *mysqlConn) ResetSession(ctx context.Context) error {
687698 err = connCheck (conn )
688699 }
689700 if err != nil {
690- mc .cfg . Logger . Print ("closing bad idle connection: " , err )
701+ mc .log ("closing bad idle connection: " , err )
691702 return driver .ErrBadConn
692703 }
693704 }
0 commit comments