From: Matt S Trout Date: Thu, 31 May 2007 23:18:23 +0000 (+0000) Subject: LEFT join problem fixed X-Git-Tag: v0.08010~150^2~33 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=24010dd8b402137a7ed0293a49d7c9cfdb696695;p=dbsrgits%2FDBIx-Class.git LEFT join problem fixed --- diff --git a/Changes b/Changes index 680d597..c6bbaad 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,6 @@ Revision history for DBIx::Class + - fixup to ensure join always LEFT after first LEFT join depthwise - converted the vendor tests to use schema objects intead of schema classes, made cleaned more reliable with END blocks - versioning support via DBIx::Class::Schema::Versioned diff --git a/lib/DBIx/Class/ResultSource.pm b/lib/DBIx/Class/ResultSource.pm index 9a2e061..a97560f 100644 --- a/lib/DBIx/Class/ResultSource.pm +++ b/lib/DBIx/Class/ResultSource.pm @@ -713,16 +713,22 @@ Returns the join structure required for the related result source. =cut sub resolve_join { - my ($self, $join, $alias, $seen) = @_; + my ($self, $join, $alias, $seen, $force_left) = @_; $seen ||= {}; + $force_left ||= { force => 0 }; if (ref $join eq 'ARRAY') { return map { $self->resolve_join($_, $alias, $seen) } @$join; } elsif (ref $join eq 'HASH') { return map { my $as = ($seen->{$_} ? $_.'_'.($seen->{$_}+1) : $_); - ($self->resolve_join($_, $alias, $seen), - $self->related_source($_)->resolve_join($join->{$_}, $as, $seen)); + local $force_left->{force}; + ( + $self->resolve_join($_, $alias, $seen, $force_left), + $self->related_source($_)->resolve_join( + $join->{$_}, $as, $seen, $force_left + ) + ); } keys %$join; } elsif (ref $join) { $self->throw_exception("No idea how to resolve join reftype ".ref $join); @@ -732,7 +738,13 @@ sub resolve_join { my $as = ($count > 1 ? "${join}_${count}" : $join); my $rel_info = $self->relationship_info($join); $self->throw_exception("No such relationship ${join}") unless $rel_info; - my $type = $rel_info->{attrs}{join_type} || ''; + my $type; + if ($force_left->{force}) { + $type = 'left'; + } else { + $type = $rel_info->{attrs}{join_type} || ''; + $force_left->{force} = 1 if lc($type) eq 'left'; + } return [ { $as => $self->related_source($join)->from, -join_type => $type }, $self->resolve_condition($rel_info->{cond}, $as, $alias) ]; diff --git a/t/76joins.t b/t/76joins.t index f384d4d..89c619d 100644 --- a/t/76joins.t +++ b/t/76joins.t @@ -336,21 +336,18 @@ SKIP: { is($rs->next->name, 'Caterwauler McCrae', "Correct artist returned"); -TODO: { - local $TODO = 'left join on prefetch to return valid rows'; - my $cd = $schema->resultset('Artist')->first->create_related('cds', - { - title => 'Unproduced Single', - year => 2007 - }); - - my $left_join = $schema->resultset('CD')->search( - { 'me.cdid' => $cd->cdid }, - { prefetch => { cd_to_producer => 'producer' } } - ); - - cmp_ok($left_join, '==', 1, 'prefetch with no join record present'); -} +my $cd = $schema->resultset('Artist')->first->create_related('cds', + { + title => 'Unproduced Single', + year => 2007 +}); + +my $left_join = $schema->resultset('CD')->search( + { 'me.cdid' => $cd->cdid }, + { prefetch => { cd_to_producer => 'producer' } } +); + +cmp_ok($left_join, '==', 1, 'prefetch with no join record present'); $queries = 0; $schema->storage->debugcb(sub { $queries++ }); diff --git a/t/90join_torture.t b/t/90join_torture.t index 7c66799..3e15664 100644 --- a/t/90join_torture.t +++ b/t/90join_torture.t @@ -23,8 +23,8 @@ cmp_ok(scalar @cds, '==', 1, "condition based on inherited join okay"); #this is wrong, should accept me.title really my $rs3 = $rs2->search_related('cds'); -cmp_ok(scalar($rs3->all), '==', 27, "All cds for artist returned"); -cmp_ok($rs3->count, '==', 27, "All cds for artist returned via count"); +cmp_ok(scalar($rs3->all), '==', 45, "All cds for artist returned"); +cmp_ok($rs3->count, '==', 45, "All cds for artist returned via count"); my $rs4 = $schema->resultset("CD")->search({ 'artist.artistid' => '1' }, { join => ['tracks', 'artist'], prefetch => 'artist' }); my @rs4_results = $rs4->all;