Merge 'trunk' into 'subquery'
Rob Kinyon [Fri, 20 Feb 2009 04:54:00 +0000 (04:54 +0000)]
r5564@rkinyon-lt-osx (orig r5563):  robkinyon | 2009-02-19 23:41:44 -0500
Fixed syntax error
r5567@rkinyon-lt-osx (orig r5566):  matthewt | 2009-02-19 23:42:42 -0500
 r27879@agaton (orig r5540):  robkinyon | 2009-02-20 03:30:17 +0000
 fixed a few more test situations

r5568@rkinyon-lt-osx (orig r5567):  matthewt | 2009-02-19 23:42:54 -0500
 r27883@agaton (orig r5544):  matthewt | 2009-02-20 04:09:04 +0000
 prevent objects implicitly passed via new_related having insertion cascaded to them unless we have to

r5569@rkinyon-lt-osx (orig r5568):  matthewt | 2009-02-19 23:43:04 -0500
 r27884@agaton (orig r5545):  matthewt | 2009-02-20 04:26:22 +0000
 verify non-staged insertion as well

r5570@rkinyon-lt-osx (orig r5569):  matthewt | 2009-02-19 23:43:22 -0500

r5573@rkinyon-lt-osx (orig r5572):  matthewt | 2009-02-19 23:50:50 -0500
changes update for mc fixes

Changes
Makefile.PL
lib/DBIx/Class/ResultSet.pm
lib/DBIx/Class/ResultSource.pm
lib/DBIx/Class/Row.pm
t/96multi_create.t
t/96multi_create_new.t

diff --git a/Changes b/Changes
index e061f5b..9bdf1b9 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,4 +1,8 @@
 Revision history for DBIx::Class
+        - Add DBIC_MULTICREATE_DEBUG env var (undocumented, quasi-internal)
+        - Fix up multi-create to:
+          - correctly propagate columns loaded during multi-insert of rels
+          - not try and insert things tagged on via new_related unless required
         - Possible to set locale in IC::DateTime extra => {} config
         - Calling the accessor of a belongs_to when the foreign_key
           was NULL and the row was not stored would unexpectedly fail (groditi)
index 38a89db..c16fcdb 100644 (file)
@@ -127,7 +127,7 @@ EOW
           alarm 0;
       };
       my $sig = $? & 127;
