add more tests for with_deferred_fk_checks
Dagfinn Ilmari Mannsåker [Tue, 25 Oct 2011 17:25:12 +0000 (18:25 +0100)]
Tests for unsatisfied deferred fk constraints throwing on commit and
tests for other types of exceptions propagating through the
with_deferred_fk_checks coderef.

lib/DBIx/Class/Storage/DBI/Informix.pm
lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm
lib/DBIx/Class/Storage/DBI/Pg.pm
t/72pg.t
t/73oracle.t
t/748informix.t

index db953d4..2a756d0 100644 (file)
@@ -5,7 +5,6 @@ use warnings;
 use base qw/DBIx::Class::Storage::DBI/;
 use mro 'c3';
 
-use Scope::Guard ();
 use Context::Preserve 'preserve_context';
 use namespace::clean;
 
@@ -67,11 +66,11 @@ sub with_deferred_fk_checks {
 
   $self->_do_query('SET CONSTRAINTS ALL DEFERRED');
 
-  my $sg = Scope::Guard->new(sub {
-    $self->_do_query('SET CONSTRAINTS ALL IMMEDIATE');
-  });
-
-  return preserve_context { $sub->() } after => sub { $txn_scope_guard->commit };
+  return preserve_context { $sub->() } after => sub {
+      $txn_scope_guard->commit;
+      $self->_do_query('SET CONSTRAINTS ALL IMMEDIATE')
+          if $self->transaction_depth;
+  };
 }
 
 =head2 connect_call_datetime_setup
index c107934..ae5d823 100644 (file)
@@ -5,7 +5,6 @@ use warnings;
 use base qw/DBIx::Class::Storage::DBI/;
 use mro 'c3';
 use DBIx::Class::Carp;
-use Scope::Guard ();
 use Context::Preserve 'preserve_context';
 use Try::Tiny;
 use List::Util 'first';
@@ -668,12 +667,12 @@ sub with_deferred_fk_checks {
 
   $self->_do_query('alter session set constraints = deferred');
 
-  my $sg = Scope::Guard->new(sub {
-    $self->_do_query('alter session set constraints = immediate');
-  });
-
   return
-    preserve_context { $sub->() } after => sub { $txn_scope_guard->commit };
+    preserve_context { $sub->() } after => sub {
+        $txn_scope_guard->commit;
+        $self->_do_query('alter session set constraints = immediate')
+            if $self->transaction_depth;
+    };
 }
 
 =head1 ATTRIBUTES
index d38f84c..40dcd8c 100644 (file)
@@ -5,7 +5,6 @@ use warnings;
 
 use base qw/DBIx::Class::Storage::DBI/;
 
-use Scope::Guard ();
 use Context::Preserve 'preserve_context';
 use DBIx::Class::Carp;
 use Try::Tiny;
@@ -30,11 +29,11 @@ sub with_deferred_fk_checks {
 
   $self->_do_query('SET CONSTRAINTS ALL DEFERRED');
 
-  my $sg = Scope::Guard->new(sub {
-    $self->_do_query('SET CONSTRAINTS ALL IMMEDIATE');
-  });
-
-  return preserve_context { $sub->() } after => sub { $txn_scope_guard->commit };
+  return preserve_context { $sub->() } after => sub {
+      $txn_scope_guard->commit;
+      $self->_do_query('SET CONSTRAINTS ALL IMMEDIATE')
+          if $self->transaction_depth;
+  };
 }
 
 # only used when INSERT ... RETURNING is disabled
index 5e4ec84..1a6ffa1 100644 (file)
--- a/t/72pg.t
+++ b/t/72pg.t
@@ -441,6 +441,24 @@ lives_ok { $cds->update({ year => '2010' }) } 'Update on prefetched rs';
       trackid => 1, cd => 9999, position => 1, title => 'Track1'
     });
   } qr/constraint/i, 'with_deferred_fk_checks is off';
+
+  throws_ok {
+    $schema->storage->with_deferred_fk_checks(sub {
+      $schema->resultset('Track')->create({
+        trackid => 9999, cd => 9999, position => 1, title => 'orphaned deferred FK track',
+      });
+    });
+  } qr/constraint/i, 'unsatisfied deferred FK throws';
+  ok !$schema->resultset('Track')->find(9999), 'orphaned deferred FK track not inserted';
+
+  throws_ok {
+    $schema->storage->with_deferred_fk_checks(sub {
+      $schema->resultset('CD')->create({
+        artist => 1, cdid => 9999, year => '2003', title => 'dupe PK cd'
+      }) foreach 0..1;
+    });
+  } qr/unique/i, 'unique constraint violation inside deferred block propagated';
+  ok !$schema->resultset('CD')->find(9999), 'duplicate PK track not inserted';
 }
 
 done_testing;
index 6433ce6..e9ac3f7 100644 (file)
@@ -358,6 +358,23 @@ sub _run_tests {
     });
   } qr/constraint/i, 'with_deferred_fk_checks is off';
 
+  throws_ok {
+    $schema->storage->with_deferred_fk_checks(sub {
+      $schema->resultset('Track')->create({
+        trackid => 9999, cd => 9999, position => 1, title => 'orphaned deferred FK track',
+      });
+    });
+  } qr/constraint/i, 'unsatisfied deferred FK throws';
+  ok !$schema->resultset('Track')->find(9999), 'orphaned deferred FK track not inserted';
+
+  throws_ok {
+    $schema->storage->with_deferred_fk_checks(sub {
+      $schema->resultset('CD')->create({
+        artist => 1, cdid => 9999, year => '2003', title => 'dupe PK cd'
+      }) foreach 0..1;
+    });
+  } qr/unique/i, 'unique constraint violation inside deferred block propagated';
+  ok !$schema->resultset('CD')->find(9999), 'duplicate PK track not inserted';
 
 # test auto increment using sequences WITHOUT triggers
   for (1..5) {
index 42bdac8..6040b15 100644 (file)
@@ -141,6 +141,24 @@ throws_ok {
   });
 } qr/constraint/i, 'with_deferred_fk_checks is off';
 
+throws_ok {
+  $schema->storage->with_deferred_fk_checks(sub {
+    $schema->resultset('Track')->create({
+      trackid => 9999, cd => 9999, position => 1, title => 'orphaned deferred FK track',
+    });
+  });
+} qr/constraint/i, 'unsatisfied deferred FK throws';
+ok !$schema->resultset('Track')->find(9999), 'orphaned deferred FK track not inserted';
+
+throws_ok {
+  $schema->storage->with_deferred_fk_checks(sub {
+    $schema->resultset('CD')->create({
+      artist => 1, cdid => 9999, year => '2003', title => 'dupe PK cd'
+    }) foreach 0..1;
+  });
+} qr/unique/i, 'unique constraint violation inside deferred block propagated';
+ok !$schema->resultset('CD')->find(9999), 'duplicate PK track not inserted';
+
 done_testing;
 
 # clean up our mess