Committed by Greg Sabino Mullane <[email protected]>
First pass at solving the ping/pg_ping problem. RT #100648
---
Pg.pm | 2 --
dbdimp.c | 31 +++++++++++++++++++------------
t/03dbmethod.t | 37 ++++++++++++++++---------------------
3 files changed, 35 insertions(+), 35 deletions(-)
diff --git a/Pg.pm b/Pg.pm
index 56110bc..831d768 100644
--- a/Pg.pm
+++ b/Pg.pm
@@ -2768,8 +2768,6 @@ return the following:
-2 An unknown transaction status was returned (e.g. after forking)
-3 The handle exists, but no data was returned from a test query.
-In practice, you should only ever see -1 and -2.
-
=head3 B<get_info>
$value = $dbh->get_info($info_type);
diff --git a/dbdimp.c b/dbdimp.c
index 022058b..334b19e 100644
--- a/dbdimp.c
+++ b/dbdimp.c
@@ -464,6 +464,7 @@ int dbd_db_ping (SV * dbh)
}
tstatus = pg_db_txn_status(aTHX_ imp_dbh);
+ /* 0=idle 1=active 2=intrans 3=inerror 4=unknown */
if (TRACE5_slow) TRC(DBILOGFP, "%sdbd_db_ping txn_status is %d\n",
THEADER_slow, tstatus);
@@ -472,25 +473,31 @@ int dbd_db_ping (SV * dbh)
return -2;
}
- if (tstatus != 0) {/* 2=active, 3=intrans, 4=inerror */
- if (TEND_slow) TRC(DBILOGFP, "%sEnd dbd_pg_ping (result:
%d)\n", THEADER_slow, 1+tstatus);
- return 1+tstatus;
- }
+ /* No matter what state we are in, send a SELECT to the backend */
+ status = _result(aTHX_ imp_dbh, "SELECT 'DBD::Pg ping test'");
- /* Even though it may be reported as normal, we have to make sure by
issuing a command */
+ if (0 == tstatus || 2 == tstatus) {
- status = _result(aTHX_ imp_dbh, "SELECT 'DBD::Pg ping test'");
+ /* 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;
+ }
- if (PGRES_TUPLES_OK == status) {
- if (TEND_slow) TRC(DBILOGFP, "%sEnd dbd_pg_ping (result: 1
PGRES_TUPLES_OK)\n", THEADER_slow);
- return 1;
}
- if (TEND_slow) TRC(DBILOGFP, "%sEnd dbd_pg_ping (result: -3)\n",
THEADER_slow);
- return -3;
+ /* A status of 7 could indicate a failed query or a dead database. We
need 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;
+ }
-} /* end of dbd_db_ping */
+ if (TEND_slow) TRC(DBILOGFP, "%sEnd dbd_pg_ping\n", THEADER_slow);
+ return 1+tstatus;
+} /* end of dbd_db_ping */
+
/* ================================================================== */
static PGTransactionStatusType pg_db_txn_status (pTHX_ imp_dbh_t * imp_dbh)
diff --git a/t/03dbmethod.t b/t/03dbmethod.t
index dffee0e..fc3bd05 100644
--- a/t/03dbmethod.t
+++ b/t/03dbmethod.t
@@ -26,7 +26,7 @@ my $dbh = connect_database();
if (! $dbh) {
plan skip_all => 'Connection to database failed, cannot continue
testing';
}
-plan tests => 547;
+plan tests => 546;
isnt ($dbh, undef, 'Connect to database for database handle method testing');
@@ -1882,10 +1882,9 @@ $dbh2->disconnect();
$t='DB handle method "ping" returns 1 on an idle connection';
is ($dbh->ping(), 1, $t);
-$t='DB handle method "ping" returns 1 for a good connection inside a
transaction';
+$t='DB handle method "ping" returns 3 for a good connection inside a
transaction';
$dbh->do('SELECT 123');
-$result = 1;
-is ($result, $dbh->ping(), $t);
+is ($dbh->ping(), 3, $t);
$t='DB handle method "ping" returns 1 on an idle connection';
$dbh->commit();
@@ -1899,21 +1898,20 @@ $dbh->do('COPY dbd_pg_test(id,pname) TO STDOUT');
local $SIG{__WARN__} = sub {};
$dbh->pg_getline($mtvar,100);
}
-#is ($dbh->ping(), 2, $t);
-1 while $dbh->pg_getline($mtvar,1000);
-
-$t='DB handle method "ping" returns 1 for a good connection inside a
transaction';
-$dbh->do('SELECT 123');
-is ($dbh->ping(), 1, $t);
+is ($dbh->ping(), 2, $t);
+## This has sent a SELECT, which messes up our COPY state!
+$dbh->rollback();
$t='DB handle method "ping" returns a 4 when inside a failed transaction';
eval {
$dbh->do('DBD::Pg creating an invalid command for testing');
};
is ($dbh->ping(), 4, $t);
+$dbh->rollback();
-
-exit;
+$t='DB handle method "ping" returns 1 on an idle connection';
+$dbh->commit();
+is ($dbh->ping(), 1, $t);
$t='DB handle method "ping" fails (returns 0) on a disconnected handle';
$dbh->disconnect();
@@ -1930,9 +1928,9 @@ isnt ($dbh, undef, $t);
$t='DB handle method "pg_ping" returns 1 on an idle connection';
is ($dbh->pg_ping(), 1, $t);
-$t='DB handle method "pg_ping" returns 1 for a good connection inside a
transaction';
+$t='DB handle method "pg_ping" returns 3 for a good connection inside a
transaction';
$dbh->do('SELECT 123');
-is ($dbh->pg_ping(), 1, $t);
+is ($dbh->pg_ping(), 3, $t);
$t='DB handle method "pg_ping" returns 1 on an idle connection';
$dbh->commit();
@@ -1942,14 +1940,11 @@ $t='DB handle method "pg_ping" returns 2 when in COPY
IN state';
$dbh->do('COPY dbd_pg_test(id,pname) TO STDOUT');
$dbh->pg_getline($mtvar,100);
is ($dbh->pg_ping(), 2, $t);
+$dbh->rollback();
-$t='DB handle method "pg_ping" returns 2 immediately after COPY IN state';
-1 while $dbh->pg_getline($mtvar,1000);
-is ($dbh->pg_ping(), 2, $t);
-
-$t='DB handle method "pg_ping" returns 1 for a good connection inside a
transaction';
+$t='DB handle method "pg_ping" returns 3 for a good connection inside a
transaction';
$dbh->do('SELECT 123');
-is ($dbh->pg_ping(), 1, $t);
+is ($dbh->pg_ping(), 3, $t);
$t='DB handle method "pg_ping" returns a 4 when inside a failed transaction';
eval {
@@ -1957,7 +1952,7 @@ eval {
};
is ($dbh->pg_ping(), 4, $t);
-$t='DB handle method "pg_ping" fails (returns 0) on a disconnected handle';
+$t='DB handle method "pg_ping" fails (returns -1) on a disconnected handle';
cleanup_database($dbh,'test');
$dbh->disconnect();
is ($dbh->pg_ping(), -1, $t);
--
1.8.4