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