Author: timbo
Date: Fri Apr 27 03:10:50 2007
New Revision: 9464

Modified:
   dbi/trunk/DBI.pm
   dbi/trunk/DBI.xs
   dbi/trunk/lib/DBI/Gofer/Execute.pm
   dbi/trunk/lib/DBI/Gofer/Response.pm
   dbi/trunk/t/70callbacks.t
   dbi/trunk/t/85gofer.t
   dbi/trunk/t/86gofer_fail.t

Log:
Move setting Executed fag to after Callback handling so flag not set if 
callback skips the method.
Add executed_flag_set accessor method to gofe Response class.
Add tests for it.


Modified: dbi/trunk/DBI.pm
==============================================================================
--- dbi/trunk/DBI.pm    (original)
+++ dbi/trunk/DBI.pm    Fri Apr 27 03:10:50 2007
@@ -3341,11 +3341,10 @@
 same time. So calling execute() on a $sth also sets the C<Executed>
 attribute on the parent $dbh.
 
-The C<Executed> attribute for a database handle is cleared by the
-commit() and rollback() methods. The C<Executed> attribute of a
-statement handle is not cleared by the DBI under any circumstances
-and so acts as a permanent record of whether the statement handle
-was ever used.
+The C<Executed> attribute for a database handle is cleared by the commit() and
+rollback() methods (even if they fail). The C<Executed> attribute of a
+statement handle is not cleared by the DBI under any circumstances and so acts
+as a permanent record of whether the statement handle was ever used.
 
 The C<Executed> attribute was added in DBI 1.41.
 

