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