Skip to content

Commit

Permalink
add as_subselect_rs
Browse files Browse the repository at this point in the history
  • Loading branch information
Arthur Axel "fREW" Schmidt committed Feb 7, 2010
1 parent 406734b commit e4bb672
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 1 deletion.
52 changes: 51 additions & 1 deletion lib/DBIx/Class/ResultSet.pm
Expand Up @@ -2502,7 +2502,7 @@ sub related_resultset {
->relname_to_table_alias($rel, $join_count);

# since this is search_related, and we already slid the select window inwards
# (the select/as attrs were deleted in the beginning), we need to flip all
# (the select/as attrs were deleted in the beginning), we need to flip all
# left joins to inner, so we get the expected results
# read the comment on top of the actual function to see what this does
$attrs->{from} = $rsrc->schema->storage->_straight_join_to_node ($attrs->{from}, $alias);
Expand Down Expand Up @@ -2588,6 +2588,56 @@ sub current_source_alias {
return ($self->{attrs} || {})->{alias} || 'me';
}

=head2 as_subselect_rs
=over 4
=item Arguments: none
=item Return Value: $resultset
=back
Act as a barrier to SQL symbols. The resultset provided will be made into a
"virtual view" by including it as a subquery within the from clause. From this
point on, any joined tables are inaccessible to ->search on the resultset (as if
it were simply where-filtered without joins). For example:
my $rs = $schema->resultset('Bar')->search({'x.name' => 'abc'},{ join => 'x' });
# 'x' now pollutes the query namespace
# So the following works as expected
my $ok_rs = $rs->search({'x.other' => 1});
# But this doesn't: instead of finding a 'Bar' related to two x rows (abc and
# def) we look for one row with contradictory terms and join in another table
# (aliased 'x_2') which we never use
my $broken_rs = $rs->search({'x.name' => 'def'});
my $rs2 = $rs->as_subselect_rs;
# doesn't work - 'x' is no longer accessible in $rs2, having been sealed away
my $not_joined_rs = $rs2->search({'x.other' => 1});
# works as expected: finds a 'table' row related to two x rows (abc and def)
my $correctly_joined_rs = $rs2->search({'x.name' => 'def'});
=cut

sub as_subselect_rs {
my $self = shift;

return $self->result_source->resultset->search( undef, {
alias => 'me',
from => [{
me => $self->as_query,
-alias => $self->current_source_alias,
-source_handle => $self->result_source->handle,
}]
});
}

# This code is called by search_related, and makes sure there
# is clear separation between the joins before, during, and
# after the relationship. This information is needed later
Expand Down
25 changes: 25 additions & 0 deletions t/resultset/as_subselect_rs.t
@@ -0,0 +1,25 @@
use strict;
use warnings;

use Test::More;
use Test::Exception;

use lib qw(t/lib);
use DBICTest;
use DBIC::SqlMakerTest;

my $schema = DBICTest->init_schema();

my $new_rs = $schema->resultset('Artist')->search({
'artwork_to_artist.artist_id' => 1
}, {
join => 'artwork_to_artist'
});
lives_ok { $new_rs->count } 'regular search works';
lives_ok { $new_rs->search({ 'artwork_to_artist.artwork_cd_id' => 1})->count }
'... and chaining off that using join works';
lives_ok { $new_rs->search({ 'artwork_to_artist.artwork_cd_id' => 1})->as_subselect_rs->count }
'... and chaining off the virtual view works';
dies_ok { $new_rs->as_subselect_rs->search({'artwork_to_artist.artwork_cd_id'=> 1})->count }
q{... but chaining off of a virtual view using join doesn't work};
done_testing;

0 comments on commit e4bb672

Please sign in to comment.