From: Peter Rabbitson Date: Fri, 27 Nov 2009 00:38:11 +0000 (+0000) Subject: Fix search_related wrt grouped resultsets (distinct is currently passed to the new... X-Git-Tag: v0.08116~117 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=533b7dba76d252c96cc17a6fe8c409bb20ebfcde;p=dbsrgits%2FDBIx-Class.git Fix search_related wrt grouped resultsets (distinct is currently passed to the new resultset, this is probably wrong) --- diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index 468816b..d8645ba 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -2518,9 +2518,9 @@ sub related_resultset { "' has no such relationship $rel") unless $rel_info; - my ($from,$seen,$attrs) = $self->_chain_relationship($rel); + my $attrs = $self->_chain_relationship($rel); - my $join_count = $seen->{$rel}; + my $join_count = $attrs->{seen_join}{$rel}; my $alias = ($join_count > 1 ? join('_', $rel, $join_count) : $rel); #XXX - temp fix for result_class bug. There likely is a more elegant fix -groditi @@ -2552,13 +2552,7 @@ sub related_resultset { ->search_rs( undef, { %$attrs, - join => undef, - prefetch => undef, - select => undef, - as => undef, - where => $self->{cond}, - seen_join => $seen, - from => $from, + where => $attrs->{where}, }); }; $new->set_cache($new_cache) if $new_cache; @@ -2627,8 +2621,16 @@ sub _chain_relationship { my $source = $self->result_source; my $attrs = { %{$self->{attrs}||{}} }; + # we need to take the prefetch the attrs into account before we + # ->_resolve_join as otherwise they get lost - captainL + my $join = $self->_merge_attr( $attrs->{join}, $attrs->{prefetch} ); + + delete @{$attrs}{qw/join prefetch collapse select as columns +select +as +columns/}; + + my $seen = { %{ (delete $attrs->{seen_join}) || {} } }; + my $from; - my @force_subq_attrs = qw/offset rows/; + my @force_subq_attrs = qw/offset rows group_by having/; if ( ($attrs->{from} && ref $attrs->{from} ne 'ARRAY') @@ -2640,7 +2642,8 @@ sub _chain_relationship { -alias => $attrs->{alias}, $attrs->{alias} => $self->as_query, }]; - delete @{$attrs}{@force_subq_attrs}; + delete @{$attrs}{@force_subq_attrs, 'where'}; + $seen->{-relation_chain_depth} = 0; } elsif ($attrs->{from}) { #shallow copy suffices $from = [ @{$attrs->{from}} ]; @@ -2653,17 +2656,12 @@ sub _chain_relationship { }]; } - my $seen = { %{$attrs->{seen_join} || {} } }; - my $jpath = ($attrs->{seen_join} && keys %{$attrs->{seen_join}}) + my $jpath = ($seen->{-relation_chain_depth}) ? $from->[-1][0]{-join_path} : []; - # we need to take the prefetch the attrs into account before we - # ->_resolve_join as otherwise they get lost - captainL - my $merged = $self->_merge_attr( $attrs->{join}, $attrs->{prefetch} ); - my @requested_joins = $source->_resolve_join( - $merged, + $join, $attrs->{alias}, $seen, $jpath, @@ -2710,7 +2708,7 @@ sub _chain_relationship { $seen->{-relation_chain_depth}++; - return ($from,$seen,$attrs); + return {%$attrs, from => $from, seen_join => $seen}; } # too many times we have to do $attrs = { %{$self->_resolved_attrs} } diff --git a/t/count/prefetch.t b/t/count/prefetch.t index a0b6d75..6959400 100644 --- a/t/count/prefetch.t +++ b/t/count/prefetch.t @@ -53,8 +53,15 @@ my $schema = DBICTest->init_schema(); SELECT COUNT( * ) FROM ( SELECT genre.genreid - FROM artist me - JOIN cd cds ON cds.artist = me.artistid + FROM ( + SELECT cds.cdid, cds.artist, cds.title, cds.year, cds.genreid, cds.single_track + FROM ( + SELECT me.artistid, me.name, me.rank, me.charfield + FROM artist me GROUP BY me.artistid, me.name, me.rank, me.charfield + ) me + LEFT JOIN cd cds ON cds.artist = me.artistid + GROUP BY cds.cdid, cds.artist, cds.title, cds.year, cds.genreid, cds.single_track + ) cds JOIN genre genre ON genre.genreid = cds.genreid LEFT JOIN cd cds_2 ON cds_2.genreid = genre.genreid WHERE ( genre.name = ? ) diff --git a/t/count/search_related.t b/t/count/search_related.t index b9804ea..11f5796 100644 --- a/t/count/search_related.t +++ b/t/count/search_related.t @@ -14,7 +14,28 @@ my $track_count = $cd_rs->first->tracks->count; cmp_ok ($track_count, '>', 1, 'First CD has several tracks'); -is ($cd_rs->search_related ('tracks')->count, $track_count, 'related->count returns correct number'); -is (scalar ($cd_rs->search_related ('tracks')->all), $track_count, 'related->all returns correct number of objects'); +is ($cd_rs->search_related ('tracks')->count, $track_count, 'related->count returns correct number chained off a limited rs'); +is (scalar ($cd_rs->search_related ('tracks')->all), $track_count, 'related->all returns correct number of objects chained off a limited rs'); + + +my $joined_cd_rs = $cd_rs->search ({}, { + join => 'tracks', rows => 2, distinct => 1, having => \ 'count(tracks.trackid) > 2', +}); + +my $multiple_track_count = $schema->resultset('Track')->search ({ + cd => { -in => $joined_cd_rs->get_column ('cdid')->as_query } +})->count; + + +is ( + $joined_cd_rs->search_related ('tracks')->count, + $multiple_track_count, + 'related->count returns correct number chained off a grouped rs', +); +is ( + scalar ($joined_cd_rs->search_related ('tracks')->all), + $multiple_track_count, + 'related->all returns correct number of objects chained off a grouped rs', +); done_testing;