Peter Rabbitson wrote:
> Byron Young wrote:
>> Hey all,
>>
>> Sorry if this is a FAQ, but I couldn't find any info in the cookbook or the 
>> joining manual or other docs.
>>
>> I have a table for test results, 'results', that has two paths through 
>> relationships to join to another table for hostnames, 'hostnames', like so:
>>
>>   results --> map_results_tested_products --> tested_product --> hostname
>>   results --> map_results_tested_hosts    --> tested_host    --> hostname
>>
>> If I want to search all results for tests that tested a product with 
>> hostname 'XXXXX', the query looks like:
>>
>>   $schema->resultset("Results")->search({ "hostname.name" => "XXXXX" },
>>                                         { join => { 
>> map_results_tested_products => { tested_product => 'hostname' } } });
>>
>> However, if I want to chain that with another search so I get all results 
>> for tests that tested a product with hostname 'XXXXX' and included a host 
>> with hostname 'YYYYY', I have to use 'hostname_2' in the search condition 
>> for the second query, since 'hostname' has already been joined:
>>
>>   $schema->resultset("Results")->search({ "hostname.name" => 'XXXXX' },
>>                                         { join => { 
>> map_results_tested_products => { tested_product => "hostname" } } })
>>                                ->search({ "hostname_2.name" => 'YYYYY' },
>>                                         { join => { map_results_tested_hosts 
>> => { tested_host => "hostname" } } });
>>
>> This is fine when the whole query is exposed in code like this, but the 
>> problem comes when I'm chaining searches on resultsets that come from 
>> somewhere else.  For example, if I add a custom resultset method for the 
>> first search, the person writing the chained search doesn't necessarily know 
>> that 'hostname' has already been joined once and that they should append 
>> '_2':
>>
>>   $schema->resultset("Results")->tested_product_name("XXXXX")
>>                                ->search({ "hostname.name" => 'YYYYY' },
>>                                         { join => { map_results_tested_hosts 
>> => { tested_host => "hostname" } } });
>>
>> The above looks right to the coder but wouldn't work how you would expect 
>> from just looking at it, because it would search on the wrong joined 
>> 'hostname' table.
>>
>> The way this is coming up for me is that I have written a simple list 
>> filtering system for my Catalyst app, where my Controller classes can 
>> provide info about the where conditions and joins for the filters in the 
>> controller config, and my List base controller class chains the filters that 
>> the user selected into a query and displays the filtered list.
>>
>> What I've done to get around it is to inspect the 'join' attributes and use 
>> a %seen hash to count the number of times a table has been joined, and then 
>> fix up the where condition appropriately.  It works, but the code is more 
>> convoluted than I would like, and I'm worried that by messing with my 
>> queries like this I'm relying on some internal DBIC behavior that may change 
>> at some point.
>>
>> Is there a better way to solve this issue so that I can chain queries that 
>> don't collide even if they join to the same table?
>>
> 
> This is definitely not a faq, and concerns one of the hairier parts
> of DBIC. Since 0.08103 DBIC can do the counting for you properly,
> but with the caveat that you are accessing internal methods which
> can change without notice:
> 
> my $aliases = $rs->_joinpath_aliases ($rs->_resolved_attrs->{from});
> 
> If you Data::Dumper the resulting hashref you will see that the answer
> to your question is then as simple as:
> 
> my $alias = $aliases->{map_results_tested_hosts}{tested_host}{hostname};
> 

Sorry, my bad. What I sent will not work correctly if you have
->search_related calls in your chain. The full code is:

my $rattr = $rs->_resolved_attrs_copy;
my $aliases = $rs->_joinpath_aliases ($rattr->{from}, $rattr->{seen_join});

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/[email protected]

Reply via email to