64bcd4ea53230b3549f94e275605bc097f47cada
[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 Carp::Clan qw/^DBIx::Class/;
10 use Data::Page;
11 use Storable;
12 use DBIx::Class::ResultSetColumn;
13 use base qw/DBIx::Class/;
14
15 __PACKAGE__->load_components(qw/AccessorGroup/);
16 __PACKAGE__->mk_group_accessors('simple' => qw/result_source result_class/);
17
18 =head1 NAME
19
20 DBIx::Class::ResultSet - Responsible for fetching and creating resultset.
21
22 =head1 SYNOPSIS
23
24   my $rs   = $schema->resultset('User')->search(registered => 1);
25   my @rows = $schema->resultset('CD')->search(year => 2005);
26
27 =head1 DESCRIPTION
28
29 The resultset is also known as an iterator. It is responsible for handling
30 queries that may return an arbitrary number of rows, e.g. via L</search>
31 or a C<has_many> relationship.
32
33 In the examples below, the following table classes are used:
34
35   package MyApp::Schema::Artist;
36   use base qw/DBIx::Class/;
37   __PACKAGE__->load_components(qw/Core/);
38   __PACKAGE__->table('artist');
39   __PACKAGE__->add_columns(qw/artistid name/);
40   __PACKAGE__->set_primary_key('artistid');
41   __PACKAGE__->has_many(cds => 'MyApp::Schema::CD');
42   1;
43
44   package MyApp::Schema::CD;
45   use base qw/DBIx::Class/;
46   __PACKAGE__->load_components(qw/Core/);
47   __PACKAGE__->table('cd');
48   __PACKAGE__->add_columns(qw/cdid artist title year/);
49   __PACKAGE__->set_primary_key('cdid');
50   __PACKAGE__->belongs_to(artist => 'MyApp::Schema::Artist');
51   1;
52
53 =head1 METHODS
54
55 =head2 new
56
57 =over 4
58
59 =item Arguments: $source, \%$attrs
60
61 =item Return Value: $rs
62
63 =back
64
65 The resultset constructor. Takes a source object (usually a
66 L<DBIx::Class::ResultSourceProxy::Table>) and an attribute hash (see
67 L</ATTRIBUTES> below).  Does not perform any queries -- these are
68 executed as needed by the other methods.
69
70 Generally you won't need to construct a resultset manually.  You'll
71 automatically get one from e.g. a L</search> called in scalar context:
72
73   my $rs = $schema->resultset('CD')->search({ title => '100th Window' });
74
75 IMPORTANT: If called on an object, proxies to new_result instead so
76
77   my $cd = $schema->resultset('CD')->new({ title => 'Spoon' });
78
79 will return a CD object, not a ResultSet.
80
81 =cut
82
83 sub new {
84   my $class = shift;
85   return $class->new_result(@_) if ref $class;
86
87   my ($source, $attrs) = @_;
88   #weaken $source;
89
90   if ($attrs->{page}) {
91     $attrs->{rows} ||= 10;
92     $attrs->{offset} ||= 0;
93     $attrs->{offset} += ($attrs->{rows} * ($attrs->{page} - 1));
94   }
95
96   $attrs->{alias} ||= 'me';
97
98   my $self = {
99     result_source => $source,
100     result_class => $attrs->{result_class} || $source->result_class,
101     cond => $attrs->{where},
102     count => undef,
103     pager => undef,
104     attrs => $attrs
105   };
106
107   bless $self, $class;
108
109   return $self;
110 }
111
112 =head2 search
113
114 =over 4
115
116 =item Arguments: $cond, \%attrs?
117
118 =item Return Value: $resultset (scalar context), @row_objs (list context)
119
120 =back
121
122   my @cds    = $cd_rs->search({ year => 2001 }); # "... WHERE year = 2001"
123   my $new_rs = $cd_rs->search({ year => 2005 });
124
125   my $new_rs = $cd_rs->search([ { year => 2005 }, { year => 2004 } ]);
126                  # year = 2005 OR year = 2004
127
128 If you need to pass in additional attributes but no additional condition,
129 call it as C<search(undef, \%attrs)>.
130
131   # "SELECT name, artistid FROM $artist_table"
132   my @all_artists = $schema->resultset('Artist')->search(undef, {
133     columns => [qw/name artistid/],
134   });
135
136 For a list of attributes that can be passed to C<search>, see L</ATTRIBUTES>. For more examples of using this function, see L<Searching|DBIx::Class::Manual::Cookbook/Searching>.
137
138 =cut
139
140 sub search {
141   my $self = shift;
142   my $rs = $self->search_rs( @_ );
143   return (wantarray ? $rs->all : $rs);
144 }
145
146 =head2 search_rs
147
148 =over 4
149
150 =item Arguments: $cond, \%attrs?
151
152 =item Return Value: $resultset
153
154 =back
155
156 This method does the same exact thing as search() except it will
157 always return a resultset, even in list context.
158
159 =cut
160
161 sub search_rs {
162   my $self = shift;
163
164   my $rows;
165
166   unless (@_) {                 # no search, effectively just a clone
167     $rows = $self->get_cache;
168   }
169
170   my $attrs = {};
171   $attrs = pop(@_) if @_ > 1 and ref $_[$#_] eq 'HASH';
172   my $our_attrs = { %{$self->{attrs}} };
173   my $having = delete $our_attrs->{having};
174   my $where = delete $our_attrs->{where};
175
176   my $new_attrs = { %{$our_attrs}, %{$attrs} };
177
178   # merge new attrs into inherited
179   foreach my $key (qw/join prefetch/) {
180     next unless exists $attrs->{$key};
181     $new_attrs->{$key} = $self->_merge_attr($our_attrs->{$key}, $attrs->{$key});
182   }
183
184   my $cond = (@_
185     ? (
186         (@_ == 1 || ref $_[0] eq "HASH")
187           ? (
188               (ref $_[0] eq 'HASH')
189                 ? (
190                     (keys %{ $_[0] }  > 0)
191                       ? shift
192                       : undef
193                    )
194                 :  shift
195              )
196           : (
197               (@_ % 2)
198                 ? $self->throw_exception("Odd number of arguments to search")
199                 : {@_}
200              )
201       )
202     : undef
203   );
204
205   if (defined $where) {
206     $new_attrs->{where} = (
207       defined $new_attrs->{where}
208         ? { '-and' => [
209               map {
210                 ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_
211               } $where, $new_attrs->{where}
212             ]
213           }
214         : $where);
215   }
216
217   if (defined $cond) {
218     $new_attrs->{where} = (
219       defined $new_attrs->{where}
220         ? { '-and' => [
221               map {
222                 ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_
223               } $cond, $new_attrs->{where}
224             ]
225           }
226         : $cond);
227   }
228
229   if (defined $having) {
230     $new_attrs->{having} = (
231       defined $new_attrs->{having}
232         ? { '-and' => [
233               map {
234                 ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_
235               } $having, $new_attrs->{having}
236             ]
237           }
238         : $having);
239   }
240
241   my $rs = (ref $self)->new($self->result_source, $new_attrs);
242   if ($rows) {
243     $rs->set_cache($rows);
244   }
245   return $rs;
246 }
247
248 =head2 search_literal
249
250 =over 4
251
252 =item Arguments: $sql_fragment, @bind_values
253
254 =item Return Value: $resultset (scalar context), @row_objs (list context)
255
256 =back
257
258   my @cds   = $cd_rs->search_literal('year = ? AND title = ?', qw/2001 Reload/);
259   my $newrs = $artist_rs->search_literal('name = ?', 'Metallica');
260
261 Pass a literal chunk of SQL to be added to the conditional part of the
262 resultset query.
263
264 =cut
265
266 sub search_literal {
267   my ($self, $cond, @vals) = @_;
268   my $attrs = (ref $vals[$#vals] eq 'HASH' ? { %{ pop(@vals) } } : {});
269   $attrs->{bind} = [ @{$self->{attrs}{bind}||[]}, @vals ];
270   return $self->search(\$cond, $attrs);
271 }
272
273 =head2 find
274
275 =over 4
276
277 =item Arguments: @values | \%cols, \%attrs?
278
279 =item Return Value: $row_object
280
281 =back
282
283 Finds a row based on its primary key or unique constraint. For example, to find
284 a row by its primary key:
285
286   my $cd = $schema->resultset('CD')->find(5);
287
288 You can also find a row by a specific unique constraint using the C<key>
289 attribute. For example:
290
291   my $cd = $schema->resultset('CD')->find('Massive Attack', 'Mezzanine', {
292     key => 'cd_artist_title'
293   });
294
295 Additionally, you can specify the columns explicitly by name:
296
297   my $cd = $schema->resultset('CD')->find(
298     {
299       artist => 'Massive Attack',
300       title  => 'Mezzanine',
301     },
302     { key => 'cd_artist_title' }
303   );
304
305 If the C<key> is specified as C<primary>, it searches only on the primary key.
306
307 If no C<key> is specified, it searches on all unique constraints defined on the
308 source, including the primary key.
309
310 If your table does not have a primary key, you B<must> provide a value for the
311 C<key> attribute matching one of the unique constraints on the source.
312
313 See also L</find_or_create> and L</update_or_create>. For information on how to
314 declare unique constraints, see
315 L<DBIx::Class::ResultSource/add_unique_constraint>.
316
317 =cut
318
319 sub find {
320   my $self = shift;
321   my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
322
323   # Default to the primary key, but allow a specific key
324   my @cols = exists $attrs->{key}
325     ? $self->result_source->unique_constraint_columns($attrs->{key})
326     : $self->result_source->primary_columns;
327   $self->throw_exception(
328     "Can't find unless a primary key is defined or unique constraint is specified"
329   ) unless @cols;
330
331   # Parse out a hashref from input
332   my $input_query;
333   if (ref $_[0] eq 'HASH') {
334     $input_query = { %{$_[0]} };
335   }
336   elsif (@_ == @cols) {
337     $input_query = {};
338     @{$input_query}{@cols} = @_;
339   }
340   else {
341     # Compatibility: Allow e.g. find(id => $value)
342     carp "Find by key => value deprecated; please use a hashref instead";
343     $input_query = {@_};
344   }
345
346   my (%related, $info);
347
348   foreach my $key (keys %$input_query) {
349     if (ref($input_query->{$key})
350         && ($info = $self->result_source->relationship_info($key))) {
351       my $rel_q = $self->result_source->resolve_condition(
352                     $info->{cond}, delete $input_query->{$key}, $key
353                   );
354       die "Can't handle OR join condition in find" if ref($rel_q) eq 'ARRAY';
355       @related{keys %$rel_q} = values %$rel_q;
356     }
357   }
358   if (my @keys = keys %related) {
359     @{$input_query}{@keys} = values %related;
360   }
361
362   my @unique_queries = $self->_unique_queries($input_query, $attrs);
363
364   # Build the final query: Default to the disjunction of the unique queries,
365   # but allow the input query in case the ResultSet defines the query or the
366   # user is abusing find
367   my $alias = exists $attrs->{alias} ? $attrs->{alias} : $self->{attrs}{alias};
368   my $query = @unique_queries
369     ? [ map { $self->_add_alias($_, $alias) } @unique_queries ]
370     : $self->_add_alias($input_query, $alias);
371
372   # Run the query
373   if (keys %$attrs) {
374     my $rs = $self->search($query, $attrs);
375     return keys %{$rs->_resolved_attrs->{collapse}} ? $rs->next : $rs->single;
376   }
377   else {
378     return keys %{$self->_resolved_attrs->{collapse}}
379       ? $self->search($query)->next
380       : $self->single($query);
381   }
382 }
383
384 # _add_alias
385 #
386 # Add the specified alias to the specified query hash. A copy is made so the
387 # original query is not modified.
388
389 sub _add_alias {
390   my ($self, $query, $alias) = @_;
391
392   my %aliased = %$query;
393   foreach my $col (grep { ! m/\./ } keys %aliased) {
394     $aliased{"$alias.$col"} = delete $aliased{$col};
395   }
396
397   return \%aliased;
398 }
399
400 # _unique_queries
401 #
402 # Build a list of queries which satisfy unique constraints.
403
404 sub _unique_queries {
405   my ($self, $query, $attrs) = @_;
406
407   my @constraint_names = exists $attrs->{key}
408     ? ($attrs->{key})
409     : $self->result_source->unique_constraint_names;
410
411   my @unique_queries;
412   foreach my $name (@constraint_names) {
413     my @unique_cols = $self->result_source->unique_constraint_columns($name);
414     my $unique_query = $self->_build_unique_query($query, \@unique_cols);
415
416     my $num_query = scalar keys %$unique_query;
417     next unless $num_query;
418
419     # XXX: Assuming quite a bit about $self->{attrs}{where}
420     my $num_cols = scalar @unique_cols;
421     my $num_where = exists $self->{attrs}{where}
422       ? scalar keys %{ $self->{attrs}{where} }
423       : 0;
424     push @unique_queries, $unique_query
425       if $num_query + $num_where == $num_cols;
426   }
427
428   return @unique_queries;
429 }
430
431 # _build_unique_query
432 #
433 # Constrain the specified query hash based on the specified column names.
434
435 sub _build_unique_query {
436   my ($self, $query, $unique_cols) = @_;
437
438   return {
439     map  { $_ => $query->{$_} }
440     grep { exists $query->{$_} }
441       @$unique_cols
442   };
443 }
444
445 =head2 search_related
446
447 =over 4
448
449 =item Arguments: $rel, $cond, \%attrs?
450
451 =item Return Value: $new_resultset
452
453 =back
454
455   $new_rs = $cd_rs->search_related('artist', {
456     name => 'Emo-R-Us',
457   });
458
459 Searches the specified relationship, optionally specifying a condition and
460 attributes for matching records. See L</ATTRIBUTES> for more information.
461
462 =cut
463
464 sub search_related {
465   return shift->related_resultset(shift)->search(@_);
466 }
467
468 =head2 cursor
469
470 =over 4
471
472 =item Arguments: none
473
474 =item Return Value: $cursor
475
476 =back
477
478 Returns a storage-driven cursor to the given resultset. See
479 L<DBIx::Class::Cursor> for more information.
480
481 =cut
482
483 sub cursor {
484   my ($self) = @_;
485
486   my $attrs = { %{$self->_resolved_attrs} };
487   return $self->{cursor}
488     ||= $self->result_source->storage->select($attrs->{from}, $attrs->{select},
489           $attrs->{where},$attrs);
490 }
491
492 =head2 single
493
494 =over 4
495
496 =item Arguments: $cond?
497
498 =item Return Value: $row_object?
499
500 =back
501
502   my $cd = $schema->resultset('CD')->single({ year => 2001 });
503
504 Inflates the first result without creating a cursor if the resultset has
505 any records in it; if not returns nothing. Used by L</find> as an optimisation.
506
507 Can optionally take an additional condition *only* - this is a fast-code-path
508 method; if you need to add extra joins or similar call ->search and then
509 ->single without a condition on the $rs returned from that.
510
511 =cut
512
513 sub single {
514   my ($self, $where) = @_;
515   my $attrs = { %{$self->_resolved_attrs} };
516   if ($where) {
517     if (defined $attrs->{where}) {
518       $attrs->{where} = {
519         '-and' =>
520             [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
521                $where, delete $attrs->{where} ]
522       };
523     } else {
524       $attrs->{where} = $where;
525     }
526   }
527
528 #  XXX: Disabled since it doesn't infer uniqueness in all cases
529 #  unless ($self->_is_unique_query($attrs->{where})) {
530 #    carp "Query not guaranteed to return a single row"
531 #      . "; please declare your unique constraints or use search instead";
532 #  }
533
534   my @data = $self->result_source->storage->select_single(
535     $attrs->{from}, $attrs->{select},
536     $attrs->{where}, $attrs
537   );
538
539   return (@data ? $self->_construct_object(@data) : ());
540 }
541
542 # _is_unique_query
543 #
544 # Try to determine if the specified query is guaranteed to be unique, based on
545 # the declared unique constraints.
546
547 sub _is_unique_query {
548   my ($self, $query) = @_;
549
550   my $collapsed = $self->_collapse_query($query);
551   my $alias = $self->{attrs}{alias};
552
553   foreach my $name ($self->result_source->unique_constraint_names) {
554     my @unique_cols = map {
555       "$alias.$_"
556     } $self->result_source->unique_constraint_columns($name);
557
558     # Count the values for each unique column
559     my %seen = map { $_ => 0 } @unique_cols;
560
561     foreach my $key (keys %$collapsed) {
562       my $aliased = $key =~ /\./ ? $key : "$alias.$key";
563       next unless exists $seen{$aliased};  # Additional constraints are okay
564       $seen{$aliased} = scalar keys %{ $collapsed->{$key} };
565     }
566
567     # If we get 0 or more than 1 value for a column, it's not necessarily unique
568     return 1 unless grep { $_ != 1 } values %seen;
569   }
570
571   return 0;
572 }
573
574 # _collapse_query
575 #
576 # Recursively collapse the query, accumulating values for each column.
577
578 sub _collapse_query {
579   my ($self, $query, $collapsed) = @_;
580
581   $collapsed ||= {};
582
583   if (ref $query eq 'ARRAY') {
584     foreach my $subquery (@$query) {
585       next unless ref $subquery;  # -or
586 #      warn "ARRAY: " . Dumper $subquery;
587       $collapsed = $self->_collapse_query($subquery, $collapsed);
588     }
589   }
590   elsif (ref $query eq 'HASH') {
591     if (keys %$query and (keys %$query)[0] eq '-and') {
592       foreach my $subquery (@{$query->{-and}}) {
593 #        warn "HASH: " . Dumper $subquery;
594         $collapsed = $self->_collapse_query($subquery, $collapsed);
595       }
596     }
597     else {
598 #      warn "LEAF: " . Dumper $query;
599       foreach my $col (keys %$query) {
600         my $value = $query->{$col};
601         $collapsed->{$col}{$value}++;
602       }
603     }
604   }
605
606   return $collapsed;
607 }
608
609 =head2 get_column
610
611 =over 4
612
613 =item Arguments: $cond?
614
615 =item Return Value: $resultsetcolumn
616
617 =back
618
619   my $max_length = $rs->get_column('length')->max;
620
621 Returns a L<DBIx::Class::ResultSetColumn> instance for a column of the ResultSet.
622
623 =cut
624
625 sub get_column {
626   my ($self, $column) = @_;
627   my $new = DBIx::Class::ResultSetColumn->new($self, $column);
628   return $new;
629 }
630
631 =head2 search_like
632
633 =over 4
634
635 =item Arguments: $cond, \%attrs?
636
637 =item Return Value: $resultset (scalar context), @row_objs (list context)
638
639 =back
640
641   # WHERE title LIKE '%blue%'
642   $cd_rs = $rs->search_like({ title => '%blue%'});
643
644 Performs a search, but uses C<LIKE> instead of C<=> as the condition. Note
645 that this is simply a convenience method. You most likely want to use
646 L</search> with specific operators.
647
648 For more information, see L<DBIx::Class::Manual::Cookbook>.
649
650 =cut
651
652 sub search_like {
653   my $class = shift;
654   my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
655   my $query = ref $_[0] eq 'HASH' ? { %{shift()} }: {@_};
656   $query->{$_} = { 'like' => $query->{$_} } for keys %$query;
657   return $class->search($query, { %$attrs });
658 }
659
660 =head2 slice
661
662 =over 4
663
664 =item Arguments: $first, $last
665
666 =item Return Value: $resultset (scalar context), @row_objs (list context)
667
668 =back
669
670 Returns a resultset or object list representing a subset of elements from the
671 resultset slice is called on. Indexes are from 0, i.e., to get the first
672 three records, call:
673
674   my ($one, $two, $three) = $rs->slice(0, 2);
675
676 =cut
677
678 sub slice {
679   my ($self, $min, $max) = @_;
680   my $attrs = {}; # = { %{ $self->{attrs} || {} } };
681   $attrs->{offset} = $self->{attrs}{offset} || 0;
682   $attrs->{offset} += $min;
683   $attrs->{rows} = ($max ? ($max - $min + 1) : 1);
684   return $self->search(undef(), $attrs);
685   #my $slice = (ref $self)->new($self->result_source, $attrs);
686   #return (wantarray ? $slice->all : $slice);
687 }
688
689 =head2 next
690
691 =over 4
692
693 =item Arguments: none
694
695 =item Return Value: $result?
696
697 =back
698
699 Returns the next element in the resultset (C<undef> is there is none).
700
701 Can be used to efficiently iterate over records in the resultset:
702
703   my $rs = $schema->resultset('CD')->search;
704   while (my $cd = $rs->next) {
705     print $cd->title;
706   }
707
708 Note that you need to store the resultset object, and call C<next> on it.
709 Calling C<< resultset('Table')->next >> repeatedly will always return the
710 first record from the resultset.
711
712 =cut
713
714 sub next {
715   my ($self) = @_;
716   if (my $cache = $self->get_cache) {
717     $self->{all_cache_position} ||= 0;
718     return $cache->[$self->{all_cache_position}++];
719   }
720   if ($self->{attrs}{cache}) {
721     $self->{all_cache_position} = 1;
722     return ($self->all)[0];
723   }
724   my @row = (
725     exists $self->{stashed_row}
726       ? @{delete $self->{stashed_row}}
727       : $self->cursor->next
728   );
729   return unless (@row);
730   return $self->_construct_object(@row);
731 }
732
733 sub _construct_object {
734   my ($self, @row) = @_;
735   my $info = $self->_collapse_result($self->{_attrs}{as}, \@row);
736   my $new = $self->result_class->inflate_result($self->result_source, @$info);
737   $new = $self->{_attrs}{record_filter}->($new)
738     if exists $self->{_attrs}{record_filter};
739   return $new;
740 }
741
742 sub _collapse_result {
743   my ($self, $as, $row, $prefix) = @_;
744
745   my %const;
746   my @copy = @$row;
747   
748   foreach my $this_as (@$as) {
749     my $val = shift @copy;
750     if (defined $prefix) {
751       if ($this_as =~ m/^\Q${prefix}.\E(.+)$/) {
752         my $remain = $1;
753         $remain =~ /^(?:(.*)\.)?([^.]+)$/;
754         $const{$1||''}{$2} = $val;
755       }
756     } else {
757       $this_as =~ /^(?:(.*)\.)?([^.]+)$/;
758       $const{$1||''}{$2} = $val;
759     }
760   }
761
762   my $alias = $self->{attrs}{alias};
763   my $info = [ {}, {} ];
764   foreach my $key (keys %const) {
765     if (length $key && $key ne $alias) {
766       my $target = $info;
767       my @parts = split(/\./, $key);
768       foreach my $p (@parts) {
769         $target = $target->[1]->{$p} ||= [];
770       }
771       $target->[0] = $const{$key};
772     } else {
773       $info->[0] = $const{$key};
774     }
775   }
776   
777   my @collapse;
778   if (defined $prefix) {
779     @collapse = map {
780         m/^\Q${prefix}.\E(.+)$/ ? ($1) : ()
781     } keys %{$self->{_attrs}{collapse}}
782   } else {
783     @collapse = keys %{$self->{_attrs}{collapse}};
784   };
785
786   if (@collapse) {
787     my ($c) = sort { length $a <=> length $b } @collapse;
788     my $target = $info;
789     foreach my $p (split(/\./, $c)) {
790       $target = $target->[1]->{$p} ||= [];
791     }
792     my $c_prefix = (defined($prefix) ? "${prefix}.${c}" : $c);
793     my @co_key = @{$self->{_attrs}{collapse}{$c_prefix}};
794     my $tree = $self->_collapse_result($as, $row, $c_prefix);
795     my %co_check = map { ($_, $tree->[0]->{$_}); } @co_key;
796     my (@final, @raw);
797
798     while (
799       !(
800         grep {
801           !defined($tree->[0]->{$_}) || $co_check{$_} ne $tree->[0]->{$_}
802         } @co_key
803         )
804     ) {
805       push(@final, $tree);
806       last unless (@raw = $self->cursor->next);
807       $row = $self->{stashed_row} = \@raw;
808       $tree = $self->_collapse_result($as, $row, $c_prefix);
809     }
810     @$target = (@final ? @final : [ {}, {} ]);
811       # single empty result to indicate an empty prefetched has_many
812   }
813
814   #print "final info: " . Dumper($info);
815   return $info;
816 }
817
818 =head2 result_source
819
820 =over 4
821
822 =item Arguments: $result_source?
823
824 =item Return Value: $result_source
825
826 =back
827
828 An accessor for the primary ResultSource object from which this ResultSet
829 is derived.
830
831 =head2 result_class
832
833 =over 4
834
835 =item Arguments: $result_class?
836
837 =item Return Value: $result_class
838
839 =back
840
841 An accessor for the class to use when creating row objects. Defaults to 
842 C<< result_source->result_class >> - which in most cases is the name of the 
843 L<"table"|DBIx::Class::Manual::Glossary/"ResultSource"> class.
844
845 =cut
846
847
848 =head2 count
849
850 =over 4
851
852 =item Arguments: $cond, \%attrs??
853
854 =item Return Value: $count
855
856 =back
857
858 Performs an SQL C<COUNT> with the same query as the resultset was built
859 with to find the number of elements. If passed arguments, does a search
860 on the resultset and counts the results of that.
861
862 Note: When using C<count> with C<group_by>, L<DBIX::Class> emulates C<GROUP BY>
863 using C<COUNT( DISTINCT( columns ) )>. Some databases (notably SQLite) do
864 not support C<DISTINCT> with multiple columns. If you are using such a
865 database, you should only use columns from the main table in your C<group_by>
866 clause.
867
868 =cut
869
870 sub count {
871   my $self = shift;
872   return $self->search(@_)->count if @_ and defined $_[0];
873   return scalar @{ $self->get_cache } if $self->get_cache;
874   my $count = $self->_count;
875   return 0 unless $count;
876
877   $count -= $self->{attrs}{offset} if $self->{attrs}{offset};
878   $count = $self->{attrs}{rows} if
879     $self->{attrs}{rows} and $self->{attrs}{rows} < $count;
880   return $count;
881 }
882
883 sub _count { # Separated out so pager can get the full count
884   my $self = shift;
885   my $select = { count => '*' };
886
887   my $attrs = { %{$self->_resolved_attrs} };
888   if (my $group_by = delete $attrs->{group_by}) {
889     delete $attrs->{having};
890     my @distinct = (ref $group_by ?  @$group_by : ($group_by));
891     # todo: try CONCAT for multi-column pk
892     my @pk = $self->result_source->primary_columns;
893     if (@pk == 1) {
894       my $alias = $attrs->{alias};
895       foreach my $column (@distinct) {
896         if ($column =~ qr/^(?:\Q${alias}.\E)?$pk[0]$/) {
897           @distinct = ($column);
898           last;
899         }
900       }
901     }
902
903     $select = { count => { distinct => \@distinct } };
904   }
905
906   $attrs->{select} = $select;
907   $attrs->{as} = [qw/count/];
908
909   # offset, order by and page are not needed to count. record_filter is cdbi
910   delete $attrs->{$_} for qw/rows offset order_by page pager record_filter/;
911
912   my $tmp_rs = (ref $self)->new($self->result_source, $attrs);
913   my ($count) = $tmp_rs->cursor->next;
914   return $count;
915 }
916
917 =head2 count_literal
918
919 =over 4
920
921 =item Arguments: $sql_fragment, @bind_values
922
923 =item Return Value: $count
924
925 =back
926
927 Counts the results in a literal query. Equivalent to calling L</search_literal>
928 with the passed arguments, then L</count>.
929
930 =cut
931
932 sub count_literal { shift->search_literal(@_)->count; }
933
934 =head2 all
935
936 =over 4
937
938 =item Arguments: none
939
940 =item Return Value: @objects
941
942 =back
943
944 Returns all elements in the resultset. Called implicitly if the resultset
945 is returned in list context.
946
947 =cut
948
949 sub all {
950   my ($self) = @_;
951   return @{ $self->get_cache } if $self->get_cache;
952
953   my @obj;
954
955   # TODO: don't call resolve here
956   if (keys %{$self->_resolved_attrs->{collapse}}) {
957 #  if ($self->{attrs}{prefetch}) {
958       # Using $self->cursor->all is really just an optimisation.
959       # If we're collapsing has_many prefetches it probably makes
960       # very little difference, and this is cleaner than hacking
961       # _construct_object to survive the approach
962     my @row = $self->cursor->next;
963     while (@row) {
964       push(@obj, $self->_construct_object(@row));
965       @row = (exists $self->{stashed_row}
966                ? @{delete $self->{stashed_row}}
967                : $self->cursor->next);
968     }
969   } else {
970     @obj = map { $self->_construct_object(@$_) } $self->cursor->all;
971   }
972
973   $self->set_cache(\@obj) if $self->{attrs}{cache};
974   return @obj;
975 }
976
977 =head2 reset
978
979 =over 4
980
981 =item Arguments: none
982
983 =item Return Value: $self
984
985 =back
986
987 Resets the resultset's cursor, so you can iterate through the elements again.
988
989 =cut
990
991 sub reset {
992   my ($self) = @_;
993   delete $self->{_attrs} if exists $self->{_attrs};
994   $self->{all_cache_position} = 0;
995   $self->cursor->reset;
996   return $self;
997 }
998
999 =head2 first
1000
1001 =over 4
1002
1003 =item Arguments: none
1004
1005 =item Return Value: $object?
1006
1007 =back
1008
1009 Resets the resultset and returns an object for the first result (if the
1010 resultset returns anything).
1011
1012 =cut
1013
1014 sub first {
1015   return $_[0]->reset->next;
1016 }
1017
1018 # _cond_for_update_delete
1019 #
1020 # update/delete require the condition to be modified to handle
1021 # the differing SQL syntax available.  This transforms the $self->{cond}
1022 # appropriately, returning the new condition.
1023
1024 sub _cond_for_update_delete {
1025   my ($self, $full_cond) = @_;
1026   my $cond = {};
1027
1028   $full_cond ||= $self->{cond};
1029   # No-op. No condition, we're updating/deleting everything
1030   return $cond unless ref $full_cond;
1031
1032   if (ref $full_cond eq 'ARRAY') {
1033     $cond = [
1034       map {
1035         my %hash;
1036         foreach my $key (keys %{$_}) {
1037           $key =~ /([^.]+)$/;
1038           $hash{$1} = $_->{$key};
1039         }
1040         \%hash;
1041       } @{$full_cond}
1042     ];
1043   }
1044   elsif (ref $full_cond eq 'HASH') {
1045     if ((keys %{$full_cond})[0] eq '-and') {
1046       $cond->{-and} = [];
1047
1048       my @cond = @{$full_cond->{-and}};
1049       for (my $i = 0; $i < @cond; $i++) {
1050         my $entry = $cond[$i];
1051
1052         my $hash;
1053         if (ref $entry eq 'HASH') {
1054           $hash = $self->_cond_for_update_delete($entry);
1055         }
1056         else {
1057           $entry =~ /([^.]+)$/;
1058           $hash->{$1} = $cond[++$i];
1059         }
1060
1061         push @{$cond->{-and}}, $hash;
1062       }
1063     }
1064     else {
1065       foreach my $key (keys %{$full_cond}) {
1066         $key =~ /([^.]+)$/;
1067         $cond->{$1} = $full_cond->{$key};
1068       }
1069     }
1070   }
1071   else {
1072     $self->throw_exception(
1073       "Can't update/delete on resultset with condition unless hash or array"
1074     );
1075   }
1076
1077   return $cond;
1078 }
1079
1080
1081 =head2 update
1082
1083 =over 4
1084
1085 =item Arguments: \%values
1086
1087 =item Return Value: $storage_rv
1088
1089 =back
1090
1091 Sets the specified columns in the resultset to the supplied values in a
1092 single query. Return value will be true if the update succeeded or false
1093 if no records were updated; exact type of success value is storage-dependent.
1094
1095 =cut
1096
1097 sub update {
1098   my ($self, $values) = @_;
1099   $self->throw_exception("Values for update must be a hash")
1100     unless ref $values eq 'HASH';
1101
1102   my $cond = $self->_cond_for_update_delete;
1103
1104   return $self->result_source->storage->update(
1105     $self->result_source->from, $values, $cond
1106   );
1107 }
1108
1109 =head2 update_all
1110
1111 =over 4
1112
1113 =item Arguments: \%values
1114
1115 =item Return Value: 1
1116
1117 =back
1118
1119 Fetches all objects and updates them one at a time. Note that C<update_all>
1120 will run DBIC cascade triggers, while L</update> will not.
1121
1122 =cut
1123
1124 sub update_all {
1125   my ($self, $values) = @_;
1126   $self->throw_exception("Values for update must be a hash")
1127     unless ref $values eq 'HASH';
1128   foreach my $obj ($self->all) {
1129     $obj->set_columns($values)->update;
1130   }
1131   return 1;
1132 }
1133
1134 =head2 delete
1135
1136 =over 4
1137
1138 =item Arguments: none
1139
1140 =item Return Value: 1
1141
1142 =back
1143
1144 Deletes the contents of the resultset from its result source. Note that this
1145 will not run DBIC cascade triggers. See L</delete_all> if you need triggers
1146 to run. See also L<DBIx::Class::Row/delete>.
1147
1148 =cut
1149
1150 sub delete {
1151   my ($self) = @_;
1152
1153   my $cond = $self->_cond_for_update_delete;
1154
1155   $self->result_source->storage->delete($self->result_source->from, $cond);
1156   return 1;
1157 }
1158
1159 =head2 delete_all
1160
1161 =over 4
1162
1163 =item Arguments: none
1164
1165 =item Return Value: 1
1166
1167 =back
1168
1169 Fetches all objects and deletes them one at a time. Note that C<delete_all>
1170 will run DBIC cascade triggers, while L</delete> will not.
1171
1172 =cut
1173
1174 sub delete_all {
1175   my ($self) = @_;
1176   $_->delete for $self->all;
1177   return 1;
1178 }
1179
1180 =head2 pager
1181
1182 =over 4
1183
1184 =item Arguments: none
1185
1186 =item Return Value: $pager
1187
1188 =back
1189
1190 Return Value a L<Data::Page> object for the current resultset. Only makes
1191 sense for queries with a C<page> attribute.
1192
1193 =cut
1194
1195 sub pager {
1196   my ($self) = @_;
1197   my $attrs = $self->{attrs};
1198   $self->throw_exception("Can't create pager for non-paged rs")
1199     unless $self->{attrs}{page};
1200   $attrs->{rows} ||= 10;
1201   return $self->{pager} ||= Data::Page->new(
1202     $self->_count, $attrs->{rows}, $self->{attrs}{page});
1203 }
1204
1205 =head2 page
1206
1207 =over 4
1208
1209 =item Arguments: $page_number
1210
1211 =item Return Value: $rs
1212
1213 =back
1214
1215 Returns a resultset for the $page_number page of the resultset on which page
1216 is called, where each page contains a number of rows equal to the 'rows'
1217 attribute set on the resultset (10 by default).
1218
1219 =cut
1220
1221 sub page {
1222   my ($self, $page) = @_;
1223   return (ref $self)->new($self->result_source, { %{$self->{attrs}}, page => $page });
1224 }
1225
1226 =head2 new_result
1227
1228 =over 4
1229
1230 =item Arguments: \%vals
1231
1232 =item Return Value: $object
1233
1234 =back
1235
1236 Creates an object in the resultset's result class and returns it.
1237
1238 =cut
1239
1240 sub new_result {
1241   my ($self, $values) = @_;
1242   $self->throw_exception( "new_result needs a hash" )
1243     unless (ref $values eq 'HASH');
1244   $self->throw_exception(
1245     "Can't abstract implicit construct, condition not a hash"
1246   ) if ($self->{cond} && !(ref $self->{cond} eq 'HASH'));
1247
1248   my $alias = $self->{attrs}{alias};
1249   my $collapsed_cond = $self->{cond} ? $self->_collapse_cond($self->{cond}) : {};
1250   my %new = (
1251     %{ $self->_remove_alias($values, $alias) },
1252     %{ $self->_remove_alias($collapsed_cond, $alias) },
1253     -result_source => $self->result_source,
1254   );
1255
1256   my $obj = $self->result_class->new(\%new);
1257   return $obj;
1258 }
1259
1260 # _collapse_cond
1261 #
1262 # Recursively collapse the condition.
1263
1264 sub _collapse_cond {
1265   my ($self, $cond, $collapsed) = @_;
1266
1267   $collapsed ||= {};
1268
1269   if (ref $cond eq 'ARRAY') {
1270     foreach my $subcond (@$cond) {
1271       next unless ref $subcond;  # -or
1272 #      warn "ARRAY: " . Dumper $subcond;
1273       $collapsed = $self->_collapse_cond($subcond, $collapsed);
1274     }
1275   }
1276   elsif (ref $cond eq 'HASH') {
1277     if (keys %$cond and (keys %$cond)[0] eq '-and') {
1278       foreach my $subcond (@{$cond->{-and}}) {
1279 #        warn "HASH: " . Dumper $subcond;
1280         $collapsed = $self->_collapse_cond($subcond, $collapsed);
1281       }
1282     }
1283     else {
1284 #      warn "LEAF: " . Dumper $cond;
1285       foreach my $col (keys %$cond) {
1286         my $value = $cond->{$col};
1287         $collapsed->{$col} = $value;
1288       }
1289     }
1290   }
1291
1292   return $collapsed;
1293 }
1294
1295 # _remove_alias
1296 #
1297 # Remove the specified alias from the specified query hash. A copy is made so
1298 # the original query is not modified.
1299
1300 sub _remove_alias {
1301   my ($self, $query, $alias) = @_;
1302
1303   my %orig = %{ $query || {} };
1304   my %unaliased;
1305
1306   foreach my $key (keys %orig) {
1307     if ($key !~ /\./) {
1308       $unaliased{$key} = $orig{$key};
1309       next;
1310     }
1311     $unaliased{$1} = $orig{$key}
1312       if $key =~ m/^(?:\Q$alias\E\.)?([^.]+)$/;
1313   }
1314
1315   return \%unaliased;
1316 }
1317
1318 =head2 find_or_new
1319
1320 =over 4
1321
1322 =item Arguments: \%vals, \%attrs?
1323
1324 =item Return Value: $object
1325
1326 =back
1327
1328 Find an existing record from this resultset. If none exists, instantiate a new
1329 result object and return it. The object will not be saved into your storage
1330 until you call L<DBIx::Class::Row/insert> on it.
1331
1332 If you want objects to be saved immediately, use L</find_or_create> instead.
1333
1334 =cut
1335
1336 sub find_or_new {
1337   my $self     = shift;
1338   my $attrs    = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
1339   my $hash     = ref $_[0] eq 'HASH' ? shift : {@_};
1340   my $exists   = $self->find($hash, $attrs);
1341   return defined $exists ? $exists : $self->new_result($hash);
1342 }
1343
1344 =head2 create
1345
1346 =over 4
1347
1348 =item Arguments: \%vals
1349
1350 =item Return Value: $object
1351
1352 =back
1353
1354 Inserts a record into the resultset and returns the object representing it.
1355
1356 Effectively a shortcut for C<< ->new_result(\%vals)->insert >>.
1357
1358 =cut
1359
1360 sub create {
1361   my ($self, $attrs) = @_;
1362   $self->throw_exception( "create needs a hashref" )
1363     unless ref $attrs eq 'HASH';
1364   return $self->new_result($attrs)->insert;
1365 }
1366
1367 =head2 find_or_create
1368
1369 =over 4
1370
1371 =item Arguments: \%vals, \%attrs?
1372
1373 =item Return Value: $object
1374
1375 =back
1376
1377   $class->find_or_create({ key => $val, ... });
1378
1379 Tries to find a record based on its primary key or unique constraint; if none
1380 is found, creates one and returns that instead.
1381
1382   my $cd = $schema->resultset('CD')->find_or_create({
1383     cdid   => 5,
1384     artist => 'Massive Attack',
1385     title  => 'Mezzanine',
1386     year   => 2005,
1387   });
1388
1389 Also takes an optional C<key> attribute, to search by a specific key or unique
1390 constraint. For example:
1391
1392   my $cd = $schema->resultset('CD')->find_or_create(
1393     {
1394       artist => 'Massive Attack',
1395       title  => 'Mezzanine',
1396     },
1397     { key => 'cd_artist_title' }
1398   );
1399
1400 See also L</find> and L</update_or_create>. For information on how to declare
1401 unique constraints, see L<DBIx::Class::ResultSource/add_unique_constraint>.
1402
1403 =cut
1404
1405 sub find_or_create {
1406   my $self     = shift;
1407   my $attrs    = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
1408   my $hash     = ref $_[0] eq 'HASH' ? shift : {@_};
1409   my $exists   = $self->find($hash, $attrs);
1410   return defined $exists ? $exists : $self->create($hash);
1411 }
1412
1413 =head2 update_or_create
1414
1415 =over 4
1416
1417 =item Arguments: \%col_values, { key => $unique_constraint }?
1418
1419 =item Return Value: $object
1420
1421 =back
1422
1423   $class->update_or_create({ col => $val, ... });
1424
1425 First, searches for an existing row matching one of the unique constraints
1426 (including the primary key) on the source of this resultset. If a row is
1427 found, updates it with the other given column values. Otherwise, creates a new
1428 row.
1429
1430 Takes an optional C<key> attribute to search on a specific unique constraint.
1431 For example:
1432
1433   # In your application
1434   my $cd = $schema->resultset('CD')->update_or_create(
1435     {
1436       artist => 'Massive Attack',
1437       title  => 'Mezzanine',
1438       year   => 1998,
1439     },
1440     { key => 'cd_artist_title' }
1441   );
1442
1443 If no C<key> is specified, it searches on all unique constraints defined on the
1444 source, including the primary key.
1445
1446 If the C<key> is specified as C<primary>, it searches only on the primary key.
1447
1448 See also L</find> and L</find_or_create>. For information on how to declare
1449 unique constraints, see L<DBIx::Class::ResultSource/add_unique_constraint>.
1450
1451 =cut
1452
1453 sub update_or_create {
1454   my $self = shift;
1455   my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
1456   my $cond = ref $_[0] eq 'HASH' ? shift : {@_};
1457
1458   my $row = $self->find($cond, $attrs);
1459   if (defined $row) {
1460     $row->update($cond);
1461     return $row;
1462   }
1463
1464   return $self->create($cond);
1465 }
1466
1467 =head2 get_cache
1468
1469 =over 4
1470
1471 =item Arguments: none
1472
1473 =item Return Value: \@cache_objects?
1474
1475 =back
1476
1477 Gets the contents of the cache for the resultset, if the cache is set.
1478
1479 =cut
1480
1481 sub get_cache {
1482   shift->{all_cache};
1483 }
1484
1485 =head2 set_cache
1486
1487 =over 4
1488
1489 =item Arguments: \@cache_objects
1490
1491 =item Return Value: \@cache_objects
1492
1493 =back
1494
1495 Sets the contents of the cache for the resultset. Expects an arrayref
1496 of objects of the same class as those produced by the resultset. Note that
1497 if the cache is set the resultset will return the cached objects rather
1498 than re-querying the database even if the cache attr is not set.
1499
1500 =cut
1501
1502 sub set_cache {
1503   my ( $self, $data ) = @_;
1504   $self->throw_exception("set_cache requires an arrayref")
1505       if defined($data) && (ref $data ne 'ARRAY');
1506   $self->{all_cache} = $data;
1507 }
1508
1509 =head2 clear_cache
1510
1511 =over 4
1512
1513 =item Arguments: none
1514
1515 =item Return Value: []
1516
1517 =back
1518
1519 Clears the cache for the resultset.
1520
1521 =cut
1522
1523 sub clear_cache {
1524   shift->set_cache(undef);
1525 }
1526
1527 =head2 related_resultset
1528
1529 =over 4
1530
1531 =item Arguments: $relationship_name
1532
1533 =item Return Value: $resultset
1534
1535 =back
1536
1537 Returns a related resultset for the supplied relationship name.
1538
1539   $artist_rs = $schema->resultset('CD')->related_resultset('Artist');
1540
1541 =cut
1542
1543 sub related_resultset {
1544   my ($self, $rel) = @_;
1545
1546   $self->{related_resultsets} ||= {};
1547   return $self->{related_resultsets}{$rel} ||= do {
1548     my $rel_obj = $self->result_source->relationship_info($rel);
1549
1550     $self->throw_exception(
1551       "search_related: result source '" . $self->result_source->name .
1552         "' has no such relationship $rel")
1553       unless $rel_obj;
1554     
1555     my ($from,$seen) = $self->_resolve_from($rel);
1556
1557     my $join_count = $seen->{$rel};
1558     my $alias = ($join_count > 1 ? join('_', $rel, $join_count) : $rel);
1559
1560     $self->result_source->schema->resultset($rel_obj->{class})->search_rs(
1561       undef, {
1562         %{$self->{attrs}||{}},
1563         join => undef,
1564         prefetch => undef,
1565         select => undef,
1566         as => undef,
1567         alias => $alias,
1568         where => $self->{cond},
1569         seen_join => $seen,
1570         from => $from,
1571     });
1572   };
1573 }
1574
1575 sub _resolve_from {
1576   my ($self, $extra_join) = @_;
1577   my $source = $self->result_source;
1578   my $attrs = $self->{attrs};
1579   
1580   my $from = $attrs->{from}
1581     || [ { $attrs->{alias} => $source->from } ];
1582     
1583   my $seen = { %{$attrs->{seen_join}||{}} };
1584
1585   my $join = ($attrs->{join}
1586                ? [ $attrs->{join}, $extra_join ]
1587                : $extra_join);
1588   $from = [
1589     @$from,
1590     ($join ? $source->resolve_join($join, $attrs->{alias}, $seen) : ()),
1591   ];
1592
1593   return ($from,$seen);
1594 }
1595
1596 sub _resolved_attrs {
1597   my $self = shift;
1598   return $self->{_attrs} if $self->{_attrs};
1599
1600   my $attrs = { %{$self->{attrs}||{}} };
1601   my $source = $self->{result_source};
1602   my $alias = $attrs->{alias};
1603
1604   $attrs->{columns} ||= delete $attrs->{cols} if exists $attrs->{cols};
1605   if ($attrs->{columns}) {
1606     delete $attrs->{as};
1607   } elsif (!$attrs->{select}) {
1608     $attrs->{columns} = [ $source->columns ];
1609   }
1610  
1611   $attrs->{select} = 
1612     ($attrs->{select}
1613       ? (ref $attrs->{select} eq 'ARRAY'
1614           ? [ @{$attrs->{select}} ]
1615           : [ $attrs->{select} ])
1616       : [ map { m/\./ ? $_ : "${alias}.$_" } @{delete $attrs->{columns}} ]
1617     );
1618   $attrs->{as} =
1619     ($attrs->{as}
1620       ? (ref $attrs->{as} eq 'ARRAY'
1621           ? [ @{$attrs->{as}} ]
1622           : [ $attrs->{as} ])
1623       : [ map { m/^\Q${alias}.\E(.+)$/ ? $1 : $_ } @{$attrs->{select}} ]
1624     );
1625   
1626   my $adds;
1627   if ($adds = delete $attrs->{include_columns}) {
1628     $adds = [$adds] unless ref $adds eq 'ARRAY';
1629     push(@{$attrs->{select}}, @$adds);
1630     push(@{$attrs->{as}}, map { m/([^.]+)$/; $1 } @$adds);
1631   }
1632   if ($adds = delete $attrs->{'+select'}) {
1633     $adds = [$adds] unless ref $adds eq 'ARRAY';
1634     push(@{$attrs->{select}},
1635            map { /\./ || ref $_ ? $_ : "${alias}.$_" } @$adds);
1636   }
1637   if (my $adds = delete $attrs->{'+as'}) {
1638     $adds = [$adds] unless ref $adds eq 'ARRAY';
1639     push(@{$attrs->{as}}, @$adds);
1640   }
1641
1642   $attrs->{from} ||= [ { 'me' => $source->from } ];
1643
1644   if (exists $attrs->{join} || exists $attrs->{prefetch}) {
1645     my $join = delete $attrs->{join} || {};
1646
1647     if (defined $attrs->{prefetch}) {
1648       $join = $self->_merge_attr(
1649         $join, $attrs->{prefetch}
1650       );
1651     }
1652
1653     $attrs->{from} =   # have to copy here to avoid corrupting the original
1654       [
1655         @{$attrs->{from}}, 
1656         $source->resolve_join($join, $alias, { %{$attrs->{seen_join}||{}} })
1657       ];
1658   }
1659
1660   $attrs->{group_by} ||= $attrs->{select} if delete $attrs->{distinct};
1661   if ($attrs->{order_by}) {
1662     $attrs->{order_by} = (ref($attrs->{order_by}) eq 'ARRAY'
1663                            ? [ @{$attrs->{order_by}} ]
1664                            : [ $attrs->{order_by} ]);
1665   } else {
1666     $attrs->{order_by} = [];    
1667   }
1668
1669   my $collapse = $attrs->{collapse} || {};
1670   if (my $prefetch = delete $attrs->{prefetch}) {
1671     $prefetch = $self->_merge_attr({}, $prefetch);
1672     my @pre_order;
1673     my $seen = $attrs->{seen_join} || {};
1674     foreach my $p (ref $prefetch eq 'ARRAY' ? @$prefetch : ($prefetch)) {
1675       # bring joins back to level of current class
1676       my @prefetch = $source->resolve_prefetch(
1677         $p, $alias, $seen, \@pre_order, $collapse
1678       );
1679       push(@{$attrs->{select}}, map { $_->[0] } @prefetch);
1680       push(@{$attrs->{as}}, map { $_->[1] } @prefetch);
1681     }
1682     push(@{$attrs->{order_by}}, @pre_order);
1683   }
1684   $attrs->{collapse} = $collapse;
1685
1686   return $self->{_attrs} = $attrs;
1687 }
1688
1689 sub _merge_attr {
1690   my ($self, $a, $b) = @_;
1691   return $b unless defined($a);
1692   return $a unless defined($b);
1693   
1694   if (ref $b eq 'HASH' && ref $a eq 'HASH') {
1695     foreach my $key (keys %{$b}) {
1696       if (exists $a->{$key}) {
1697         $a->{$key} = $self->_merge_attr($a->{$key}, $b->{$key});
1698       } else {
1699         $a->{$key} = $b->{$key};
1700       }
1701     }
1702     return $a;
1703   } else {
1704     $a = [$a] unless ref $a eq 'ARRAY';
1705     $b = [$b] unless ref $b eq 'ARRAY';
1706
1707     my $hash = {};
1708     my @array;
1709     foreach my $x ($a, $b) {
1710       foreach my $element (@{$x}) {
1711         if (ref $element eq 'HASH') {
1712           $hash = $self->_merge_attr($hash, $element);
1713         } elsif (ref $element eq 'ARRAY') {
1714           push(@array, @{$element});
1715         } else {
1716           push(@array, $element) unless $b == $x
1717             && grep { $_ eq $element } @array;
1718         }
1719       }
1720     }
1721     
1722     @array = grep { !exists $hash->{$_} } @array;
1723
1724     return keys %{$hash}
1725       ? ( scalar(@array)
1726             ? [$hash, @array]
1727             : $hash
1728         )
1729       : \@array;
1730   }
1731 }
1732
1733 =head2 throw_exception
1734
1735 See L<DBIx::Class::Schema/throw_exception> for details.
1736
1737 =cut
1738
1739 sub throw_exception {
1740   my $self=shift;
1741   $self->result_source->schema->throw_exception(@_);
1742 }
1743
1744 # XXX: FIXME: Attributes docs need clearing up
1745
1746 =head1 ATTRIBUTES
1747
1748 The resultset takes various attributes that modify its behavior. Here's an
1749 overview of them:
1750
1751 =head2 order_by
1752
1753 =over 4
1754
1755 =item Value: ($order_by | \@order_by)
1756
1757 =back
1758
1759 Which column(s) to order the results by. This is currently passed
1760 through directly to SQL, so you can give e.g. C<year DESC> for a
1761 descending order on the column `year'.
1762
1763 Please note that if you have quoting enabled (see
1764 L<DBIx::Class::Storage/quote_char>) you will need to do C<\'year DESC' > to
1765 specify an order. (The scalar ref causes it to be passed as raw sql to the DB,
1766 so you will need to manually quote things as appropriate.)
1767
1768 =head2 columns
1769
1770 =over 4
1771
1772 =item Value: \@columns
1773
1774 =back
1775
1776 Shortcut to request a particular set of columns to be retrieved.  Adds
1777 C<me.> onto the start of any column without a C<.> in it and sets C<select>
1778 from that, then auto-populates C<as> from C<select> as normal. (You may also
1779 use the C<cols> attribute, as in earlier versions of DBIC.)
1780
1781 =head2 include_columns
1782
1783 =over 4
1784
1785 =item Value: \@columns
1786
1787 =back
1788
1789 Shortcut to include additional columns in the returned results - for example
1790
1791   $schema->resultset('CD')->search(undef, {
1792     include_columns => ['artist.name'],
1793     join => ['artist']
1794   });
1795
1796 would return all CDs and include a 'name' column to the information
1797 passed to object inflation
1798
1799 =head2 select
1800
1801 =over 4
1802
1803 =item Value: \@select_columns
1804
1805 =back
1806
1807 Indicates which columns should be selected from the storage. You can use
1808 column names, or in the case of RDBMS back ends, function or stored procedure
1809 names:
1810
1811   $rs = $schema->resultset('Employee')->search(undef, {
1812     select => [
1813       'name',
1814       { count => 'employeeid' },
1815       { sum => 'salary' }
1816     ]
1817   });
1818
1819 When you use function/stored procedure names and do not supply an C<as>
1820 attribute, the column names returned are storage-dependent. E.g. MySQL would
1821 return a column named C<count(employeeid)> in the above example.
1822
1823 =head2 +select
1824
1825 =over 4
1826
1827 Indicates additional columns to be selected from storage.  Works the same as
1828 L<select> but adds columns to the selection.
1829
1830 =back
1831
1832 =head2 +as
1833
1834 =over 4
1835
1836 Indicates additional column names for those added via L<+select>.
1837
1838 =back
1839
1840 =head2 as
1841
1842 =over 4
1843
1844 =item Value: \@inflation_names
1845
1846 =back
1847
1848 Indicates column names for object inflation. This is used in conjunction with
1849 C<select>, usually when C<select> contains one or more function or stored
1850 procedure names:
1851
1852   $rs = $schema->resultset('Employee')->search(undef, {
1853     select => [
1854       'name',
1855       { count => 'employeeid' }
1856     ],
1857     as => ['name', 'employee_count'],
1858   });
1859
1860   my $employee = $rs->first(); # get the first Employee
1861
1862 If the object against which the search is performed already has an accessor
1863 matching a column name specified in C<as>, the value can be retrieved using
1864 the accessor as normal:
1865
1866   my $name = $employee->name();
1867
1868 If on the other hand an accessor does not exist in the object, you need to
1869 use C<get_column> instead:
1870
1871   my $employee_count = $employee->get_column('employee_count');
1872
1873 You can create your own accessors if required - see
1874 L<DBIx::Class::Manual::Cookbook> for details.
1875
1876 Please note: This will NOT insert an C<AS employee_count> into the SQL
1877 statement produced, it is used for internal access only. Thus
1878 attempting to use the accessor in an C<order_by> clause or similar
1879 will fail miserably.
1880
1881 To get around this limitation, you can supply literal SQL to your
1882 C<select> attibute that contains the C<AS alias> text, eg:
1883
1884   select => [\'myfield AS alias']
1885
1886 =head2 join
1887
1888 =over 4
1889
1890 =item Value: ($rel_name | \@rel_names | \%rel_names)
1891
1892 =back
1893
1894 Contains a list of relationships that should be joined for this query.  For
1895 example:
1896
1897   # Get CDs by Nine Inch Nails
1898   my $rs = $schema->resultset('CD')->search(
1899     { 'artist.name' => 'Nine Inch Nails' },
1900     { join => 'artist' }
1901   );
1902
1903 Can also contain a hash reference to refer to the other relation's relations.
1904 For example:
1905
1906   package MyApp::Schema::Track;
1907   use base qw/DBIx::Class/;
1908   __PACKAGE__->table('track');
1909   __PACKAGE__->add_columns(qw/trackid cd position title/);
1910   __PACKAGE__->set_primary_key('trackid');
1911   __PACKAGE__->belongs_to(cd => 'MyApp::Schema::CD');
1912   1;
1913
1914   # In your application
1915   my $rs = $schema->resultset('Artist')->search(
1916     { 'track.title' => 'Teardrop' },
1917     {
1918       join     => { cd => 'track' },
1919       order_by => 'artist.name',
1920     }
1921   );
1922
1923 You need to use the relationship (not the table) name in  conditions, 
1924 because they are aliased as such. The current table is aliased as "me", so 
1925 you need to use me.column_name in order to avoid ambiguity. For example:
1926
1927   # Get CDs from 1984 with a 'Foo' track 
1928   my $rs = $schema->resultset('CD')->search(
1929     { 
1930       'me.year' => 1984,
1931       'tracks.name' => 'Foo'
1932     },
1933     { join => 'tracks' }
1934   );
1935   
1936 If the same join is supplied twice, it will be aliased to <rel>_2 (and
1937 similarly for a third time). For e.g.
1938
1939   my $rs = $schema->resultset('Artist')->search({
1940     'cds.title'   => 'Down to Earth',
1941     'cds_2.title' => 'Popular',
1942   }, {
1943     join => [ qw/cds cds/ ],
1944   });
1945
1946 will return a set of all artists that have both a cd with title 'Down
1947 to Earth' and a cd with title 'Popular'.
1948
1949 If you want to fetch related objects from other tables as well, see C<prefetch>
1950 below.
1951
1952 =head2 prefetch
1953
1954 =over 4
1955
1956 =item Value: ($rel_name | \@rel_names | \%rel_names)
1957
1958 =back
1959
1960 Contains one or more relationships that should be fetched along with the main
1961 query (when they are accessed afterwards they will have already been
1962 "prefetched").  This is useful for when you know you will need the related
1963 objects, because it saves at least one query:
1964
1965   my $rs = $schema->resultset('Tag')->search(
1966     undef,
1967     {
1968       prefetch => {
1969         cd => 'artist'
1970       }
1971     }
1972   );
1973
1974 The initial search results in SQL like the following:
1975
1976   SELECT tag.*, cd.*, artist.* FROM tag
1977   JOIN cd ON tag.cd = cd.cdid
1978   JOIN artist ON cd.artist = artist.artistid
1979
1980 L<DBIx::Class> has no need to go back to the database when we access the
1981 C<cd> or C<artist> relationships, which saves us two SQL statements in this
1982 case.
1983
1984 Simple prefetches will be joined automatically, so there is no need
1985 for a C<join> attribute in the above search. If you're prefetching to
1986 depth (e.g. { cd => { artist => 'label' } or similar), you'll need to
1987 specify the join as well.
1988
1989 C<prefetch> can be used with the following relationship types: C<belongs_to>,
1990 C<has_one> (or if you're using C<add_relationship>, any relationship declared
1991 with an accessor type of 'single' or 'filter').
1992
1993 =head2 page
1994
1995 =over 4
1996
1997 =item Value: $page
1998
1999 =back
2000
2001 Makes the resultset paged and specifies the page to retrieve. Effectively
2002 identical to creating a non-pages resultset and then calling ->page($page)
2003 on it.
2004
2005 If L<rows> attribute is not specified it defualts to 10 rows per page.
2006
2007 =head2 rows
2008
2009 =over 4
2010
2011 =item Value: $rows
2012
2013 =back
2014
2015 Specifes the maximum number of rows for direct retrieval or the number of
2016 rows per page if the page attribute or method is used.
2017
2018 =head2 offset
2019
2020 =over 4
2021
2022 =item Value: $offset
2023
2024 =back
2025
2026 Specifies the (zero-based) row number for the  first row to be returned, or the
2027 of the first row of the first page if paging is used.
2028
2029 =head2 group_by
2030
2031 =over 4
2032
2033 =item Value: \@columns
2034
2035 =back
2036
2037 A arrayref of columns to group by. Can include columns of joined tables.
2038
2039   group_by => [qw/ column1 column2 ... /]
2040
2041 =head2 having
2042
2043 =over 4
2044
2045 =item Value: $condition
2046
2047 =back
2048
2049 HAVING is a select statement attribute that is applied between GROUP BY and
2050 ORDER BY. It is applied to the after the grouping calculations have been
2051 done.
2052
2053   having => { 'count(employee)' => { '>=', 100 } }
2054
2055 =head2 distinct
2056
2057 =over 4
2058
2059 =item Value: (0 | 1)
2060
2061 =back
2062
2063 Set to 1 to group by all columns.
2064
2065 =head2 where
2066
2067 =over 4
2068
2069 Adds to the WHERE clause.
2070
2071   # only return rows WHERE deleted IS NULL for all searches
2072   __PACKAGE__->resultset_attributes({ where => { deleted => undef } }); )
2073
2074 Can be overridden by passing C<{ where => undef }> as an attribute
2075 to a resulset.
2076
2077 =back
2078
2079 =head2 cache
2080
2081 Set to 1 to cache search results. This prevents extra SQL queries if you
2082 revisit rows in your ResultSet:
2083
2084   my $resultset = $schema->resultset('Artist')->search( undef, { cache => 1 } );
2085
2086   while( my $artist = $resultset->next ) {
2087     ... do stuff ...
2088   }
2089
2090   $rs->first; # without cache, this would issue a query
2091
2092 By default, searches are not cached.
2093
2094 For more examples of using these attributes, see
2095 L<DBIx::Class::Manual::Cookbook>.
2096
2097 =head2 from
2098
2099 =over 4
2100
2101 =item Value: \@from_clause
2102
2103 =back
2104
2105 The C<from> attribute gives you manual control over the C<FROM> clause of SQL
2106 statements generated by L<DBIx::Class>, allowing you to express custom C<JOIN>
2107 clauses.
2108
2109 NOTE: Use this on your own risk.  This allows you to shoot off your foot!
2110
2111 C<join> will usually do what you need and it is strongly recommended that you
2112 avoid using C<from> unless you cannot achieve the desired result using C<join>.
2113 And we really do mean "cannot", not just tried and failed. Attempting to use
2114 this because you're having problems with C<join> is like trying to use x86
2115 ASM because you've got a syntax error in your C. Trust us on this.
2116
2117 Now, if you're still really, really sure you need to use this (and if you're
2118 not 100% sure, ask the mailing list first), here's an explanation of how this
2119 works.
2120
2121 The syntax is as follows -
2122
2123   [
2124     { <alias1> => <table1> },
2125     [
2126       { <alias2> => <table2>, -join_type => 'inner|left|right' },
2127       [], # nested JOIN (optional)
2128       { <table1.column1> => <table2.column2>, ... (more conditions) },
2129     ],
2130     # More of the above [ ] may follow for additional joins
2131   ]
2132
2133   <table1> <alias1>
2134   JOIN
2135     <table2> <alias2>
2136     [JOIN ...]
2137   ON <table1.column1> = <table2.column2>
2138   <more joins may follow>
2139
2140 An easy way to follow the examples below is to remember the following:
2141
2142     Anything inside "[]" is a JOIN
2143     Anything inside "{}" is a condition for the enclosing JOIN
2144
2145 The following examples utilize a "person" table in a family tree application.
2146 In order to express parent->child relationships, this table is self-joined:
2147
2148     # Person->belongs_to('father' => 'Person');
2149     # Person->belongs_to('mother' => 'Person');
2150
2151 C<from> can be used to nest joins. Here we return all children with a father,
2152 then search against all mothers of those children:
2153
2154   $rs = $schema->resultset('Person')->search(
2155       undef,
2156       {
2157           alias => 'mother', # alias columns in accordance with "from"
2158           from => [
2159               { mother => 'person' },
2160               [
2161                   [
2162                       { child => 'person' },
2163                       [
2164                           { father => 'person' },
2165                           { 'father.person_id' => 'child.father_id' }
2166                       ]
2167                   ],
2168                   { 'mother.person_id' => 'child.mother_id' }
2169               ],
2170           ]
2171       },
2172   );
2173
2174   # Equivalent SQL:
2175   # SELECT mother.* FROM person mother
2176   # JOIN (
2177   #   person child
2178   #   JOIN person father
2179   #   ON ( father.person_id = child.father_id )
2180   # )
2181   # ON ( mother.person_id = child.mother_id )
2182
2183 The type of any join can be controlled manually. To search against only people
2184 with a father in the person table, we could explicitly use C<INNER JOIN>:
2185
2186     $rs = $schema->resultset('Person')->search(
2187         undef,
2188         {
2189             alias => 'child', # alias columns in accordance with "from"
2190             from => [
2191                 { child => 'person' },
2192                 [
2193                     { father => 'person', -join_type => 'inner' },
2194                     { 'father.id' => 'child.father_id' }
2195                 ],
2196             ]
2197         },
2198     );
2199
2200     # Equivalent SQL:
2201     # SELECT child.* FROM person child
2202     # INNER JOIN person father ON child.father_id = father.id
2203
2204 =cut
2205
2206 1;