handle the throw_exception bit. Drop DBIx::Class::Exception
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / ResultSet.pm
1 package DBIx::Class::ResultSet;
2
3 use strict;
4 use warnings;
5 use overload
6         '0+'     => 'count',
7         'bool'   => sub { 1; },
8         fallback => 1;
9 use Data::Page;
10 use Storable;
11
12 use base qw/DBIx::Class/;
13 __PACKAGE__->load_components(qw/AccessorGroup/);
14 __PACKAGE__->mk_group_accessors('simple' => 'result_source');
15
16 =head1 NAME
17
18 DBIx::Class::ResultSet - Responsible for fetching and creating resultset.
19
20 =head1 SYNOPSIS
21
22   my $rs   = $schema->resultset('User')->search(registered => 1);
23   my @rows = $schema->resultset('Foo')->search(bar => 'baz');
24
25 =head1 DESCRIPTION
26
27 The resultset is also known as an iterator. It is responsible for handling
28 queries that may return an arbitrary number of rows, e.g. via L</search>
29 or a C<has_many> relationship.
30
31 In the examples below, the following table classes are used:
32
33   package MyApp::Schema::Artist;
34   use base qw/DBIx::Class/;
35   __PACKAGE__->table('artist');
36   __PACKAGE__->add_columns(qw/artistid name/);
37   __PACKAGE__->set_primary_key('artistid');
38   __PACKAGE__->has_many(cds => 'MyApp::Schema::CD');
39   1;
40
41   package MyApp::Schema::CD;
42   use base qw/DBIx::Class/;
43   __PACKAGE__->table('artist');
44   __PACKAGE__->add_columns(qw/cdid artist title year/);
45   __PACKAGE__->set_primary_key('cdid');
46   __PACKAGE__->belongs_to(artist => 'MyApp::Schema::Artist');
47   1;
48
49 =head1 METHODS
50
51 =head2 new($source, \%$attrs)
52
53 The resultset constructor. Takes a source object (usually a
54 L<DBIx::Class::ResultSourceProxy::Table>) and an attribute hash (see L</ATRRIBUTES>
55 below).  Does not perform any queries -- these are executed as needed by the
56 other methods.
57
58 Generally you won't need to construct a resultset manually.  You'll
59 automatically get one from e.g. a L</search> called in scalar context:
60
61   my $rs = $schema->resultset('CD')->search({ title => '100th Window' });
62
63 =cut
64
65 sub new {
66   my $class = shift;
67   return $class->new_result(@_) if ref $class;
68   my ($source, $attrs) = @_;
69   #use Data::Dumper; warn Dumper($attrs);
70   $attrs = Storable::dclone($attrs || {}); # { %{ $attrs || {} } };
71   my %seen;
72   my $alias = ($attrs->{alias} ||= 'me');
73   if ($attrs->{cols} || !$attrs->{select}) {
74     delete $attrs->{as} if $attrs->{cols};
75     my @cols = ($attrs->{cols}
76                  ? @{delete $attrs->{cols}}
77                  : $source->columns);
78     $attrs->{select} = [ map { m/\./ ? $_ : "${alias}.$_" } @cols ];
79   }
80   $attrs->{as} ||= [ map { m/^$alias\.(.*)$/ ? $1 : $_ } @{$attrs->{select}} ];
81   #use Data::Dumper; warn Dumper(@{$attrs}{qw/select as/});
82   $attrs->{from} ||= [ { $alias => $source->from } ];
83   if (my $join = delete $attrs->{join}) {
84     foreach my $j (ref $join eq 'ARRAY'
85               ? (@{$join}) : ($join)) {
86       if (ref $j eq 'HASH') {
87         $seen{$_} = 1 foreach keys %$j;
88       } else {
89         $seen{$j} = 1;
90       }
91     }
92     push(@{$attrs->{from}}, $source->resolve_join($join, $attrs->{alias}));
93   }
94   $attrs->{group_by} ||= $attrs->{select} if delete $attrs->{distinct};
95
96   if (my $prefetch = delete $attrs->{prefetch}) {
97     foreach my $p (ref $prefetch eq 'ARRAY'
98               ? (@{$prefetch}) : ($prefetch)) {
99       if( ref $p eq 'HASH' ) {
100         foreach my $key (keys %$p) {
101           push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
102             unless $seen{$key};
103         }
104       }
105       else {
106         push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
107             unless $seen{$p};
108       }
109       my @cols = ();
110       push @cols, $source->resolve_prefetch($p, $attrs->{alias});
111       #die Dumper \@cols;
112       push(@{$attrs->{select}}, @cols);
113       push(@{$attrs->{as}}, @cols);
114     }
115   }
116
117   if ($attrs->{page}) {
118     $attrs->{rows} ||= 10;
119     $attrs->{offset} ||= 0;
120     $attrs->{offset} += ($attrs->{rows} * ($attrs->{page} - 1));
121   }
122   my $new = {
123     result_source => $source,
124     cond => $attrs->{where},
125     from => $attrs->{from},
126     count => undef,
127     page => delete $attrs->{page},
128     pager => undef,
129     attrs => $attrs };
130   bless ($new, $class);
131   return $new;
132 }
133
134 =head2 search
135
136   my @obj    = $rs->search({ foo => 3 }); # "... WHERE foo = 3"
137   my $new_rs = $rs->search({ foo => 3 });
138
139 If you need to pass in additional attributes but no additional condition,
140 call it as C<search({}, \%attrs);>.
141
142   # "SELECT foo, bar FROM $class_table"
143   my @all = $class->search({}, { cols => [qw/foo bar/] });
144
145 =cut
146
147 sub search {
148   my $self = shift;
149
150   #use Data::Dumper;warn Dumper(@_);
151
152   my $attrs = { %{$self->{attrs}} };
153   if (@_ > 1 && ref $_[$#_] eq 'HASH') {
154     $attrs = { %$attrs, %{ pop(@_) } };
155   }
156
157   my $where = (@_ ? ((@_ == 1 || ref $_[0] eq "HASH") ? shift : {@_}) : undef());
158   if (defined $where) {
159     $where = (defined $attrs->{where}
160                 ? { '-and' =>
161                     [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
162                         $where, $attrs->{where} ] }
163                 : $where);
164     $attrs->{where} = $where;
165   }
166
167   my $rs = (ref $self)->new($self->result_source, $attrs);
168
169   return (wantarray ? $rs->all : $rs);
170 }
171
172 =head2 search_literal
173
174   my @obj    = $rs->search_literal($literal_where_cond, @bind);
175   my $new_rs = $rs->search_literal($literal_where_cond, @bind);
176
177 Pass a literal chunk of SQL to be added to the conditional part of the
178 resultset.
179
180 =cut
181                                                          
182 sub search_literal {
183   my ($self, $cond, @vals) = @_;
184   my $attrs = (ref $vals[$#vals] eq 'HASH' ? { %{ pop(@vals) } } : {});
185   $attrs->{bind} = [ @{$self->{attrs}{bind}||[]}, @vals ];
186   return $self->search(\$cond, $attrs);
187 }
188
189 =head2 find(@colvalues), find(\%cols, \%attrs?)
190
191 Finds a row based on its primary key or unique constraint. For example:
192
193   my $cd = $schema->resultset('CD')->find(5);
194
195 Also takes an optional C<key> attribute, to search by a specific key or unique
196 constraint. For example:
197
198   my $cd = $schema->resultset('CD')->find_or_create(
199     {
200       artist => 'Massive Attack',
201       title  => 'Mezzanine',
202     },
203     { key => 'artist_title' }
204   );
205
206 See also L</find_or_create> and L</update_or_create>.
207
208 =cut
209
210 sub find {
211   my ($self, @vals) = @_;
212   my $attrs = (@vals > 1 && ref $vals[$#vals] eq 'HASH' ? pop(@vals) : {});
213
214   my @cols = $self->result_source->primary_columns;
215   if (exists $attrs->{key}) {
216     my %uniq = $self->result_source->unique_constraints;
217     $self->( "Unknown key " . $attrs->{key} . " on " . $self->name )
218       unless exists $uniq{$attrs->{key}};
219     @cols = @{ $uniq{$attrs->{key}} };
220   }
221   #use Data::Dumper; warn Dumper($attrs, @vals, @cols);
222   $self->throw_exception( "Can't find unless a primary key or unique constraint is defined" )
223     unless @cols;
224
225   my $query;
226   if (ref $vals[0] eq 'HASH') {
227     $query = $vals[0];
228   } elsif (@cols == @vals) {
229     $query = {};
230     @{$query}{@cols} = @vals;
231   } else {
232     $query = {@vals};
233   }
234   #warn Dumper($query);
235   return $self->search($query)->next;
236 }
237
238 =head2 search_related
239
240   $rs->search_related('relname', $cond?, $attrs?);
241
242 Search the specified relationship. Optionally specify a condition for matching
243 records.
244
245 =cut
246
247 sub search_related {
248   my ($self, $rel, @rest) = @_;
249   my $rel_obj = $self->result_source->relationship_info($rel);
250   $self->throw_exception(
251     "No such relationship ${rel} in search_related")
252       unless $rel_obj;
253   my $rs = $self->search(undef, { join => $rel });
254   return $self->result_source->schema->resultset($rel_obj->{class}
255            )->search( undef,
256              { %{$rs->{attrs}},
257                alias => $rel,
258                select => undef(),
259                as => undef() }
260            )->search(@rest);
261 }
262
263 =head2 cursor
264
265 Returns a storage-driven cursor to the given resultset.
266
267 =cut
268
269 sub cursor {
270   my ($self) = @_;
271   my ($attrs) = $self->{attrs};
272   $attrs = { %$attrs };
273   return $self->{cursor}
274     ||= $self->result_source->storage->select($self->{from}, $attrs->{select},
275           $attrs->{where},$attrs);
276 }
277
278 =head2 search_like
279
280 Perform a search, but use C<LIKE> instead of equality as the condition. Note
281 that this is simply a convenience method; you most likely want to use
282 L</search> with specific operators.
283
284 For more information, see L<DBIx::Class::Manual::Cookbook>.
285
286 =cut
287
288 sub search_like {
289   my $class    = shift;
290   my $attrs = { };
291   if (@_ > 1 && ref $_[$#_] eq 'HASH') {
292     $attrs = pop(@_);
293   }
294   my $query    = ref $_[0] eq "HASH" ? { %{shift()} }: {@_};
295   $query->{$_} = { 'like' => $query->{$_} } for keys %$query;
296   return $class->search($query, { %$attrs });
297 }
298
299 =head2 slice($first, $last)
300
301 Returns a subset of elements from the resultset.
302
303 =cut
304
305 sub slice {
306   my ($self, $min, $max) = @_;
307   my $attrs = { %{ $self->{attrs} || {} } };
308   $attrs->{offset} ||= 0;
309   $attrs->{offset} += $min;
310   $attrs->{rows} = ($max ? ($max - $min + 1) : 1);
311   my $slice = (ref $self)->new($self->result_source, $attrs);
312   return (wantarray ? $slice->all : $slice);
313 }
314
315 =head2 next
316
317 Returns the next element in the resultset (C<undef> is there is none).
318
319 Can be used to efficiently iterate over records in the resultset:
320
321   my $rs = $schema->resultset('CD')->search({});
322   while (my $cd = $rs->next) {
323     print $cd->title;
324   }
325
326 =cut
327
328 sub next {
329   my ($self) = @_;
330   my @row = $self->cursor->next;
331 #  warn Dumper(\@row); use Data::Dumper;
332   return unless (@row);
333   return $self->_construct_object(@row);
334 }
335
336 sub _construct_object {
337   my ($self, @row) = @_;
338   my @as = @{ $self->{attrs}{as} };
339   #warn "@cols -> @row";
340   my $info = [ {}, {} ];
341   foreach my $as (@as) {
342     my $target = $info;
343     my @parts = split(/\./, $as);
344     my $col = pop(@parts);
345     foreach my $p (@parts) {
346       $target = $target->[1]->{$p} ||= [];
347     }
348     $target->[0]->{$col} = shift @row;
349   }
350   #use Data::Dumper; warn Dumper(\@as, $info);
351   my $new = $self->result_source->result_class->inflate_result(
352               $self->result_source, @$info);
353   $new = $self->{attrs}{record_filter}->($new)
354     if exists $self->{attrs}{record_filter};
355   return $new;
356 }
357
358 =head2 result_source 
359
360 Returns a reference to the result source for this recordset.
361
362 =cut
363
364
365 =head2 count
366
367 Performs an SQL C<COUNT> with the same query as the resultset was built
368 with to find the number of elements. If passed arguments, does a search
369 on the resultset and counts the results of that.
370
371 =cut
372
373 sub count {
374   my $self = shift;
375   return $self->search(@_)->count if @_ && defined $_[0];
376   $self->throw_exception(
377     "Unable to ->count with a GROUP BY" 
378   ) if defined $self->{attrs}{group_by};
379   unless (defined $self->{count}) {
380     my $attrs = { %{ $self->{attrs} },
381                   select => { 'count' => '*' },
382                   as => [ 'count' ] };
383     # offset, order by and page are not needed to count. record_filter is cdbi
384     delete $attrs->{$_} for qw/rows offset order_by page pager record_filter/;
385         
386     ($self->{count}) = (ref $self)->new($self->result_source, $attrs)->cursor->next;
387   }
388   return 0 unless $self->{count};
389   my $count = $self->{count};
390   $count -= $self->{attrs}{offset} if $self->{attrs}{offset};
391   $count = $self->{attrs}{rows} if
392     ($self->{attrs}{rows} && $self->{attrs}{rows} < $count);
393   return $count;
394 }
395
396 =head2 count_literal
397
398 Calls L</search_literal> with the passed arguments, then L</count>.
399
400 =cut
401
402 sub count_literal { shift->search_literal(@_)->count; }
403
404 =head2 all
405
406 Returns all elements in the resultset. Called implictly if the resultset
407 is returned in list context.
408
409 =cut
410
411 sub all {
412   my ($self) = @_;
413   return map { $self->_construct_object(@$_); }
414            $self->cursor->all;
415 }
416
417 =head2 reset
418
419 Resets the resultset's cursor, so you can iterate through the elements again.
420
421 =cut
422
423 sub reset {
424   my ($self) = @_;
425   $self->cursor->reset;
426   return $self;
427 }
428
429 =head2 first
430
431 Resets the resultset and returns the first element.
432
433 =cut
434
435 sub first {
436   return $_[0]->reset->next;
437 }
438
439 =head2 update(\%values)
440
441 Sets the specified columns in the resultset to the supplied values.
442
443 =cut
444
445 sub update {
446   my ($self, $values) = @_;
447   $self->throw_exception("Values for update must be a hash") unless ref $values eq 'HASH';
448   return $self->result_source->storage->update(
449            $self->result_source->from, $values, $self->{cond});
450 }
451
452 =head2 update_all(\%values)
453
454 Fetches all objects and updates them one at a time.  Note that C<update_all>
455 will run cascade triggers while L</update> will not.
456
457 =cut
458
459 sub update_all {
460   my ($self, $values) = @_;
461   $self->throw_exception("Values for update must be a hash") unless ref $values eq 'HASH';
462   foreach my $obj ($self->all) {
463     $obj->set_columns($values)->update;
464   }
465   return 1;
466 }
467
468 =head2 delete
469
470 Deletes the contents of the resultset from its result source.
471
472 =cut
473
474 sub delete {
475   my ($self) = @_;
476   $self->result_source->storage->delete($self->result_source->from, $self->{cond});
477   return 1;
478 }
479
480 =head2 delete_all
481
482 Fetches all objects and deletes them one at a time.  Note that C<delete_all>
483 will run cascade triggers while L</delete> will not.
484
485 =cut
486
487 sub delete_all {
488   my ($self) = @_;
489   $_->delete for $self->all;
490   return 1;
491 }
492
493 =head2 pager
494
495 Returns a L<Data::Page> object for the current resultset. Only makes
496 sense for queries with a C<page> attribute.
497
498 =cut
499
500 sub pager {
501   my ($self) = @_;
502   my $attrs = $self->{attrs};
503   $self->throw_exception("Can't create pager for non-paged rs") unless $self->{page};
504   $attrs->{rows} ||= 10;
505   $self->count;
506   return $self->{pager} ||= Data::Page->new(
507     $self->{count}, $attrs->{rows}, $self->{page});
508 }
509
510 =head2 page($page_num)
511
512 Returns a new resultset for the specified page.
513
514 =cut
515
516 sub page {
517   my ($self, $page) = @_;
518   my $attrs = { %{$self->{attrs}} };
519   $attrs->{page} = $page;
520   return (ref $self)->new($self->result_source, $attrs);
521 }
522
523 =head2 new_result(\%vals)
524
525 Creates a result in the resultset's result class.
526
527 =cut
528
529 sub new_result {
530   my ($self, $values) = @_;
531   $self->throw_exception( "new_result needs a hash" )
532     unless (ref $values eq 'HASH');
533   $self->throw_exception( "Can't abstract implicit construct, condition not a hash" )
534     if ($self->{cond} && !(ref $self->{cond} eq 'HASH'));
535   my %new = %$values;
536   my $alias = $self->{attrs}{alias};
537   foreach my $key (keys %{$self->{cond}||{}}) {
538     $new{$1} = $self->{cond}{$key} if ($key =~ m/^(?:$alias\.)?([^\.]+)$/);
539   }
540   my $obj = $self->result_source->result_class->new(\%new);
541   $obj->result_source($self->result_source) if $obj->can('result_source');
542   $obj;
543 }
544
545 =head2 create(\%vals)
546
547 Inserts a record into the resultset and returns the object.
548
549 Effectively a shortcut for C<< ->new_result(\%vals)->insert >>.
550
551 =cut
552
553 sub create {
554   my ($self, $attrs) = @_;
555   $self->throw_exception( "create needs a hashref" ) unless ref $attrs eq 'HASH';
556   return $self->new_result($attrs)->insert;
557 }
558
559 =head2 find_or_create(\%vals, \%attrs?)
560
561   $class->find_or_create({ key => $val, ... });
562
563 Searches for a record matching the search condition; if it doesn't find one,    
564 creates one and returns that instead.                                       
565
566   my $cd = $schema->resultset('CD')->find_or_create({
567     cdid   => 5,
568     artist => 'Massive Attack',
569     title  => 'Mezzanine',
570     year   => 2005,
571   });
572
573 Also takes an optional C<key> attribute, to search by a specific key or unique
574 constraint. For example:
575
576   my $cd = $schema->resultset('CD')->find_or_create(
577     {
578       artist => 'Massive Attack',
579       title  => 'Mezzanine',
580     },
581     { key => 'artist_title' }
582   );
583
584 See also L</find> and L</update_or_create>.
585
586 =cut
587
588 sub find_or_create {
589   my $self     = shift;
590   my $attrs    = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
591   my $hash     = ref $_[0] eq "HASH" ? shift : {@_};
592   my $exists   = $self->find($hash, $attrs);
593   return defined($exists) ? $exists : $self->create($hash);
594 }
595
596 =head2 update_or_create
597
598   $class->update_or_create({ key => $val, ... });
599
600 First, search for an existing row matching one of the unique constraints
601 (including the primary key) on the source of this resultset.  If a row is
602 found, update it with the other given column values.  Otherwise, create a new
603 row.
604
605 Takes an optional C<key> attribute to search on a specific unique constraint.
606 For example:
607
608   # In your application
609   my $cd = $schema->resultset('CD')->update_or_create(
610     {
611       artist => 'Massive Attack',
612       title  => 'Mezzanine',
613       year   => 1998,
614     },
615     { key => 'artist_title' }
616   );
617
618 If no C<key> is specified, it searches on all unique constraints defined on the
619 source, including the primary key.
620
621 If the C<key> is specified as C<primary>, search only on the primary key.
622
623 See also L</find> and L</find_or_create>.
624
625 =cut
626
627 sub update_or_create {
628   my $self = shift;
629
630   my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
631   my $hash  = ref $_[0] eq "HASH" ? shift : {@_};
632
633   my %unique_constraints = $self->result_source->unique_constraints;
634   my @constraint_names   = (exists $attrs->{key}
635                             ? ($attrs->{key})
636                             : keys %unique_constraints);
637
638   my @unique_hashes;
639   foreach my $name (@constraint_names) {
640     my @unique_cols = @{ $unique_constraints{$name} };
641     my %unique_hash =
642       map  { $_ => $hash->{$_} }
643       grep { exists $hash->{$_} }
644       @unique_cols;
645
646     push @unique_hashes, \%unique_hash
647       if (scalar keys %unique_hash == scalar @unique_cols);
648   }
649
650   my $row;
651   if (@unique_hashes) {
652     $row = $self->search(\@unique_hashes, { rows => 1 })->first;
653     if ($row) {
654       $row->set_columns($hash);
655       $row->update;
656     }
657   }
658
659   unless ($row) {
660     $row = $self->create($hash);
661   }
662
663   return $row;
664 }
665
666 =head2 throw_exception
667
668 See Schema's throw_exception
669
670 =cut
671
672 sub throw_exception {
673   my $self=shift;
674   $self->result_source->schema->throw_exception(@_);
675 }
676
677 =head1 ATTRIBUTES
678
679 The resultset takes various attributes that modify its behavior. Here's an
680 overview of them:
681
682 =head2 order_by
683
684 Which column(s) to order the results by. This is currently passed through
685 directly to SQL, so you can give e.g. C<foo DESC> for a descending order.
686
687 =head2 cols (arrayref)
688
689 Shortcut to request a particular set of columns to be retrieved.  Adds
690 C<me.> onto the start of any column without a C<.> in it and sets C<select>
691 from that, then auto-populates C<as> from C<select> as normal.
692
693 =head2 select (arrayref)
694
695 Indicates which columns should be selected from the storage. You can use
696 column names, or in the case of RDBMS back ends, function or stored procedure
697 names:
698
699   $rs = $schema->resultset('Foo')->search(
700     {},
701     {
702       select => [
703         'column_name',
704         { count => 'column_to_count' },
705         { sum => 'column_to_sum' }
706       ]
707     }
708   );
709
710 When you use function/stored procedure names and do not supply an C<as>
711 attribute, the column names returned are storage-dependent. E.g. MySQL would
712 return a column named C<count(column_to_count)> in the above example.
713
714 =head2 as (arrayref)
715
716 Indicates column names for object inflation. This is used in conjunction with
717 C<select>, usually when C<select> contains one or more function or stored
718 procedure names:
719
720   $rs = $schema->resultset('Foo')->search(
721     {},
722     {
723       select => [
724         'column1',
725         { count => 'column2' }
726       ],
727       as => [qw/ column1 column2_count /]
728     }
729   );
730
731   my $foo = $rs->first(); # get the first Foo
732
733 If the object against which the search is performed already has an accessor
734 matching a column name specified in C<as>, the value can be retrieved using
735 the accessor as normal:
736
737   my $column1 = $foo->column1();
738
739 If on the other hand an accessor does not exist in the object, you need to
740 use C<get_column> instead:
741
742   my $column2_count = $foo->get_column('column2_count');
743
744 You can create your own accessors if required - see
745 L<DBIx::Class::Manual::Cookbook> for details.
746
747 =head2 join
748
749 Contains a list of relationships that should be joined for this query.  For
750 example:
751
752   # Get CDs by Nine Inch Nails
753   my $rs = $schema->resultset('CD')->search(
754     { 'artist.name' => 'Nine Inch Nails' },
755     { join => 'artist' }
756   );
757
758 Can also contain a hash reference to refer to the other relation's relations.
759 For example:
760
761   package MyApp::Schema::Track;
762   use base qw/DBIx::Class/;
763   __PACKAGE__->table('track');
764   __PACKAGE__->add_columns(qw/trackid cd position title/);
765   __PACKAGE__->set_primary_key('trackid');
766   __PACKAGE__->belongs_to(cd => 'MyApp::Schema::CD');
767   1;
768
769   # In your application
770   my $rs = $schema->resultset('Artist')->search(
771     { 'track.title' => 'Teardrop' },
772     {
773       join     => { cd => 'track' },
774       order_by => 'artist.name',
775     }
776   );
777
778 If you want to fetch columns from related tables as well, see C<prefetch>
779 below.
780
781 =head2 prefetch arrayref/hashref
782
783 Contains one or more relationships that should be fetched along with the main 
784 query (when they are accessed afterwards they will have already been
785 "prefetched").  This is useful for when you know you will need the related
786 objects, because it saves at least one query:
787
788   my $rs = $schema->resultset('Tag')->search(
789     {},
790     {
791       prefetch => {
792         cd => 'artist'
793       }
794     }
795   );
796
797 The initial search results in SQL like the following:
798
799   SELECT tag.*, cd.*, artist.* FROM tag
800   JOIN cd ON tag.cd = cd.cdid
801   JOIN artist ON cd.artist = artist.artistid
802
803 L<DBIx::Class> has no need to go back to the database when we access the
804 C<cd> or C<artist> relationships, which saves us two SQL statements in this
805 case.
806
807 Any prefetched relationship will be joined automatically, so there is no need
808 for a C<join> attribute in the above search.
809
810 C<prefetch> can be used with the following relationship types: C<belongs_to>,
811 C<has_one>.
812
813 =head2 from (arrayref)
814
815 The C<from> attribute gives you manual control over the C<FROM> clause of SQL
816 statements generated by L<DBIx::Class>, allowing you to express custom C<JOIN>
817 clauses.
818
819 NOTE: Use this on your own risk.  This allows you to shoot off your foot!
820 C<join> will usually do what you need and it is strongly recommended that you
821 avoid using C<from> unless you cannot achieve the desired result using C<join>.
822
823 In simple terms, C<from> works as follows:
824
825     [
826         { <alias> => <table>, -join-type => 'inner|left|right' }
827         [] # nested JOIN (optional)
828         { <table.column> = <foreign_table.foreign_key> }
829     ]
830
831     JOIN
832         <alias> <table>
833         [JOIN ...]
834     ON <table.column> = <foreign_table.foreign_key>
835
836 An easy way to follow the examples below is to remember the following:
837
838     Anything inside "[]" is a JOIN
839     Anything inside "{}" is a condition for the enclosing JOIN
840
841 The following examples utilize a "person" table in a family tree application.
842 In order to express parent->child relationships, this table is self-joined:
843
844     # Person->belongs_to('father' => 'Person');
845     # Person->belongs_to('mother' => 'Person');
846
847 C<from> can be used to nest joins. Here we return all children with a father,
848 then search against all mothers of those children:
849
850   $rs = $schema->resultset('Person')->search(
851       {},
852       {
853           alias => 'mother', # alias columns in accordance with "from"
854           from => [
855               { mother => 'person' },
856               [
857                   [
858                       { child => 'person' },
859                       [
860                           { father => 'person' },
861                           { 'father.person_id' => 'child.father_id' }
862                       ]
863                   ],
864                   { 'mother.person_id' => 'child.mother_id' }
865               ],                
866           ]
867       },
868   );
869
870   # Equivalent SQL:
871   # SELECT mother.* FROM person mother
872   # JOIN (
873   #   person child
874   #   JOIN person father
875   #   ON ( father.person_id = child.father_id )
876   # )
877   # ON ( mother.person_id = child.mother_id )
878
879 The type of any join can be controlled manually. To search against only people
880 with a father in the person table, we could explicitly use C<INNER JOIN>:
881
882     $rs = $schema->resultset('Person')->search(
883         {},
884         {
885             alias => 'child', # alias columns in accordance with "from"
886             from => [
887                 { child => 'person' },
888                 [
889                     { father => 'person', -join-type => 'inner' },
890                     { 'father.id' => 'child.father_id' }
891                 ],
892             ]
893         },
894     );
895
896     # Equivalent SQL:
897     # SELECT child.* FROM person child
898     # INNER JOIN person father ON child.father_id = father.id
899
900 =head2 page
901
902 For a paged resultset, specifies which page to retrieve.  Leave unset
903 for an unpaged resultset.
904
905 =head2 rows
906
907 For a paged resultset, how many rows per page:
908
909   rows => 10
910
911 Can also be used to simulate an SQL C<LIMIT>.
912
913 =head2 group_by (arrayref)
914
915 A arrayref of columns to group by. Can include columns of joined tables. Note
916 note that L</count> doesn't work on grouped resultsets.
917
918   group_by => [qw/ column1 column2 ... /]
919
920 =head2 distinct
921
922 Set to 1 to group by all columns.
923
924 For more examples of using these attributes, see
925 L<DBIx::Class::Manual::Cookbook>.
926
927 =cut
928
929 1;