From: Peter Rabbitson Date: Mon, 8 Feb 2010 11:42:09 +0000 (+0000) Subject: Merge fix of RT54039 from prefetch branch X-Git-Tag: v0.08118~1 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=13d0694958bdf4711743bc0c9b70f8a9d7e93522;p=dbsrgits%2FDBIx-Class.git Merge fix of RT54039 from prefetch branch --- diff --git a/Changes b/Changes index 36bb1ac..2ba69d7 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,7 @@ Revision history for DBIx::Class - - Fix a bug causing UTF8 columns not to be decoded (RT #54395) + - Fix a bug causing UTF8 columns not to be decoded (RT#54395) + - Fix bug in One->Many->One prefetch-collapse handling (RT#54039) - Cleanup handling of relationship accessor types 0.08117 2010-02-05 17:10:00 (UTC) diff --git a/lib/DBIx/Class/Row.pm b/lib/DBIx/Class/Row.pm index e4a1865..eafafe9 100644 --- a/lib/DBIx/Class/Row.pm +++ b/lib/DBIx/Class/Row.pm @@ -1062,9 +1062,10 @@ sub inflate_result { my ($source_handle) = $source; if ($source->isa('DBIx::Class::ResultSourceHandle')) { - $source = $source_handle->resolve - } else { - $source_handle = $source->handle + $source = $source_handle->resolve + } + else { + $source_handle = $source->handle } my $new = { @@ -1073,17 +1074,29 @@ sub inflate_result { }; bless $new, (ref $class || $class); - my $schema; foreach my $pre (keys %{$prefetch||{}}) { - my $pre_val = $prefetch->{$pre}; - my $pre_source = $source->related_source($pre); - $class->throw_exception("Can't prefetch non-existent relationship ${pre}") - unless $pre_source; - if (ref($pre_val->[0]) eq 'ARRAY') { # multi - my @pre_objects; - for my $me_pref (@$pre_val) { + my $pre_source = $source->related_source($pre) + or $class->throw_exception("Can't prefetch non-existent relationship ${pre}"); + + my $accessor = $source->relationship_info($pre)->{attrs}{accessor} + or $class->throw_exception("No accessor for prefetched $pre"); + + my @pre_vals; + if (ref $prefetch->{$pre}[0] eq 'ARRAY') { + @pre_vals = @{$prefetch->{$pre}}; + } + elsif ($accessor eq 'multi') { + $class->throw_exception("Implicit prefetch (via select/columns) not supported with accessor 'multi'"); + } + else { + @pre_vals = $prefetch->{$pre}; + } + + my @pre_objects; + for my $me_pref (@pre_vals) { + # FIXME - this should not be necessary # the collapser currently *could* return bogus elements with all # columns set to undef my $has_def; @@ -1098,31 +1111,16 @@ sub inflate_result { push @pre_objects, $pre_source->result_class->inflate_result( $pre_source, @$me_pref ); - } - - $new->related_resultset($pre)->set_cache(\@pre_objects); - } elsif (defined $pre_val->[0]) { - my $fetched; - unless ($pre_source->primary_columns == grep { exists $pre_val->[0]{$_} - and !defined $pre_val->[0]{$_} } $pre_source->primary_columns) - { - $fetched = $pre_source->result_class->inflate_result( - $pre_source, @{$pre_val}); - } - my $acc_type = $source->relationship_info($pre)->{attrs}{accessor} - or $class->throw_exception("No accessor type for prefetched $pre"); + } - if ($acc_type eq 'single') { - $new->{_relationship_data}{$pre} = $fetched; - } - elsif ($acc_type eq 'filter') { - $new->{_inflated_column}{$pre} = $fetched; - } - else { - $class->throw_exception("Implicit prefetch (via select/columns) not supported with accessor type '$acc_type'"); - } - $new->related_resultset($pre)->set_cache([ $fetched ]); + if ($accessor eq 'single') { + $new->{_relationship_data}{$pre} = $pre_objects[0]; } + elsif ($accessor eq 'filter') { + $new->{_inflated_column}{$pre} = $pre_objects[0]; + } + + $new->related_resultset($pre)->set_cache(\@pre_objects); } $new->in_storage (1); diff --git a/t/prefetch/one_to_many_to_one.t b/t/prefetch/one_to_many_to_one.t new file mode 100644 index 0000000..daa76bd --- /dev/null +++ b/t/prefetch/one_to_many_to_one.t @@ -0,0 +1,35 @@ +use strict; +use warnings; + +use Test::More; +use Test::Exception; + +use lib qw(t/lib); +use DBICTest; + +my $schema = DBICTest->init_schema(); + +my $artist = $schema->resultset ('Artist')->find ({artistid => 1}); +is ($artist->cds->count, 3, 'Correct number of CDs'); +is ($artist->cds->search_related ('genre')->count, 1, 'Only one of the cds has a genre'); + +my $queries = 0; +my $orig_cb = $schema->storage->debugcb; +$schema->storage->debugcb(sub { $queries++ }); +$schema->storage->debug(1); + + +my $pref = $schema->resultset ('Artist') + ->search ({ 'me.artistid' => $artist->id }, { prefetch => { cds => 'genre' } }) + ->next; + +is ($pref->cds->count, 3, 'Correct number of CDs prefetched'); +is ($pref->cds->search_related ('genre')->count, 1, 'Only one of the prefetched cds has a prefetched genre'); + + +is ($queries, 1, 'All happened within one query only'); +$schema->storage->debugcb($orig_cb); +$schema->storage->debug(0); + + +done_testing;