From: Peter Rabbitson Date: Sun, 17 Jan 2010 14:57:06 +0000 (+0000) Subject: Turned out to be much trickier X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=38f42d8556c1df2265c242a1eee7ebabc5e6dfb5;p=dbsrgits%2FDBIx-Class-Historic.git Turned out to be much trickier --- diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index b0d2e12..7cae67c 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -2673,21 +2673,13 @@ sub _chain_relationship { # we consider the last one thus reverse for my $j (reverse @requested_joins) { - if ($rel eq $j->[0]{-join_path}[-1]) { + my ($last_j) = keys %{$j->[0]{-join_path}[-1]}; + if ($rel eq $last_j) { $j->[0]{-relation_chain_depth}++; $already_joined++; last; } } -# alternative way to scan the entire chain - not backwards compatible -# 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}++; -# $already_joined++; -# last; -# } -# } unless ($already_joined) { push @$from, $source->_resolve_join( @@ -2877,7 +2869,26 @@ sub _resolved_attrs { my $prefetch_ordering = []; - my $join_map = $self->_joinpath_aliases ($attrs->{from}, $attrs->{seen_join}); + # this is a separate structure (we don't look in {from} directly) + # as the resolver needs to shift things off the lists to work + # properly (identical-prefetches on different branches) + my $join_map = {}; + if (ref $attrs->{from} eq 'ARRAY') { + + my $start_depth = $attrs->{seen_join}{-relation_chain_depth} || 0; + + for my $j ( @{$attrs->{from}}[1 .. $#{$attrs->{from}} ] ) { + next unless $j->[0]{-alias}; + next unless $j->[0]{-join_path}; + next if ($j->[0]{-relation_chain_depth} || 0) < $start_depth; + + my @jpath = map { keys %$_ } @{$j->[0]{-join_path}}; + + my $p = $join_map; + $p = $p->{$_} ||= {} for @jpath[ ($start_depth/2) .. $#jpath]; #only even depths are actual jpath boundaries + push @{$p->{-join_aliases} }, $j->[0]{-alias}; + } + } my @prefetch = $source->_resolve_prefetch( $prefetch, $alias, $join_map, $prefetch_ordering, $attrs->{collapse} ); @@ -2906,33 +2917,6 @@ sub _resolved_attrs { return $self->{_attrs} = $attrs; } -sub _joinpath_aliases { - my ($self, $fromspec, $seen) = @_; - - my $paths = {}; - return $paths unless ref $fromspec eq 'ARRAY'; - - my $cur_depth = $seen->{-relation_chain_depth} || 0; - - if ($cur_depth % 2) { - $self->throw_exception ("-relation_chain_depth is not even, something went horribly wrong ($cur_depth)"); - } - - for my $j (@$fromspec) { - - next if ref $j ne 'ARRAY'; - next if ($j->[0]{-relation_chain_depth} || 0) < $cur_depth; - - my $jpath = $j->[0]{-join_path}; - - my $p = $paths; - $p = $p->{$_} ||= {} for @{$jpath}[ ($cur_depth/2) .. $#$jpath]; #only even depths are actual jpath boundaries - push @{$p->{-join_aliases} }, $j->[0]{-alias}; - } - - return $paths; -} - sub _rollout_attr { my ($self, $attr) = @_; diff --git a/lib/DBIx/Class/ResultSource.pm b/lib/DBIx/Class/ResultSource.pm index 0a2ae05..824c34d 100644 --- a/lib/DBIx/Class/ResultSource.pm +++ b/lib/DBIx/Class/ResultSource.pm @@ -1205,7 +1205,7 @@ sub _resolve_join { $self->throw_exception ('You must supply a joinpath arrayref as the 4th argument to _resolve_join') unless ref $jpath eq 'ARRAY'; - $jpath = [@$jpath]; + $jpath = [@$jpath]; # copy if (not defined $join) { return (); @@ -1235,7 +1235,7 @@ sub _resolve_join { push @ret, ( $self->_resolve_join($rel, $alias, $seen, [@$jpath], $force_left), $self->related_source($rel)->_resolve_join( - $join->{$rel}, $as, $seen, [@$jpath, $rel], $force_left + $join->{$rel}, $as, $seen, [@$jpath, { $rel => $as }], $force_left ) ); } @@ -1261,7 +1261,7 @@ sub _resolve_join { ? 'left' : $rel_info->{attrs}{join_type} , - -join_path => [@$jpath, $as], + -join_path => [@$jpath, { $join => $as } ], -is_single => (List::Util::first { $rel_info->{attrs}{accessor} eq $_ } (qw/single filter/) ), -alias => $as, -relation_chain_depth => $seen->{-relation_chain_depth} || 0, @@ -1448,8 +1448,7 @@ sub resolve_prefetch { # Accepts one or more relationships for the current source and returns an # array of column names for each of those relationships. Column names are # prefixed relative to the current source, in accordance with where they appear -# in the supplied relationships. Needs an alias_map generated by -# $rs->_joinpath_aliases +# in the supplied relationships. sub _resolve_prefetch { my ($self, $pre, $alias, $alias_map, $order, $collapse, $pref_path) = @_; diff --git a/lib/DBIx/Class/Storage/DBIHacks.pm b/lib/DBIx/Class/Storage/DBIHacks.pm index f549204..43faccf 100644 --- a/lib/DBIx/Class/Storage/DBIHacks.pm +++ b/lib/DBIx/Class/Storage/DBIHacks.pm @@ -43,7 +43,6 @@ sub _prune_unused_joins { return \@newfrom; } - # # This is the code producing joined subqueries like: # SELECT me.*, other.* FROM ( SELECT me.* FROM ... ) JOIN other ON ... @@ -255,7 +254,7 @@ sub _resolve_aliastypes_from_select_args { for my $type (keys %$aliases_by_type) { for my $alias (keys %{$aliases_by_type->{$type}}) { $aliases_by_type->{$type}{$_} = 1 - for (@{ $alias_list->{$alias}{-join_path} || [] }); + for (map { keys %$_ } @{ $alias_list->{$alias}{-join_path} || [] }); } } @@ -400,7 +399,7 @@ sub _straight_join_to_node { # anyway, and deep cloning is just too fucking expensive # So replace the first hashref in the node arrayref manually my @new_from = ($from->[0]); - my $sw_idx = { map { $_ => 1 } @$switch_branch }; + my $sw_idx = { map { values %$_ => 1 } @$switch_branch }; for my $j (@{$from}[1 .. $#$from]) { my $jalias = $j->[0]{-alias};