aboutsummaryrefslogtreecommitdiff
path: root/src/database/sql/sql.go
diff options
context:
space:
mode:
authorDaniel Theophanes <kardianos@gmail.com>2020-01-24 07:29:56 -0800
committerDaniel Theophanes <kardianos@gmail.com>2020-04-20 18:47:26 +0000
commitc9af5523f324a031b23c6f1dcf448c051c994c00 (patch)
tree58d2cbd38f60282a7bceb9fe5a9ce411d12ff448 /src/database/sql/sql.go
parentd8f0a229b5036e42b7bc5371c32c302cead9b635 (diff)
downloadgo-c9af5523f324a031b23c6f1dcf448c051c994c00.tar.xz
database/sql: on Tx rollback, retain connection if driver can reset session
Previously the Tx would drop the connection after rolling back from a context cancel. Now if the driver can reset the session, keep the connection. Change-Id: Ie6a3124275632787629844d91a06bb2e70cc060b Reviewed-on: https://go-review.googlesource.com/c/go/+/216241 Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com> Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/database/sql/sql.go')
-rw-r--r--src/database/sql/sql.go27
1 files changed, 20 insertions, 7 deletions
diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go
index 3710264dcf..b63d5591f6 100644
--- a/src/database/sql/sql.go
+++ b/src/database/sql/sql.go
@@ -1746,7 +1746,11 @@ func (db *DB) begin(ctx context.Context, opts *TxOptions, strategy connReuseStra
// beginDC starts a transaction. The provided dc must be valid and ready to use.
func (db *DB) beginDC(ctx context.Context, dc *driverConn, release func(error), opts *TxOptions) (tx *Tx, err error) {
var txi driver.Tx
+ keepConnOnRollback := false
withLock(dc, func() {
+ _, hasSessionResetter := dc.ci.(driver.SessionResetter)
+ _, hasConnectionValidator := dc.ci.(driver.Validator)
+ keepConnOnRollback = hasSessionResetter && hasConnectionValidator
txi, err = ctxDriverBegin(ctx, opts, dc.ci)
})
if err != nil {
@@ -1758,12 +1762,13 @@ func (db *DB) beginDC(ctx context.Context, dc *driverConn, release func(error),
// The cancel function in Tx will be called after done is set to true.
ctx, cancel := context.WithCancel(ctx)
tx = &Tx{
- db: db,
- dc: dc,
- releaseConn: release,
- txi: txi,
- cancel: cancel,
- ctx: ctx,
+ db: db,
+ dc: dc,
+ releaseConn: release,
+ txi: txi,
+ cancel: cancel,
+ keepConnOnRollback: keepConnOnRollback,
+ ctx: ctx,
}
go tx.awaitDone()
return tx, nil
@@ -2025,6 +2030,11 @@ type Tx struct {
// Use atomic operations on value when checking value.
done int32
+ // keepConnOnRollback is true if the driver knows
+ // how to reset the connection's session and if need be discard
+ // the connection.
+ keepConnOnRollback bool
+
// All Stmts prepared for this transaction. These will be closed after the
// transaction has been committed or rolled back.
stmts struct {
@@ -2050,7 +2060,10 @@ func (tx *Tx) awaitDone() {
// transaction is closed and the resources are released. This
// rollback does nothing if the transaction has already been
// committed or rolled back.
- tx.rollback(true)
+ // Do not discard the connection if the connection knows
+ // how to reset the session.
+ discardConnection := !tx.keepConnOnRollback
+ tx.rollback(discardConnection)
}
func (tx *Tx) isDone() bool {