X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FResultSet.pm;h=d8645bac656513e3ef8fb9df14c893c079beb845;hb=1475a98b653113fdd138d6928fb1e033412c0e97;hp=81538b571fec452b16dc49a98e771df0ba3b10d2;hpb=fa7a51af4487a72a925277f2bec709055fe2ef5b;p=dbsrgits%2FDBIx-Class-Historic.git diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index 81538b5..d8645ba 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -2518,14 +2518,13 @@ sub related_resultset { "' has no such relationship $rel") unless $rel_info; - my ($from,$seen) = $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 - my %attrs = %{$self->{attrs}||{}}; - delete @attrs{qw(result_class alias)}; + delete @{$attrs}{qw(result_class alias)}; my $new_cache; @@ -2546,20 +2545,14 @@ sub related_resultset { # to work sanely (e.g. RestrictWithObject wants to be able to add # extra query restrictions, and these may need to be $alias.) - my $attrs = $rel_source->resultset_attributes; - local $attrs->{alias} = $alias; + my $rel_attrs = $rel_source->resultset_attributes; + local $rel_attrs->{alias} = $alias; $rel_source->resultset ->search_rs( undef, { - %attrs, - join => undef, - prefetch => undef, - select => undef, - as => undef, - where => $self->{cond}, - seen_join => $seen, - from => $from, + %$attrs, + where => $attrs->{where}, }); }; $new->set_cache($new_cache) if $new_cache; @@ -2617,37 +2610,58 @@ sub current_source_alias { # with a relation_chain_depth less than the depth of the # current prefetch is not considered) # -# The increments happen in 1/2s to make it easier to correlate the -# join depth with the join path. An integer means a relationship -# specified via a search_related, whereas a fraction means an added -# join/prefetch via attributes +# The increments happen twice per join. An even number means a +# relationship specified via a search_related, whereas an odd +# number indicates a join/prefetch added via attributes +# +# Also this code will wrap the current resultset (the one we +# chain to) in a subselect IFF it contains limiting attributes sub _chain_relationship { my ($self, $rel) = @_; my $source = $self->result_source; - my $attrs = $self->{attrs}; + my $attrs = { %{$self->{attrs}||{}} }; - my $from = [ @{ - $attrs->{from} - || - [{ - -source_handle => $source->handle, - -alias => $attrs->{alias}, - $attrs->{alias} => $source->from, - }] - }]; + # 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} ); - my $seen = { %{$attrs->{seen_join} || {} } }; - my $jpath = ($attrs->{seen_join} && keys %{$attrs->{seen_join}}) - ? $from->[-1][0]{-join_path} - : []; + delete @{$attrs}{qw/join prefetch collapse select as columns +select +as +columns/}; + my $seen = { %{ (delete $attrs->{seen_join}) || {} } }; - # 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 $from; + my @force_subq_attrs = qw/offset rows group_by having/; + + if ( + ($attrs->{from} && ref $attrs->{from} ne 'ARRAY') + || + $self->_has_resolved_attr (@force_subq_attrs) + ) { + $from = [{ + -source_handle => $source->handle, + -alias => $attrs->{alias}, + $attrs->{alias} => $self->as_query, + }]; + delete @{$attrs}{@force_subq_attrs, 'where'}; + $seen->{-relation_chain_depth} = 0; + } + elsif ($attrs->{from}) { #shallow copy suffices + $from = [ @{$attrs->{from}} ]; + } + else { + $from = [{ + -source_handle => $source->handle, + -alias => $attrs->{alias}, + $attrs->{alias} => $source->from, + }]; + } + + my $jpath = ($seen->{-relation_chain_depth}) + ? $from->[-1][0]{-join_path} + : []; my @requested_joins = $source->_resolve_join( - $merged, + $join, $attrs->{alias}, $seen, $jpath, @@ -2655,7 +2669,7 @@ sub _chain_relationship { push @$from, @requested_joins; - $seen->{-relation_chain_depth} += 0.5; + $seen->{-relation_chain_depth}++; # 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 @@ -2667,7 +2681,7 @@ sub _chain_relationship { # we consider the last one thus reverse for my $j (reverse @requested_joins) { if ($rel eq $j->[0]{-join_path}[-1]) { - $j->[0]{-relation_chain_depth} += 0.5; + $j->[0]{-relation_chain_depth}++; $already_joined++; last; } @@ -2677,7 +2691,7 @@ sub _chain_relationship { # for my $j (reverse @$from) { # next unless ref $j eq 'ARRAY'; # if ($j->[0]{-join_path} && $j->[0]{-join_path}[-1] eq $rel) { -# $j->[0]{-relation_chain_depth} += 0.5; +# $j->[0]{-relation_chain_depth}++; # $already_joined++; # last; # } @@ -2692,9 +2706,9 @@ sub _chain_relationship { ); } - $seen->{-relation_chain_depth} += 0.5; + $seen->{-relation_chain_depth}++; - return ($from,$seen); + return {%$attrs, from => $from, seen_join => $seen}; } # too many times we have to do $attrs = { %{$self->_resolved_attrs} } @@ -2908,8 +2922,8 @@ sub _joinpath_aliases { my $cur_depth = $seen->{-relation_chain_depth} || 0; - if (int ($cur_depth) != $cur_depth) { - $self->throw_exception ("-relation_chain_depth is not an integer, something went horribly wrong ($cur_depth)"); + if ($cur_depth % 2) { + $self->throw_exception ("-relation_chain_depth is not even, something went horribly wrong ($cur_depth)"); } for my $j (@$fromspec) { @@ -2920,7 +2934,7 @@ sub _joinpath_aliases { my $jpath = $j->[0]{-join_path}; my $p = $paths; - $p = $p->{$_} ||= {} for @{$jpath}[$cur_depth .. $#$jpath]; + $p = $p->{$_} ||= {} for @{$jpath}[$cur_depth/2 .. $#$jpath]; #only even depths are actual jpath boundaries push @{$p->{-join_aliases} }, $j->[0]{-alias}; }