-      if ($@ || $sig == POSIX::SIGSEGV) {
+      if ($@ || $sig == POSIX::SIGSEGV()) {
           warn (<<EOE);
 
 ############################### WARNING #################################
index 28b2f9a..92cbbd7 100644 (file)
@@ -1701,6 +1701,7 @@ sub new_result {
     && $self->{cond} eq $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION
   ) {
     %new = %{$self->{attrs}{related_objects}};
+    $new{-from_resultset} = [ keys %new ] if keys %new;
   } else {
     $self->throw_exception(
       "Can't abstract implicit construct, condition not a hash"
index 89bc6ff..bc88091 100644 (file)
@@ -1014,9 +1014,6 @@ sub reverse_relationship_info {
       $ret->{$otherrel} =  $otherrel_info;
     }
   }
-use Data::Dumper;
-#warn "return for reverse_relationship_info called on ".$self->name." for $rel:\n";
-#warn Dumper($ret);
   return $ret;
 }
 
index abc34ab..7b22897 100644 (file)
@@ -131,6 +131,10 @@ sub new {
     $new->result_source($source);
   }
 
+  if (my $related = delete $attrs->{-from_resultset}) {
+    @{$new->{_ignore_at_insert}={}}{@$related} = ();
+  }
+
   if ($attrs) {
     $new->throw_exception("attrs must be a hashref")
       unless ref($attrs) eq 'HASH';
@@ -156,7 +160,7 @@ sub new {
             $new->set_from_related($key, $rel_obj);
           } else {
             $new->{_rel_in_storage} = 0;
-            MULTICREATE_DEBUG and warn "MC $new: uninserted $key $rel_obj\n";
+            MULTICREATE_DEBUG and warn "MC $new uninserted $key $rel_obj\n";
           }
 
           $related->{$key} = $rel_obj;
@@ -178,7 +182,7 @@ sub new {
             } else {
               $new->{_rel_in_storage} = 0;
               MULTICREATE_DEBUG and
-                warn "MC $new: uninserted $key $rel_obj ($idx of $total)\n";
+                warn "MC $new uninserted $key $rel_obj (${\($idx+1)} of $total)\n";
             }
             $new->set_from_related($key, $rel_obj) if $rel_obj->in_storage;
             push(@objects, $rel_obj);
@@ -195,7 +199,7 @@ sub new {
           }
           unless ($rel_obj->in_storage) {
             $new->{_rel_in_storage} = 0;
-            MULTICREATE_DEBUG and warn "MC $new: uninserted $key $rel_obj";
+            MULTICREATE_DEBUG and warn "MC $new uninserted $key $rel_obj";
           }
           $inflated->{$key} = $rel_obj;
           next;
@@ -288,7 +292,10 @@ sub insert {
     }
   }
 
-  MULTICREATE_DEBUG and warn "MC $self inserting self\n";
+  MULTICREATE_DEBUG and do {
+    no warnings 'uninitialized';
+    warn "MC $self inserting (".join(', ', $self->get_columns).")\n";
+  };
   my $updated_cols = $source->storage->insert($source, { $self->get_columns });
   foreach my $col (keys %$updated_cols) {
     $self->store_column($col, $updated_cols->{$col});
@@ -319,7 +326,7 @@ sub insert {
   $self->{related_resultsets} = {};
 
   if(!$self->{_rel_in_storage}) {
-    ## Now do the has_many rels, that need $selfs ID.
+    ## Now do the relationships that need our ID (has_many etc.)
     foreach my $relname (keys %related_stuff) {
       my $rel_obj = $related_stuff{$relname};
       my @cands;
@@ -335,10 +342,14 @@ sub insert {
           $obj->set_from_related($_, $self) for keys %$reverse;
           my $them = { %{$obj->{_relationship_data} || {} }, $obj->get_inflated_columns };
           if ($self->__their_pk_needs_us($relname, $them)) {
-            MULTICREATE_DEBUG and warn "MC $self re-creating $relname $obj";
-            my $re = $self->find_or_create_related($relname, $them);
-            $obj->{_column_data} = $re->{_column_data};
-            MULTICREATE_DEBUG and warn "MC $self new $relname $obj";
+            if (exists $self->{_ignore_at_insert}{$relname}) {
+              MULTICREATE_DEBUG and warn "MC $self skipping post-insert on $relname";
+            } else {
+              MULTICREATE_DEBUG and warn "MC $self re-creating $relname $obj";
+              my $re = $self->find_or_create_related($relname, $them);
+              %{$obj} = %{$re};
+              MULTICREATE_DEBUG and warn "MC $self new $relname $obj";
+            }
           } else {
             MULTICREATE_DEBUG and warn "MC $self post-inserting $obj";
             $obj->insert();
@@ -346,6 +357,7 @@ sub insert {
         }
       }
     }
+    delete $self->{_ignore_at_insert};
     $rollback_guard->commit;
   }
 
index 9c75cac..d808eba 100644 (file)
@@ -6,7 +6,7 @@ use Test::Exception;
 use lib qw(t/lib);
 use DBICTest;
 
-plan tests => 85;
+plan tests => 77;
 
 my $schema = DBICTest->init_schema();
 
@@ -513,9 +513,6 @@ eval {
 };
 diag $@ if $@;
 
-TODO: {
-local $TODO = 'Next 2 evals are NOT supposed to work, jnaps code will be torn to bits in another branch';
-#SPECIAL_CASE
 eval {
   my $kurt_cobain = { name => 'Kurt Cobain' };
 
@@ -536,7 +533,8 @@ eval {
 };
 diag $@ if $@;
 
-#SPECIAL_CASE2
+=pod
+# This test case has been moved to t/96multi_create/cd_single.t
 eval {
   my $pink_floyd = { name => 'Pink Floyd' };
 
@@ -552,10 +550,11 @@ eval {
   is($a->cds && $a->cds->first->title, 'The Wall', 'CD insertion ok');
 };
 diag $@ if $@;
-}
-
+=cut
 
 diag '* Create foreign key col obj including PK (See test 20 in 66relationships.t)';
+## Create foreign key col obj including PK
+## See test 20 in 66relationships.t
 eval {
   my $new_cd_hashref = { 
     cdid => 27, 
index 909419f..3d7c1f1 100644 (file)
@@ -6,7 +6,7 @@ use Test::Exception;
 use lib qw(t/lib);
 use DBICTest;
 
-plan 'no_plan';
+plan tests => 9;
 
 my $schema = DBICTest->init_schema();
 
@@ -22,28 +22,42 @@ my $schema = DBICTest->init_schema();
 # to new(). All other objects should be insert()able afterwards too.
 
 
-my $new_artist = $schema->resultset("Artist")->new_result({ 'name' => 'Depeche Mode' });
-my $new_related_cd = $new_artist->new_related('cds', { 'title' => 'Leave in Silence', 'year' => 1982});
-eval {
-       $new_artist->insert;
-       $new_related_cd->insert;
-};
-is ($@, '', 'Staged insertion successful');
-ok($new_artist->in_storage, 'artist inserted');
-ok($new_related_cd->in_storage, 'new_related_cd inserted');
-
-
-my $new_cd = $schema->resultset("CD")->new_result({});
-my $new_related_artist = $new_cd->new_related('artist', { 'name' => 'Marillion',});
-lives_ok (
-    sub {
-       $new_related_artist->insert;
-       $new_cd->title( 'Misplaced Childhood' );
-       $new_cd->year ( 1985 );
-       $new_cd->artist( $new_related_artist );  # For exact backward compatibility
-       $new_cd->insert;
-    },
-    'Reversed staged insertion successful'
-);
-ok($new_related_artist->in_storage, 'related artist inserted');
-ok($new_cd->in_storage, 'cd inserted');
+{
+    my $new_artist = $schema->resultset("Artist")->new_result({ 'name' => 'Depeche Mode' });
+    my $new_related_cd = $new_artist->new_related('cds', { 'title' => 'Leave in Silence', 'year' => 1982});
+    eval {
+        $new_artist->insert;
+        $new_related_cd->insert;
+    };
+    is ($@, '', 'Staged insertion successful');
+    ok($new_artist->in_storage, 'artist inserted');
+    ok($new_related_cd->in_storage, 'new_related_cd inserted');
+}
+
+{
+    my $new_artist = $schema->resultset("Artist")->new_result({ 'name' => 'Depeche Mode' });
+    my $new_related_cd = $new_artist->new_related('cds', { 'title' => 'Leave in Silence', 'year' => 1982});
+    eval {
+        $new_related_cd->insert;
+    };
+    is ($@, '', 'CD insertion survives by inserting artist');
+    ok($new_artist->in_storage, 'artist inserted');
+    ok($new_related_cd->in_storage, 'new_related_cd inserted');
+}
+
+{
+    my $new_cd = $schema->resultset("CD")->new_result({});
+    my $new_related_artist = $new_cd->new_related('artist', { 'name' => 'Marillion',});
+    lives_ok (
+        sub {
+            $new_related_artist->insert;
+            $new_cd->title( 'Misplaced Childhood' );
+            $new_cd->year ( 1985 );
+            $new_cd->artist( $new_related_artist );  # For exact backward compatibility
+            $new_cd->insert;
+        },
+        'Reversed staged insertion successful'
+    );
+    ok($new_related_artist->in_storage, 'related artist inserted');
+    ok($new_cd->in_storage, 'cd inserted');
+}