From: Graham Knop Date: Wed, 18 Jan 2012 15:43:20 +0000 (-0500) Subject: add support for with_deferred_fk_checks to SQLite driver X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=96dfdf51d407d04b91b146681dafd147a25271de;p=dbsrgits%2FDBIx-Class.git add support for with_deferred_fk_checks to SQLite driver --- diff --git a/lib/DBIx/Class/Storage/DBI/SQLite.pm b/lib/DBIx/Class/Storage/DBI/SQLite.pm index 6943c77..fe67702 100644 --- a/lib/DBIx/Class/Storage/DBI/SQLite.pm +++ b/lib/DBIx/Class/Storage/DBI/SQLite.pm @@ -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 diff --git a/t/752sqlite.t b/t/752sqlite.t index 1446128..fa2fc98 100644 --- a/t/752sqlite.t +++ b/t/752sqlite.t @@ -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: diff --git a/t/lib/sqlite.sql b/t/lib/sqlite.sql index 163a4d8..c6d5bf7 100644 --- a/t/lib/sqlite.sql +++ b/t/lib/sqlite.sql @@ -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,