X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FRelationship%2FBase.pm;h=c4d4df592c05d3c727a43a02306e4f13a825408e;hb=ea3ee77d2d9e137b07ca4b2db14986e8310f4bec;hp=f82d2ec5d2b0b89a395472dbb6b5ea00fe534d5f;hpb=786c1cddede6675b9fc5fc46ae4e1e136ef2c392;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Relationship/Base.pm b/lib/DBIx/Class/Relationship/Base.pm index f82d2ec..c4d4df5 100644 --- a/lib/DBIx/Class/Relationship/Base.pm +++ b/lib/DBIx/Class/Relationship/Base.pm @@ -6,7 +6,10 @@ use warnings; use base qw/DBIx::Class/; use Scalar::Util qw/weaken blessed/; -use DBIx::Class::_Util qw( UNRESOLVABLE_CONDITION fail_on_internal_call ); +use DBIx::Class::_Util qw( + UNRESOLVABLE_CONDITION DUMMY_ALIASPAIR + fail_on_internal_call +); use DBIx::Class::Carp; use namespace::clean; @@ -514,83 +517,86 @@ sub related_resultset { my ($self, $rel) = @_; - return $self->{related_resultsets}{$rel} = do { + my $rsrc = $self->result_source; - my $rsrc = $self->result_source; + my $rel_info = $rsrc->relationship_info($rel) + or $self->throw_exception( "No such relationship '$rel'" ); - my $rel_info = $rsrc->relationship_info($rel) - or $self->throw_exception( "No such relationship '$rel'" ); + my $relcond_is_freeform = ref $rel_info->{cond} eq 'CODE'; - my $cond_res = $rsrc->_resolve_relationship_condition( - rel_name => $rel, - self_result_object => $self, + my $jfc = $rsrc->_resolve_relationship_condition( - # this may look weird, but remember that we are making a resultset - # out of an existing object, with the new source being at the head - # of the FROM chain. Having a 'me' alias is nothing but expected there - foreign_alias => 'me', + rel_name => $rel, + self_result_object => $self, + + # an extra sanity check guard + require_join_free_condition => ! $relcond_is_freeform, + + # an API where these are optional would be too cumbersome, + # instead always pass in some dummy values + DUMMY_ALIASPAIR, + + # this may look weird, but remember that we are making a resultset + # out of an existing object, with the new source being at the head + # of the FROM chain. Having a 'me' alias is nothing but expected there + foreign_alias => 'me', + + )->{join_free_condition}; - self_alias => "!!!\xFF()!!!_SHOULD_NEVER_BE_SEEN_IN_USE_!!!()\xFF!!!", + my $rel_rset; - # not strictly necessary, but shouldn't hurt either - require_join_free_condition => !!(ref $rel_info->{cond} ne 'CODE'), + if( defined $jfc ) { + + $rel_rset = $rsrc->related_source($rel)->resultset->search( + $jfc, + $rel_info->{attrs}, ); + } + elsif( $relcond_is_freeform ) { + + # A WHOREIFFIC hack to reinvoke the entire condition resolution + # with the correct alias. Another way of doing this involves a + # lot of state passing around, and the @_ positions are already + # mapped out, making this crap a less icky option. + # + # The point of this exercise is to retain the spirit of the original + # $obj->search_related($rel) where the resulting rset will have the + # root alias as 'me', instead of $rel (as opposed to invoking + # $rs->search_related) + + # make the fake 'me' rel + local $rsrc->{_relationships}{me} = { + %{ $rsrc->{_relationships}{$rel} }, + _original_name => $rel, + }; + + my $obj_table_alias = lc($rsrc->source_name) . '__row'; + $obj_table_alias =~ s/\W+/_/g; + + $rel_rset = $rsrc->resultset->search( + $self->ident_condition($obj_table_alias), + { alias => $obj_table_alias }, + )->related_resultset('me')->search(undef, $rel_info->{attrs}) + } + else { - # keep in mind that the following if() block is part of a do{} - no return()s!!! - if ( - ! $cond_res->{join_free_condition} - and - ref $rel_info->{cond} eq 'CODE' - ) { - - # A WHOREIFFIC hack to reinvoke the entire condition resolution - # with the correct alias. Another way of doing this involves a - # lot of state passing around, and the @_ positions are already - # mapped out, making this crap a less icky option. - # - # The point of this exercise is to retain the spirit of the original - # $obj->search_related($rel) where the resulting rset will have the - # root alias as 'me', instead of $rel (as opposed to invoking - # $rs->search_related) - - # make the fake 'me' rel - local $rsrc->{_relationships}{me} = { - %{ $rsrc->{_relationships}{$rel} }, - _original_name => $rel, - }; + my $attrs = { %{$rel_info->{attrs}} }; + my $reverse = $rsrc->reverse_relationship_info($rel); - my $obj_table_alias = lc($rsrc->source_name) . '__row'; - $obj_table_alias =~ s/\W+/_/g; + # FIXME - this loop doesn't seem correct - got to figure out + # at some point what exactly it does. + ( ( $reverse->{$_}{attrs}{accessor}||'') eq 'multi' ) + ? weaken( $attrs->{related_objects}{$_}[0] = $self ) + : weaken( $attrs->{related_objects}{$_} = $self ) + for keys %$reverse; - $rsrc->resultset->search( - $self->ident_condition($obj_table_alias), - { alias => $obj_table_alias }, - )->related_resultset('me')->search(undef, $rel_info->{attrs}) - } - else { - - # FIXME - this conditional doesn't seem correct - got to figure out - # at some point what it does. Also the entire UNRESOLVABLE_CONDITION - # business seems shady - we could simply not query *at all* - my $attrs; - if ( $cond_res->{join_free_condition} eq UNRESOLVABLE_CONDITION ) { - $attrs = { %{$rel_info->{attrs}} }; - my $reverse = $rsrc->reverse_relationship_info($rel); - foreach my $rev_rel (keys %$reverse) { - if ($reverse->{$rev_rel}{attrs}{accessor} && $reverse->{$rev_rel}{attrs}{accessor} eq 'multi') { - weaken($attrs->{related_objects}{$rev_rel}[0] = $self); - } else { - weaken($attrs->{related_objects}{$rev_rel} = $self); - } - } - } + $rel_rset = $rsrc->related_source($rel)->resultset->search( + UNRESOLVABLE_CONDITION, # guards potential use of the $rs in the future + $attrs, + ); + } - $rsrc->related_source($rel)->resultset->search( - $cond_res->{join_free_condition}, - $attrs || $rel_info->{attrs}, - ); - } - }; + $self->{related_resultsets}{$rel} = $rel_rset; } =head2 search_related @@ -672,8 +678,11 @@ sub new_related { infer_values_based_on => $data, rel_name => $rel, self_result_object => $self, - foreign_alias => $rel, - self_alias => 'me', + + # an API where these are optional would be too cumbersome, + # instead always pass in some dummy values + DUMMY_ALIASPAIR, + )->{inferred_values} ); } @@ -851,8 +860,11 @@ sub set_from_related { +{ $f_obj->get_columns }; } ), - foreign_alias => $rel, - self_alias => 'me', + + # an API where these are optional would be too cumbersome, + # instead always pass in some dummy values + DUMMY_ALIASPAIR, + )->{inferred_values} ); return 1;