Merge 'multicreate_fixes' into 'trunk'
Peter Rabbitson [Sun, 9 Aug 2009 13:25:34 +0000 (13:25 +0000)]
r6535@Thesaurus (orig r6534):  ribasushi | 2009-06-06 11:12:03 +0200
Let's try again
r6536@Thesaurus (orig r6535):  ribasushi | 2009-06-06 11:32:00 +0200
Two failing MC tests
r6624@Thesaurus (orig r6623):  ribasushi | 2009-06-11 16:54:09 +0200
Another multicreate failing test - has_many should not do find_or_create
r6625@Thesaurus (orig r6624):  ribasushi | 2009-06-11 16:54:49 +0200
 r6538@Thesaurus (orig r6537):  ribasushi | 2009-06-07 23:07:55 +0200
 Fix for mysql subquery problem
 r6539@Thesaurus (orig r6538):  ribasushi | 2009-06-07 23:36:43 +0200
 Make empty/default inserts use standard SQL
 r6540@Thesaurus (orig r6539):  ribasushi | 2009-06-08 00:59:21 +0200
 Add mysql empty insert SQL override
 Make SQLAHacks parts loadable at runtime via ensure_class_loaded
 r6541@Thesaurus (orig r6540):  ribasushi | 2009-06-08 01:03:04 +0200
 Make podcoverage happy
 r6542@Thesaurus (orig r6541):  ribasushi | 2009-06-08 01:24:06 +0200
 Fix find_or_new/create to stop returning random rows when default value insert is requested
 r6543@Thesaurus (orig r6542):  ribasushi | 2009-06-08 11:36:56 +0200
 Simply order_by/_virtual_order_by handling
 r6553@Thesaurus (orig r6552):  ribasushi | 2009-06-08 23:56:41 +0200
 duh
 r6557@Thesaurus (orig r6556):  ash | 2009-06-09 12:20:34 +0200
 Addjust bug to show problem with rows => 1 + child rel

 r6558@Thesaurus (orig r6557):  ribasushi | 2009-06-09 13:12:46 +0200
 Require a recent bugfixed Devel::Cycle
 r6560@Thesaurus (orig r6559):  ash | 2009-06-09 15:07:30 +0200
 Make IC::DT extra warning state the column name too

 r6575@Thesaurus (orig r6574):  ribasushi | 2009-06-10 00:19:48 +0200
 AuthorCheck fixes
 r6579@Thesaurus (orig r6578):  ribasushi | 2009-06-10 00:52:17 +0200
  r6522@Thesaurus (orig r6521):  ribasushi | 2009-06-05 19:27:55 +0200
  New branch to try resultsource related stuff
  r6545@Thesaurus (orig r6544):  ribasushi | 2009-06-08 13:00:54 +0200
  First stab at adding resultsources to each join in select - works won-der-ful-ly
  r6546@Thesaurus (orig r6545):  ribasushi | 2009-06-08 13:14:08 +0200
  Commit failing test and thoughts on search arg deflation
  r6576@Thesaurus (orig r6575):  ribasushi | 2009-06-10 00:31:55 +0200
  Todoify DT in search deflation test until after 0.09
  r6577@Thesaurus (orig r6576):  ribasushi | 2009-06-10 00:48:07 +0200
  Factor out the $ident resolver

 r6581@Thesaurus (orig r6580):  ribasushi | 2009-06-10 01:21:50 +0200
 Move as_query out of the cursor
 r6582@Thesaurus (orig r6581):  ribasushi | 2009-06-10 01:27:19 +0200
 Think before commit
 r6583@Thesaurus (orig r6582):  ribasushi | 2009-06-10 09:37:19 +0200
 Clarify and disable rows/prefetch test - fix is easy, but architecturally unsound - need more time
 r6591@Thesaurus (orig r6590):  ribasushi | 2009-06-10 13:33:37 +0200
  r6544@Thesaurus (orig r6543):  ribasushi | 2009-06-08 11:44:59 +0200
  Attempt to figure out why do we repeat joins on complex search_related
  r6586@Thesaurus (orig r6585):  ribasushi | 2009-06-10 11:22:05 +0200
  Move the rs preservation test to a more suitable place
  r6589@Thesaurus (orig r6588):  ribasushi | 2009-06-10 13:15:48 +0200
  Finally commit trully failing test
  r6590@Thesaurus (orig r6589):  ribasushi | 2009-06-10 13:33:14 +0200
  Duh, this was a pretty simple bug

 r6593@Thesaurus (orig r6592):  ribasushi | 2009-06-10 13:43:31 +0200
 What was I thinking - resultsource does not have an ->alias
 r6598@Thesaurus (orig r6597):  ribasushi | 2009-06-10 14:48:39 +0200
 Adjust changelog
 r6601@Thesaurus (orig r6600):  ribasushi | 2009-06-10 15:50:43 +0200
 Release 0.08104
 r6615@Thesaurus (orig r6614):  ribasushi | 2009-06-11 14:29:48 +0200
 Move around inflation tests
 r6616@Thesaurus (orig r6615):  ribasushi | 2009-06-11 14:32:07 +0200
 explicitly remove manifest on author mode make
 r6617@Thesaurus (orig r6616):  ribasushi | 2009-06-11 15:02:41 +0200
 IC::DT changes:
 Switch SQLite storage to DT::F::SQLite
 Fix exception when undef_if_invalid and timezone are both set on a column
 Split t/89inflate_datetime into separate tests
 Adjust makefile author dependencies
 r6618@Thesaurus (orig r6617):  ribasushi | 2009-06-11 15:07:41 +0200
 Move file_column test to inflate/ too
 r6621@Thesaurus (orig r6620):  ribasushi | 2009-06-11 16:16:20 +0200
  r5713@Thesaurus (orig r5712):  ribasushi | 2009-03-08 23:53:28 +0100
  Branch for datatype-aware updates
  r6604@Thesaurus (orig r6603):  ribasushi | 2009-06-10 18:08:25 +0200
  Test for type-aware update
  r6607@Thesaurus (orig r6606):  ribasushi | 2009-06-10 19:57:04 +0200
  Datatype aware update works
  r6609@Thesaurus (orig r6608):  ribasushi | 2009-06-10 20:06:40 +0200
  Whoops
  r6614@Thesaurus (orig r6613):  ribasushi | 2009-06-11 09:23:54 +0200
  Add attribute doc
  r6620@Thesaurus (orig r6619):  ribasushi | 2009-06-11 16:15:53 +0200
  Use equality, not comparison

 r6623@Thesaurus (orig r6622):  ribasushi | 2009-06-11 16:21:53 +0200
 Changes

