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