[Dbix-class] Q: prefetch has_many relation
Peter Rabbitson
rabbit+dbic at rabbit.us
Thu Apr 8 20:39:29 GMT 2010
Bernhard Graf wrote:
> Am 08.04.2010 18:15, schrieb Peter Rabbitson:
>
>>> Prefetching a has_many relation is not possible (says the manual).
>> o.O Please point out where does it say that so we can fix it.
>
> http://search.cpan.org/~ribasushi/DBIx-Class/lib/DBIx/Class/ResultSet.pm#prefetch
> <cite>
> prefetch can be used with the following relationship types: belongs_to,
> has_one (or if you're using add_relationship, any relationship declared
> with an accessor type of 'single' or 'filter').
> </cite>
Crap. Will fix.
> I also tried to understand
> http://search.cpan.org/~ribasushi/DBIx-Class/lib/DBIx/Class/Manual/Cookbook.pod#Using_joins_and_prefetch
> but it seems contradictory, because here sometimes CDs seem to have many
> artists
>
> My::Schema::CD->has_many(artists => 'My::Schema::Artist', 'artist_id');
>
> my $rs = $schema->resultset('CD')->search(
> {
> 'artists.name' => 'Bob Marley'
> },
> {
> join => 'artists',
> order_by => [qw/ artists.name /],
> prefetch => 'artists' # return artist data too!
> }
> );
>
> while (my $cd = $rs->next) {
> print "CD: " . $cd->title . ", Artist: " . $cd->artist->name;
> }
>
> quite confusing...
Crap x2
>
>>> How do I select all CDs of the artists of $artist_rs with one query?
>> my $new_rs = $artist_rs->search ({}, { prefetch => 'cds' });
>
> I already noticed, that this builds a quite "impressive" SQL statement
> with a sub-query - no idea why - but when I did
>
> for my $row ($rs->all) {
> say join(', ', $row->cds->get_column('title')->all);
> }
>
> it still fetched each of the CDs again one by one.
get_column on a resultset ($row->cds is such a resultset) is different from
get_column on an object. The resultset version must ensure there is only
one column selected in the result - thus the "impressive" subquery. By
the way I would like to see the generated SQL, there might be a problem
with the logic, especially if it seems to you that the query could have
been much simpler (and if this is indeed the case I will definitely fix it).
>
> Changing this to
>
> for my $row ($rs->all) {
> say join(',', map {$_->role_id} $row->user2roles->all);
> }
>
> fixed it indeed: no more additional queries. :)
Right, because you pull the role_id from the object, not from a resultset.
>
> So actually it works - but I have no idea, why the SQL query has to be
> so sophisticated... don't sub-queries usually slow down significantly?
>
Show the actual SQL - I'll be able to answer this.
More information about the DBIx-Class
mailing list