From: Peter Rabbitson Date: Sun, 28 Jun 2009 08:35:11 +0000 (+0000) Subject: The proposed fix (do not add an extra join if it is already present in the topmost... X-Git-Tag: v0.08108~43^2~2 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=096395af8e16de3f81ba55540e7379e82a192abf;p=dbsrgits%2FDBIx-Class.git The proposed fix (do not add an extra join if it is already present in the topmost join) --- diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index b012e03..1524efe 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -2450,7 +2450,7 @@ sub related_resultset { "' has no such relationship $rel") unless $rel_info; - my ($from,$seen) = $self->_resolve_from($rel); + my ($from,$seen) = $self->_chain_relationship($rel); my $join_count = $seen->{$rel}; my $alias = ($join_count > 1 ? join('_', $rel, $join_count) : $rel); @@ -2548,7 +2548,7 @@ sub current_source_alias { # in order to properly resolve prefetch aliases (any alias # with a relation_chain_depth less than the depth of the # current prefetch is not considered) -sub _resolve_from { +sub _chain_relationship { my ($self, $rel) = @_; my $source = $self->result_source; my $attrs = $self->{attrs}; @@ -2569,11 +2569,28 @@ sub _resolve_from { # ->_resolve_join as otherwise they get lost - captainL my $merged = $self->_merge_attr( $attrs->{join}, $attrs->{prefetch} ); - push @$from, $source->_resolve_join($merged, $attrs->{alias}, $seen) if ($merged); + my @requested_joins = $source->_resolve_join($merged, $attrs->{alias}, $seen); + + push @$from, @requested_joins; ++$seen->{-relation_chain_depth}; - push @$from, $source->_resolve_join($rel, $attrs->{alias}, $seen); + # if $self already had a join/prefetch specified on it, the requested + # $rel might very well be already included. What we do in this case + # is effectively a no-op (except that we bump up the chain_depth on + # the join in question + my $already_joined; + for my $j (@requested_joins) { + if ($rel eq $j->[0]{-join_path}[-1]) { + $j->[0]{-relation_chain_depth}++; + $already_joined++; + last; + } + } + + unless ($already_joined) { + push @$from, $source->_resolve_join($rel, $attrs->{alias}, $seen); + } ++$seen->{-relation_chain_depth}; diff --git a/lib/DBIx/Class/ResultSource.pm b/lib/DBIx/Class/ResultSource.pm index d6fd004..4eca0f8 100644 --- a/lib/DBIx/Class/ResultSource.pm +++ b/lib/DBIx/Class/ResultSource.pm @@ -893,7 +893,7 @@ sub add_relationship { } return unless $f_source; # Can't test rel without f_source - eval { $self->_resolve_join($rel, 'me') }; + eval { $self->_resolve_join($rel, 'me', {}) }; if ($@) { # If the resolve failed, back out and re-throw the error delete $rels{$rel}; # @@ -1117,6 +1117,8 @@ sub _resolve_join { $self->throw_exception("No idea how to resolve join reftype ".ref $join); } else { + return() unless defined $join; + my $count = ++$seen->{$join}; my $as = ($count > 1 ? "${join}_${count}" : $join);