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();