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