r6626@Thesaurus (orig r6625):  ribasushi | 2009-06-11 17:00:06 +0200
Adjust renamed relationship
r6646@Thesaurus (orig r6645):  ribasushi | 2009-06-12 09:00:02 +0200
This is not update_or_create - create any non-belongs_to without asking many questions
r7194@Thesaurus (orig r7191):  ribasushi | 2009-08-04 15:20:35 +0200
fix merge fallout
r7195@Thesaurus (orig r7192):  ribasushi | 2009-08-04 15:39:05 +0200
Remove bogus test - the real test is in t/multi_create/has_many.t
r7196@Thesaurus (orig r7193):  ribasushi | 2009-08-04 15:48:33 +0200
Separate the diamond MC test
Use the new Test::More's no_plan ability
r7274@Thesaurus (orig r7271):  ribasushi | 2009-08-09 14:39:29 +0200
Fix an arcane case with pk==fk tables (use the relationship direction specification if it is available
r7275@Thesaurus (orig r7272):  ribasushi | 2009-08-09 14:45:20 +0200
Optimize handling of {_rel_in_storage}, greatly reducing the amounf ot find_or_create calls (as indicated by the TODOs in t/multi_create/reentrance_count.t
r7277@Thesaurus (orig r7274):  ribasushi | 2009-08-09 15:23:24 +0200
Comment and todoify remaining test - too much of an undertaking / needs discussion
r7278@Thesaurus (orig r7275):  ribasushi | 2009-08-09 15:24:58 +0200
newline

Changes
lib/DBIx/Class/ResultSource.pm
lib/DBIx/Class/Row.pm
t/multi_create/diamond.t [new file with mode: 0644]
t/multi_create/existing_in_chain.t [new file with mode: 0644]
t/multi_create/has_many.t [new file with mode: 0644]
t/multi_create/multilev_single_PKeqFK.t
t/multi_create/standard.t

diff --git a/Changes b/Changes
index 51cd72a..a561748 100644 (file)
--- a/Changes
+++ b/Changes
@@ -36,6 +36,7 @@ Revision history for DBIx::Class
         - New ::Storage::DBI method last_dbh() - it will still return a
           newly connected $dbh if we start unconnected, but will not ping
           the server on every invocation unlike dbh()
+        - Some fixes of multi-create corner cases
         - Multiple POD improvements
 
 0.08108 2009-07-05 23:15:00 (UTC)
index f3c4b4f..dfa4c78 100644 (file)
@@ -1265,18 +1265,22 @@ sub pk_depends_on {
 # hashref of columns of the related object.
 sub _pk_depends_on {
   my ($self, $relname, $rel_data) = @_;
-  my $cond = $self->relationship_info($relname)->{cond};
 
+  my $relinfo = $self->relationship_info($relname);
+
+  # don't assume things if the relationship direction is specified
+  return $relinfo->{attrs}{is_foreign_key_constraint}
+    if exists ($relinfo->{attrs}{is_foreign_key_constraint});
+
+  my $cond = $relinfo->{cond};
   return 0 unless ref($cond) eq 'HASH';
 
   # map { foreign.foo => 'self.bar' } to { bar => 'foo' }
-
   my $keyhash = { map { my $x = $_; $x =~ s/.*\.//; $x; } reverse %$cond };
 
   # assume anything that references our PK probably is dependent on us
   # rather than vice versa, unless the far side is (a) defined or (b)
   # auto-increment
-
   my $rel_source = $self->related_source($relname);
 
   foreach my $p ($self->primary_columns) {
index 158c215..89f1de3 100644 (file)
@@ -164,8 +164,6 @@ sub new {
       unless ref($attrs) eq 'HASH';
 
     my ($related,$inflated);
-    ## Pretend all the rels are actual objects, unset below if not, for insert() to fix
-    $new->{_rel_in_storage} = 1;
 
     foreach my $key (keys %$attrs) {
       if (ref $attrs->{$key}) {
@@ -181,9 +179,9 @@ sub new {
           }
 
           if ($rel_obj->in_storage) {
+            $new->{_rel_in_storage}{$key} = 1;
             $new->set_from_related($key, $rel_obj);
           } else {
-            $new->{_rel_in_storage} = 0;
             MULTICREATE_DEBUG and warn "MC $new uninserted $key $rel_obj\n";
           }
 
@@ -202,13 +200,11 @@ sub new {
             }
 
             if ($rel_obj->in_storage) {
-              $new->set_from_related($key, $rel_obj);
+              $rel_obj->throw_exception ('A multi relationship can not be pre-existing when doing multicreate. Something went wrong');
             } else {
-              $new->{_rel_in_storage} = 0;
               MULTICREATE_DEBUG and
                 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);
           }
           $related->{$key} = \@objects;
@@ -221,8 +217,10 @@ sub new {
           if(!Scalar::Util::blessed($rel_obj)) {
             $rel_obj = $new->__new_related_find_or_new_helper($key, $rel_obj);
           }
-          unless ($rel_obj->in_storage) {
-            $new->{_rel_in_storage} = 0;
+          if ($rel_obj->in_storage) {
+            $new->{_rel_in_storage}{$key} = 1;
+          }
+          else {
             MULTICREATE_DEBUG and warn "MC $new uninserted $key $rel_obj";
           }
           $inflated->{$key} = $rel_obj;
@@ -286,27 +284,21 @@ sub insert {
   my %related_stuff = (%{$self->{_relationship_data} || {}},
                        %{$self->{_inflated_column} || {}});
 
-  if(!$self->{_rel_in_storage}) {
-
-    # The guard will save us if we blow out of this scope via die
-    $rollback_guard = $source->storage->txn_scope_guard;
-
-    ## Should all be in relationship_data, but we need to get rid of the
-    ## 'filter' reltype..
-    ## These are the FK rels, need their IDs for the insert.
-
-    my @pri = $self->primary_columns;
+  # insert what needs to be inserted before us
+  my %pre_insert;
+  for my $relname (keys %related_stuff) {
+    my $rel_obj = $related_stuff{$relname};
 
-    REL: foreach my $relname (keys %related_stuff) {
+    if (! $self->{_rel_in_storage}{$relname}) {
+      next unless (Scalar::Util::blessed($rel_obj)
+                    && $rel_obj->isa('DBIx::Class::Row'));
 
-      my $rel_obj = $related_stuff{$relname};
+      next unless $source->_pk_depends_on(
+                    $relname, { $rel_obj->get_columns }
+                  );
 
-      next REL unless (Scalar::Util::blessed($rel_obj)
-                       && $rel_obj->isa('DBIx::Class::Row'));
-
-      next REL unless $source->_pk_depends_on(
-                        $relname, { $rel_obj->get_columns }
-                      );
+      # The guard will save us if we blow out of this scope via die
+      $rollback_guard ||= $source->storage->txn_scope_guard;
 
       MULTICREATE_DEBUG and warn "MC $self pre-reconstructing $relname $rel_obj\n";
 
@@ -315,10 +307,19 @@ sub insert {
                     ->related_source($relname)
                     ->resultset
                     ->find_or_create($them);
+
       %{$rel_obj} = %{$re};
-      $self->set_from_related($relname, $rel_obj);
-      delete $related_stuff{$relname};
+      $self->{_rel_in_storage}{$relname} = 1;
     }
+
+    $self->set_from_related($relname, $rel_obj);
+    delete $related_stuff{$relname};
+  }
+
+  # start a transaction here if not started yet and there is more stuff
+  # to insert after us
+  if (keys %related_stuff) {
+    $rollback_guard ||= $source->storage->txn_scope_guard
   }
 
   MULTICREATE_DEBUG and do {
@@ -332,13 +333,12 @@ sub insert {
 
   ## PK::Auto
   my @auto_pri = grep {
-                   !defined $self->get_column($_) ||
-                   ref($self->get_column($_)) eq 'SCALAR'
+                  (not defined $self->get_column($_))
+                    ||
+                  (ref($self->get_column($_)) eq 'SCALAR')
                  } $self->primary_columns;
 
   if (@auto_pri) {
-    #$self->throw_exception( "More than one possible key found for auto-inc on ".ref $self )
-    #  if defined $too_many;
     MULTICREATE_DEBUG and warn "MC $self fetching missing PKs ".join(', ', @auto_pri)."\n";
     my $storage = $self->result_source->storage;
     $self->throw_exception( "Missing primary key but Storage doesn't support last_insert_id" )
@@ -353,47 +353,48 @@ sub insert {
   $self->{_dirty_columns} = {};
   $self->{related_resultsets} = {};
 
-  if(!$self->{_rel_in_storage}) {
-    ## 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;
-      if (Scalar::Util::blessed($rel_obj)
-          && $rel_obj->isa('DBIx::Class::Row')) {
-        @cands = ($rel_obj);
-      } elsif (ref $rel_obj eq 'ARRAY') {
-        @cands = @$rel_obj;
-      }
-      if (@cands) {
-        my $reverse = $source->reverse_relationship_info($relname);
-        foreach my $obj (@cands) {
-          $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)) {
-            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->result_source
-                            ->related_source($relname)
-                            ->resultset
-                            ->find_or_create($them);
-              %{$obj} = %{$re};
-              MULTICREATE_DEBUG and warn "MC $self new $relname $obj";
-            }
+  foreach my $relname (keys %related_stuff) {
+    my $rel_obj = $related_stuff{$relname};
+    my @cands;
+    if (Scalar::Util::blessed($rel_obj)
+          && $rel_obj->isa('DBIx::Class::Row'))
+    {
+      @cands = ($rel_obj);
+    }
+    elsif (ref $rel_obj eq 'ARRAY') {
+      @cands = @$rel_obj;
+    }
+
+    if (@cands) {
+      my $reverse = $source->reverse_relationship_info($relname);
+      foreach my $obj (@cands) {
+        $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)) {
+          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 post-inserting $obj";
-            $obj->insert();
+            MULTICREATE_DEBUG and warn "MC $self re-creating $relname $obj";
+            my $re = $self->result_source
+                          ->related_source($relname)
+                          ->resultset
+                          ->create($them);
+            %{$obj} = %{$re};
+            MULTICREATE_DEBUG and warn "MC $self new $relname $obj";
           }
+        } else {
+          MULTICREATE_DEBUG and warn "MC $self post-inserting $obj";
+          $obj->insert();
         }
       }
     }
-    delete $self->{_ignore_at_insert};
-    $rollback_guard->commit;
   }
 
   $self->in_storage(1);
-  undef $self->{_orig_ident};
+  delete $self->{_orig_ident};
+  delete $self->{_ignore_at_insert};
+  $rollback_guard->commit if $rollback_guard;
+
   return $self;
 }
 
diff --git a/t/multi_create/diamond.t b/t/multi_create/diamond.t
new file mode 100644 (file)
index 0000000..499f7a1
--- /dev/null
@@ -0,0 +1,52 @@
+use strict;
+use warnings;
+
+use Test::More;
+use Test::Exception;
+use lib qw(t/lib);
+use DBICTest;
+
+sub mc_diag { diag (@_) if $ENV{DBIC_MULTICREATE_DEBUG} };
+
+my $schema = DBICTest->init_schema();
+
+mc_diag (<<'DG');
+* Try a diamond multicreate
+
+Artist -> has_many -> Artwork_to_Artist -> belongs_to
+                                               /
+  belongs_to <- CD <- belongs_to <- Artwork <-/
+    \
+     \-> Artist2
+
+DG
+
+lives_ok (sub {
+  $schema->resultset ('Artist')->create ({
+    name => 'The wooled wolf',
+    artwork_to_artist => [{
+      artwork => {
+        cd => {
+          title => 'Wool explosive',
+          year => 1999,
+          artist => { name => 'The black exploding sheep' },
+        }
+      }
+    }],
+  });
+
+  my $art2 = $schema->resultset ('Artist')->find ({ name => 'The black exploding sheep' });
+  ok ($art2, 'Second artist exists');
+
+  my $cd = $art2->cds->single;
+  is ($cd->title, 'Wool explosive', 'correctly created CD');
+
+  is_deeply (
+    [ $cd->artwork->artists->get_column ('name')->all ],
+    [ 'The wooled wolf' ],
+    'Artist correctly attached to artwork',
+  );
+
+}, 'Diamond chain creation ok');
+
+done_testing;
diff --git a/t/multi_create/existing_in_chain.t b/t/multi_create/existing_in_chain.t
new file mode 100644 (file)
index 0000000..825fad4
--- /dev/null
@@ -0,0 +1,105 @@
+use strict;
+use warnings;
+
+use Test::More;
+use Test::Exception;
+use lib qw(t/lib);
+use DBICTest;
+
+my $schema = DBICTest->init_schema();
+
+# For fully intuitive multicreate any relationships in a chain
+# that do not exist for one reason or another should be created,
+# even if the preceeding relationship already exists.
+#
+# To get this to work a minor rewrite of find() is necessary, and
+# more importantly some sort of recursive_insert() call needs to 
+# be available. The way things will work then is:
+# *) while traversing the hierarchy code calls find_or_create()
+# *) this in turn calls find(%\nested_dataset)
+# *) this should return not only the existing object, but must
+#    also attach all non-existing (in fact maybe existing) related
+#    bits of data to it, with in_storage => 0
+# *) then before returning the result of the succesful find(), we
+#    simply call $obj->recursive_insert and all is dandy
+#
+# Since this will not be a very clean solution, todoifying for the
+# time being until an actual need arises
+#
+# ribasushi
+
+TODO: { my $f = __FILE__; local $TODO = "See comment at top of $f for discussion of the TODO";
+
+{
+  my $counts;
+  $counts->{$_} = $schema->resultset($_)->count for qw/Track CD Genre/;
+
+  lives_ok (sub {
+    my $existing_nogen_cd = $schema->resultset('CD')->search (
+      { 'genre.genreid' => undef },
+      { join => 'genre' },
+    )->first;
+
+    $schema->resultset('Track')->create ({
+      title => 'Sugar-coated',
+      cd => {
+        title => $existing_nogen_cd->title,
+        genre => {
+          name => 'sugar genre',
+        }
+      }
+    });
+
+    is ($schema->resultset('Track')->count, $counts->{Track} + 1, '1 new track');
+    is ($schema->resultset('CD')->count, $counts->{CD}, 'No new cds');
+    is ($schema->resultset('Genre')->count, $counts->{Genre} + 1, '1 new genre');
+
+    is ($existing_nogen_cd->genre->title,  'sugar genre', 'Correct genre assigned to CD');
+  }, 'create() did not throw');
+}
+{
+  my $counts;
+  $counts->{$_} = $schema->resultset($_)->count for qw/Artist CD Producer/;
+
+  lives_ok (sub {
+    my $artist = $schema->resultset('Artist')->first;
+    my $producer = $schema->resultset('Producer')->create ({ name => 'the queen of england' });
+
+    $schema->resultset('CD')->create ({
+      artist => $artist,
+      title => 'queen1',
+      year => 2007,
+      cd_to_producer => [
+        {
+          producer => {
+          name => $producer->name,
+            producer_to_cd => [
+              {
+                cd => {
+                  title => 'queen2',
+                  year => 2008,
+                  artist => $artist,
+                },
+              },
+            ],
+          },
+        },
+      ],
+    });
+
+    is ($schema->resultset('Artist')->count, $counts->{Artist}, 'No new artists');
+    is ($schema->resultset('Producer')->count, $counts->{Producer} + 1, '1 new producers');
+    is ($schema->resultset('CD')->count, $counts->{CD} + 2, '2 new cds');
+
+    is ($producer->cds->count, 2, 'CDs assigned to correct producer');
+    is_deeply (
+      [ $producer->cds->search ({}, { order_by => 'title' })->get_column('title')->all],
+      [ qw/queen1 queen2/ ],
+      'Correct cd names',
+    );
+  }, 'create() did not throw');
+}
+
+}
+
+done_testing;
diff --git a/t/multi_create/has_many.t b/t/multi_create/has_many.t
new file mode 100644 (file)
index 0000000..2d6818e
--- /dev/null
@@ -0,0 +1,33 @@
+use strict;
+use warnings;
+
+use Test::More;
+use Test::Exception;
+use lib qw(t/lib);
+use DBICTest;
+
+plan tests => 2;
+
+my $schema = DBICTest->init_schema();
+
+my $track_no_lyrics = $schema->resultset ('Track')
+              ->search ({ 'lyrics.lyric_id' => undef }, { join => 'lyrics' })
+                ->first;
+
+my $lyric = $track_no_lyrics->create_related ('lyrics', {
+  lyric_versions => [
+    { text => 'english doubled' },
+    { text => 'english doubled' },
+  ],
+});
+is ($lyric->lyric_versions->count, 2, "Two identical has_many's created");
+
+
+my $link = $schema->resultset ('Link')->create ({
+  url => 'lolcats!',
+  bookmarks => [
+    {},
+    {},
+  ]
+});
+is ($link->bookmarks->count, 2, "Two identical default-insert has_many's created");
index 07101a2..ef5c9a8 100644 (file)
@@ -8,8 +8,6 @@ use DBICTest;
 
 sub mc_diag { diag (@_) if $ENV{DBIC_MULTICREATE_DEBUG} };
 
-plan tests => 26;
-
 my $schema = DBICTest->init_schema();
 
 mc_diag (<<'DG');
@@ -102,4 +100,4 @@ for my $type (qw/has_one might_have/) {
   }, "multilevel $type with a PK == FK in the $type/has_many table ok");
 }
 
-1;
+done_testing;
index 9cd754f..57993cf 100644 (file)
@@ -6,7 +6,7 @@ use Test::Exception;
 use lib qw(t/lib);
 use DBICTest;
 
-plan tests => 93;
+plan tests => 91;
 
 my $schema = DBICTest->init_schema();
 
@@ -329,26 +329,6 @@ lives_ok ( sub {
 }, 'Nested find_or_create');
 
 lives_ok ( sub {
-  my $artist2 = $schema->resultset('Artist')->create({
-    name => 'Fred 4',
-    cds => [
-      {
-        title => 'Music to code by',
-        year => 2007,
-      },
-    ],
-    cds_unordered => [
-      {
-        title => 'Music to code by',
-        year => 2007,
-      },
-    ]
-  });
-
-  is($artist2->in_storage, 1, 'artist with duplicate rels inserted okay');
-}, 'Multiple same level has_many create');
-
-lives_ok ( sub {
        my $artist = $schema->resultset('Artist')->first;
        
        my $cd_result = $artist->create_related('cds', {