[DBD::Pg] Revert kill version of ping testing: use better file descriptor method as proposed by Tim Bunce. Change some of the ping logic in dbdimp.c Still fails on a disconnect while in failed transaction. Not sure if there is a clean way to detect that yet...

[email protected] Sun, 28 Dec 2014 01:03:53 +0000
Newsgroups perl.dbd.pg.changes
Message-ID <[email protected]>
Committed by Greg Sabino Mullane <[email protected]>

Revert kill version of ping testing: use better file
descriptor method as proposed by Tim Bunce. Change some of the ping logic in
dbdimp.c Still fails on a disconnect while in failed transaction. Not sure if
there is a clean way to detect that yet...

---
 dbdimp.c       |  9 ++++++---
 t/03dbmethod.t | 30 +++++++++++++++++++++++++-----
 2 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/dbdimp.c b/dbdimp.c
index 334b19e..359865c 100644
--- a/dbdimp.c
+++ b/dbdimp.c
@@ -476,18 +476,21 @@ int dbd_db_ping (SV * dbh)
 	/* No matter what state we are in, send a SELECT to the backend */
 	status = _result(aTHX_ imp_dbh, "SELECT 'DBD::Pg ping test'");
 
+	/* If we are idle or in a transaction, we should see tuples */
 	if (0 == tstatus || 2 == tstatus) {
 
-		/* If we are simply idle or in a transaction, we should see tuples */
-
 		if (PGRES_TUPLES_OK == status) {
 			if (TEND_slow) TRC(DBILOGFP, "%sEnd dbd_pg_ping (result: 1 PGRES_TUPLES_OK)\n", THEADER_slow);
 			return 1+tstatus;
 		}
 
+		/* Something is wrong, so we return an error */
+		return -2;
 	}
 
-	/* A status of 7 could indicate a failed query or a dead database. We need PQstatus to be sure */
+	/* We are in some other state. As a status of 7 could be a bad query or a dead database,
+	   we need to call PQstatus to be sure
+	*/
 	if (CONNECTION_BAD == PQstatus(imp_dbh->conn)) {
 		if (TEND_slow) TRC(DBILOGFP, "%sEnd dbd_pg_ping (PQstatus returned CONNECTION_BAD)\n", THEADER_slow);
 		return -3;
diff --git a/t/03dbmethod.t b/t/03dbmethod.t
index 77ba407..e78f75d 100644
--- a/t/03dbmethod.t
+++ b/t/03dbmethod.t
@@ -1925,17 +1925,37 @@ $t='DB handle method "ping" returns 1 on an idle connection';
 $dbh->commit();
 is ($dbh->ping(), 1, $t);
 
-$t='DB handle method "ping" returns 0 when the underlying connection is gone';
+$t='DB handle method "ping" returns 0 after a lost network connection (outside transaction)';
+my $fd = $dbh->{pg_socket} or die "Could not determine socket";
+open(DBH_PG_FH, "<&=".$fd) or die "Could not open socket: $!";
+close DBH_PG_FH or die "Could not close socket: $!";
+is ($dbh->ping(), 0, $t);
 
-$pid = $dbh->selectall_arrayref('SELECT pg_backend_pid()')->[0][0];
-$dbh->commit();
-kill 15, $pid;
-sleep 1;
+## Reconnect, and try the same thing but inside a transaction
+$t='DB handle method "ping" returns 0 after a lost network connection (inside transaction)';
+diag "About to call...";
+$dbh->disconnect();
+$dbh = connect_database({nosetup => 1});
+$dbh->do("SELECT 'DBD::Pg testing'");
+$fd = $dbh->{pg_socket} or die "Could not determine socket";
+open(DBH_PG_FH, "<&=".$fd) or die "Could not open socket: $!";
+close DBH_PG_FH or die "Could not close socket: $!";
+is ($dbh->ping(), 0, $t);
+
+$t='DB handle method "ping" returns 0 after a lost network connection (inside failed transaction)';
+$dbh->{InactiveDestroy} = 1;
+undef $dbh;
+$dbh = connect_database({nosetup => 1});
+eval { $dbh->do("SELECT 'DBD::Pg testing, will fail'::int"); };
+$fd = $dbh->{pg_socket} or die "Could not determine socket";
+open(DBH_PG_FH, "<&=".$fd) or die "Could not open socket: $!";
+close DBH_PG_FH or die "Could not close socket: $!";
 is ($dbh->ping(), 0, $t);
 
 $dbh->disconnect();
 $dbh = connect_database({nosetup => 1});
 
+
 #
 # Test of the "pg_ping" database handle method
 #
-- 
1.8.4