5575a0a925ca16108122c18996f9af8b3940dcef
[dbsrgits/DBIx-Class-Historic.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 use Scalar::Util qw/weaken/;
12
13 use DBIx::Class::ResultSetColumn;
14 use base qw/DBIx::Class/;
15 __PACKAGE__->load_components(qw/AccessorGroup/);
16 __PACKAGE__->mk_group_accessors('simple' => qw/result_source result_class/);
17
18 =head1 NAME
19
20 DBIx::Class::ResultSet - Responsible for fetching and creating resultset.
21
22 =head1 SYNOPSIS
23
24   my $rs   = $schema->resultset('User')->search(registered => 1);
25   my @rows = $schema->resultset('CD')->search(year => 2005);
26
27 =head1 DESCRIPTION
28
29 The resultset is also known as an iterator. It is responsible for handling
30 queries that may return an arbitrary number of rows, e.g. via L</search>
31 or a C<has_many> relationship.
32
33 In the examples below, the following table classes are used:
34
35   package MyApp::Schema::Artist;
36   use base qw/DBIx::Class/;
37   __PACKAGE__->load_components(qw/Core/);
38   __PACKAGE__->table('artist');
39   __PACKAGE__->add_columns(qw/artistid name/);
40   __PACKAGE__->set_primary_key('artistid');
41   __PACKAGE__->has_many(cds => 'MyApp::Schema::CD');
42   1;
43
44   package MyApp::Schema::CD;
45   use base qw/DBIx::Class/;
46   __PACKAGE__->load_components(qw/Core/);
47   __PACKAGE__->table('cd');
48   __PACKAGE__->add_columns(qw/cdid artist title year/);
49   __PACKAGE__->set_primary_key('cdid');
50   __PACKAGE__->belongs_to(artist => 'MyApp::Schema::Artist');
51   1;
52
53 =head1 METHODS
54
55 =head2 new
56
57 =over 4
58
59 =item Arguments: $source, \%$attrs
60
61 =item Return Value: $rs
62
63 =back
64
65 The resultset constructor. Takes a source object (usually a
66 L<DBIx::Class::ResultSourceProxy::Table>) and an attribute hash (see
67 L</ATTRIBUTES> below).  Does not perform any queries -- these are
68 executed as needed by the other methods.
69
70 Generally you won't need to construct a resultset manually.  You'll
71 automatically get one from e.g. a L</search> called in scalar context:
72
73   my $rs = $schema->resultset('CD')->search({ title => '100th Window' });
74
75 IMPORTANT: If called on an object, proxies to new_result instead so
76
77   my $cd = $schema->resultset('CD')->new({ title => 'Spoon' });
78
79 will return a CD object, not a ResultSet.
80
81 =cut
82
83 sub new {
84   my $class = shift;
85   return $class->new_result(@_) if ref $class;
86   
87   my ($source, $attrs) = @_;
88   weaken $source;
89   $attrs = Storable::dclone($attrs || {}); # { %{ $attrs || {} } };
90   #use Data::Dumper; warn Dumper($attrs);
91   my $alias = ($attrs->{alias} ||= 'me');
92   
93   $attrs->{columns} ||= delete $attrs->{cols} if $attrs->{cols};
94   delete $attrs->{as} if $attrs->{columns};
95   $attrs->{columns} ||= [ $source->columns ] unless $attrs->{select};
96   $attrs->{select} = [
97     map { m/\./ ? $_ : "${alias}.$_" } @{delete $attrs->{columns}}
98   ] if $attrs->{columns};
99   $attrs->{as} ||= [
100     map { m/^\Q$alias.\E(.+)$/ ? $1 : $_ } @{$attrs->{select}}
101   ];
102   if (my $include = delete $attrs->{include_columns}) {
103     push(@{$attrs->{select}}, @$include);
104     push(@{$attrs->{as}}, map { m/([^.]+)$/; $1; } @$include);
105   }
106   #use Data::Dumper; warn Dumper(@{$attrs}{qw/select as/});
107
108   $attrs->{from} ||= [ { $alias => $source->from } ];
109   $attrs->{seen_join} ||= {};
110   my %seen;
111   if (my $join = delete $attrs->{join}) {
112     foreach my $j (ref $join eq 'ARRAY' ? @$join : ($join)) {
113       if (ref $j eq 'HASH') {
114         $seen{$_} = 1 foreach keys %$j;
115       } else {
116         $seen{$j} = 1;
117       }
118     }
119     push(@{$attrs->{from}}, $source->resolve_join(
120       $join, $attrs->{alias}, $attrs->{seen_join})
121     );
122   }
123   
124   $attrs->{group_by} ||= $attrs->{select} if delete $attrs->{distinct};
125   $attrs->{order_by} = [ $attrs->{order_by} ] if
126     $attrs->{order_by} and !ref($attrs->{order_by});
127   $attrs->{order_by} ||= [];
128
129   my $collapse = $attrs->{collapse} || {};
130   if (my $prefetch = delete $attrs->{prefetch}) {
131     my @pre_order;
132     foreach my $p (ref $prefetch eq 'ARRAY' ? @$prefetch : ($prefetch)) {
133       if ( ref $p eq 'HASH' ) {
134         foreach my $key (keys %$p) {
135           push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
136             unless $seen{$key};
137         }
138       } else {
139         push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
140             unless $seen{$p};
141       }
142       my @prefetch = $source->resolve_prefetch(
143            $p, $attrs->{alias}, {}, \@pre_order, $collapse);
144       push(@{$attrs->{select}}, map { $_->[0] } @prefetch);
145       push(@{$attrs->{as}}, map { $_->[1] } @prefetch);
146     }
147     push(@{$attrs->{order_by}}, @pre_order);
148   }
149   $attrs->{collapse} = $collapse;
150 #  use Data::Dumper; warn Dumper($collapse) if keys %{$collapse};
151
152   if ($attrs->{page}) {
153     $attrs->{rows} ||= 10;
154     $attrs->{offset} ||= 0;
155     $attrs->{offset} += ($attrs->{rows} * ($attrs->{page} - 1));
156   }
157
158   bless {
159     result_source => $source,
160     result_class => $attrs->{result_class} || $source->result_class,
161     cond => $attrs->{where},
162     from => $attrs->{from},
163     collapse => $collapse,
164     count => undef,
165     page => delete $attrs->{page},
166     pager => undef,
167     attrs => $attrs
168   }, $class;
169 }
170
171 =head2 search
172
173 =over 4
174
175 =item Arguments: $cond, \%attrs?
176
177 =item Return Value: $resultset (scalar context), @row_objs (list context)
178
179 =back
180
181   my @cds    = $cd_rs->search({ year => 2001 }); # "... WHERE year = 2001"
182   my $new_rs = $cd_rs->search({ year => 2005 });
183
184   my $new_rs = $cd_rs->search([ { year => 2005 }, { year => 2004 } ]);
185                  # year = 2005 OR year = 2004
186
187 If you need to pass in additional attributes but no additional condition,
188 call it as C<search(undef, \%attrs)>.
189
190   # "SELECT name, artistid FROM $artist_table"
191   my @all_artists = $schema->resultset('Artist')->search(undef, {
192     columns => [qw/name artistid/],
193   });
194
195 =cut
196
197 sub search {
198   my $self = shift;
199
200   my $rs;
201   if( @_ ) {
202     
203     my $attrs = { %{$self->{attrs}} };
204     my $having = delete $attrs->{having};
205     $attrs = { %$attrs, %{ pop(@_) } } if @_ > 1 and ref $_[$#_] eq 'HASH';
206
207     my $where = (@_
208                   ? ((@_ == 1 || ref $_[0] eq "HASH")
209                       ? shift
210                       : ((@_ % 2)
211                           ? $self->throw_exception(
212                               "Odd number of arguments to search")
213                           : {@_}))
214                   : undef());
215     if (defined $where) {
216       $attrs->{where} = (defined $attrs->{where}
217                 ? { '-and' =>
218                     [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
219                         $where, $attrs->{where} ] }
220                 : $where);
221     }
222
223     if (defined $having) {
224       $attrs->{having} = (defined $attrs->{having}
225                 ? { '-and' =>
226                     [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
227                         $having, $attrs->{having} ] }
228                 : $having);
229     }
230
231     $rs = (ref $self)->new($self->result_source, $attrs);
232   }
233   else {
234     $rs = $self;
235     $rs->reset;
236   }
237   return (wantarray ? $rs->all : $rs);
238 }
239
240 =head2 search_literal
241
242 =over 4
243
244 =item Arguments: $sql_fragment, @bind_values
245
246 =item Return Value: $resultset (scalar context), @row_objs (list context)
247
248 =back
249
250   my @cds   = $cd_rs->search_literal('year = ? AND title = ?', qw/2001 Reload/);
251   my $newrs = $artist_rs->search_literal('name = ?', 'Metallica');
252
253 Pass a literal chunk of SQL to be added to the conditional part of the
254 resultset query.
255
256 =cut
257
258 sub search_literal {
259   my ($self, $cond, @vals) = @_;
260   my $attrs = (ref $vals[$#vals] eq 'HASH' ? { %{ pop(@vals) } } : {});
261   $attrs->{bind} = [ @{$self->{attrs}{bind}||[]}, @vals ];
262   return $self->search(\$cond, $attrs);
263 }
264
265 =head2 find
266
267 =over 4
268
269 =item Arguments: @values | \%cols, \%attrs?
270
271 =item Return Value: $row_object
272
273 =back
274
275 Finds a row based on its primary key or unique constraint. For example, to find
276 a row by its primary key:
277
278   my $cd = $schema->resultset('CD')->find(5);
279
280 You can also find a row by a specific key or unique constraint by specifying
281 the C<key> attribute. For example:
282
283   my $cd = $schema->resultset('CD')->find('Massive Attack', 'Mezzanine', { key => 'artist_title' });
284
285 Additionally, you can specify the columns explicitly by name:
286
287   my $cd = $schema->resultset('CD')->find(
288     {
289       artist => 'Massive Attack',
290       title  => 'Mezzanine',
291     },
292     { key => 'artist_title' }
293   );
294
295 If no C<key> is specified and you explicitly name columns, it searches on all
296 unique constraints defined on the source, including the primary key.
297
298 If the C<key> is specified as C<primary>, it searches only on the primary key.
299
300 See also L</find_or_create> and L</update_or_create>. For information on how to
301 declare unique constraints, see
302 L<DBIx::Class::ResultSource/add_unique_constraint>.
303
304 =cut
305
306 sub find {
307   my ($self, @vals) = @_;
308   my $attrs = (@vals > 1 && ref $vals[$#vals] eq 'HASH' ? pop(@vals) : {});
309
310   my %unique_constraints = $self->result_source->unique_constraints;
311   $self->throw_exception(
312     "Can't find unless a primary key or unique constraint is defined"
313   ) unless %unique_constraints;
314
315   $self->throw_exception(
316     "Unknown key $attrs->{key} on '" . $self->result_source->name . "'"
317   ) if (exists $attrs->{key} and not exists $unique_constraints{$attrs->{key}});
318
319   # Build a list of queries
320   my @unique_hashes;
321
322   if (ref $vals[0] eq 'HASH') {
323     my @constraint_names = exists $attrs->{key}
324       ? ($attrs->{key})
325       : keys %unique_constraints;
326
327     foreach my $name (@constraint_names) {
328       my @unique_cols = @{ $unique_constraints{$name} };
329       my $unique_hash = $self->_unique_hash($vals[0], \@unique_cols);
330
331       # TODO: Check that the ResultSet defines the rest of the query
332       push @unique_hashes, $unique_hash
333         if scalar keys %$unique_hash;# == scalar @unique_cols;
334     }
335   }
336   else {
337     my @unique_cols = exists $attrs->{key}
338       ? @{ $unique_constraints{$attrs->{key}} }
339       : $self->result_source->primary_columns;
340
341     if (@vals == @unique_cols) {
342       my %unique_hash;
343       @unique_hash{@unique_cols} = @vals;
344
345       push @unique_hashes, \%unique_hash;
346     }
347     else {
348       # Hack for CDBI queries
349       my %hash = @vals;
350       push @unique_hashes, \%hash;
351     }
352   }
353
354   # Add the ResultSet's alias
355   foreach my $unique_hash (@unique_hashes) {
356     foreach my $key (grep { ! m/\./ } keys %$unique_hash) {
357       $unique_hash->{"$self->{attrs}{alias}.$key"} = delete $unique_hash->{$key};
358     }
359   }
360
361   # Handle cases where the ResultSet already defines the query
362   my $query = @unique_hashes ? \@unique_hashes : undef;
363
364   if (keys %$attrs) {
365     my $rs = $self->search($query, $attrs);
366     return keys %{$rs->{collapse}} ? $rs->next : $rs->single;
367   }
368   else {
369     return keys %{$self->{collapse}}
370       ? $self->search($query)->next
371       : $self->single($query);
372   }
373 }
374
375 # _unique_hash
376 #
377 # Constrain the specified hash based on the specific column names.
378
379 sub _unique_hash {
380   my ($self, $hash, $unique_cols) = @_;
381
382   # Ugh, CDBI lowercases column names
383   if (exists $INC{'DBIx/Class/CDBICompat/ColumnCase.pm'}) {
384     foreach my $key (keys %$hash) {
385       $hash->{lc $key} = delete $hash->{$key};
386     }
387   }
388
389   my %unique_hash =
390     map  { $_ => $hash->{$_} }
391     grep { exists $hash->{$_} }
392     @$unique_cols;
393
394   return \%unique_hash;
395 }
396
397 =head2 search_related
398
399 =over 4
400
401 =item Arguments: $cond, \%attrs?
402
403 =item Return Value: $new_resultset
404
405 =back
406
407   $new_rs = $cd_rs->search_related('artist', {
408     name => 'Emo-R-Us',
409   });
410
411 Searches the specified relationship, optionally specifying a condition and
412 attributes for matching records. See L</ATTRIBUTES> for more information.
413
414 =cut
415
416 sub search_related {
417   return shift->related_resultset(shift)->search(@_);
418 }
419
420 =head2 cursor
421
422 =over 4
423
424 =item Arguments: none
425
426 =item Return Value: $cursor
427
428 =back
429
430 Returns a storage-driven cursor to the given resultset. See
431 L<DBIx::Class::Cursor> for more information.
432
433 =cut
434
435 sub cursor {
436   my ($self) = @_;
437   my $attrs = { %{$self->{attrs}} };
438   return $self->{cursor}
439     ||= $self->result_source->storage->select($self->{from}, $attrs->{select},
440           $attrs->{where},$attrs);
441 }
442
443 =head2 single
444
445 =over 4
446
447 =item Arguments: $cond?
448
449 =item Return Value: $row_object?
450
451 =back
452
453   my $cd = $schema->resultset('CD')->single({ year => 2001 });
454
455 Inflates the first result without creating a cursor if the resultset has
456 any records in it; if not returns nothing. Used by L</find> as an optimisation.
457
458 =cut
459
460 sub single {
461   my ($self, $where) = @_;
462   my $attrs = { %{$self->{attrs}} };
463   if ($where) {
464     if (defined $attrs->{where}) {
465       $attrs->{where} = {
466         '-and' =>
467             [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
468                $where, delete $attrs->{where} ]
469       };
470     } else {
471       $attrs->{where} = $where;
472     }
473   }
474   my @data = $self->result_source->storage->select_single(
475           $self->{from}, $attrs->{select},
476           $attrs->{where},$attrs);
477   return (@data ? $self->_construct_object(@data) : ());
478 }
479
480 =head2 get_column
481
482 =over 4
483
484 =item Arguments: $cond?
485
486 =item Return Value: $resultsetcolumn
487
488 =back
489
490   my $max_length = $rs->get_column('length')->max;
491
492 Returns a ResultSetColumn instance for $column based on $self
493
494 =cut
495
496 sub get_column {
497   my ($self, $column) = @_;
498
499   my $new = DBIx::Class::ResultSetColumn->new($self, $column);
500   return $new;
501 }
502
503 =head2 search_like
504
505 =over 4
506
507 =item Arguments: $cond, \%attrs?
508
509 =item Return Value: $resultset (scalar context), @row_objs (list context)
510
511 =back
512
513   # WHERE title LIKE '%blue%'
514   $cd_rs = $rs->search_like({ title => '%blue%'});
515
516 Performs a search, but uses C<LIKE> instead of C<=> as the condition. Note
517 that this is simply a convenience method. You most likely want to use
518 L</search> with specific operators.
519
520 For more information, see L<DBIx::Class::Manual::Cookbook>.
521
522 =cut
523
524 sub search_like {
525   my $class = shift;
526   my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
527   my $query = ref $_[0] eq 'HASH' ? { %{shift()} }: {@_};
528   $query->{$_} = { 'like' => $query->{$_} } for keys %$query;
529   return $class->search($query, { %$attrs });
530 }
531
532 =head2 slice
533
534 =over 4
535
536 =item Arguments: $first, $last
537
538 =item Return Value: $resultset (scalar context), @row_objs (list context)
539
540 =back
541
542 Returns a resultset or object list representing a subset of elements from the
543 resultset slice is called on. Indexes are from 0, i.e., to get the first
544 three records, call:
545
546   my ($one, $two, $three) = $rs->slice(0, 2);
547
548 =cut
549
550 sub slice {
551   my ($self, $min, $max) = @_;
552   my $attrs = {}; # = { %{ $self->{attrs} || {} } };
553   $attrs->{offset} = $self->{attrs}{offset} || 0;
554   $attrs->{offset} += $min;
555   $attrs->{rows} = ($max ? ($max - $min + 1) : 1);
556   return $self->search(undef(), $attrs);
557   #my $slice = (ref $self)->new($self->result_source, $attrs);
558   #return (wantarray ? $slice->all : $slice);
559 }
560
561 =head2 next
562
563 =over 4
564
565 =item Arguments: none
566
567 =item Return Value: $result?
568
569 =back
570
571 Returns the next element in the resultset (C<undef> is there is none).
572
573 Can be used to efficiently iterate over records in the resultset:
574
575   my $rs = $schema->resultset('CD')->search;
576   while (my $cd = $rs->next) {
577     print $cd->title;
578   }
579
580 Note that you need to store the resultset object, and call C<next> on it. 
581 Calling C<< resultset('Table')->next >> repeatedly will always return the
582 first record from the resultset.
583
584 =cut
585
586 sub next {
587   my ($self) = @_;
588   if (@{$self->{all_cache} || []}) {
589     $self->{all_cache_position} ||= 0;
590     return $self->{all_cache}->[$self->{all_cache_position}++];
591   }
592   if ($self->{attrs}{cache}) {
593     $self->{all_cache_position} = 1;
594     return ($self->all)[0];
595   }
596   my @row = (exists $self->{stashed_row} ?
597                @{delete $self->{stashed_row}} :
598                $self->cursor->next
599   );
600 #  warn Dumper(\@row); use Data::Dumper;
601   return unless (@row);
602   return $self->_construct_object(@row);
603 }
604
605 sub _construct_object {
606   my ($self, @row) = @_;
607   my @as = @{ $self->{attrs}{as} };
608   
609   my $info = $self->_collapse_result(\@as, \@row);
610   
611   my $new = $self->result_class->inflate_result($self->result_source, @$info);
612   
613   $new = $self->{attrs}{record_filter}->($new)
614     if exists $self->{attrs}{record_filter};
615   return $new;
616 }
617
618 sub _collapse_result {
619   my ($self, $as, $row, $prefix) = @_;
620
621   my %const;
622
623   my @copy = @$row;
624   foreach my $this_as (@$as) {
625     my $val = shift @copy;
626     if (defined $prefix) {
627       if ($this_as =~ m/^\Q${prefix}.\E(.+)$/) {
628         my $remain = $1;
629         $remain =~ /^(?:(.*)\.)?([^.]+)$/;
630         $const{$1||''}{$2} = $val;
631       }
632     } else {
633       $this_as =~ /^(?:(.*)\.)?([^.]+)$/;
634       $const{$1||''}{$2} = $val;
635     }
636   }
637
638   my $info = [ {}, {} ];
639   foreach my $key (keys %const) {
640     if (length $key) {
641       my $target = $info;
642       my @parts = split(/\./, $key);
643       foreach my $p (@parts) {
644         $target = $target->[1]->{$p} ||= [];
645       }
646       $target->[0] = $const{$key};
647     } else {
648       $info->[0] = $const{$key};
649     }
650   }
651
652   my @collapse;
653   if (defined $prefix) {
654     @collapse = map {
655         m/^\Q${prefix}.\E(.+)$/ ? ($1) : ()
656     } keys %{$self->{collapse}}
657   } else {
658     @collapse = keys %{$self->{collapse}};
659   };
660
661   if (@collapse) {
662     my ($c) = sort { length $a <=> length $b } @collapse;
663     my $target = $info;
664     foreach my $p (split(/\./, $c)) {
665       $target = $target->[1]->{$p} ||= [];
666     }
667     my $c_prefix = (defined($prefix) ? "${prefix}.${c}" : $c);
668     my @co_key = @{$self->{collapse}{$c_prefix}};
669     my %co_check = map { ($_, $target->[0]->{$_}); } @co_key;
670     my $tree = $self->_collapse_result($as, $row, $c_prefix);
671     my (@final, @raw);
672     while ( !(grep {
673                 !defined($tree->[0]->{$_}) ||
674                 $co_check{$_} ne $tree->[0]->{$_}
675               } @co_key) ) {
676       push(@final, $tree);
677       last unless (@raw = $self->cursor->next);
678       $row = $self->{stashed_row} = \@raw;
679       $tree = $self->_collapse_result($as, $row, $c_prefix);
680       #warn Data::Dumper::Dumper($tree, $row);
681     }
682     @$target = @final;
683   }
684
685   return $info;
686 }
687
688 =head2 result_source
689
690 =over 4
691
692 =item Arguments: $result_source?
693
694 =item Return Value: $result_source
695
696 =back
697
698 An accessor for the primary ResultSource object from which this ResultSet
699 is derived.
700
701 =cut
702
703
704 =head2 count
705
706 =over 4
707
708 =item Arguments: $cond, \%attrs??
709
710 =item Return Value: $count
711
712 =back
713
714 Performs an SQL C<COUNT> with the same query as the resultset was built
715 with to find the number of elements. If passed arguments, does a search
716 on the resultset and counts the results of that.
717
718 Note: When using C<count> with C<group_by>, L<DBIX::Class> emulates C<GROUP BY>
719 using C<COUNT( DISTINCT( columns ) )>. Some databases (notably SQLite) do
720 not support C<DISTINCT> with multiple columns. If you are using such a
721 database, you should only use columns from the main table in your C<group_by>
722 clause.
723
724 =cut
725
726 sub count {
727   my $self = shift;
728   return $self->search(@_)->count if @_ and defined $_[0];
729   return scalar @{ $self->get_cache } if @{ $self->get_cache };
730
731   my $count = $self->_count;
732   return 0 unless $count;
733
734   $count -= $self->{attrs}{offset} if $self->{attrs}{offset};
735   $count = $self->{attrs}{rows} if
736     $self->{attrs}{rows} and $self->{attrs}{rows} < $count;
737   return $count;
738 }
739
740 sub _count { # Separated out so pager can get the full count
741   my $self = shift;
742   my $select = { count => '*' };
743   my $attrs = { %{ $self->{attrs} } };
744   if (my $group_by = delete $attrs->{group_by}) {
745     delete $attrs->{having};
746     my @distinct = (ref $group_by ?  @$group_by : ($group_by));
747     # todo: try CONCAT for multi-column pk
748     my @pk = $self->result_source->primary_columns;
749     if (@pk == 1) {
750       foreach my $column (@distinct) {
751         if ($column =~ qr/^(?:\Q$attrs->{alias}.\E)?$pk[0]$/) {
752           @distinct = ($column);
753           last;
754         }
755       }
756     }
757
758     $select = { count => { distinct => \@distinct } };
759     #use Data::Dumper; die Dumper $select;
760   }
761
762   $attrs->{select} = $select;
763   $attrs->{as} = [qw/count/];
764
765   # offset, order by and page are not needed to count. record_filter is cdbi
766   delete $attrs->{$_} for qw/rows offset order_by page pager record_filter/;
767         
768   my ($count) = (ref $self)->new($self->result_source, $attrs)->cursor->next;
769   return $count;
770 }
771
772 =head2 count_literal
773
774 =over 4
775
776 =item Arguments: $sql_fragment, @bind_values
777
778 =item Return Value: $count
779
780 =back
781
782 Counts the results in a literal query. Equivalent to calling L</search_literal>
783 with the passed arguments, then L</count>.
784
785 =cut
786
787 sub count_literal { shift->search_literal(@_)->count; }
788
789 =head2 all
790
791 =over 4
792
793 =item Arguments: none
794
795 =item Return Value: @objects
796
797 =back
798
799 Returns all elements in the resultset. Called implicitly if the resultset
800 is returned in list context.
801
802 =cut
803
804 sub all {
805   my ($self) = @_;
806   return @{ $self->get_cache } if @{ $self->get_cache };
807
808   my @obj;
809
810   if (keys %{$self->{collapse}}) {
811       # Using $self->cursor->all is really just an optimisation.
812       # If we're collapsing has_many prefetches it probably makes
813       # very little difference, and this is cleaner than hacking
814       # _construct_object to survive the approach
815     $self->cursor->reset;
816     my @row = $self->cursor->next;
817     while (@row) {
818       push(@obj, $self->_construct_object(@row));
819       @row = (exists $self->{stashed_row}
820                ? @{delete $self->{stashed_row}}
821                : $self->cursor->next);
822     }
823   } else {
824     @obj = map { $self->_construct_object(@$_) } $self->cursor->all;
825   }
826
827   $self->set_cache(\@obj) if $self->{attrs}{cache};
828   return @obj;
829 }
830
831 =head2 reset
832
833 =over 4
834
835 =item Arguments: none
836
837 =item Return Value: $self
838
839 =back
840
841 Resets the resultset's cursor, so you can iterate through the elements again.
842
843 =cut
844
845 sub reset {
846   my ($self) = @_;
847   $self->{all_cache_position} = 0;
848   $self->cursor->reset;
849   return $self;
850 }
851
852 =head2 first
853
854 =over 4
855
856 =item Arguments: none
857
858 =item Return Value: $object?
859
860 =back
861
862 Resets the resultset and returns an object for the first result (if the
863 resultset returns anything).
864
865 =cut
866
867 sub first {
868   return $_[0]->reset->next;
869 }
870
871 # _cond_for_update_delete
872 #
873 # update/delete require the condition to be modified to handle
874 # the differing SQL syntax available.  This transforms the $self->{cond}
875 # appropriately, returning the new condition.
876
877 sub _cond_for_update_delete {
878   my ($self) = @_;
879   my $cond = {};
880
881   if (!ref($self->{cond})) {
882     # No-op. No condition, we're updating/deleting everything
883   }
884   elsif (ref $self->{cond} eq 'ARRAY') {
885     $cond = [
886       map {
887         my %hash;
888         foreach my $key (keys %{$_}) {
889           $key =~ /([^.]+)$/;
890           $hash{$1} = $_->{$key};
891         }
892         \%hash;
893       } @{$self->{cond}}
894     ];
895   }
896   elsif (ref $self->{cond} eq 'HASH') {
897     if ((keys %{$self->{cond}})[0] eq '-and') {
898       $cond->{-and} = [];
899
900       my @cond = @{$self->{cond}{-and}};
901       for (my $i = 0; $i < @cond - 1; $i++) {
902         my $entry = $cond[$i];
903
904         my %hash;
905         if (ref $entry eq 'HASH') {
906           foreach my $key (keys %{$entry}) {
907             $key =~ /([^.]+)$/;
908             $hash{$1} = $entry->{$key};
909           }
910         }
911         else {
912           $entry =~ /([^.]+)$/;
913           $hash{$entry} = $cond[++$i];
914         }
915
916         push @{$cond->{-and}}, \%hash;
917       }
918     }
919     else {
920       foreach my $key (keys %{$self->{cond}}) {
921         $key =~ /([^.]+)$/;
922         $cond->{$1} = $self->{cond}{$key};
923       }
924     }
925   }
926   else {
927     $self->throw_exception(
928       "Can't update/delete on resultset with condition unless hash or array"
929     );
930   }
931
932   return $cond;
933 }
934
935
936 =head2 update
937
938 =over 4
939
940 =item Arguments: \%values
941
942 =item Return Value: $storage_rv
943
944 =back
945
946 Sets the specified columns in the resultset to the supplied values in a
947 single query. Return value will be true if the update succeeded or false
948 if no records were updated; exact type of success value is storage-dependent.
949
950 =cut
951
952 sub update {
953   my ($self, $values) = @_;
954   $self->throw_exception("Values for update must be a hash")
955     unless ref $values eq 'HASH';
956
957   my $cond = $self->_cond_for_update_delete;
958
959   return $self->result_source->storage->update(
960     $self->result_source->from, $values, $cond
961   );
962 }
963
964 =head2 update_all
965
966 =over 4
967
968 =item Arguments: \%values
969
970 =item Return Value: 1
971
972 =back
973
974 Fetches all objects and updates them one at a time. Note that C<update_all>
975 will run DBIC cascade triggers, while L</update> will not.
976
977 =cut
978
979 sub update_all {
980   my ($self, $values) = @_;
981   $self->throw_exception("Values for update must be a hash")
982     unless ref $values eq 'HASH';
983   foreach my $obj ($self->all) {
984     $obj->set_columns($values)->update;
985   }
986   return 1;
987 }
988
989 =head2 delete
990
991 =over 4
992
993 =item Arguments: none
994
995 =item Return Value: 1
996
997 =back
998
999 Deletes the contents of the resultset from its result source. Note that this
1000 will not run DBIC cascade triggers. See L</delete_all> if you need triggers
1001 to run.
1002
1003 =cut
1004
1005 sub delete {
1006   my ($self) = @_;
1007   my $del = {};
1008
1009   my $cond = $self->_cond_for_update_delete;
1010
1011   $self->result_source->storage->delete($self->result_source->from, $cond);
1012   return 1;
1013 }
1014
1015 =head2 delete_all
1016
1017 =over 4
1018
1019 =item Arguments: none
1020
1021 =item Return Value: 1
1022
1023 =back
1024
1025 Fetches all objects and deletes them one at a time. Note that C<delete_all>
1026 will run DBIC cascade triggers, while L</delete> will not.
1027
1028 =cut
1029
1030 sub delete_all {
1031   my ($self) = @_;
1032   $_->delete for $self->all;
1033   return 1;
1034 }
1035
1036 =head2 pager
1037
1038 =over 4
1039
1040 =item Arguments: none
1041
1042 =item Return Value: $pager
1043
1044 =back
1045
1046 Return Value a L<Data::Page> object for the current resultset. Only makes
1047 sense for queries with a C<page> attribute.
1048
1049 =cut
1050
1051 sub pager {
1052   my ($self) = @_;
1053   my $attrs = $self->{attrs};
1054   $self->throw_exception("Can't create pager for non-paged rs")
1055     unless $self->{page};
1056   $attrs->{rows} ||= 10;
1057   return $self->{pager} ||= Data::Page->new(
1058     $self->_count, $attrs->{rows}, $self->{page});
1059 }
1060
1061 =head2 page
1062
1063 =over 4
1064
1065 =item Arguments: $page_number
1066
1067 =item Return Value: $rs
1068
1069 =back
1070
1071 Returns a resultset for the $page_number page of the resultset on which page
1072 is called, where each page contains a number of rows equal to the 'rows'
1073 attribute set on the resultset (10 by default).
1074
1075 =cut
1076
1077 sub page {
1078   my ($self, $page) = @_;
1079   my $attrs = { %{$self->{attrs}} };
1080   $attrs->{page} = $page;
1081   return (ref $self)->new($self->result_source, $attrs);
1082 }
1083
1084 =head2 new_result
1085
1086 =over 4
1087
1088 =item Arguments: \%vals
1089
1090 =item Return Value: $object
1091
1092 =back
1093
1094 Creates an object in the resultset's result class and returns it.
1095
1096 =cut
1097
1098 sub new_result {
1099   my ($self, $values) = @_;
1100   $self->throw_exception( "new_result needs a hash" )
1101     unless (ref $values eq 'HASH');
1102   $self->throw_exception(
1103     "Can't abstract implicit construct, condition not a hash"
1104   ) if ($self->{cond} && !(ref $self->{cond} eq 'HASH'));
1105   my %new = %$values;
1106   my $alias = $self->{attrs}{alias};
1107   foreach my $key (keys %{$self->{cond}||{}}) {
1108     $new{$1} = $self->{cond}{$key} if ($key =~ m/^(?:\Q${alias}.\E)?([^.]+)$/);
1109   }
1110   my $obj = $self->result_class->new(\%new);
1111   $obj->result_source($self->result_source) if $obj->can('result_source');
1112   return $obj;
1113 }
1114
1115 =head2 find_or_new
1116
1117 =over 4
1118
1119 =item Arguments: \%vals, \%attrs?
1120
1121 =item Return Value: $object
1122
1123 =back
1124
1125 Find an existing record from this resultset. If none exists, instantiate a new
1126 result object and return it. The object will not be saved into your storage
1127 until you call L<DBIx::Class::Row/insert> on it.
1128
1129 If you want objects to be saved immediately, use L</find_or_create> instead.
1130
1131 =cut
1132
1133 sub find_or_new {
1134   my $self     = shift;
1135   my $attrs    = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
1136   my $hash     = ref $_[0] eq 'HASH' ? shift : {@_};
1137   my $exists   = $self->find($hash, $attrs);
1138   return defined $exists ? $exists : $self->new_result($hash);
1139 }
1140
1141 =head2 create
1142
1143 =over 4
1144
1145 =item Arguments: \%vals
1146
1147 =item Return Value: $object
1148
1149 =back
1150
1151 Inserts a record into the resultset and returns the object representing it.
1152
1153 Effectively a shortcut for C<< ->new_result(\%vals)->insert >>.
1154
1155 =cut
1156
1157 sub create {
1158   my ($self, $attrs) = @_;
1159   $self->throw_exception( "create needs a hashref" )
1160     unless ref $attrs eq 'HASH';
1161   return $self->new_result($attrs)->insert;
1162 }
1163
1164 =head2 find_or_create
1165
1166 =over 4
1167
1168 =item Arguments: \%vals, \%attrs?
1169
1170 =item Return Value: $object
1171
1172 =back
1173
1174   $class->find_or_create({ key => $val, ... });
1175
1176 Searches for a record matching the search condition; if it doesn't find one,
1177 creates one and returns that instead.
1178
1179   my $cd = $schema->resultset('CD')->find_or_create({
1180     cdid   => 5,
1181     artist => 'Massive Attack',
1182     title  => 'Mezzanine',
1183     year   => 2005,
1184   });
1185
1186 Also takes an optional C<key> attribute, to search by a specific key or unique
1187 constraint. For example:
1188
1189   my $cd = $schema->resultset('CD')->find_or_create(
1190     {
1191       artist => 'Massive Attack',
1192       title  => 'Mezzanine',
1193     },
1194     { key => 'artist_title' }
1195   );
1196
1197 See also L</find> and L</update_or_create>. For information on how to declare
1198 unique constraints, see L<DBIx::Class::ResultSource/add_unique_constraint>.
1199
1200 =cut
1201
1202 sub find_or_create {
1203   my $self     = shift;
1204   my $attrs    = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
1205   my $hash     = ref $_[0] eq 'HASH' ? shift : {@_};
1206   my $exists   = $self->find($hash, $attrs);
1207   return defined $exists ? $exists : $self->create($hash);
1208 }
1209
1210 =head2 update_or_create
1211
1212 =over 4
1213
1214 =item Arguments: \%col_values, { key => $unique_constraint }?
1215
1216 =item Return Value: $object
1217
1218 =back
1219
1220   $class->update_or_create({ col => $val, ... });
1221
1222 First, searches for an existing row matching one of the unique constraints
1223 (including the primary key) on the source of this resultset. If a row is
1224 found, updates it with the other given column values. Otherwise, creates a new
1225 row.
1226
1227 Takes an optional C<key> attribute to search on a specific unique constraint.
1228 For example:
1229
1230   # In your application
1231   my $cd = $schema->resultset('CD')->update_or_create(
1232     {
1233       artist => 'Massive Attack',
1234       title  => 'Mezzanine',
1235       year   => 1998,
1236     },
1237     { key => 'artist_title' }
1238   );
1239
1240 If no C<key> is specified, it searches on all unique constraints defined on the
1241 source, including the primary key.
1242
1243 If the C<key> is specified as C<primary>, it searches only on the primary key.
1244
1245 See also L</find> and L</find_or_create>. For information on how to declare
1246 unique constraints, see L<DBIx::Class::ResultSource/add_unique_constraint>.
1247
1248 =cut
1249
1250 sub update_or_create {
1251   my $self = shift;
1252   my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
1253   my $hash = ref $_[0] eq 'HASH' ? shift : {@_};
1254
1255   my $row = $self->find($hash, $attrs);
1256   if (defined $row) {
1257     $row->set_columns($hash);
1258     $row->update;
1259     return $row;
1260   }
1261
1262   return $self->create($hash);
1263 }
1264
1265 =head2 get_cache
1266
1267 =over 4
1268
1269 =item Arguments: none
1270
1271 =item Return Value: \@cache_objects?
1272
1273 =back
1274
1275 Gets the contents of the cache for the resultset, if the cache is set.
1276
1277 =cut
1278
1279 sub get_cache {
1280   shift->{all_cache} || [];
1281 }
1282
1283 =head2 set_cache
1284
1285 =over 4
1286
1287 =item Arguments: \@cache_objects
1288
1289 =item Return Value: \@cache_objects
1290
1291 =back
1292
1293 Sets the contents of the cache for the resultset. Expects an arrayref
1294 of objects of the same class as those produced by the resultset. Note that
1295 if the cache is set the resultset will return the cached objects rather
1296 than re-querying the database even if the cache attr is not set.
1297
1298 =cut
1299
1300 sub set_cache {
1301   my ( $self, $data ) = @_;
1302   $self->throw_exception("set_cache requires an arrayref")
1303     if ref $data ne 'ARRAY';
1304   my $result_class = $self->result_class;
1305   foreach( @$data ) {
1306     $self->throw_exception(
1307       "cannot cache object of type '$_', expected '$result_class'"
1308     ) if ref $_ ne $result_class;
1309   }
1310   $self->{all_cache} = $data;
1311 }
1312
1313 =head2 clear_cache
1314
1315 =over 4
1316
1317 =item Arguments: none
1318
1319 =item Return Value: []
1320
1321 =back
1322
1323 Clears the cache for the resultset.
1324
1325 =cut
1326
1327 sub clear_cache {
1328   shift->set_cache([]);
1329 }
1330
1331 =head2 related_resultset
1332
1333 =over 4
1334
1335 =item Arguments: $relationship_name
1336
1337 =item Return Value: $resultset
1338
1339 =back
1340
1341 Returns a related resultset for the supplied relationship name.
1342
1343   $artist_rs = $schema->resultset('CD')->related_resultset('Artist');
1344
1345 =cut
1346
1347 sub related_resultset {
1348   my ( $self, $rel ) = @_;
1349   $self->{related_resultsets} ||= {};
1350   return $self->{related_resultsets}{$rel} ||= do {
1351       #warn "fetching related resultset for rel '$rel'";
1352       my $rel_obj = $self->result_source->relationship_info($rel);
1353       $self->throw_exception(
1354         "search_related: result source '" . $self->result_source->name .
1355         "' has no such relationship ${rel}")
1356         unless $rel_obj; #die Dumper $self->{attrs};
1357
1358       my $rs = $self->search(undef, { join => $rel });
1359       my $alias = defined $rs->{attrs}{seen_join}{$rel}
1360                     && $rs->{attrs}{seen_join}{$rel} > 1
1361                   ? join('_', $rel, $rs->{attrs}{seen_join}{$rel})
1362                   : $rel;
1363
1364       $self->result_source->schema->resultset($rel_obj->{class}
1365            )->search( undef,
1366              { %{$rs->{attrs}},
1367                alias => $alias,
1368                select => undef,
1369                as => undef }
1370            );
1371   };
1372 }
1373
1374 =head2 throw_exception
1375
1376 See L<DBIx::Class::Schema/throw_exception> for details.
1377
1378 =cut
1379
1380 sub throw_exception {
1381   my $self=shift;
1382   $self->result_source->schema->throw_exception(@_);
1383 }
1384
1385 # XXX: FIXME: Attributes docs need clearing up
1386
1387 =head1 ATTRIBUTES
1388
1389 The resultset takes various attributes that modify its behavior. Here's an
1390 overview of them:
1391
1392 =head2 order_by
1393
1394 =over 4
1395
1396 =item Value: ($order_by | \@order_by)
1397
1398 =back
1399
1400 Which column(s) to order the results by. This is currently passed
1401 through directly to SQL, so you can give e.g. C<year DESC> for a
1402 descending order on the column `year'.
1403
1404 =head2 columns
1405
1406 =over 4
1407
1408 =item Value: \@columns
1409
1410 =back
1411
1412 Shortcut to request a particular set of columns to be retrieved.  Adds
1413 C<me.> onto the start of any column without a C<.> in it and sets C<select>
1414 from that, then auto-populates C<as> from C<select> as normal. (You may also
1415 use the C<cols> attribute, as in earlier versions of DBIC.)
1416
1417 =head2 include_columns
1418
1419 =over 4
1420
1421 =item Value: \@columns
1422
1423 =back
1424
1425 Shortcut to include additional columns in the returned results - for example
1426
1427   $schema->resultset('CD')->search(undef, {
1428     include_columns => ['artist.name'],
1429     join => ['artist']
1430   });
1431
1432 would return all CDs and include a 'name' column to the information
1433 passed to object inflation
1434
1435 =head2 select
1436
1437 =over 4
1438
1439 =item Value: \@select_columns
1440
1441 =back
1442
1443 Indicates which columns should be selected from the storage. You can use
1444 column names, or in the case of RDBMS back ends, function or stored procedure
1445 names:
1446
1447   $rs = $schema->resultset('Employee')->search(undef, {
1448     select => [
1449       'name',
1450       { count => 'employeeid' },
1451       { sum => 'salary' }
1452     ]
1453   });
1454
1455 When you use function/stored procedure names and do not supply an C<as>
1456 attribute, the column names returned are storage-dependent. E.g. MySQL would
1457 return a column named C<count(employeeid)> in the above example.
1458
1459 =head2 as
1460
1461 =over 4
1462
1463 =item Value: \@inflation_names
1464
1465 =back
1466
1467 Indicates column names for object inflation. This is used in conjunction with
1468 C<select>, usually when C<select> contains one or more function or stored
1469 procedure names:
1470
1471   $rs = $schema->resultset('Employee')->search(undef, {
1472     select => [
1473       'name',
1474       { count => 'employeeid' }
1475     ],
1476     as => ['name', 'employee_count'],
1477   });
1478
1479   my $employee = $rs->first(); # get the first Employee
1480
1481 If the object against which the search is performed already has an accessor
1482 matching a column name specified in C<as>, the value can be retrieved using
1483 the accessor as normal:
1484
1485   my $name = $employee->name();
1486
1487 If on the other hand an accessor does not exist in the object, you need to
1488 use C<get_column> instead:
1489
1490   my $employee_count = $employee->get_column('employee_count');
1491
1492 You can create your own accessors if required - see
1493 L<DBIx::Class::Manual::Cookbook> for details.
1494
1495 =head2 join
1496
1497 =over 4
1498
1499 =item Value: ($rel_name | \@rel_names | \%rel_names)
1500
1501 =back
1502
1503 Contains a list of relationships that should be joined for this query.  For
1504 example:
1505
1506   # Get CDs by Nine Inch Nails
1507   my $rs = $schema->resultset('CD')->search(
1508     { 'artist.name' => 'Nine Inch Nails' },
1509     { join => 'artist' }
1510   );
1511
1512 Can also contain a hash reference to refer to the other relation's relations.
1513 For example:
1514
1515   package MyApp::Schema::Track;
1516   use base qw/DBIx::Class/;
1517   __PACKAGE__->table('track');
1518   __PACKAGE__->add_columns(qw/trackid cd position title/);
1519   __PACKAGE__->set_primary_key('trackid');
1520   __PACKAGE__->belongs_to(cd => 'MyApp::Schema::CD');
1521   1;
1522
1523   # In your application
1524   my $rs = $schema->resultset('Artist')->search(
1525     { 'track.title' => 'Teardrop' },
1526     {
1527       join     => { cd => 'track' },
1528       order_by => 'artist.name',
1529     }
1530   );
1531
1532 If the same join is supplied twice, it will be aliased to <rel>_2 (and
1533 similarly for a third time). For e.g.
1534
1535   my $rs = $schema->resultset('Artist')->search({
1536     'cds.title'   => 'Down to Earth',
1537     'cds_2.title' => 'Popular',
1538   }, {
1539     join => [ qw/cds cds/ ],
1540   });
1541
1542 will return a set of all artists that have both a cd with title 'Down
1543 to Earth' and a cd with title 'Popular'.
1544
1545 If you want to fetch related objects from other tables as well, see C<prefetch>
1546 below.
1547
1548 =head2 prefetch
1549
1550 =over 4
1551
1552 =item Value: ($rel_name | \@rel_names | \%rel_names)
1553
1554 =back
1555
1556 Contains one or more relationships that should be fetched along with the main
1557 query (when they are accessed afterwards they will have already been
1558 "prefetched").  This is useful for when you know you will need the related
1559 objects, because it saves at least one query:
1560
1561   my $rs = $schema->resultset('Tag')->search(
1562     undef,
1563     {
1564       prefetch => {
1565         cd => 'artist'
1566       }
1567     }
1568   );
1569
1570 The initial search results in SQL like the following:
1571
1572   SELECT tag.*, cd.*, artist.* FROM tag
1573   JOIN cd ON tag.cd = cd.cdid
1574   JOIN artist ON cd.artist = artist.artistid
1575
1576 L<DBIx::Class> has no need to go back to the database when we access the
1577 C<cd> or C<artist> relationships, which saves us two SQL statements in this
1578 case.
1579
1580 Simple prefetches will be joined automatically, so there is no need
1581 for a C<join> attribute in the above search. If you're prefetching to
1582 depth (e.g. { cd => { artist => 'label' } or similar), you'll need to
1583 specify the join as well.
1584
1585 C<prefetch> can be used with the following relationship types: C<belongs_to>,
1586 C<has_one> (or if you're using C<add_relationship>, any relationship declared
1587 with an accessor type of 'single' or 'filter').
1588
1589 =head2 from
1590
1591 =over 4
1592
1593 =item Value: \@from_clause
1594
1595 =back
1596
1597 The C<from> attribute gives you manual control over the C<FROM> clause of SQL
1598 statements generated by L<DBIx::Class>, allowing you to express custom C<JOIN>
1599 clauses.
1600
1601 NOTE: Use this on your own risk.  This allows you to shoot off your foot!
1602 C<join> will usually do what you need and it is strongly recommended that you
1603 avoid using C<from> unless you cannot achieve the desired result using C<join>.
1604
1605 In simple terms, C<from> works as follows:
1606
1607     [
1608         { <alias> => <table>, -join_type => 'inner|left|right' }
1609         [] # nested JOIN (optional)
1610         { <table.column> => <foreign_table.foreign_key> }
1611     ]
1612
1613     JOIN
1614         <alias> <table>
1615         [JOIN ...]
1616     ON <table.column> = <foreign_table.foreign_key>
1617
1618 An easy way to follow the examples below is to remember the following:
1619
1620     Anything inside "[]" is a JOIN
1621     Anything inside "{}" is a condition for the enclosing JOIN
1622
1623 The following examples utilize a "person" table in a family tree application.
1624 In order to express parent->child relationships, this table is self-joined:
1625
1626     # Person->belongs_to('father' => 'Person');
1627     # Person->belongs_to('mother' => 'Person');
1628
1629 C<from> can be used to nest joins. Here we return all children with a father,
1630 then search against all mothers of those children:
1631
1632   $rs = $schema->resultset('Person')->search(
1633       undef,
1634       {
1635           alias => 'mother', # alias columns in accordance with "from"
1636           from => [
1637               { mother => 'person' },
1638               [
1639                   [
1640                       { child => 'person' },
1641                       [
1642                           { father => 'person' },
1643                           { 'father.person_id' => 'child.father_id' }
1644                       ]
1645                   ],
1646                   { 'mother.person_id' => 'child.mother_id' }
1647               ],
1648           ]
1649       },
1650   );
1651
1652   # Equivalent SQL:
1653   # SELECT mother.* FROM person mother
1654   # JOIN (
1655   #   person child
1656   #   JOIN person father
1657   #   ON ( father.person_id = child.father_id )
1658   # )
1659   # ON ( mother.person_id = child.mother_id )
1660
1661 The type of any join can be controlled manually. To search against only people
1662 with a father in the person table, we could explicitly use C<INNER JOIN>:
1663
1664     $rs = $schema->resultset('Person')->search(
1665         undef,
1666         {
1667             alias => 'child', # alias columns in accordance with "from"
1668             from => [
1669                 { child => 'person' },
1670                 [
1671                     { father => 'person', -join_type => 'inner' },
1672                     { 'father.id' => 'child.father_id' }
1673                 ],
1674             ]
1675         },
1676     );
1677
1678     # Equivalent SQL:
1679     # SELECT child.* FROM person child
1680     # INNER JOIN person father ON child.father_id = father.id
1681
1682 =head2 page
1683
1684 =over 4
1685
1686 =item Value: $page
1687
1688 =back
1689
1690 Makes the resultset paged and specifies the page to retrieve. Effectively
1691 identical to creating a non-pages resultset and then calling ->page($page)
1692 on it.
1693
1694 =head2 rows
1695
1696 =over 4
1697
1698 =item Value: $rows
1699
1700 =back
1701
1702 Specifes the maximum number of rows for direct retrieval or the number of
1703 rows per page if the page attribute or method is used.
1704
1705 =head2 group_by
1706
1707 =over 4
1708
1709 =item Value: \@columns
1710
1711 =back
1712
1713 A arrayref of columns to group by. Can include columns of joined tables.
1714
1715   group_by => [qw/ column1 column2 ... /]
1716
1717 =head2 having
1718
1719 =over 4
1720
1721 =item Value: $condition
1722
1723 =back
1724
1725 HAVING is a select statement attribute that is applied between GROUP BY and
1726 ORDER BY. It is applied to the after the grouping calculations have been
1727 done. 
1728
1729   having => { 'count(employee)' => { '>=', 100 } }
1730
1731 =head2 distinct
1732
1733 =over 4
1734
1735 =item Value: (0 | 1)
1736
1737 =back
1738
1739 Set to 1 to group by all columns.
1740
1741 =head2 cache
1742
1743 Set to 1 to cache search results. This prevents extra SQL queries if you
1744 revisit rows in your ResultSet:
1745
1746   my $resultset = $schema->resultset('Artist')->search( undef, { cache => 1 } );
1747   
1748   while( my $artist = $resultset->next ) {
1749     ... do stuff ...
1750   }
1751
1752   $rs->first; # without cache, this would issue a query
1753
1754 By default, searches are not cached.
1755
1756 For more examples of using these attributes, see
1757 L<DBIx::Class::Manual::Cookbook>.
1758
1759 =cut
1760
1761 1;