From: Peter Rabbitson Date: Fri, 24 Oct 2008 13:29:08 +0000 (+0000) Subject: Massive multi-create testing, with two regression fixes: X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=76b8cf987a839f2f4f5108994396a9470e7d3e5a;p=dbsrgits%2FDBIx-Class-Historic.git Massive multi-create testing, with two regression fixes: - An uninserted row must be passed to find_or_create_related with all uninserted objects on which it depends. Since currently we store those in {_inflated_column} as opposed to {_relationship_data} as we should, a simple ->get_inflated_columns will suffice - We must find_or_create related rows, as find_or_new might queue multiple identical objects for insertions, which will subsequently violate existing unique constraints --- diff --git a/lib/DBIx/Class/Row.pm b/lib/DBIx/Class/Row.pm index 5bbabba..3e0bf64 100644 --- a/lib/DBIx/Class/Row.pm +++ b/lib/DBIx/Class/Row.pm @@ -58,7 +58,7 @@ sub __new_related_find_or_new_helper { return $self->result_source ->related_source($relname) ->resultset - ->find_or_new($data); + ->find_or_create($data); } return $self->find_or_new_related($relname, $data); } @@ -265,7 +265,7 @@ sub insert { my $reverse = $source->reverse_relationship_info($relname); foreach my $obj (@cands) { $obj->set_from_related($_, $self) for keys %$reverse; - my $them = { $obj->get_columns }; + my $them = { $obj->get_inflated_columns }; if ($self->__their_pk_needs_us($relname, $them)) { $obj = $self->find_or_create_related($relname, $them); } else { diff --git a/t/96multi_create.t b/t/96multi_create.t index ba1fe07..8242908 100644 --- a/t/96multi_create.t +++ b/t/96multi_create.t @@ -219,19 +219,93 @@ eval { like($@, qr/cd.artist may not be NULL/, "Exception propogated properly"); # Test multi create over many_to_many -eval { - $schema->resultset('CD')->create ({ - artist => $new_artist, - title => 'Warble Marble', - year => '2009', - cd_to_producer => [ - { producer => { name => 'Cowboy Neal' } }, - ], - }); - - my $m2m_cd = $schema->resultset('CD')->search ({ title => 'Warble Marble'}); - is ($m2m_cd->count, 1, 'One CD object created via M2M create'); - is ($m2m_cd->first->producers->count, 1, 'CD object created with one producer'); - is ($m2m_cd->first->producers->first->name, 'Cowboy Neal', 'Correct producer object created'); -}; -ok (! $@, 'No exceptions on m2m create'); +$schema->resultset('CD')->create ({ + artist => $new_artist, + title => 'Warble Marble', + year => '2009', + cd_to_producer => [ + { producer => { name => 'Cowboy Neal' } }, + ], +}); + +my $m2m_cd = $schema->resultset('CD')->search ({ title => 'Warble Marble'}); +is ($m2m_cd->count, 1, 'One CD row created via M2M create'); +is ($m2m_cd->first->producers->count, 1, 'CD row created with one producer'); +is ($m2m_cd->first->producers->first->name, 'Cowboy Neal', 'Correct producer row created'); + +# and some insane multicreate +# (should work, despite the fact that no one will probably use it this way) + +# first count how many rows do we have + +my $counts; +$counts->{$_} = $schema->resultset($_)->count for qw/Artist CD Genre Producer/; + +# do the crazy create +$schema->resultset('CD')->create ({ + artist => $new_artist, + title => 'Greatest hits 1', + year => '2012', + genre => { + name => '"Greatest" collections', + }, + cd_to_producer => [ + { + producer => { + name => 'Dirty Harry', + producer_to_cd => [ + { + cd => { + artist => { + name => 'Dirty Harry himself', + }, + title => 'Greatest hits 2', + year => 2012, + genre => { + name => '"Greatest" collections', + }, + }, + }, + { + cd => { + artist => { + name => 'Dirty Harry himself', + }, + title => 'Greatest hits 3', + year => 2012, + genre => { + name => '"Greatest" collections', + }, + }, + }, + { + cd => { + artist => $new_artist, + title => 'Greatest hits 4', + year => 2012, + }, + }, + ], + }, + }, + ], +}); + +is ($schema->resultset ('Artist')->count, $counts->{Artist} + 1, 'One new artists created'); # even though the 'name' is not uniquely constrained find_or_create will arguably DWIM +is ($schema->resultset ('Genre')->count, $counts->{Genre} + 1, 'One additional genre created'); +is ($schema->resultset ('Producer')->count, $counts->{Producer} + 1, 'One new producer'); +is ($schema->resultset ('CD')->count, $counts->{CD} + 4, '4 new CDs'); + +my $harry_cds = $schema->resultset ('Artist')->single ({name => 'Dirty Harry himself'})->cds; +is ($harry_cds->count, 2, 'Two CDs created by Harry'); +ok ($harry_cds->single ({title => 'Greatest hits 2'}), 'First CD name correct'); +ok ($harry_cds->single ({title => 'Greatest hits 3'}), 'Second CD name correct'); + +my $harry_productions = $schema->resultset ('Producer')->single ({name => 'Dirty Harry'}) + ->search_related ('producer_to_cd', {})->search_related ('cd', {}); +is ($harry_productions->count, 4, 'All 4 CDs are produced by Harry'); +is ($harry_productions->search ({ year => 2012 })->count, 4, 'All 4 CDs have the correct year'); + +my $hits_genre = $schema->resultset ('Genre')->single ({name => '"Greatest" collections'}); +ok ($hits_genre, 'New genre row found'); +is ($hits_genre->cds->count, 3, 'Three of the new CDs fall into the new genre');