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