"' 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);
# 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};
# ->_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};
}
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}; #
$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);