added cascade_copy relationship attribute
Matt S Trout [Tue, 14 Feb 2006 18:52:28 +0000 (18:52 +0000)]
13 files changed:
Changes
lib/DBIx/Class/Relationship/HasMany.pm
lib/DBIx/Class/Row.pm
t/basicrels/22cascade_copy.t [new file with mode: 0644]
t/helperrels/22cascade_copy.t [new file with mode: 0644]
t/lib/DBICTest/Schema/Artist.pm
t/lib/DBICTest/Schema/BasicRels.pm
t/lib/DBICTest/Schema/CD.pm
t/lib/DBICTest/Schema/HelperRels.pm
t/lib/DBICTest/Schema/OneKey.pm
t/lib/DBICTest/Schema/Tag.pm
t/lib/sqlite.sql
t/run/22cascade_copy.tl [new file with mode: 0644]

diff --git a/Changes b/Changes
index de60b28..e051591 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,7 +1,10 @@
 Revision history for DBIx::Class
 
+        - added cascade_copy relationship attribute
+          (sponsored by Airspace Software, http://www.airspace.co.uk/)
         - clean up set_from_related
         - made copy() automatically null out auto-inc columns
+        - remove dependency on Module::Find in 40resultsetmanager.t (RT #17598)
        - Another fix for count with scalar group_by.
 
 0.05005 2006-02-13 21:24:51
index 716c292..1e61c74 100644 (file)
@@ -35,6 +35,7 @@ sub has_many {
                             { accessor => 'multi',
                               join_type => 'LEFT',
                               cascade_delete => 1,
+                              cascade_copy => 1,
                               %{$attrs||{}} } );
 }
 
index 9128599..0d4a8a4 100644 (file)
@@ -236,6 +236,7 @@ Inserts a new row with the specified changes.
 
 sub copy {
   my ($self, $changes) = @_;
+  $changes ||= {};
   my $col_data = { %{$self->{_column_data}} };
   foreach my $col (keys %$col_data) {
     delete $col_data->{$col}
@@ -243,7 +244,18 @@ sub copy {
   }
   my $new = bless({ _column_data => $col_data }, ref $self);
   $new->set_column($_ => $changes->{$_}) for keys %$changes;
-  return $new->insert;
+  $new->insert;
+  foreach my $rel ($self->result_source->relationships) {
+    my $rel_info = $self->result_source->relationship_info($rel);
+    if ($rel_info->{attrs}{cascade_copy}) {
+      my $resolved = $self->result_source->resolve_condition(
+       $rel_info->{cond}, $rel, $new);
+      foreach my $related ($self->search_related($rel)) {
+        $related->copy($resolved);
+      }
+    }
+  }
+  $new;
 }
 
 =head2 store_column
diff --git a/t/basicrels/22cascade_copy.t b/t/basicrels/22cascade_copy.t
new file mode 100644 (file)
index 0000000..c670152
--- /dev/null
@@ -0,0 +1,7 @@
+use Test::More;
+use lib qw(t/lib);
+use DBICTest;
+use DBICTest::BasicRels;
+
+require "t/run/22cascade_copy.tl";
+run_tests(DBICTest->schema);
diff --git a/t/helperrels/22cascade_copy.t b/t/helperrels/22cascade_copy.t
new file mode 100644 (file)
index 0000000..bc124e1
--- /dev/null
@@ -0,0 +1,7 @@
+use Test::More;
+use lib qw(t/lib);
+use DBICTest;
+use DBICTest::HelperRels;
+
+require "t/run/22cascade_copy.tl";
+run_tests(DBICTest->schema);
index 2200cd4..d05526f 100644 (file)
@@ -2,6 +2,8 @@ package DBICTest::Schema::Artist;
 
 use base 'DBIx::Class::Core';
 
+__PACKAGE__->load_components('PK::Auto');
+
 DBICTest::Schema::Artist->table('artist');
 DBICTest::Schema::Artist->add_columns(
   'artistid' => {
index 7a6f520..2a4942c 100644 (file)
@@ -5,11 +5,12 @@ use base 'DBIx::Class::Core';
 DBICTest::Schema::Artist->add_relationship(
     cds => 'DBICTest::Schema::CD',
     { 'foreign.artist' => 'self.artistid' },
-    { order_by => 'year', join_type => 'LEFT', cascade_delete => 1 }
+    { order_by => 'year', join_type => 'LEFT', cascade_delete => 1, cascade_copy => 1 }
 );
 DBICTest::Schema::Artist->add_relationship(
     twokeys => 'DBICTest::Schema::TwoKeys',
-    { 'foreign.artist' => 'self.artistid' }
+    { 'foreign.artist' => 'self.artistid' },
+    { cascade_copy => 1 }
 );
 DBICTest::Schema::Artist->add_relationship(
     onekeys => 'DBICTest::Schema::OneKey',
@@ -37,7 +38,7 @@ DBICTest::Schema::CD->add_relationship(
 DBICTest::Schema::CD->add_relationship(
     tags => 'DBICTest::Schema::Tag',
     { 'foreign.cd' => 'self.cdid' },
-    { join_type => 'LEFT', cascade_delete => 1 }
+    { join_type => 'LEFT', cascade_delete => 1, cascade_copy => 1 }
 );
 #DBICTest::Schema::CD->might_have(liner_notes => 'DBICTest::Schema::LinerNotes' => qw/notes/);
 DBICTest::Schema::CD->add_relationship(
index 8e04c16..4eaba4f 100644 (file)
@@ -2,6 +2,8 @@ package DBICTest::Schema::CD;
 
 use base 'DBIx::Class::Core';
 
+__PACKAGE__->load_components('PK::Auto');
+
 DBICTest::Schema::CD->table('cd');
 DBICTest::Schema::CD->add_columns(
   'cdid' => {
index ff47640..1fb8886 100644 (file)
@@ -42,7 +42,8 @@ DBICTest::Schema::CD_to_Producer->belongs_to(
 );
 DBICTest::Schema::Artist->has_many(
   'artist_undirected_maps', 'DBICTest::Schema::ArtistUndirectedMap',
-  [{'foreign.id1' => 'self.artistid'}, {'foreign.id2' => 'self.artistid'}]
+  [{'foreign.id1' => 'self.artistid'}, {'foreign.id2' => 'self.artistid'}],
+  { cascade_copy => 0 } # this would *so* not make sense
 );
 DBICTest::Schema::ArtistUndirectedMap->belongs_to(
   'artist1', 'DBICTest::Schema::Artist', 'id1');
index 081c94b..19387eb 100644 (file)
@@ -2,6 +2,8 @@ package DBICTest::Schema::OneKey;
 
 use base 'DBIx::Class::Core';
 
+__PACKAGE__->load_components('PK::Auto');
+
 DBICTest::Schema::OneKey->table('onekey');
 DBICTest::Schema::OneKey->add_columns(
   'id' => {
index 0a303d6..5b4eb20 100644 (file)
@@ -2,10 +2,12 @@ package DBICTest::Schema::Tag;
 
 use base qw/DBIx::Class::Core/;
 
+__PACKAGE__->load_components('PK::Auto');
+
 DBICTest::Schema::Tag->table('tags');
 DBICTest::Schema::Tag->add_columns(
   'tagid' => {
-    data_type => 'varchar',
+    data_type => 'integer',
     is_auto_increment => 1,
   },
   'cd' => {
index 8015b29..f6060fe 100644 (file)
@@ -1,6 +1,6 @@
 -- 
 -- Created by SQL::Translator::Producer::SQLite
--- Created on Mon Feb  6 01:07:16 2006
+-- Created on Tue Feb 14 16:16:19 2006
 -- 
 BEGIN TRANSACTION;
 
@@ -117,10 +117,9 @@ CREATE TABLE treelike (
 -- Table: tags
 --
 CREATE TABLE tags (
-  tagid varchar NOT NULL,
+  tagid INTEGER PRIMARY KEY NOT NULL,
   cd integer NOT NULL,
-  tag varchar NOT NULL,
-  PRIMARY KEY (tagid)
+  tag varchar NOT NULL
 );
 
 --
diff --git a/t/run/22cascade_copy.tl b/t/run/22cascade_copy.tl
new file mode 100644 (file)
index 0000000..8c682e5
--- /dev/null
@@ -0,0 +1,23 @@
+use strict;
+use warnings;
+
+sub run_tests {
+my $schema = shift;
+
+plan tests => 4;
+my $artist = $schema->resultset('Artist')->find(1);
+my $artist_cds = $artist->search_related('cds');
+my $cover_band = $artist->copy;
+my $cover_cds = $cover_band->search_related('cds');
+cmp_ok($cover_band->id, '!=', $artist->id, 'ok got new column id...');
+is($cover_cds->count, $artist_cds->count, 'duplicated rows count ok');
+
+#check multi-keyed
+cmp_ok($cover_band->search_related('twokeys')->count, '>', 0, 'duplicated multiPK ok');
+
+#and check copying a few relations away
+cmp_ok($cover_cds->search_related('tags')->count, '==',
+   $artist_cds->search_related('tags')->count , 'duplicated count ok');
+
+}
+1;