X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FResultSet.pm;h=206569a94e6988105ff2e393359f6a8e5fce804c;hb=e4bb67275eafae2905d88eb061f1e5a7dca21d18;hp=c0221b4ac2e1284669104b4ef44674eecd4f3ab9;hpb=fe426cb6fbd90178cb2f9fe6721ba8a4e6ab42cc;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index c0221b4..206569a 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -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); @@ -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 @@ -2851,14 +2901,10 @@ sub _resolved_attrs { my %already_grouped = map { $_ => 1 } (@{$attrs->{group_by}}); my $storage = $self->result_source->schema->storage; - my $sql_maker = $storage->sql_maker; - local $sql_maker->{quote_char}; #disable quoting my $rs_column_list = $storage->_resolve_column_info ($attrs->{from}); - my @chunks = $sql_maker->_order_by_chunks ($attrs->{order_by}); - for my $chunk (map { ref $_ ? @$_ : $_ } (@chunks) ) { - $chunk =~ s/\s+ (?: ASC|DESC ) \s* $//ix; + for my $chunk ($storage->_parse_order_by($attrs->{order_by})) { if ($rs_column_list->{$chunk} && not $already_grouped{$chunk}++) { push @{$attrs->{group_by}}, $chunk; } @@ -2888,7 +2934,7 @@ sub _resolved_attrs { 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 + $p = $p->{$_} ||= {} for @jpath[ ($start_depth/2) .. $#jpath]; #only even depths are actual jpath boundaries push @{$p->{-join_aliases} }, $j->[0]{-alias}; } }