--- DBI.pm.joet	Tue Aug  9 14:55:42 2005
+++ DBI.pm	Tue Aug  9 14:54:27 2005
@@ -23,6 +23,8 @@
 my %PingTimeOut;  # stores the timeout values per data_source, a negative value de-activates ping, default = 0
 my %LastPingTime; # keeps track of last ping per data_source
 
+# Check to see if we need to reset TaintIn and TaintOut
+my $TaintInOut = ($DBI::VERSION>=1.31)?1:0;
 
 # supposed to be called in a startup script.
 # stores the data_source of all connections, which are supposed to be created upon
@@ -109,9 +111,11 @@
         }   
     }
 
-    # this PerlCleanupHandler is supposed to initiate a rollback after the script has finished if AutoCommit is off.
-    my $needCleanup = ($Idx =~ /AutoCommit[^\d]+0/) ? 1 : 0;
-    if(!$Rollback{$Idx} and $needCleanup and Apache->can('push_handlers')) {
+    # this PerlCleanupHandler is supposed to initiate a rollback after the
+    # script has finished if AutoCommit is off.  however, cleanup can only
+    # be determined at end of handle life as begin_work may have been called
+    # to temporarily turn off AutoCommit.
+    if(!$Rollback{$Idx} and Apache->can('push_handlers')) {
         print STDERR "$prefix push PerlCleanupHandler \n" if $Apache::DBI::DEBUG > 1;
         if ($ENV{MOD_PERL_API_VERSION} == 2) {
             require Apache2::ServerUtil;
@@ -145,6 +149,10 @@
     # RaiseError being on and the handle is invalid.
     if ($Connected{$Idx} and (!$needping or eval{$Connected{$Idx}->ping})) {
         print STDERR "$prefix already connected to '$Idx'\n" if $Apache::DBI::DEBUG > 1;
+
+        # Force clean up of handle in case previous transaction failed to clean up the handle
+        &reset_startup_state($Idx);
+
         return (bless $Connected{$Idx}, 'Apache::DBI::db');
     }
 
@@ -154,6 +162,9 @@
     $Connected{$Idx} = $drh->connect(@args);
     return undef if !$Connected{$Idx};
 
+    # store the parameters of the initial connection in the handle
+    set_startup_state($Idx);
+
     # return the new database handle
     print STDERR "$prefix new connect to '$Idx'\n" if $Apache::DBI::DEBUG;
     return (bless $Connected{$Idx}, 'Apache::DBI::db');
@@ -192,6 +203,49 @@
     1;
 }
 
+# Store the default start state of each dbh in the handle
+# Note: This uses private_Apache_DBI hash ref to store it in the handle itself
+
+sub set_startup_state {
+    my $Idx = shift;
+    foreach my $key qw{ AutoCommit Warn CompatMode InactiveDestroy 
+                        PrintError RaiseError HandleError 
+                        ShowErrorStatement TraceLevel FetchHashKeyName 
+                        ChopBlanks LongReadLen LongTruncOk 
+                        Taint Profile} {
+        $Connected{$Idx}->{private_Apache_DBI}{$key} = $Connected{$Idx}->{$key};
+    }
+    if ($TaintInOut) {
+        foreach my $key qw{ TaintIn TaintOut } {
+            $Connected{$Idx}->{private_Apache_DBI}{$key} = $Connected{$Idx}->{$key};
+        }
+    }
+    1;
+}
+
+
+# Restore the default start state of each dbh
+
+sub reset_startup_state {
+    my $Idx = shift;
+    # Rollback current transaction if currently in one
+    $Connected{$Idx}->{Active} and !$Connected{$Idx}->{AutoCommit} and eval {$Connected{$Idx}->rollback};
+
+    foreach my $key qw{ AutoCommit Warn CompatMode InactiveDestroy 
+                        PrintError RaiseError HandleError 
+                        ShowErrorStatement TraceLevel FetchHashKeyName 
+                        ChopBlanks LongReadLen LongTruncOk 
+                        Taint Profile } {
+        $Connected{$Idx}->{$key} = $Connected{$Idx}->{private_Apache_DBI}{$key};
+    }
+    if ($TaintInOut) {
+        foreach my $key qw{ TaintIn TaintOut } {
+            $Connected{$Idx}->{$key} = $Connected{$Idx}->{private_Apache_DBI}{$key};
+        }
+    }
+    1;
+}
+
 
 # This function can be called from other handlers to perform tasks on all cached database handles.
 
@@ -347,8 +401,10 @@
 AutoCommit is off and the script finishes without an explicit rollback, the 
 Apache::DBI module uses a PerlCleanupHandler to issue a rollback at the
 end of every request. Note, that this CleanupHandler will only be used, if 
-the initial data_source sets AutoCommit = 0. It will not be used, if AutoCommit 
-will be turned off, after the connect has been done. 
+the initial data_source sets AutoCommit = 0 or AutoCommit is turned off, after 
+the connect has been done (ie begin_work). However, because a connection may have
+set other parameters, the handle is reset to its initial connection state before 
+it is returned for a second time.
 
 This module plugs in a menu item for Apache::Status or Apache2::Status. 
 The menu lists the current database connections. It should be considered 
