X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=dbsrgits%2FDBIx-Class.git;a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FResultSet.pm;h=5c87ffa38900305e77f77fa3e8e68e57e77a2420;hp=fc6bdd0164dfa40d1d98a2925d16cf9f5f5ef06f;hb=307f12659a1a370e5e41a23ef35839e2807f1ca4;hpb=86a51471ceeeae4998e11ca3971c026f1b829a43
diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm
index fc6bdd0..5c87ffa 100644
--- a/lib/DBIx/Class/ResultSet.pm
+++ b/lib/DBIx/Class/ResultSet.pm
@@ -3966,28 +3966,122 @@ case.
Simple prefetches will be joined automatically, so there is no need
for a C attribute in the above search.
-C can be used with the following relationship types: C,
-C (or if you're using C, any relationship declared
-with an accessor type of 'single' or 'filter'). A more complex example that
-prefetches an artists cds, the tracks on those cds, and the tags associated
-with that artist is given below (assuming many-to-many from artists to tags):
+L can be used with the any of the relationship types and
+multiple prefetches can be specified together. Below is a more complex
+example that prefetches a CD's artist, its liner notes (if present),
+the cover image, the tracks on that cd, and the guests on those
+tracks.
- my $rs = $schema->resultset('Artist')->search(
+ # Assuming:
+ My::Schema::CD->belongs_to( artist => 'My::Schema::Artist' );
+ My::Schema::CD->might_have( liner_note => 'My::Schema::LinerNotes' );
+ My::Schema::CD->has_one( cover_image => 'My::Schema::Artwork' );
+ My::Schema::CD->has_many( tracks => 'My::Schema::Track' );
+
+ My::Schema::Artist->belongs_to( record_label => 'My::Schema::RecordLabel' );
+
+ My::Schema::Track->has_many( guests => 'My::Schema::Guest' );
+
+
+ my $rs = $schema->resultset('CD')->search(
undef,
{
prefetch => [
- { cds => 'tracks' },
- { artist_tags => 'tags' }
+ { artist => 'record_label'}, # belongs_to => belongs_to
+ 'liner_note', # might_have
+ 'cover_image', # has_one
+ { tracks => 'guests' }, # has_many => has_many
]
}
);
+This will produce SQL like the following:
+
+ SELECT cd.*, artist.*, record_label.*, liner_note.*, cover_image.*,
+ tracks.*, guests.*
+ FROM cd me
+ JOIN artist artist
+ ON artist.artistid = me.artistid
+ JOIN record_label record_label
+ ON record_label.labelid = artist.labelid
+ LEFT JOIN track tracks
+ ON tracks.cdid = me.cdid
+ LEFT JOIN guest guests
+ ON guests.trackid = track.trackid
+ LEFT JOIN liner_notes liner_note
+ ON liner_note.cdid = me.cdid
+ JOIN cd_artwork cover_image
+ ON cover_image.cdid = me.cdid
+ ORDER BY tracks.cd
+
+Now the C, C, C, C,
+C, and C of the CD will all be available through the
+relationship accessors without the need for additional queries to the
+database.
+
+However, there is one caveat to be observed: it can be dangerous to
+prefetch more than one L
+relationship on a given level. e.g.:
+
+ my $rs = $schema->resultset('CD')->search(
+ undef,
+ {
+ prefetch => [
+ 'tracks', # has_many
+ { cd_to_producer => 'producer' }, # has_many => belongs_to (i.e. m2m)
+ ]
+ }
+ );
+
+In fact, C will emit the following warning:
+
+ Prefetching multiple has_many rels tracks and cd_to_producer at top
+ level will explode the number of row objects retrievable via ->next
+ or ->all. Use at your own risk.
+
+The collapser currently can't identify duplicate tuples for multiple
+L relationships and as a
+result the second L
+relation could contain redundant objects.
+
+=head3 Using L with L
+
+L implies a L with the equivalent argument, and is
+properly merged with any existing L specification. So the
+following:
+
+ my $rs = $schema->resultset('CD')->search(
+ {'record_label.name' => 'Music Product Ltd.'},
+ {
+ join => {artist => 'record_label'},
+ prefetch => 'artist',
+ }
+ );
+
+... will work, searching on the record label's name, but only
+prefetching the C.
+
+=head3 Using L with L / L+select> / L / L+as>
+
+L implies a L+select>/L+as> with the fields of the
+prefetched relations. So given:
+
+ my $rs = $schema->resultset('CD')->search(
+ undef,
+ {
+ select => ['cd.title'],
+ as => ['cd_title'],
+ prefetch => 'artist',
+ }
+ );
+
+The L becomes: C<'cd.title', 'artist.*'> and the L
+becomes: C<'cd_title', 'artist.*'>.
-B If you specify a C attribute, the C and C