stdlib.ReleaseConn closes connections left in invalid state

If a connection is in a transaction or has an open result set then
close the connection when returning it to database/sql. When next
database/sql attempts to use it the connection will return
driver.ErrBadConn and database/sql will remove it from the pool.

fixes #673
pull/674/head
Jack Christensen 2020-02-01 12:00:26 -06:00
parent 06c3181836
commit 77c1076d39
2 changed files with 39 additions and 0 deletions

View File

@ -570,6 +570,12 @@ func ReleaseConn(db *sql.DB, conn *pgx.Conn) error {
var tx *sql.Tx
var ok bool
if conn.PgConn().IsBusy() || conn.PgConn().TxStatus() != 'I' {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
conn.Close(ctx)
}
fakeTxMutex.Lock()
tx, ok = fakeTxConns[conn]
if ok {

View File

@ -692,6 +692,39 @@ func TestAcquireConn(t *testing.T) {
ensureConnValid(t, db)
}
// https://github.com/jackc/pgx/issues/673
func TestReleaseConnWithTxInProgress(t *testing.T) {
db := openDB(t)
defer closeDB(t, db)
c1, err := stdlib.AcquireConn(db)
require.NoError(t, err)
_, err = c1.Exec(context.Background(), "begin")
require.NoError(t, err)
c1PID := c1.PgConn().PID()
err = stdlib.ReleaseConn(db, c1)
require.NoError(t, err)
c2, err := stdlib.AcquireConn(db)
require.NoError(t, err)
c2PID := c2.PgConn().PID()
err = stdlib.ReleaseConn(db, c2)
require.NoError(t, err)
require.NotEqual(t, c1PID, c2PID)
// Releasing a conn with a tx in progress should close the connection
stats := db.Stats()
require.Equal(t, 1, stats.OpenConnections)
ensureConnValid(t, db)
}
func TestConnPingContextSuccess(t *testing.T) {
db := openDB(t)
defer closeDB(t, db)