From: Dagfinn Ilmari Mannsåker Date: Tue, 21 Oct 2014 13:29:27 +0000 (+0100) Subject: Factor SQL-standard deferred FK checks into a component X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=dbsrgits%2FDBIx-Class.git;a=commitdiff_plain;h=9334469ca4b326877bb2b6ea20cf087703e2094d Factor SQL-standard deferred FK checks into a component PostgreSQL, Informix and Oracle all support this standard syntax, so factor it out in a separate component --- diff --git a/lib/DBIx/Class/Storage/DBI/Informix.pm b/lib/DBIx/Class/Storage/DBI/Informix.pm index cab66da..79996d3 100644 --- a/lib/DBIx/Class/Storage/DBI/Informix.pm +++ b/lib/DBIx/Class/Storage/DBI/Informix.pm @@ -2,11 +2,9 @@ package DBIx::Class::Storage::DBI::Informix; use strict; use warnings; -use base qw/DBIx::Class::Storage::DBI/; +use base qw/DBIx::Class::Storage::DBI::SetConstraintsDeferred/; use mro 'c3'; -use Scope::Guard (); -use Context::Preserve 'preserve_context'; use namespace::clean; __PACKAGE__->sql_limit_dialect ('SkipFirst'); @@ -59,22 +57,6 @@ sub _exec_svp_rollback { $self->_dbh->do("ROLLBACK TO SAVEPOINT $name") } -sub with_deferred_fk_checks { - my ($self, $sub) = @_; - - my $txn_scope_guard = $self->txn_scope_guard; - - $self->_do_query('SET CONSTRAINTS ALL DEFERRED'); - - return preserve_context { - my $inner_self = $self; # avoid nested closure leak on 5.8 - my $sg = Scope::Guard->new(sub { - $inner_self->_do_query('SET CONSTRAINTS ALL IMMEDIATE'); - }); - $sub->() - } after => sub { $txn_scope_guard->commit }; -} - =head2 connect_call_datetime_setup Used as: diff --git a/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm b/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm index 695d432..66bfc81 100644 --- a/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm +++ b/lib/DBIx/Class/Storage/DBI/Oracle/Generic.pm @@ -2,11 +2,9 @@ package DBIx::Class::Storage::DBI::Oracle::Generic; use strict; use warnings; -use base qw/DBIx::Class::Storage::DBI/; +use base qw/DBIx::Class::Storage::DBI::SetConstraintsDeferred/; use mro 'c3'; use DBIx::Class::Carp; -use Scope::Guard (); -use Context::Preserve 'preserve_context'; use Try::Tiny; use List::Util 'first'; use namespace::clean; @@ -650,35 +648,6 @@ sub relname_to_table_alias { return $self->sql_maker->_shorten_identifier($alias); } -=head2 with_deferred_fk_checks - -Runs a coderef between: - - alter session set constraints = deferred - ... - alter session set constraints = immediate - -to defer foreign key checks. - -Constraints must be declared C for this to work. - -=cut - -sub with_deferred_fk_checks { - my ($self, $sub) = @_; - - my $txn_scope_guard = $self->txn_scope_guard; - - $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 }; -} - =head1 ATTRIBUTES Following additional attributes can be used in resultsets. diff --git a/lib/DBIx/Class/Storage/DBI/Pg.pm b/lib/DBIx/Class/Storage/DBI/Pg.pm index dacfdb6..ee134c9 100644 --- a/lib/DBIx/Class/Storage/DBI/Pg.pm +++ b/lib/DBIx/Class/Storage/DBI/Pg.pm @@ -3,10 +3,8 @@ package DBIx::Class::Storage::DBI::Pg; use strict; use warnings; -use base qw/DBIx::Class::Storage::DBI/; +use base qw/DBIx::Class::Storage::DBI::SetConstraintsDeferred/; -use Scope::Guard (); -use Context::Preserve 'preserve_context'; use DBIx::Class::Carp; use Try::Tiny; use namespace::clean; @@ -23,22 +21,6 @@ sub _determine_supports_insert_returning { ; } -sub with_deferred_fk_checks { - my ($self, $sub) = @_; - - my $txn_scope_guard = $self->txn_scope_guard; - - $self->_do_query('SET CONSTRAINTS ALL DEFERRED'); - - return preserve_context { - my $inner_self = $self; # avoid nested closure leak on 5.8 - my $sg = Scope::Guard->new(sub { - $inner_self->_do_query('SET CONSTRAINTS ALL IMMEDIATE'); - }); - $sub->() - } after => sub { $txn_scope_guard->commit }; -} - # only used when INSERT ... RETURNING is disabled sub last_insert_id { my ($self,$source,@cols) = @_; diff --git a/lib/DBIx/Class/Storage/DBI/SetConstraintsDeferred.pm b/lib/DBIx/Class/Storage/DBI/SetConstraintsDeferred.pm new file mode 100644 index 0000000..6784c7c --- /dev/null +++ b/lib/DBIx/Class/Storage/DBI/SetConstraintsDeferred.pm @@ -0,0 +1,55 @@ +package DBIx::Class::Storage::DBI::SetConstraintsDeferred; + +use strict; +use warnings; + +use base 'DBIx::Class::Storage::DBI'; +use mro 'c3'; + +use Scope::Guard (); +use Context::Preserve 'preserve_context'; + +use namespace::clean; + +=head1 NAME + +DBIx::Class::Storage::DBI::SetConstraintsDeferred - Storage component for deferred constraints via C + +=head1 DESCRIPTION + +This component implements L +by wrapping the the coderef in C and +C. + +=cut + +sub with_deferred_fk_checks { + my ($self, $sub) = @_; + + my $txn_scope_guard = $self->txn_scope_guard; + + $self->_do_query('SET CONSTRAINTS ALL DEFERRED'); + + return preserve_context { + my $inner_self = $self; # avoid nested closure leak on 5.8 + my $sg = Scope::Guard->new(sub { + $inner_self->_do_query('SET CONSTRAINTS ALL IMMEDIATE'); + }); + $sub->() + } after => sub { $txn_scope_guard->commit }; +} + +=head1 FURTHER QUESTIONS? + +Check the list of L. + +=head1 COPYRIGHT AND LICENSE + +This module is free software L +by the L. You can +redistribute it and/or modify it under the same terms as the +L. + +=cut + +1;