Author: turnstep
Date: Sat Jan 19 10:58:09 2008
New Revision: 10616

Modified:
   DBD-Pg/trunk/Changes
   DBD-Pg/trunk/dbdimp.c
   DBD-Pg/trunk/t/04misc.t

Log:
Always check transaction status, bug #23423


Modified: DBD-Pg/trunk/Changes
==============================================================================
--- DBD-Pg/trunk/Changes        (original)
+++ DBD-Pg/trunk/Changes        Sat Jan 19 10:58:09 2008
@@ -1,6 +1,9 @@
 ('GSM' is Greg Sabino Mullane, [EMAIL PROTECTED])
 
 2.0.0
+       - Check transaction status after each command, to allow 
+               things such as 'PREPARE TRANSACTION' to work properly.
+               (CPAN bug #32423) [GSM]
        - Allow raw transaction statements through - in other words, 
                do not croak if $dbh->prepare("COMMIT") is attempted. Not 
                only was this a little too controlling, there is a growing 

Modified: DBD-Pg/trunk/dbdimp.c
==============================================================================
--- DBD-Pg/trunk/dbdimp.c       (original)
+++ DBD-Pg/trunk/dbdimp.c       Sat Jan 19 10:58:09 2008
@@ -2419,10 +2419,11 @@
 int pg_quickexec (SV * dbh, const char * sql, int asyncflag)
 {
        D_imp_dbh(dbh);
-       PGresult *     result;
-       ExecStatusType status = PGRES_FATAL_ERROR; /* Assume the worst */
-       char *         cmdStatus = NULL;
-       int            rows = 0;
+       PGresult *              result;
+       ExecStatusType          status = PGRES_FATAL_ERROR; /* Assume the worst 
*/
+       PGTransactionStatusType txn_status;
+       char *                  cmdStatus = NULL;
+       int                     rows = 0;
 
        if (dbis->debug >= 4)
                (void)PerlIO_printf(DBILOGFP, "dbdpg: pg_quickexec begins; 
query=(%s) async=(%d) async_status=(%d)\n",
@@ -2514,8 +2515,20 @@
        else
                return -2;
 
+       txn_status = PQtransactionStatus(imp_dbh->conn);
+
+       if (PQTRANS_IDLE == txn_status) {
+               imp_dbh->done_begin = DBDPG_FALSE;
+               imp_dbh->copystate=0;
+               /* If begin_work has been called, turn AutoCommit back on and 
BegunWork off */
+               if (DBIc_has(imp_dbh, DBIcf_BegunWork)!=0) {
+                       DBIc_set(imp_dbh, DBIcf_AutoCommit, 1);
+                       DBIc_set(imp_dbh, DBIcf_BegunWork, 0);
+               }
+       }
+
        if (dbis->debug >= 4)
-               (void)PerlIO_printf(DBILOGFP, "dbdpg: pg_quickexec ends; 
returns %d\n", rows);
+               (void)PerlIO_printf(DBILOGFP, "dbdpg: pg_quickexec ends; 
rows=%d, txn_status=%d\n", rows, txn_status);
 
        return rows;
 
@@ -2879,7 +2892,15 @@
                        ret = atoi(PQcmdTuples(imp_sth->result));
                }
                else {
-                       /* We assume that no rows are affected for successful 
commands (e.g. ALTER TABLE) */
+                       /* No rows affected, but check for change of state */
+                       if (PQTRANS_IDLE == PQtransactionStatus(imp_dbh->conn)) 
{
+                               imp_dbh->done_begin = DBDPG_FALSE;
+                               /* If begin_work has been called, turn 
AutoCommit back on and BegunWork off */
+                               if (DBIc_has(imp_dbh, DBIcf_BegunWork)!=0) {
+                                       DBIc_set(imp_dbh, DBIcf_AutoCommit, 1);
+                                       DBIc_set(imp_dbh, DBIcf_BegunWork, 0);
+                               }
+                       }
                        return 0;
                }
        }

Modified: DBD-Pg/trunk/t/04misc.t
==============================================================================
--- DBD-Pg/trunk/t/04misc.t     (original)
+++ DBD-Pg/trunk/t/04misc.t     Sat Jan 19 10:58:09 2008
@@ -14,7 +14,7 @@
 my $dbh = connect_database();
 
 if (defined $dbh) {
-       plan tests => 6;
+       plan tests => 13;
 }
 else {
        plan skip_all => 'Connection to database failed, cannot continue 
testing';
@@ -56,5 +56,37 @@
 $sth->execute(602,123);
 ok (!$@, qq{Using \$DBDPG_DEFAULT ($DBDPG_DEFAULT) works});
 
+#
+# Test transaction status changes
+#
+
+$dbh->{AutoCommit} = 1;
+$dbh->begin_work();
+$dbh->do('SELECT 123');
+
+$t = q{Raw ROLLBACK via do() resets the transaction status correctly};
+eval { $dbh->do('ROLLBACK'); };
+is($@, q{}, $t);
+eval { $dbh->begin_work(); };
+is($@, q{}, $t);
+
+$t = q{Using dbh->commit() resets the transaction status correctly};
+eval { $dbh->commit(); };
+is($@, q{}, $t);
+eval { $dbh->begin_work(); };
+is($@, q{}, $t);
+
+$t = q{Raw COMMIT via do() resets the transaction status correctly};
+eval { $dbh->do('COMMIT'); };
+is($@, q{}, $t);
+eval { $dbh->begin_work(); };
+is($@, q{}, $t);
+
+$t = q{Calling COMMIT via prepare/execute resets the transaction status 
correctly};
+$sth = $dbh->prepare('COMMIT');
+$sth->execute();
+eval { $dbh->begin_work(); };
+is($@, q{}, $t);
+
 cleanup_database($dbh,'test');
 $dbh->disconnect();

Reply via email to