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