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