Author: timbo
Date: Thu Jan 26 08:36:16 2006
New Revision: 2458

Modified:
   dbi/trunk/Changes
   dbi/trunk/Driver.xst
   dbi/trunk/lib/DBD/Proxy.pm
Log:
Fixed DBD::Proxy to not alter $@ in disconnect or AUTOLOADd methods.
Reworded code comment re auto-rollback on DESTROY.


Modified: dbi/trunk/Changes
==============================================================================
--- dbi/trunk/Changes   (original)
+++ dbi/trunk/Changes   Thu Jan 26 08:36:16 2006
@@ -10,6 +10,7 @@ DBI::Changes - List of significant chang
   Fixed default ping() method to return false if !$dbh->{Active}.
   Fixed t/40profile.t to be insensitive to long double precision.
   Fixed for perl 5.8.0's more limited weaken() function.
+  Fixed DBD::Proxy to not alter $@ in disconnect or AUTOLOADd methods.
 
   Improved performance for thread-enabled perls thanks to Gisle Aas.
   Drivers can now use PERL_NO_GET_CONTEXT thanks to Gisle Aas.

Modified: dbi/trunk/Driver.xst
==============================================================================
--- dbi/trunk/Driver.xst        (original)
+++ dbi/trunk/Driver.xst        Thu Jan 26 08:36:16 2006
@@ -341,16 +341,23 @@ DESTROY(dbh)
                 PerlIO_printf(DBIc_LOGPIO(imp_dbh), "         DESTROY %s 
skipped due to InactiveDestroy\n", SvPV_nolen(dbh));
         }
        if (DBIc_ACTIVE(imp_dbh)) {
-           /* The application has not explicitly disconnected. That's bad.     
*/
-           /* To ensure integrity we *must* issue a rollback. This will be     
*/
-           /* harmless if the application has issued a commit. If it hasn't    
*/
-           /* then it'll ensure integrity. Consider a Ctrl-C killing perl      
*/
-           /* between two statements that must be executed as a transaction.   
*/
-           /* Perl will call DESTROY on the dbh and, if we don't rollback,     
*/
-           /* the server may automatically commit! Bham! Corrupt database!     
*/
            if (!DBIc_has(imp_dbh,DBIcf_AutoCommit)) {
+               /* Application is using transactions and hasn't explicitly 
disconnected.
+                   Some databases will automatically commit on graceful 
disconnect.
+                   Since we're about to gracefully disconnect as part of the 
DESTROY
+                   we want to be sure we're not about to implicitly commit 
changes
+                   that are incomplete and should be rolled back. (The DESTROY 
may
+                   be due to a RaiseError, for example.) So we rollback here.
+                   This will be harmless if the application has issued a 
commit,
+                   XXX Could add an attribute flag to indicate that the driver
+                   doesn't have this problem. Patches welcome.
+                   XXX or could just move the DBIc_is(imp_dbh, DBIcf_Executed) 
test
+                   to cover the rollback as well. That just needs sanity 
checking
+                   that DBIcf_Executed is set by any/all possible way to 
execute a
+                   statement that might start a transaction.
+               */
                if (DBIc_WARN(imp_dbh)
-               &&  DBIc_is(imp_dbh, DBIcf_Executed)
+               &&  DBIc_is(imp_dbh, DBIcf_Executed) /* has not just called 
commit/rollback */
                && (!dirty || DBIc_DBISTATE(imp_dbh)->debug >= 3)
                )
                     warn("Issuing rollback() for database handle being 
DESTROY'd without explicit disconnect()");

Modified: dbi/trunk/lib/DBD/Proxy.pm
==============================================================================
--- dbi/trunk/lib/DBD/Proxy.pm  (original)
+++ dbi/trunk/lib/DBD/Proxy.pm  Thu Jan 26 08:36:16 2006
@@ -262,6 +262,7 @@ sub AUTOLOAD {
        q/package ~class~;
           sub ~method~ {
             my $h = shift;
+           local $@;
            my @result = wantarray
                ? eval {        $h->{'proxy_~type~h'}->~method~(@_) }
                : eval { scalar $h->{'proxy_~type~h'}->~method~(@_) };
@@ -272,6 +273,7 @@ sub AUTOLOAD {
         q/package ~class~;
          sub ~method~ {
            my $h = shift;
+           local $@;
            my @result = wantarray
                ? eval {        $h->{'proxy_~type~h'}->func(@_, '~method~') }
                : eval { scalar $h->{'proxy_~type~h'}->func(@_, '~method~') };
@@ -304,6 +306,7 @@ sub disconnect ($) {
     # Drop database connection at remote end
     my $rdbh = $dbh->{'proxy_dbh'};
     local $SIG{__DIE__} = 'DEFAULT';
+    local $@;
     eval { $rdbh->disconnect() };
     DBD::Proxy::proxy_set_err($dbh, $@) if $@;
     

Reply via email to