add support for with_deferred_fk_checks to SQLite driver
Graham Knop [Wed, 18 Jan 2012 15:43:20 +0000 (10:43 -0500)]
lib/DBIx/Class/Storage/DBI/SQLite.pm
t/752sqlite.t
t/lib/sqlite.sql

index 6943c77..fe67702 100644 (file)
@@ -8,6 +8,8 @@ use mro 'c3';
 
 use DBIx::Class::Carp;
 use Scalar::Util 'looks_like_number';
+use Scope::Guard ();
+use Context::Preserve 'preserve_context';
 use namespace::clean;
 
 __PACKAGE__->sql_maker_class('DBIx::Class::SQLMaker::SQLite');
@@ -174,6 +176,24 @@ sub connect_call_use_foreign_keys {
   );
 }
 
+sub with_deferred_fk_checks {
+  my ($self, $sub) = @_;
+
+  my ($fk_state) = $self->_get_dbh->selectrow_array('PRAGMA foreign_keys');
+  $self->_do_query('PRAGMA foreign_keys = OFF');
+
+  my $txn_scope_guard = $self->txn_scope_guard;
+
+  my $sg;
+  if ($fk_state) {
+    $sg = Scope::Guard->new(sub {
+      $self->_do_query('PRAGMA foreign_keys = ON')
+    })
+  }
+
+  return preserve_context { $sub->() } after => sub { $txn_scope_guard->commit };
+}
+
 1;
 
 =head1 AUTHORS
index 1446128..fa2fc98 100644 (file)
@@ -96,6 +96,42 @@ for my $bi (qw/
   }
 }
 
+$schema->storage->dbh_do(sub {
+  my $dbh = $_[1];
+  SKIP: {
+    my ($fk_enabled) = $dbh->selectrow_array('PRAGMA foreign_keys');
+    if (! defined $fk_enabled) {
+      # skip
+      skip 'SQLite not compiled with foreign key enforcement', 2;
+      return;
+    }
+    $schema->storage->connect_call_use_foreign_keys;
+
+    lives_ok {
+      $schema->storage->with_deferred_fk_checks(sub {
+        $schema->resultset('Track')->create({
+          trackid => 999, cd => 999, position => 1, title => 'deferred FK track'
+        });
+        $schema->resultset('CD')->create({
+          artist => 1, cdid => 999, year => '2003', title => 'deferred FK cd'
+        });
+      });
+    } 'with_deferred_fk_checks code survived';
+
+    is eval { $schema->resultset('Track')->find(999)->title }, 'deferred FK track',
+       'code in with_deferred_fk_checks worked';
+
+    throws_ok {
+      $schema->resultset('Track')->create({
+        trackid => 1, cd => 9999, position => 1, title => 'Track1'
+      });
+    } qr/constraint/i, 'with_deferred_fk_checks is off';
+
+    ok $dbh->selectrow_array('PRAGMA foreign_keys'), 'foreign key checks reenabled';
+  }
+});
+
+
 done_testing;
 
 # vim:sts=2 sw=2:
index 163a4d8..c6d5bf7 100644 (file)
@@ -287,7 +287,7 @@ CREATE INDEX self_ref_alias_idx_self_ref ON self_ref_alias (self_ref);
 --
 CREATE TABLE track (
   trackid INTEGER PRIMARY KEY NOT NULL,
-  cd integer NOT NULL,
+  cd integer NOT NULL REFERENCES cd(cdid),
   position int NOT NULL,
   title varchar(100) NOT NULL,
   last_updated_on datetime,
@@ -305,7 +305,7 @@ CREATE UNIQUE INDEX track_cd_title ON track (cd, title);
 --
 CREATE TABLE cd (
   cdid INTEGER PRIMARY KEY NOT NULL,
-  artist integer NOT NULL,
+  artist integer NOT NULL REFERENCES artist(artistid),
   title varchar(100) NOT NULL,
   year varchar(100) NOT NULL,
   genreid integer,