Modified: dbi/trunk/DBI.xs
==============================================================================
--- dbi/trunk/DBI.xs    (original)
+++ dbi/trunk/DBI.xs    Fri Apr 27 03:10:50 2007
@@ -2773,7 +2773,7 @@
     /* Check method call against Internal Method Attributes */
     if (ima) {
 
-       if (ima_flags & 
(IMA_STUB|IMA_FUNC_REDIRECT|IMA_KEEP_ERR|IMA_KEEP_ERR_SUB|IMA_CLEAR_STMT|IMA_EXECUTE))
 {
+       if (ima_flags & 
(IMA_STUB|IMA_FUNC_REDIRECT|IMA_KEEP_ERR|IMA_KEEP_ERR_SUB|IMA_CLEAR_STMT)) {
 
            if (ima_flags & IMA_STUB) {
                if (*meth_name == 'c' && strEQ(meth_name,"can")) {
@@ -2807,12 +2807,6 @@
                            neatsvpv(h,0), meth_name, neatsvpv(meth_name_sv,0));
                meth_name = SvPV_nolen(meth_name_sv);
            }
-           if (ima_flags & IMA_EXECUTE) {
-               imp_xxh_t *parent = DBIc_PARENT_COM(imp_xxh);
-               DBIc_on(imp_xxh, DBIcf_Executed);
-               if (parent)
-                   DBIc_on(parent, DBIcf_Executed);
-           }
            if (ima_flags & IMA_KEEP_ERR)
                keep_error = TRUE;
            if (ima_flags & IMA_KEEP_ERR_SUB
@@ -2990,6 +2984,14 @@
         }
     }
 
+    /* set Executed after Callbacks so it's not set if callback elects to skip 
the method */
+    if (ima_flags & IMA_EXECUTE) {
+        imp_xxh_t *parent = DBIc_PARENT_COM(imp_xxh);
+        DBIc_on(imp_xxh, DBIcf_Executed);
+        if (parent)
+            DBIc_on(parent, DBIcf_Executed);
+    }
+
     /* The "quick_FETCH" logic...                                      */
     /* Shortcut for fetching attributes to bypass method call overheads */
     if ( (is_FETCH = (*meth_name=='F' && strEQ(meth_name,"FETCH"))) && 
!DBIc_COMPAT(imp_xxh)) {

Modified: dbi/trunk/lib/DBI/Gofer/Execute.pm
==============================================================================
--- dbi/trunk/lib/DBI/Gofer/Execute.pm  (original)
+++ dbi/trunk/lib/DBI/Gofer/Execute.pm  Fri Apr 27 03:10:50 2007
@@ -203,7 +203,7 @@
 
 
 sub new_response_with_err {
-    my ($self, $rv, $eval_error, $h) = @_;
+    my ($self, $rv, $eval_error, $dbh) = @_;
     # capture err+errstr etc and merge in $eval_error ($@)
 
     my ($err, $errstr, $state) = ($DBI::err, $DBI::errstr, $DBI::state);
@@ -218,7 +218,9 @@
     }
 
     my $flags;
-    $flags |= GOf_RESPONSE_EXECUTED if $h && $h->{Executed};
+    # (XXX if we ever add transaction support then we'll need to take extra
+    # steps because the commit/rollback would reset Executed before we get 
here)
+    $flags |= GOf_RESPONSE_EXECUTED if $dbh && $dbh->{Executed};
 
     my $response = DBI::Gofer::Response->new({
         rv     => $rv,

Modified: dbi/trunk/lib/DBI/Gofer/Response.pm
==============================================================================
--- dbi/trunk/lib/DBI/Gofer/Response.pm (original)
+++ dbi/trunk/lib/DBI/Gofer/Response.pm Fri Apr 27 03:10:50 2007
@@ -43,6 +43,14 @@
 }   
 
 
+
+sub executed_flag_set {
+    my $flags = shift->flags
+        or return 0;
+    return $flags & GOf_RESPONSE_EXECUTED;
+}
+
+
 sub add_err {
     my ($self, $err, $errstr, $state, $trace) = @_;
 

Modified: dbi/trunk/t/70callbacks.t
==============================================================================
--- dbi/trunk/t/70callbacks.t   (original)
+++ dbi/trunk/t/70callbacks.t   Fri Apr 27 03:10:50 2007
@@ -9,7 +9,7 @@
 BEGIN {
         plan skip_all => '$h->{Callbacks} attribute not supported for 
DBI::PurePerl'
                 if $DBI::PurePerl && $DBI::PurePerl; # doubled to avoid typo 
warning
-        plan tests => 49;
+        plan tests => 53;
 }
 
 $| = 1;
@@ -120,7 +120,7 @@
 local $dbh->{RaiseError} = 1;
 local $dbh->{PrintError} = 0;
 is eval { $dbh->commit }, undef, 'intercepted commit should return undef';
-like $@, '/DBD::ExampleP::db commit failed: faked commit failure/';
+like $@, '/DBD::\w+::db commit failed: faked commit failure/';
 is $DBI::err, 42;
 is $DBI::errstr, "faked commit failure";
 }

Modified: dbi/trunk/t/85gofer.t
==============================================================================
--- dbi/trunk/t/85gofer.t       (original)
+++ dbi/trunk/t/85gofer.t       Fri Apr 27 03:10:50 2007
@@ -156,6 +156,7 @@
     is_deeply($rowset, [ [ '1', 'oranges' ], [ '2', 'oranges' ] ]);
 
     ok $dbh->do("UPDATE fruit SET dVal='apples' WHERE dVal='oranges'");
+    ok $dbh->{go_response}->executed_flag_set, 'go_response executed flag 
should be true';
 
     ok $sth = $dbh->prepare("SELECT dKey, dVal FROM fruit");
     ok $sth->execute;

Modified: dbi/trunk/t/86gofer_fail.t
==============================================================================
--- dbi/trunk/t/86gofer_fail.t  (original)
+++ dbi/trunk/t/86gofer_fail.t  Fri Apr 27 03:10:50 2007
@@ -30,28 +30,21 @@
 # silence the "DBI_GOFER_RANDOM_FAIL set ..." warning
 $SIG{__WARN__} = sub { warn "@_" unless "@_" =~ /^DBI_GOFER_RANDOM_FAIL set/ };
 
+# --- 100% failure rate
+
 $ENV{DBI_GOFER_RANDOM_FAIL} = "1,do"; # total failure (almost)
 my $dbh_100 = 
DBI->connect("dbi:Gofer:transport=null;policy=rush;dsn=dbi:ExampleP:", 0, 0, {
     RaiseError => 1, PrintError => 0,
 });
 ok $dbh_100;
 
-sub precentage_exceptions {
-    my ($count, $sub) = @_;
-    my $i = $count;
-    my $exceptions;
-    while ($i--) {
-        eval { $sub->() };
-        if ($@) {
-            die "Unexpected failure: $@" unless $@ =~ /DBI_GOFER_RANDOM_FAIL/;
-            ++$exceptions;
-        }
-    }
-    return $exceptions/$count*100;
-}
+ok !eval { $dbh_100->do("set foo=1") }, 'do method should fail';
+like $dbh_100->errstr, '/DBI_GOFER_RANDOM_FAIL/', 'errstr should contain 
DBI_GOFER_RANDOM_FAIL';
+ok !$dbh_100->{go_response}->executed_flag_set, 'go_response executed flag 
should be false';
 
 is precentage_exceptions(200, sub { $dbh_100->do("set foo=1") }), 100;
 
+# --- 50% failure rate
 
 $ENV{DBI_GOFER_RANDOM_FAIL} = "2,do"; # 50% failure (almost)
 my $dbh_50 = 
DBI->connect("dbi:Gofer:transport=null;policy=rush;dsn=dbi:ExampleP:", 0, 0, {
@@ -64,5 +57,18 @@
 cmp_ok $fails, '>', 10, 'should fail about 50% of the time, but at least 10%';
 cmp_ok $fails, '<', 90, 'should fail about 50% of the time, but not more than 
90%';
 
-undef $@;
-1;
+exit 0;
+
+sub precentage_exceptions {
+    my ($count, $sub) = @_;
+    my $i = $count;
+    my $exceptions;
+    while ($i--) {
+        eval { $sub->() };
+        if ($@) {
+            die "Unexpected failure: $@" unless $@ =~ /DBI_GOFER_RANDOM_FAIL/;
+            ++$exceptions;
+        }
+    }
+    return $exceptions/$count*100;
+}

Reply via email to