776443637341a7f9c0ee6fa1c886b8788c6a0f6a
[dbsrgits/DBIx-Class-Historic.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'   => "_bool",
8         fallback => 1;
9 use Carp::Clan qw/^DBIx::Class/;
10 use Data::Page;
11 use Storable;
12 use DBIx::Class::ResultSetColumn;
13 use DBIx::Class::ResultSourceHandle;
14 use List::Util ();
15 use Scalar::Util ();
16 use base qw/DBIx::Class/;
17
18 __PACKAGE__->mk_group_accessors('simple' => qw/result_class _source_handle/);
19
20 =head1 NAME
21
22 DBIx::Class::ResultSet - Responsible for fetching and creating resultset.
23
24 =head1 SYNOPSIS
25
26   my $rs   = $schema->resultset('User')->search({ registered => 1 });
27   my @rows = $schema->resultset('CD')->search({ year => 2005 })->all();
28
29 =head1 DESCRIPTION
30
31 The resultset is also known as an iterator. It is responsible for handling
32 queries that may return an arbitrary number of rows, e.g. via L</search>
33 or a C<has_many> relationship.
34
35 In the examples below, the following table classes are used:
36
37   package MyApp::Schema::Artist;
38   use base qw/DBIx::Class/;
39   __PACKAGE__->load_components(qw/Core/);
40   __PACKAGE__->table('artist');
41   __PACKAGE__->add_columns(qw/artistid name/);
42   __PACKAGE__->set_primary_key('artistid');
43   __PACKAGE__->has_many(cds => 'MyApp::Schema::CD');
44   1;
45
46   package MyApp::Schema::CD;
47   use base qw/DBIx::Class/;
48   __PACKAGE__->load_components(qw/Core/);
49   __PACKAGE__->table('cd');
50   __PACKAGE__->add_columns(qw/cdid artist title year/);
51   __PACKAGE__->set_primary_key('cdid');
52   __PACKAGE__->belongs_to(artist => 'MyApp::Schema::Artist');
53   1;
54
55 =head1 OVERLOADING
56
57 If a resultset is used in a numeric context it returns the L</count>.
58 However, if it is used in a booleand context it is always true.  So if
59 you want to check if a resultset has any results use C<if $rs != 0>.
60 C<if $rs> will always be true.
61
62 =head1 METHODS
63
64 =head2 new
65
66 =over 4
67
68 =item Arguments: $source, \%$attrs
69
70 =item Return Value: $rs
71
72 =back
73
74 The resultset constructor. Takes a source object (usually a
75 L<DBIx::Class::ResultSourceProxy::Table>) and an attribute hash (see
76 L</ATTRIBUTES> below).  Does not perform any queries -- these are
77 executed as needed by the other methods.
78
79 Generally you won't need to construct a resultset manually.  You'll
80 automatically get one from e.g. a L</search> called in scalar context:
81
82   my $rs = $schema->resultset('CD')->search({ title => '100th Window' });
83
84 IMPORTANT: If called on an object, proxies to new_result instead so
85
86   my $cd = $schema->resultset('CD')->new({ title => 'Spoon' });
87
88 will return a CD object, not a ResultSet.
89
90 =cut
91
92 sub new {
93   my $class = shift;
94   return $class->new_result(@_) if ref $class;
95
96   my ($source, $attrs) = @_;
97   $source = $source->handle 
98     unless $source->isa('DBIx::Class::ResultSourceHandle');
99   $attrs = { %{$attrs||{}} };
100
101   if ($attrs->{page}) {
102     $attrs->{rows} ||= 10;
103   }
104
105   $attrs->{alias} ||= 'me';
106
107   # Creation of {} and bless separated to mitigate RH perl bug
108   # see https://bugzilla.redhat.com/show_bug.cgi?id=196836
109   my $self = {
110     _source_handle => $source,
111     result_class => $attrs->{result_class} || $source->resolve->result_class,
112     cond => $attrs->{where},
113     count => undef,
114     pager => undef,
115     attrs => $attrs
116   };
117
118   bless $self, $class;
119
120   return $self;
121 }
122
123 =head2 search
124
125 =over 4
126
127 =item Arguments: $cond, \%attrs?
128
129 =item Return Value: $resultset (scalar context), @row_objs (list context)
130
131 =back
132
133   my @cds    = $cd_rs->search({ year => 2001 }); # "... WHERE year = 2001"
134   my $new_rs = $cd_rs->search({ year => 2005 });
135
136   my $new_rs = $cd_rs->search([ { year => 2005 }, { year => 2004 } ]);
137                  # year = 2005 OR year = 2004
138
139 If you need to pass in additional attributes but no additional condition,
140 call it as C<search(undef, \%attrs)>.
141
142   # "SELECT name, artistid FROM $artist_table"
143   my @all_artists = $schema->resultset('Artist')->search(undef, {
144     columns => [qw/name artistid/],
145   });
146
147 For a list of attributes that can be passed to C<search>, see
148 L</ATTRIBUTES>. For more examples of using this function, see
149 L<Searching|DBIx::Class::Manual::Cookbook/Searching>. For a complete
150 documentation for the first argument, see L<SQL::Abstract>.
151
152 For more help on using joins with search, see L<DBIx::Class::Manual::Joining>.
153
154 =cut
155
156 sub search {
157   my $self = shift;
158   my $rs = $self->search_rs( @_ );
159   return (wantarray ? $rs->all : $rs);
160 }
161
162 =head2 search_rs
163
164 =over 4
165
166 =item Arguments: $cond, \%attrs?
167
168 =item Return Value: $resultset
169
170 =back
171
172 This method does the same exact thing as search() except it will
173 always return a resultset, even in list context.
174
175 =cut
176
177 sub search_rs {
178   my $self = shift;
179
180   my $attrs = {};
181   $attrs = pop(@_) if @_ > 1 and ref $_[$#_] eq 'HASH';
182   my $our_attrs = { %{$self->{attrs}} };
183   my $having = delete $our_attrs->{having};
184   my $where = delete $our_attrs->{where};
185
186   my $rows;
187
188   my %safe = (alias => 1, cache => 1);
189
190   unless (
191     (@_ && defined($_[0])) # @_ == () or (undef)
192     || 
193     (keys %$attrs # empty attrs or only 'safe' attrs
194     && List::Util::first { !$safe{$_} } keys %$attrs)
195   ) {
196     # no search, effectively just a clone
197     $rows = $self->get_cache;
198   }
199
200   my $new_attrs = { %{$our_attrs}, %{$attrs} };
201
202   # merge new attrs into inherited
203   foreach my $key (qw/join prefetch +select +as/) {
204     next unless exists $attrs->{$key};
205     $new_attrs->{$key} = $self->_merge_attr($our_attrs->{$key}, $attrs->{$key});
206   }
207
208   my $cond = (@_
209     ? (
210         (@_ == 1 || ref $_[0] eq "HASH")
211           ? (
212               (ref $_[0] eq 'HASH')
213                 ? (
214                     (keys %{ $_[0] }  > 0)
215                       ? shift
216                       : undef
217                    )
218                 :  shift
219              )
220           : (
221               (@_ % 2)
222                 ? $self->throw_exception("Odd number of arguments to search")
223                 : {@_}
224              )
225       )
226     : undef
227   );
228
229   if (defined $where) {
230     $new_attrs->{where} = (
231       defined $new_attrs->{where}
232         ? { '-and' => [
233               map {
234                 ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_
235               } $where, $new_attrs->{where}
236             ]
237           }
238         : $where);
239   }
240
241   if (defined $cond) {
242     $new_attrs->{where} = (
243       defined $new_attrs->{where}
244         ? { '-and' => [
245               map {
246                 ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_
247               } $cond, $new_attrs->{where}
248             ]
249           }
250         : $cond);
251   }
252
253   if (defined $having) {
254     $new_attrs->{having} = (
255       defined $new_attrs->{having}
256         ? { '-and' => [
257               map {
258                 ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_
259               } $having, $new_attrs->{having}
260             ]
261           }
262         : $having);
263   }
264
265   my $rs = (ref $self)->new($self->result_source, $new_attrs);
266   if ($rows) {
267     $rs->set_cache($rows);
268   }
269   return $rs;
270 }
271
272 =head2 search_literal
273
274 =over 4
275
276 =item Arguments: $sql_fragment, @bind_values
277
278 =item Return Value: $resultset (scalar context), @row_objs (list context)
279
280 =back
281
282   my @cds   = $cd_rs->search_literal('year = ? AND title = ?', qw/2001 Reload/);
283   my $newrs = $artist_rs->search_literal('name = ?', 'Metallica');
284
285 Pass a literal chunk of SQL to be added to the conditional part of the
286 resultset query.
287
288 CAVEAT: C<search_literal> is provided for Class::DBI compatibility and should
289 only be used in that context. There are known problems using C<search_literal>
290 in chained queries; it can result in bind values in the wrong order.  See
291 L<DBIx::Class::Manual::Cookbook/Searching> and
292 L<DBIx::Class::Manual::FAQ/Searching> for searching techniques that do not
293 require C<search_literal>.
294
295 =cut
296
297 sub search_literal {
298   my ($self, $cond, @vals) = @_;
299   my $attrs = (ref $vals[$#vals] eq 'HASH' ? { %{ pop(@vals) } } : {});
300   $attrs->{bind} = [ @{$self->{attrs}{bind}||[]}, @vals ];
301   return $self->search(\$cond, $attrs);
302 }
303
304 =head2 find
305
306 =over 4
307
308 =item Arguments: @values | \%cols, \%attrs?
309
310 =item Return Value: $row_object | undef
311
312 =back
313
314 Finds a row based on its primary key or unique constraint. For example, to find
315 a row by its primary key:
316
317   my $cd = $schema->resultset('CD')->find(5);
318
319 You can also find a row by a specific unique constraint using the C<key>
320 attribute. For example:
321
322   my $cd = $schema->resultset('CD')->find('Massive Attack', 'Mezzanine', {
323     key => 'cd_artist_title'
324   });
325
326 Additionally, you can specify the columns explicitly by name:
327
328   my $cd = $schema->resultset('CD')->find(
329     {
330       artist => 'Massive Attack',
331       title  => 'Mezzanine',
332     },
333     { key => 'cd_artist_title' }
334   );
335
336 If the C<key> is specified as C<primary>, it searches only on the primary key.
337
338 If no C<key> is specified, it searches on all unique constraints defined on the
339 source for which column data is provided, including the primary key.
340
341 If your table does not have a primary key, you B<must> provide a value for the
342 C<key> attribute matching one of the unique constraints on the source.
343
344 Note: If your query does not return only one row, a warning is generated:
345
346   Query returned more than one row
347
348 See also L</find_or_create> and L</update_or_create>. For information on how to
349 declare unique constraints, see
350 L<DBIx::Class::ResultSource/add_unique_constraint>.
351
352 =cut
353
354 sub find {
355   my $self = shift;
356   my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
357
358   # Default to the primary key, but allow a specific key
359   my @cols = exists $attrs->{key}
360     ? $self->result_source->unique_constraint_columns($attrs->{key})
361     : $self->result_source->primary_columns;
362   $self->throw_exception(
363     "Can't find unless a primary key is defined or unique constraint is specified"
364   ) unless @cols;
365
366   # Parse out a hashref from input
367   my $input_query;
368   if (ref $_[0] eq 'HASH') {
369     $input_query = { %{$_[0]} };
370   }
371   elsif (@_ == @cols) {
372     $input_query = {};
373     @{$input_query}{@cols} = @_;
374   }
375   else {
376     # Compatibility: Allow e.g. find(id => $value)
377     carp "Find by key => value deprecated; please use a hashref instead";
378     $input_query = {@_};
379   }
380
381   my (%related, $info);
382
383   KEY: foreach my $key (keys %$input_query) {
384     if (ref($input_query->{$key})
385         && ($info = $self->result_source->relationship_info($key))) {
386       my $val = delete $input_query->{$key};
387       next KEY if (ref($val) eq 'ARRAY'); # has_many for multi_create
388       my $rel_q = $self->result_source->resolve_condition(
389                     $info->{cond}, $val, $key
390                   );
391       die "Can't handle OR join condition in find" if ref($rel_q) eq 'ARRAY';
392       @related{keys %$rel_q} = values %$rel_q;
393     }
394   }
395   if (my @keys = keys %related) {
396     @{$input_query}{@keys} = values %related;
397   }
398
399
400   # Build the final query: Default to the disjunction of the unique queries,
401   # but allow the input query in case the ResultSet defines the query or the
402   # user is abusing find
403   my $alias = exists $attrs->{alias} ? $attrs->{alias} : $self->{attrs}{alias};
404   my $query;
405   if (exists $attrs->{key}) {
406     my @unique_cols = $self->result_source->unique_constraint_columns($attrs->{key});
407     my $unique_query = $self->_build_unique_query($input_query, \@unique_cols);
408     $query = $self->_add_alias($unique_query, $alias);
409   }
410   else {
411     my @unique_queries = $self->_unique_queries($input_query, $attrs);
412     $query = @unique_queries
413       ? [ map { $self->_add_alias($_, $alias) } @unique_queries ]
414       : $self->_add_alias($input_query, $alias);
415   }
416
417   # Run the query
418   if (keys %$attrs) {
419     my $rs = $self->search($query, $attrs);
420     if (keys %{$rs->_resolved_attrs->{collapse}}) {
421       my $row = $rs->next;
422       carp "Query returned more than one row" if $rs->next;
423       return $row;
424     }
425     else {
426       return $rs->single;
427     }
428   }
429   else {
430     if (keys %{$self->_resolved_attrs->{collapse}}) {
431       my $rs = $self->search($query);
432       my $row = $rs->next;
433       carp "Query returned more than one row" if $rs->next;
434       return $row;
435     }
436     else {
437       return $self->single($query);
438     }
439   }
440 }
441
442 # _add_alias
443 #
444 # Add the specified alias to the specified query hash. A copy is made so the
445 # original query is not modified.
446
447 sub _add_alias {
448   my ($self, $query, $alias) = @_;
449
450   my %aliased = %$query;
451   foreach my $col (grep { ! m/\./ } keys %aliased) {
452     $aliased{"$alias.$col"} = delete $aliased{$col};
453   }
454
455   return \%aliased;
456 }
457
458 # _unique_queries
459 #
460 # Build a list of queries which satisfy unique constraints.
461
462 sub _unique_queries {
463   my ($self, $query, $attrs) = @_;
464
465   my @constraint_names = exists $attrs->{key}
466     ? ($attrs->{key})
467     : $self->result_source->unique_constraint_names;
468
469   my $where = $self->_collapse_cond($self->{attrs}{where} || {});
470   my $num_where = scalar keys %$where;
471
472   my @unique_queries;
473   foreach my $name (@constraint_names) {
474     my @unique_cols = $self->result_source->unique_constraint_columns($name);
475     my $unique_query = $self->_build_unique_query($query, \@unique_cols);
476
477     my $num_cols = scalar @unique_cols;
478     my $num_query = scalar keys %$unique_query;
479
480     my $total = $num_query + $num_where;
481     if ($num_query && ($num_query == $num_cols || $total == $num_cols)) {
482       # The query is either unique on its own or is unique in combination with
483       # the existing where clause
484       push @unique_queries, $unique_query;
485     }
486   }
487
488   return @unique_queries;
489 }
490
491 # _build_unique_query
492 #
493 # Constrain the specified query hash based on the specified column names.
494
495 sub _build_unique_query {
496   my ($self, $query, $unique_cols) = @_;
497
498   return {
499     map  { $_ => $query->{$_} }
500     grep { exists $query->{$_} }
501       @$unique_cols
502   };
503 }
504
505 =head2 search_related
506
507 =over 4
508
509 =item Arguments: $rel, $cond, \%attrs?
510
511 =item Return Value: $new_resultset
512
513 =back
514
515   $new_rs = $cd_rs->search_related('artist', {
516     name => 'Emo-R-Us',
517   });
518
519 Searches the specified relationship, optionally specifying a condition and
520 attributes for matching records. See L</ATTRIBUTES> for more information.
521
522 =cut
523
524 sub search_related {
525   return shift->related_resultset(shift)->search(@_);
526 }
527
528 =head2 search_related_rs
529
530 This method works exactly the same as search_related, except that
531 it guarantees a restultset, even in list context.
532
533 =cut
534
535 sub search_related_rs {
536   return shift->related_resultset(shift)->search_rs(@_);
537 }
538
539 =head2 cursor
540
541 =over 4
542
543 =item Arguments: none
544
545 =item Return Value: $cursor
546
547 =back
548
549 Returns a storage-driven cursor to the given resultset. See
550 L<DBIx::Class::Cursor> for more information.
551
552 =cut
553
554 sub cursor {
555   my ($self) = @_;
556
557   my $attrs = { %{$self->_resolved_attrs} };
558   return $self->{cursor}
559     ||= $self->result_source->storage->select($attrs->{from}, $attrs->{select},
560           $attrs->{where},$attrs);
561 }
562
563 =head2 single
564
565 =over 4
566
567 =item Arguments: $cond?
568
569 =item Return Value: $row_object?
570
571 =back
572
573   my $cd = $schema->resultset('CD')->single({ year => 2001 });
574
575 Inflates the first result without creating a cursor if the resultset has
576 any records in it; if not returns nothing. Used by L</find> as a lean version of
577 L</search>.
578
579 While this method can take an optional search condition (just like L</search>)
580 being a fast-code-path it does not recognize search attributes. If you need to
581 add extra joins or similar, call L</search> and then chain-call L</single> on the
582 L<DBIx::Class::ResultSet> returned.
583
584 =over
585
586 =item B<Note>
587
588 As of 0.08100, this method enforces the assumption that the preceeding
589 query returns only one row. If more than one row is returned, you will receive
590 a warning:
591
592   Query returned more than one row
593
594 In this case, you should be using L</first> or L</find> instead, or if you really
595 know what you are doing, use the L</rows> attribute to explicitly limit the size 
596 of the resultset.
597
598 =back
599
600 =cut
601
602 sub single {
603   my ($self, $where) = @_;
604   my $attrs = { %{$self->_resolved_attrs} };
605   if ($where) {
606     if (defined $attrs->{where}) {
607       $attrs->{where} = {
608         '-and' =>
609             [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
610                $where, delete $attrs->{where} ]
611       };
612     } else {
613       $attrs->{where} = $where;
614     }
615   }
616
617 #  XXX: Disabled since it doesn't infer uniqueness in all cases
618 #  unless ($self->_is_unique_query($attrs->{where})) {
619 #    carp "Query not guaranteed to return a single row"
620 #      . "; please declare your unique constraints or use search instead";
621 #  }
622
623   my @data = $self->result_source->storage->select_single(
624     $attrs->{from}, $attrs->{select},
625     $attrs->{where}, $attrs
626   );
627
628   return (@data ? ($self->_construct_object(@data))[0] : undef);
629 }
630
631 # _is_unique_query
632 #
633 # Try to determine if the specified query is guaranteed to be unique, based on
634 # the declared unique constraints.
635
636 sub _is_unique_query {
637   my ($self, $query) = @_;
638
639   my $collapsed = $self->_collapse_query($query);
640   my $alias = $self->{attrs}{alias};
641
642   foreach my $name ($self->result_source->unique_constraint_names) {
643     my @unique_cols = map {
644       "$alias.$_"
645     } $self->result_source->unique_constraint_columns($name);
646
647     # Count the values for each unique column
648     my %seen = map { $_ => 0 } @unique_cols;
649
650     foreach my $key (keys %$collapsed) {
651       my $aliased = $key =~ /\./ ? $key : "$alias.$key";
652       next unless exists $seen{$aliased};  # Additional constraints are okay
653       $seen{$aliased} = scalar keys %{ $collapsed->{$key} };
654     }
655
656     # If we get 0 or more than 1 value for a column, it's not necessarily unique
657     return 1 unless grep { $_ != 1 } values %seen;
658   }
659
660   return 0;
661 }
662
663 # _collapse_query
664 #
665 # Recursively collapse the query, accumulating values for each column.
666
667 sub _collapse_query {
668   my ($self, $query, $collapsed) = @_;
669
670   $collapsed ||= {};
671
672   if (ref $query eq 'ARRAY') {
673     foreach my $subquery (@$query) {
674       next unless ref $subquery;  # -or
675 #      warn "ARRAY: " . Dumper $subquery;
676       $collapsed = $self->_collapse_query($subquery, $collapsed);
677     }
678   }
679   elsif (ref $query eq 'HASH') {
680     if (keys %$query and (keys %$query)[0] eq '-and') {
681       foreach my $subquery (@{$query->{-and}}) {
682 #        warn "HASH: " . Dumper $subquery;
683         $collapsed = $self->_collapse_query($subquery, $collapsed);
684       }
685     }
686     else {
687 #      warn "LEAF: " . Dumper $query;
688       foreach my $col (keys %$query) {
689         my $value = $query->{$col};
690         $collapsed->{$col}{$value}++;
691       }
692     }
693   }
694
695   return $collapsed;
696 }
697
698 =head2 get_column
699
700 =over 4
701
702 =item Arguments: $cond?
703
704 =item Return Value: $resultsetcolumn
705
706 =back
707
708   my $max_length = $rs->get_column('length')->max;
709
710 Returns a L<DBIx::Class::ResultSetColumn> instance for a column of the ResultSet.
711
712 =cut
713
714 sub get_column {
715   my ($self, $column) = @_;
716   my $new = DBIx::Class::ResultSetColumn->new($self, $column);
717   return $new;
718 }
719
720 =head2 search_like
721
722 =over 4
723
724 =item Arguments: $cond, \%attrs?
725
726 =item Return Value: $resultset (scalar context), @row_objs (list context)
727
728 =back
729
730   # WHERE title LIKE '%blue%'
731   $cd_rs = $rs->search_like({ title => '%blue%'});
732
733 Performs a search, but uses C<LIKE> instead of C<=> as the condition. Note
734 that this is simply a convenience method. You most likely want to use
735 L</search> with specific operators.
736
737 For more information, see L<DBIx::Class::Manual::Cookbook>.
738
739 =cut
740
741 sub search_like {
742   my $class = shift;
743   my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
744   my $query = ref $_[0] eq 'HASH' ? { %{shift()} }: {@_};
745   $query->{$_} = { 'like' => $query->{$_} } for keys %$query;
746   return $class->search($query, { %$attrs });
747 }
748
749 =head2 slice
750
751 =over 4
752
753 =item Arguments: $first, $last
754
755 =item Return Value: $resultset (scalar context), @row_objs (list context)
756
757 =back
758
759 Returns a resultset or object list representing a subset of elements from the
760 resultset slice is called on. Indexes are from 0, i.e., to get the first
761 three records, call:
762
763   my ($one, $two, $three) = $rs->slice(0, 2);
764
765 =cut
766
767 sub slice {
768   my ($self, $min, $max) = @_;
769   my $attrs = {}; # = { %{ $self->{attrs} || {} } };
770   $attrs->{offset} = $self->{attrs}{offset} || 0;
771   $attrs->{offset} += $min;
772   $attrs->{rows} = ($max ? ($max - $min + 1) : 1);
773   return $self->search(undef(), $attrs);
774   #my $slice = (ref $self)->new($self->result_source, $attrs);
775   #return (wantarray ? $slice->all : $slice);
776 }
777
778 =head2 next
779
780 =over 4
781
782 =item Arguments: none
783
784 =item Return Value: $result?
785
786 =back
787
788 Returns the next element in the resultset (C<undef> is there is none).
789
790 Can be used to efficiently iterate over records in the resultset:
791
792   my $rs = $schema->resultset('CD')->search;
793   while (my $cd = $rs->next) {
794     print $cd->title;
795   }
796
797 Note that you need to store the resultset object, and call C<next> on it.
798 Calling C<< resultset('Table')->next >> repeatedly will always return the
799 first record from the resultset.
800
801 =cut
802
803 sub next {
804   my ($self) = @_;
805   if (my $cache = $self->get_cache) {
806     $self->{all_cache_position} ||= 0;
807     return $cache->[$self->{all_cache_position}++];
808   }
809   if ($self->{attrs}{cache}) {
810     $self->{all_cache_position} = 1;
811     return ($self->all)[0];
812   }
813   if ($self->{stashed_objects}) {
814     my $obj = shift(@{$self->{stashed_objects}});
815     delete $self->{stashed_objects} unless @{$self->{stashed_objects}};
816     return $obj;
817   }
818   my @row = (
819     exists $self->{stashed_row}
820       ? @{delete $self->{stashed_row}}
821       : $self->cursor->next
822   );
823   return undef unless (@row);
824   my ($row, @more) = $self->_construct_object(@row);
825   $self->{stashed_objects} = \@more if @more;
826   return $row;
827 }
828
829 sub _construct_object {
830   my ($self, @row) = @_;
831   my $info = $self->_collapse_result($self->{_attrs}{as}, \@row);
832   my @new = $self->result_class->inflate_result($self->result_source, @$info);
833   @new = $self->{_attrs}{record_filter}->(@new)
834     if exists $self->{_attrs}{record_filter};
835   return @new;
836 }
837
838 sub _collapse_result {
839   my ($self, $as_proto, $row) = @_;
840
841   my @copy = @$row;
842
843   # 'foo'         => [ undef, 'foo' ]
844   # 'foo.bar'     => [ 'foo', 'bar' ]
845   # 'foo.bar.baz' => [ 'foo.bar', 'baz' ]
846
847   my @construct_as = map { [ (/^(?:(.*)\.)?([^.]+)$/) ] } @$as_proto;
848
849   my %collapse = %{$self->{_attrs}{collapse}||{}};
850
851   my @pri_index;
852
853   # if we're doing collapsing (has_many prefetch) we need to grab records
854   # until the PK changes, so fill @pri_index. if not, we leave it empty so
855   # we know we don't have to bother.
856
857   # the reason for not using the collapse stuff directly is because if you
858   # had for e.g. two artists in a row with no cds, the collapse info for
859   # both would be NULL (undef) so you'd lose the second artist
860
861   # store just the index so we can check the array positions from the row
862   # without having to contruct the full hash
863
864   if (keys %collapse) {
865     my %pri = map { ($_ => 1) } $self->result_source->primary_columns;
866     foreach my $i (0 .. $#construct_as) {
867       next if defined($construct_as[$i][0]); # only self table
868       if (delete $pri{$construct_as[$i][1]}) {
869         push(@pri_index, $i);
870       }
871       last unless keys %pri; # short circuit (Johnny Five Is Alive!)
872     }
873   }
874
875   # no need to do an if, it'll be empty if @pri_index is empty anyway
876
877   my %pri_vals = map { ($_ => $copy[$_]) } @pri_index;
878
879   my @const_rows;
880
881   do { # no need to check anything at the front, we always want the first row
882
883     my %const;
884   
885     foreach my $this_as (@construct_as) {
886       $const{$this_as->[0]||''}{$this_as->[1]} = shift(@copy);
887     }
888
889     push(@const_rows, \%const);
890
891   } until ( # no pri_index => no collapse => drop straight out
892       !@pri_index
893     or
894       do { # get another row, stash it, drop out if different PK
895
896         @copy = $self->cursor->next;
897         $self->{stashed_row} = \@copy;
898
899         # last thing in do block, counts as true if anything doesn't match
900
901         # check xor defined first for NULL vs. NOT NULL then if one is
902         # defined the other must be so check string equality
903
904         grep {
905           (defined $pri_vals{$_} ^ defined $copy[$_])
906           || (defined $pri_vals{$_} && ($pri_vals{$_} ne $copy[$_]))
907         } @pri_index;
908       }
909   );
910
911   my $alias = $self->{attrs}{alias};
912   my $info = [];
913
914   my %collapse_pos;
915
916   my @const_keys;
917
918   foreach my $const (@const_rows) {
919     scalar @const_keys or do {
920       @const_keys = sort { length($a) <=> length($b) } keys %$const;
921     };
922     foreach my $key (@const_keys) {
923       if (length $key) {
924         my $target = $info;
925         my @parts = split(/\./, $key);
926         my $cur = '';
927         my $data = $const->{$key};
928         foreach my $p (@parts) {
929           $target = $target->[1]->{$p} ||= [];
930           $cur .= ".${p}";
931           if ($cur eq ".${key}" && (my @ckey = @{$collapse{$cur}||[]})) { 
932             # collapsing at this point and on final part
933             my $pos = $collapse_pos{$cur};
934             CK: foreach my $ck (@ckey) {
935               if (!defined $pos->{$ck} || $pos->{$ck} ne $data->{$ck}) {
936                 $collapse_pos{$cur} = $data;
937                 delete @collapse_pos{ # clear all positioning for sub-entries
938                   grep { m/^\Q${cur}.\E/ } keys %collapse_pos
939                 };
940                 push(@$target, []);
941                 last CK;
942               }
943             }
944           }
945           if (exists $collapse{$cur}) {
946             $target = $target->[-1];
947           }
948         }
949         $target->[0] = $data;
950       } else {
951         $info->[0] = $const->{$key};
952       }
953     }
954   }
955
956   return $info;
957 }
958
959 =head2 result_source
960
961 =over 4
962
963 =item Arguments: $result_source?
964
965 =item Return Value: $result_source
966
967 =back
968
969 An accessor for the primary ResultSource object from which this ResultSet
970 is derived.
971
972 =head2 result_class
973
974 =over 4
975
976 =item Arguments: $result_class?
977
978 =item Return Value: $result_class
979
980 =back
981
982 An accessor for the class to use when creating row objects. Defaults to 
983 C<< result_source->result_class >> - which in most cases is the name of the 
984 L<"table"|DBIx::Class::Manual::Glossary/"ResultSource"> class.
985
986 =cut
987
988
989 =head2 count
990
991 =over 4
992
993 =item Arguments: $cond, \%attrs??
994
995 =item Return Value: $count
996
997 =back
998
999 Performs an SQL C<COUNT> with the same query as the resultset was built
1000 with to find the number of elements. If passed arguments, does a search
1001 on the resultset and counts the results of that.
1002
1003 Note: When using C<count> with C<group_by>, L<DBIx::Class> emulates C<GROUP BY>
1004 using C<COUNT( DISTINCT( columns ) )>. Some databases (notably SQLite) do
1005 not support C<DISTINCT> with multiple columns. If you are using such a
1006 database, you should only use columns from the main table in your C<group_by>
1007 clause.
1008
1009 =cut
1010
1011 sub count {
1012   my $self = shift;
1013   return $self->search(@_)->count if @_ and defined $_[0];
1014   return scalar @{ $self->get_cache } if $self->get_cache;
1015   my $count = $self->_count;
1016   return 0 unless $count;
1017
1018   # need to take offset from resolved attrs
1019
1020   $count -= $self->{_attrs}{offset} if $self->{_attrs}{offset};
1021   $count = $self->{attrs}{rows} if
1022     $self->{attrs}{rows} and $self->{attrs}{rows} < $count;
1023   $count = 0 if ($count < 0);
1024   return $count;
1025 }
1026
1027 sub _count { # Separated out so pager can get the full count
1028   my $self = shift;
1029   my $select = { count => '*' };
1030
1031   my $attrs = { %{$self->_resolved_attrs} };
1032   if (my $group_by = delete $attrs->{group_by}) {
1033     delete $attrs->{having};
1034     my @distinct = (ref $group_by ?  @$group_by : ($group_by));
1035     # todo: try CONCAT for multi-column pk
1036     my @pk = $self->result_source->primary_columns;
1037     if (@pk == 1) {
1038       my $alias = $attrs->{alias};
1039       foreach my $column (@distinct) {
1040         if ($column =~ qr/^(?:\Q${alias}.\E)?$pk[0]$/) {
1041           @distinct = ($column);
1042           last;
1043         }
1044       }
1045     }
1046
1047     $select = { count => { distinct => \@distinct } };
1048   }
1049
1050   $attrs->{select} = $select;
1051   $attrs->{as} = [qw/count/];
1052
1053   # offset, order by and page are not needed to count. record_filter is cdbi
1054   delete $attrs->{$_} for qw/rows offset order_by page pager record_filter/;
1055
1056   my $tmp_rs = (ref $self)->new($self->result_source, $attrs);
1057   my ($count) = $tmp_rs->cursor->next;
1058   return $count;
1059 }
1060
1061 sub _bool {
1062   return 1;
1063 }
1064
1065 =head2 count_literal
1066
1067 =over 4
1068
1069 =item Arguments: $sql_fragment, @bind_values
1070
1071 =item Return Value: $count
1072
1073 =back
1074
1075 Counts the results in a literal query. Equivalent to calling L</search_literal>
1076 with the passed arguments, then L</count>.
1077
1078 =cut
1079
1080 sub count_literal { shift->search_literal(@_)->count; }
1081
1082 =head2 all
1083
1084 =over 4
1085
1086 =item Arguments: none
1087
1088 =item Return Value: @objects
1089
1090 =back
1091
1092 Returns all elements in the resultset. Called implicitly if the resultset
1093 is returned in list context.
1094
1095 =cut
1096
1097 sub all {
1098   my ($self) = @_;
1099   return @{ $self->get_cache } if $self->get_cache;
1100
1101   my @obj;
1102
1103   # TODO: don't call resolve here
1104   if (keys %{$self->_resolved_attrs->{collapse}}) {
1105 #  if ($self->{attrs}{prefetch}) {
1106       # Using $self->cursor->all is really just an optimisation.
1107       # If we're collapsing has_many prefetches it probably makes
1108       # very little difference, and this is cleaner than hacking
1109       # _construct_object to survive the approach
1110     my @row = $self->cursor->next;
1111     while (@row) {
1112       push(@obj, $self->_construct_object(@row));
1113       @row = (exists $self->{stashed_row}
1114                ? @{delete $self->{stashed_row}}
1115                : $self->cursor->next);
1116     }
1117   } else {
1118     @obj = map { $self->_construct_object(@$_) } $self->cursor->all;
1119   }
1120
1121   $self->set_cache(\@obj) if $self->{attrs}{cache};
1122   return @obj;
1123 }
1124
1125 =head2 reset
1126
1127 =over 4
1128
1129 =item Arguments: none
1130
1131 =item Return Value: $self
1132
1133 =back
1134
1135 Resets the resultset's cursor, so you can iterate through the elements again.
1136
1137 =cut
1138
1139 sub reset {
1140   my ($self) = @_;
1141   delete $self->{_attrs} if exists $self->{_attrs};
1142   $self->{all_cache_position} = 0;
1143   $self->cursor->reset;
1144   return $self;
1145 }
1146
1147 =head2 first
1148
1149 =over 4
1150
1151 =item Arguments: none
1152
1153 =item Return Value: $object?
1154
1155 =back
1156
1157 Resets the resultset and returns an object for the first result (if the
1158 resultset returns anything).
1159
1160 =cut
1161
1162 sub first {
1163   return $_[0]->reset->next;
1164 }
1165
1166 # _cond_for_update_delete
1167 #
1168 # update/delete require the condition to be modified to handle
1169 # the differing SQL syntax available.  This transforms the $self->{cond}
1170 # appropriately, returning the new condition.
1171
1172 sub _cond_for_update_delete {
1173   my ($self, $full_cond) = @_;
1174   my $cond = {};
1175
1176   $full_cond ||= $self->{cond};
1177   # No-op. No condition, we're updating/deleting everything
1178   return $cond unless ref $full_cond;
1179
1180   if (ref $full_cond eq 'ARRAY') {
1181     $cond = [
1182       map {
1183         my %hash;
1184         foreach my $key (keys %{$_}) {
1185           $key =~ /([^.]+)$/;
1186           $hash{$1} = $_->{$key};
1187         }
1188         \%hash;
1189       } @{$full_cond}
1190     ];
1191   }
1192   elsif (ref $full_cond eq 'HASH') {
1193     if ((keys %{$full_cond})[0] eq '-and') {
1194       $cond->{-and} = [];
1195
1196       my @cond = @{$full_cond->{-and}};
1197       for (my $i = 0; $i < @cond; $i++) {
1198         my $entry = $cond[$i];
1199
1200         my $hash;
1201         if (ref $entry eq 'HASH') {
1202           $hash = $self->_cond_for_update_delete($entry);
1203         }
1204         else {
1205           $entry =~ /([^.]+)$/;
1206           $hash->{$1} = $cond[++$i];
1207         }
1208
1209         push @{$cond->{-and}}, $hash;
1210       }
1211     }
1212     else {
1213       foreach my $key (keys %{$full_cond}) {
1214         $key =~ /([^.]+)$/;
1215         $cond->{$1} = $full_cond->{$key};
1216       }
1217     }
1218   }
1219   else {
1220     $self->throw_exception(
1221       "Can't update/delete on resultset with condition unless hash or array"
1222     );
1223   }
1224
1225   return $cond;
1226 }
1227
1228
1229 =head2 update
1230
1231 =over 4
1232
1233 =item Arguments: \%values
1234
1235 =item Return Value: $storage_rv
1236
1237 =back
1238
1239 Sets the specified columns in the resultset to the supplied values in a
1240 single query. Return value will be true if the update succeeded or false
1241 if no records were updated; exact type of success value is storage-dependent.
1242
1243 =cut
1244
1245 sub update {
1246   my ($self, $values) = @_;
1247   $self->throw_exception("Values for update must be a hash")
1248     unless ref $values eq 'HASH';
1249
1250   my $cond = $self->_cond_for_update_delete;
1251    
1252   return $self->result_source->storage->update(
1253     $self->result_source, $values, $cond
1254   );
1255 }
1256
1257 =head2 update_all
1258
1259 =over 4
1260
1261 =item Arguments: \%values
1262
1263 =item Return Value: 1
1264
1265 =back
1266
1267 Fetches all objects and updates them one at a time. Note that C<update_all>
1268 will run DBIC cascade triggers, while L</update> will not.
1269
1270 =cut
1271
1272 sub update_all {
1273   my ($self, $values) = @_;
1274   $self->throw_exception("Values for update must be a hash")
1275     unless ref $values eq 'HASH';
1276   foreach my $obj ($self->all) {
1277     $obj->set_columns($values)->update;
1278   }
1279   return 1;
1280 }
1281
1282 =head2 delete
1283
1284 =over 4
1285
1286 =item Arguments: none
1287
1288 =item Return Value: 1
1289
1290 =back
1291
1292 Deletes the contents of the resultset from its result source. Note that this
1293 will not run DBIC cascade triggers. See L</delete_all> if you need triggers
1294 to run. See also L<DBIx::Class::Row/delete>.
1295
1296 delete may not generate correct SQL for a query with joins or a resultset
1297 chained from a related resultset.  In this case it will generate a warning:-
1298
1299   WARNING! Currently $rs->delete() does not generate proper SQL on
1300   joined resultsets, and may delete rows well outside of the contents
1301   of $rs. Use at your own risk
1302
1303 In these cases you may find that delete_all is more appropriate, or you
1304 need to respecify your query in a way that can be expressed without a join.
1305
1306 =cut
1307
1308 sub delete {
1309   my ($self) = @_;
1310   $self->throw_exception("Delete should not be passed any arguments")
1311     if $_[1];
1312   carp(   'WARNING! Currently $rs->delete() does not generate proper SQL'
1313         . ' on joined resultsets, and may delete rows well outside of the'
1314         . ' contents of $rs. Use at your own risk' )
1315     if ( $self->{attrs}{seen_join} );
1316   my $cond = $self->_cond_for_update_delete;
1317
1318   $self->result_source->storage->delete($self->result_source, $cond);
1319   return 1;
1320 }
1321
1322 =head2 delete_all
1323
1324 =over 4
1325
1326 =item Arguments: none
1327
1328 =item Return Value: 1
1329
1330 =back
1331
1332 Fetches all objects and deletes them one at a time. Note that C<delete_all>
1333 will run DBIC cascade triggers, while L</delete> will not.
1334
1335 =cut
1336
1337 sub delete_all {
1338   my ($self) = @_;
1339   $_->delete for $self->all;
1340   return 1;
1341 }
1342
1343 =head2 populate
1344
1345 =over 4
1346
1347 =item Arguments: \@data;
1348
1349 =back
1350
1351 Pass an arrayref of hashrefs. Each hashref should be a structure suitable for
1352 submitting to a $resultset->create(...) method.
1353
1354 In void context, C<insert_bulk> in L<DBIx::Class::Storage::DBI> is used
1355 to insert the data, as this is a faster method.  
1356
1357 Otherwise, each set of data is inserted into the database using
1358 L<DBIx::Class::ResultSet/create>, and a arrayref of the resulting row
1359 objects is returned.
1360
1361 Example:  Assuming an Artist Class that has many CDs Classes relating:
1362
1363   my $Artist_rs = $schema->resultset("Artist");
1364   
1365   ## Void Context Example 
1366   $Artist_rs->populate([
1367      { artistid => 4, name => 'Manufactured Crap', cds => [ 
1368         { title => 'My First CD', year => 2006 },
1369         { title => 'Yet More Tweeny-Pop crap', year => 2007 },
1370       ],
1371      },
1372      { artistid => 5, name => 'Angsty-Whiny Girl', cds => [
1373         { title => 'My parents sold me to a record company' ,year => 2005 },
1374         { title => 'Why Am I So Ugly?', year => 2006 },
1375         { title => 'I Got Surgery and am now Popular', year => 2007 }
1376       ],
1377      },
1378   ]);
1379   
1380   ## Array Context Example
1381   my ($ArtistOne, $ArtistTwo, $ArtistThree) = $Artist_rs->populate([
1382     { name => "Artist One"},
1383     { name => "Artist Two"},
1384     { name => "Artist Three", cds=> [
1385     { title => "First CD", year => 2007},
1386     { title => "Second CD", year => 2008},
1387   ]}
1388   ]);
1389   
1390   print $ArtistOne->name; ## response is 'Artist One'
1391   print $ArtistThree->cds->count ## reponse is '2'
1392   
1393 Please note an important effect on your data when choosing between void and
1394 wantarray context. Since void context goes straight to C<insert_bulk> in 
1395 L<DBIx::Class::Storage::DBI> this will skip any component that is overriding
1396 c<insert>.  So if you are using something like L<DBIx-Class-UUIDColumns> to 
1397 create primary keys for you, you will find that your PKs are empty.  In this 
1398 case you will have to use the wantarray context in order to create those 
1399 values.
1400
1401 =cut
1402
1403 sub populate {
1404   my ($self, $data) = @_;
1405   
1406   if(defined wantarray) {
1407     my @created;
1408     foreach my $item (@$data) {
1409       push(@created, $self->create($item));
1410     }
1411     return @created;
1412   } else {
1413     my ($first, @rest) = @$data;
1414
1415     my @names = grep {!ref $first->{$_}} keys %$first;
1416     my @rels = grep { $self->result_source->has_relationship($_) } keys %$first;
1417     my @pks = $self->result_source->primary_columns;  
1418
1419     ## do the belongs_to relationships  
1420     foreach my $index (0..$#$data) {
1421       if( grep { !defined $data->[$index]->{$_} } @pks ) {
1422         my @ret = $self->populate($data);
1423         return;
1424       }
1425     
1426       foreach my $rel (@rels) {
1427         next unless $data->[$index]->{$rel} && ref $data->[$index]->{$rel} eq "HASH";
1428         my $result = $self->related_resultset($rel)->create($data->[$index]->{$rel});
1429         my ($reverse) = keys %{$self->result_source->reverse_relationship_info($rel)};
1430         my $related = $result->result_source->resolve_condition(
1431           $result->result_source->relationship_info($reverse)->{cond},
1432           $self,        
1433           $result,        
1434         );
1435
1436         delete $data->[$index]->{$rel};
1437         $data->[$index] = {%{$data->[$index]}, %$related};
1438       
1439         push @names, keys %$related if $index == 0;
1440       }
1441     }
1442
1443     ## do bulk insert on current row
1444     my @values = map { [ @$_{@names} ] } @$data;
1445
1446     $self->result_source->storage->insert_bulk(
1447       $self->result_source, 
1448       \@names, 
1449       \@values,
1450     );
1451
1452     ## do the has_many relationships
1453     foreach my $item (@$data) {
1454
1455       foreach my $rel (@rels) {
1456         next unless $item->{$rel} && ref $item->{$rel} eq "ARRAY";
1457
1458         my $parent = $self->find(map {{$_=>$item->{$_}} } @pks) 
1459      || $self->throw_exception('Cannot find the relating object.');
1460      
1461         my $child = $parent->$rel;
1462     
1463         my $related = $child->result_source->resolve_condition(
1464           $parent->result_source->relationship_info($rel)->{cond},
1465           $child,
1466           $parent,
1467         );
1468
1469         my @rows_to_add = ref $item->{$rel} eq 'ARRAY' ? @{$item->{$rel}} : ($item->{$rel});
1470         my @populate = map { {%$_, %$related} } @rows_to_add;
1471
1472         $child->populate( \@populate );
1473       }
1474     }
1475   }
1476 }
1477
1478 =head2 pager
1479
1480 =over 4
1481
1482 =item Arguments: none
1483
1484 =item Return Value: $pager
1485
1486 =back
1487
1488 Return Value a L<Data::Page> object for the current resultset. Only makes
1489 sense for queries with a C<page> attribute.
1490
1491 =cut
1492
1493 sub pager {
1494   my ($self) = @_;
1495   my $attrs = $self->{attrs};
1496   $self->throw_exception("Can't create pager for non-paged rs")
1497     unless $self->{attrs}{page};
1498   $attrs->{rows} ||= 10;
1499   return $self->{pager} ||= Data::Page->new(
1500     $self->_count, $attrs->{rows}, $self->{attrs}{page});
1501 }
1502
1503 =head2 page
1504
1505 =over 4
1506
1507 =item Arguments: $page_number
1508
1509 =item Return Value: $rs
1510
1511 =back
1512
1513 Returns a resultset for the $page_number page of the resultset on which page
1514 is called, where each page contains a number of rows equal to the 'rows'
1515 attribute set on the resultset (10 by default).
1516
1517 =cut
1518
1519 sub page {
1520   my ($self, $page) = @_;
1521   return (ref $self)->new($self->result_source, { %{$self->{attrs}}, page => $page });
1522 }
1523
1524 =head2 new_result
1525
1526 =over 4
1527
1528 =item Arguments: \%vals
1529
1530 =item Return Value: $rowobject
1531
1532 =back
1533
1534 Creates a new row object in the resultset's result class and returns
1535 it. The row is not inserted into the database at this point, call
1536 L<DBIx::Class::Row/insert> to do that. Calling L<DBIx::Class::Row/in_storage>
1537 will tell you whether the row object has been inserted or not.
1538
1539 Passes the hashref of input on to L<DBIx::Class::Row/new>.
1540
1541 =cut
1542
1543 sub new_result {
1544   my ($self, $values) = @_;
1545   $self->throw_exception( "new_result needs a hash" )
1546     unless (ref $values eq 'HASH');
1547
1548   my %new;
1549   my $alias = $self->{attrs}{alias};
1550
1551   if (
1552     defined $self->{cond}
1553     && $self->{cond} eq $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION
1554   ) {
1555     %new = %{$self->{attrs}{related_objects}};
1556   } else {
1557     $self->throw_exception(
1558       "Can't abstract implicit construct, condition not a hash"
1559     ) if ($self->{cond} && !(ref $self->{cond} eq 'HASH'));
1560   
1561     my $collapsed_cond = (
1562       $self->{cond}
1563         ? $self->_collapse_cond($self->{cond})
1564         : {}
1565     );
1566   
1567     # precendence must be given to passed values over values inherited from
1568     # the cond, so the order here is important.
1569     my %implied =  %{$self->_remove_alias($collapsed_cond, $alias)};
1570     while( my($col,$value) = each %implied ){
1571       if(ref($value) eq 'HASH' && keys(%$value) && (keys %$value)[0] eq '='){
1572         $new{$col} = $value->{'='};
1573         next;
1574       }
1575       $new{$col} = $value if $self->_is_deterministic_value($value);
1576     }
1577   }
1578
1579   %new = (
1580     %new,
1581     %{ $self->_remove_alias($values, $alias) },
1582     -source_handle => $self->_source_handle,
1583     -result_source => $self->result_source, # DO NOT REMOVE THIS, REQUIRED
1584   );
1585
1586   return $self->result_class->new(\%new);
1587 }
1588
1589 # _is_deterministic_value
1590 #
1591 # Make an effor to strip non-deterministic values from the condition, 
1592 # to make sure new_result chokes less
1593
1594 sub _is_deterministic_value {
1595   my $self = shift;
1596   my $value = shift;
1597   my $ref_type = ref $value;
1598   return 1 if $ref_type eq '' || $ref_type eq 'SCALAR';
1599   return 1 if Scalar::Util::blessed($value);
1600   return 0;
1601 }
1602
1603 # _collapse_cond
1604 #
1605 # Recursively collapse the condition.
1606
1607 sub _collapse_cond {
1608   my ($self, $cond, $collapsed) = @_;
1609
1610   $collapsed ||= {};
1611
1612   if (ref $cond eq 'ARRAY') {
1613     foreach my $subcond (@$cond) {
1614       next unless ref $subcond;  # -or
1615 #      warn "ARRAY: " . Dumper $subcond;
1616       $collapsed = $self->_collapse_cond($subcond, $collapsed);
1617     }
1618   }
1619   elsif (ref $cond eq 'HASH') {
1620     if (keys %$cond and (keys %$cond)[0] eq '-and') {
1621       foreach my $subcond (@{$cond->{-and}}) {
1622 #        warn "HASH: " . Dumper $subcond;
1623         $collapsed = $self->_collapse_cond($subcond, $collapsed);
1624       }
1625     }
1626     else {
1627 #      warn "LEAF: " . Dumper $cond;
1628       foreach my $col (keys %$cond) {
1629         my $value = $cond->{$col};
1630         $collapsed->{$col} = $value;
1631       }
1632     }
1633   }
1634
1635   return $collapsed;
1636 }
1637
1638 # _remove_alias
1639 #
1640 # Remove the specified alias from the specified query hash. A copy is made so
1641 # the original query is not modified.
1642
1643 sub _remove_alias {
1644   my ($self, $query, $alias) = @_;
1645
1646   my %orig = %{ $query || {} };
1647   my %unaliased;
1648
1649   foreach my $key (keys %orig) {
1650     if ($key !~ /\./) {
1651       $unaliased{$key} = $orig{$key};
1652       next;
1653     }
1654     $unaliased{$1} = $orig{$key}
1655       if $key =~ m/^(?:\Q$alias\E\.)?([^.]+)$/;
1656   }
1657
1658   return \%unaliased;
1659 }
1660
1661 =head2 find_or_new
1662
1663 =over 4
1664
1665 =item Arguments: \%vals, \%attrs?
1666
1667 =item Return Value: $rowobject
1668
1669 =back
1670
1671   my $artist = $schema->resultset('Artist')->find_or_new(
1672     { artist => 'fred' }, { key => 'artists' });
1673
1674   $cd->cd_to_producer->find_or_new({ producer => $producer },
1675                                    { key => 'primary });
1676
1677 Find an existing record from this resultset, based on it's primary
1678 key, or a unique constraint. If none exists, instantiate a new result
1679 object and return it. The object will not be saved into your storage
1680 until you call L<DBIx::Class::Row/insert> on it.
1681
1682 You most likely want this method when looking for existing rows using
1683 a unique constraint that is not the primary key, or looking for
1684 related rows.
1685
1686 If you want objects to be saved immediately, use L</find_or_create> instead.
1687
1688 B<Note>: C<find_or_new> is probably not what you want when creating a
1689 new row in a table that uses primary keys supplied by the
1690 database. Passing in a primary key column with a value of I<undef>
1691 will cause L</find> to attempt to search for a row with a value of
1692 I<NULL>.
1693
1694 =cut
1695
1696 sub find_or_new {
1697   my $self     = shift;
1698   my $attrs    = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
1699   my $hash     = ref $_[0] eq 'HASH' ? shift : {@_};
1700   my $exists   = $self->find($hash, $attrs);
1701   return defined $exists ? $exists : $self->new_result($hash);
1702 }
1703
1704 =head2 create
1705
1706 =over 4
1707
1708 =item Arguments: \%vals
1709
1710 =item Return Value: a L<DBIx::Class::Row> $object
1711
1712 =back
1713
1714 Attempt to create a single new row or a row with multiple related rows
1715 in the table represented by the resultset (and related tables). This
1716 will not check for duplicate rows before inserting, use
1717 L</find_or_create> to do that.
1718
1719 To create one row for this resultset, pass a hashref of key/value
1720 pairs representing the columns of the table and the values you wish to
1721 store. If the appropriate relationships are set up, foreign key fields
1722 can also be passed an object representing the foreign row, and the
1723 value will be set to it's primary key.
1724
1725 To create related objects, pass a hashref for the value if the related
1726 item is a foreign key relationship (L<DBIx::Class::Relationship/belongs_to>),
1727 and use the name of the relationship as the key. (NOT the name of the field,
1728 necessarily). For C<has_many> and C<has_one> relationships, pass an arrayref
1729 of hashrefs containing the data for each of the rows to create in the foreign
1730 tables, again using the relationship name as the key.
1731
1732 Instead of hashrefs of plain related data (key/value pairs), you may
1733 also pass new or inserted objects. New objects (not inserted yet, see
1734 L</new>), will be inserted into their appropriate tables.
1735
1736 Effectively a shortcut for C<< ->new_result(\%vals)->insert >>.
1737
1738 Example of creating a new row.
1739
1740   $person_rs->create({
1741     name=>"Some Person",
1742         email=>"somebody@someplace.com"
1743   });
1744   
1745 Example of creating a new row and also creating rows in a related C<has_many>
1746 or C<has_one> resultset.  Note Arrayref.
1747
1748   $artist_rs->create(
1749      { artistid => 4, name => 'Manufactured Crap', cds => [ 
1750         { title => 'My First CD', year => 2006 },
1751         { title => 'Yet More Tweeny-Pop crap', year => 2007 },
1752       ],
1753      },
1754   );
1755
1756 Example of creating a new row and also creating a row in a related
1757 C<belongs_to>resultset. Note Hashref.
1758
1759   $cd_rs->create({
1760     title=>"Music for Silly Walks",
1761         year=>2000,
1762         artist => {
1763           name=>"Silly Musician",
1764         }
1765   });
1766
1767 =cut
1768
1769 sub create {
1770   my ($self, $attrs) = @_;
1771   $self->throw_exception( "create needs a hashref" )
1772     unless ref $attrs eq 'HASH';
1773   return $self->new_result($attrs)->insert;
1774 }
1775
1776 =head2 find_or_create
1777
1778 =over 4
1779
1780 =item Arguments: \%vals, \%attrs?
1781
1782 =item Return Value: $rowobject
1783
1784 =back
1785
1786   $cd->cd_to_producer->find_or_create({ producer => $producer },
1787                                       { key => 'primary });
1788
1789 Tries to find a record based on its primary key or unique constraints; if none
1790 is found, creates one and returns that instead.
1791
1792   my $cd = $schema->resultset('CD')->find_or_create({
1793     cdid   => 5,
1794     artist => 'Massive Attack',
1795     title  => 'Mezzanine',
1796     year   => 2005,
1797   });
1798
1799 Also takes an optional C<key> attribute, to search by a specific key or unique
1800 constraint. For example:
1801
1802   my $cd = $schema->resultset('CD')->find_or_create(
1803     {
1804       artist => 'Massive Attack',
1805       title  => 'Mezzanine',
1806     },
1807     { key => 'cd_artist_title' }
1808   );
1809
1810 B<Note>: Because find_or_create() reads from the database and then
1811 possibly inserts based on the result, this method is subject to a race
1812 condition. Another process could create a record in the table after
1813 the find has completed and before the create has started. To avoid
1814 this problem, use find_or_create() inside a transaction.
1815
1816 B<Note>: C<find_or_create> is probably not what you want when creating
1817 a new row in a table that uses primary keys supplied by the
1818 database. Passing in a primary key column with a value of I<undef>
1819 will cause L</find> to attempt to search for a row with a value of
1820 I<NULL>.
1821
1822 See also L</find> and L</update_or_create>. For information on how to declare
1823 unique constraints, see L<DBIx::Class::ResultSource/add_unique_constraint>.
1824
1825 =cut
1826
1827 sub find_or_create {
1828   my $self     = shift;
1829   my $attrs    = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
1830   my $hash     = ref $_[0] eq 'HASH' ? shift : {@_};
1831   my $exists   = $self->find($hash, $attrs);
1832   return defined $exists ? $exists : $self->create($hash);
1833 }
1834
1835 =head2 update_or_create
1836
1837 =over 4
1838
1839 =item Arguments: \%col_values, { key => $unique_constraint }?
1840
1841 =item Return Value: $rowobject
1842
1843 =back
1844
1845   $resultset->update_or_create({ col => $val, ... });
1846
1847 First, searches for an existing row matching one of the unique constraints
1848 (including the primary key) on the source of this resultset. If a row is
1849 found, updates it with the other given column values. Otherwise, creates a new
1850 row.
1851
1852 Takes an optional C<key> attribute to search on a specific unique constraint.
1853 For example:
1854
1855   # In your application
1856   my $cd = $schema->resultset('CD')->update_or_create(
1857     {
1858       artist => 'Massive Attack',
1859       title  => 'Mezzanine',
1860       year   => 1998,
1861     },
1862     { key => 'cd_artist_title' }
1863   );
1864
1865   $cd->cd_to_producer->update_or_create({ 
1866     producer => $producer, 
1867     name => 'harry',
1868   }, { 
1869     key => 'primary,
1870   });
1871
1872
1873 If no C<key> is specified, it searches on all unique constraints defined on the
1874 source, including the primary key.
1875
1876 If the C<key> is specified as C<primary>, it searches only on the primary key.
1877
1878 See also L</find> and L</find_or_create>. For information on how to declare
1879 unique constraints, see L<DBIx::Class::ResultSource/add_unique_constraint>.
1880
1881 B<Note>: C<update_or_create> is probably not what you want when
1882 looking for a row in a table that uses primary keys supplied by the
1883 database, unless you actually have a key value. Passing in a primary
1884 key column with a value of I<undef> will cause L</find> to attempt to
1885 search for a row with a value of I<NULL>.
1886
1887 =cut
1888
1889 sub update_or_create {
1890   my $self = shift;
1891   my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
1892   my $cond = ref $_[0] eq 'HASH' ? shift : {@_};
1893
1894   my $row = $self->find($cond, $attrs);
1895   if (defined $row) {
1896     $row->update($cond);
1897     return $row;
1898   }
1899
1900   return $self->create($cond);
1901 }
1902
1903 =head2 get_cache
1904
1905 =over 4
1906
1907 =item Arguments: none
1908
1909 =item Return Value: \@cache_objects?
1910
1911 =back
1912
1913 Gets the contents of the cache for the resultset, if the cache is set.
1914
1915 The cache is populated either by using the L</prefetch> attribute to
1916 L</search> or by calling L</set_cache>.
1917
1918 =cut
1919
1920 sub get_cache {
1921   shift->{all_cache};
1922 }
1923
1924 =head2 set_cache
1925
1926 =over 4
1927
1928 =item Arguments: \@cache_objects
1929
1930 =item Return Value: \@cache_objects
1931
1932 =back
1933
1934 Sets the contents of the cache for the resultset. Expects an arrayref
1935 of objects of the same class as those produced by the resultset. Note that
1936 if the cache is set the resultset will return the cached objects rather
1937 than re-querying the database even if the cache attr is not set.
1938
1939 The contents of the cache can also be populated by using the
1940 L</prefetch> attribute to L</search>.
1941
1942 =cut
1943
1944 sub set_cache {
1945   my ( $self, $data ) = @_;
1946   $self->throw_exception("set_cache requires an arrayref")
1947       if defined($data) && (ref $data ne 'ARRAY');
1948   $self->{all_cache} = $data;
1949 }
1950
1951 =head2 clear_cache
1952
1953 =over 4
1954
1955 =item Arguments: none
1956
1957 =item Return Value: []
1958
1959 =back
1960
1961 Clears the cache for the resultset.
1962
1963 =cut
1964
1965 sub clear_cache {
1966   shift->set_cache(undef);
1967 }
1968
1969 =head2 related_resultset
1970
1971 =over 4
1972
1973 =item Arguments: $relationship_name
1974
1975 =item Return Value: $resultset
1976
1977 =back
1978
1979 Returns a related resultset for the supplied relationship name.
1980
1981   $artist_rs = $schema->resultset('CD')->related_resultset('Artist');
1982
1983 =cut
1984
1985 sub related_resultset {
1986   my ($self, $rel) = @_;
1987
1988   $self->{related_resultsets} ||= {};
1989   return $self->{related_resultsets}{$rel} ||= do {
1990     my $rel_obj = $self->result_source->relationship_info($rel);
1991
1992     $self->throw_exception(
1993       "search_related: result source '" . $self->result_source->source_name .
1994         "' has no such relationship $rel")
1995       unless $rel_obj;
1996     
1997     my ($from,$seen) = $self->_resolve_from($rel);
1998
1999     my $join_count = $seen->{$rel};
2000     my $alias = ($join_count > 1 ? join('_', $rel, $join_count) : $rel);
2001
2002     #XXX - temp fix for result_class bug. There likely is a more elegant fix -groditi
2003     my %attrs = %{$self->{attrs}||{}};
2004     delete @attrs{qw(result_class alias)};
2005
2006     my $new_cache;
2007
2008     if (my $cache = $self->get_cache) {
2009       if ($cache->[0] && $cache->[0]->related_resultset($rel)->get_cache) {
2010         $new_cache = [ map { @{$_->related_resultset($rel)->get_cache} }
2011                         @$cache ];
2012       }
2013     }
2014
2015     my $rel_source = $self->result_source->related_source($rel);
2016
2017     my $new = do {
2018
2019       # The reason we do this now instead of passing the alias to the
2020       # search_rs below is that if you wrap/overload resultset on the
2021       # source you need to know what alias it's -going- to have for things
2022       # to work sanely (e.g. RestrictWithObject wants to be able to add
2023       # extra query restrictions, and these may need to be $alias.)
2024
2025       my $attrs = $rel_source->resultset_attributes;
2026       local $attrs->{alias} = $alias;
2027
2028       $rel_source->resultset
2029                  ->search_rs(
2030                      undef, {
2031                        %attrs,
2032                        join => undef,
2033                        prefetch => undef,
2034                        select => undef,
2035                        as => undef,
2036                        where => $self->{cond},
2037                        seen_join => $seen,
2038                        from => $from,
2039                    });
2040     };
2041     $new->set_cache($new_cache) if $new_cache;
2042     $new;
2043   };
2044 }
2045
2046 sub _resolve_from {
2047   my ($self, $extra_join) = @_;
2048   my $source = $self->result_source;
2049   my $attrs = $self->{attrs};
2050   
2051   my $from = $attrs->{from}
2052     || [ { $attrs->{alias} => $source->from } ];
2053     
2054   my $seen = { %{$attrs->{seen_join}||{}} };
2055
2056   my $join = ($attrs->{join}
2057                ? [ $attrs->{join}, $extra_join ]
2058                : $extra_join);
2059
2060   # we need to take the prefetch the attrs into account before we 
2061   # ->resolve_join as otherwise they get lost - captainL
2062   my $merged = $self->_merge_attr( $join, $attrs->{prefetch} );
2063
2064   $from = [
2065     @$from,
2066     ($join ? $source->resolve_join($merged, $attrs->{alias}, $seen) : ()),
2067   ];
2068
2069   return ($from,$seen);
2070 }
2071
2072 sub _resolved_attrs {
2073     my $self = shift;
2074     return $self->{_attrs} if $self->{_attrs};
2075
2076     my $attrs  = { %{ $self->{attrs} || {} } };
2077     my $source = $self->result_source;
2078     my $alias  = $attrs->{alias};
2079
2080     $attrs->{columns} ||= delete $attrs->{cols} if exists $attrs->{cols};
2081     $attrs->{columns} ||= [ $source->columns ] unless ( $attrs->{select} );
2082     if ( $attrs->{columns} ) {
2083
2084         # if columns is set we overwrite select & as
2085         $attrs->{select} = [];
2086         $attrs->{as}     = [];
2087         foreach my $colbit ( @{ $attrs->{columns} } ) {
2088             if ( ref($_) eq 'HASH' ) {
2089                 push(
2090                     @{ $attrs->{select} },
2091                     map { ref($_) ? $_ : m/\./ ? $_ : "${alias}.$_" }
2092                       values( %{$colbit} )
2093                 );
2094                 push(
2095                     @{ $attrs->{as} },
2096                     map { m/^\Q${alias}.\E(.+)$/ ? $1 : $_ } keys( %{$colbit} )
2097                 );
2098             }
2099             else {
2100                 push(
2101                     @{ $attrs->{select} },
2102                     ( $colbit =~ m/\./ ) ? $colbit : "${alias}.${colbit}"
2103                 );
2104                 push(
2105                     @{ $attrs->{as} },
2106                     ( $colbit =~ m/^\Q${alias}.\E(.+)$/ ) ? $1 : $colbit
2107                 );
2108             }
2109         }
2110         delete $attrs->{columns};
2111     }
2112     else {
2113         $attrs->{select} =
2114             ( ref $attrs->{select} eq 'ARRAY' )
2115           ? [ @{ $attrs->{select} } ]
2116           : [ $attrs->{select} ];
2117         $attrs->{as} = (
2118             $attrs->{as}
2119             ? (
2120                 ref $attrs->{as} eq 'ARRAY'
2121                 ? [ @{ $attrs->{as} } ]
2122                 : [ $attrs->{as} ]
2123               )
2124             : [
2125                 map { m/^\Q${alias}.\E(.+)$/ ? $1 : $_ } @{ $attrs->{select} }
2126             ]
2127         );
2128     }
2129     my $adds;
2130     if ( $adds = delete $attrs->{include_columns} ) {
2131         $adds = [$adds] unless ref $adds eq 'ARRAY';
2132         push( @{ $attrs->{select} }, @$adds );
2133         push( @{ $attrs->{as} }, map { m/([^.]+)$/; $1 } @$adds );
2134     }
2135     if ( $adds = delete $attrs->{'+columns'} ) {
2136         $adds = [$adds] unless ref $adds eq 'ARRAY';
2137         push(
2138             @{ $attrs->{select} },
2139             map { ref($_) eq 'HASH' ? values( %{$_} ) : $_ } @$adds
2140         );
2141         push(
2142             @{ $attrs->{as} },
2143             map { ref($_) eq 'HASH' ? keys( %{$_} ) : $_ } @$adds
2144         );
2145     }
2146     if ( $adds = delete $attrs->{'+select'} ) {
2147         $adds = [$adds] unless ref $adds eq 'ARRAY';
2148         push(
2149             @{ $attrs->{select} },
2150             map { /\./ || ref $_ ? $_ : "${alias}.$_" } @$adds
2151         );
2152     }
2153     if ( $adds = delete $attrs->{'+as'} ) {
2154         $adds = [$adds] unless ref $adds eq 'ARRAY';
2155         push( @{ $attrs->{as} }, @$adds );
2156     }
2157
2158     $attrs->{from} ||= [ { 'me' => $source->from } ];
2159
2160     if ( exists $attrs->{join} || exists $attrs->{prefetch} ) {
2161         my $join = delete $attrs->{join} || {};
2162
2163         if ( defined $attrs->{prefetch} ) {
2164             $join = $self->_merge_attr( $join, $attrs->{prefetch} );
2165
2166         }
2167
2168         $attrs->{from} =    # have to copy here to avoid corrupting the original
2169           [
2170             @{ $attrs->{from} },
2171             $source->resolve_join(
2172                 $join, $alias, { %{ $attrs->{seen_join} || {} } }
2173             )
2174           ];
2175
2176     }
2177
2178     $attrs->{group_by} ||= $attrs->{select} if delete $attrs->{distinct};
2179     if ( $attrs->{order_by} ) {
2180         $attrs->{order_by} = (
2181             ref( $attrs->{order_by} ) eq 'ARRAY'
2182             ? [ @{ $attrs->{order_by} } ]
2183             : [ $attrs->{order_by} ]
2184         );
2185     }
2186     else {
2187         $attrs->{order_by} = [];
2188     }
2189
2190     my $collapse = $attrs->{collapse} || {};
2191     if ( my $prefetch = delete $attrs->{prefetch} ) {
2192         $prefetch = $self->_merge_attr( {}, $prefetch );
2193         my @pre_order;
2194         my $seen = $attrs->{seen_join} || {};
2195         foreach my $p ( ref $prefetch eq 'ARRAY' ? @$prefetch : ($prefetch) ) {
2196
2197             # bring joins back to level of current class
2198             my @prefetch =
2199               $source->resolve_prefetch( $p, $alias, $seen, \@pre_order,
2200                 $collapse );
2201             push( @{ $attrs->{select} }, map { $_->[0] } @prefetch );
2202             push( @{ $attrs->{as} },     map { $_->[1] } @prefetch );
2203         }
2204         push( @{ $attrs->{order_by} }, @pre_order );
2205     }
2206     $attrs->{collapse} = $collapse;
2207
2208     if ( $attrs->{page} ) {
2209         $attrs->{offset} ||= 0;
2210         $attrs->{offset} += ( $attrs->{rows} * ( $attrs->{page} - 1 ) );
2211     }
2212
2213     return $self->{_attrs} = $attrs;
2214 }
2215
2216 sub _rollout_attr {
2217   my ($self, $attr) = @_;
2218   
2219   if (ref $attr eq 'HASH') {
2220     return $self->_rollout_hash($attr);
2221   } elsif (ref $attr eq 'ARRAY') {
2222     return $self->_rollout_array($attr);
2223   } else {
2224     return [$attr];
2225   }
2226 }
2227
2228 sub _rollout_array {
2229   my ($self, $attr) = @_;
2230
2231   my @rolled_array;
2232   foreach my $element (@{$attr}) {
2233     if (ref $element eq 'HASH') {
2234       push( @rolled_array, @{ $self->_rollout_hash( $element ) } );
2235     } elsif (ref $element eq 'ARRAY') {
2236       #  XXX - should probably recurse here
2237       push( @rolled_array, @{$self->_rollout_array($element)} );
2238     } else {
2239       push( @rolled_array, $element );
2240     }
2241   }
2242   return \@rolled_array;
2243 }
2244
2245 sub _rollout_hash {
2246   my ($self, $attr) = @_;
2247
2248   my @rolled_array;
2249   foreach my $key (keys %{$attr}) {
2250     push( @rolled_array, { $key => $attr->{$key} } );
2251   }
2252   return \@rolled_array;
2253 }
2254
2255 sub _calculate_score {
2256   my ($self, $a, $b) = @_;
2257
2258   if (ref $b eq 'HASH') {
2259     my ($b_key) = keys %{$b};
2260     if (ref $a eq 'HASH') {
2261       my ($a_key) = keys %{$a};
2262       if ($a_key eq $b_key) {
2263         return (1 + $self->_calculate_score( $a->{$a_key}, $b->{$b_key} ));
2264       } else {
2265         return 0;
2266       }
2267     } else {
2268       return ($a eq $b_key) ? 1 : 0;
2269     }       
2270   } else {
2271     if (ref $a eq 'HASH') {
2272       my ($a_key) = keys %{$a};
2273       return ($b eq $a_key) ? 1 : 0;
2274     } else {
2275       return ($b eq $a) ? 1 : 0;
2276     }
2277   }
2278 }
2279
2280 sub _merge_attr {
2281   my ($self, $orig, $import) = @_;
2282
2283   return $import unless defined($orig);
2284   return $orig unless defined($import);
2285   
2286   $orig = $self->_rollout_attr($orig);
2287   $import = $self->_rollout_attr($import);
2288
2289   my $seen_keys;
2290   foreach my $import_element ( @{$import} ) {
2291     # find best candidate from $orig to merge $b_element into
2292     my $best_candidate = { position => undef, score => 0 }; my $position = 0;
2293     foreach my $orig_element ( @{$orig} ) {
2294       my $score = $self->_calculate_score( $orig_element, $import_element );
2295       if ($score > $best_candidate->{score}) {
2296         $best_candidate->{position} = $position;
2297         $best_candidate->{score} = $score;
2298       }
2299       $position++;
2300     }
2301     my ($import_key) = ( ref $import_element eq 'HASH' ) ? keys %{$import_element} : ($import_element);
2302
2303     if ($best_candidate->{score} == 0 || exists $seen_keys->{$import_key}) {
2304       push( @{$orig}, $import_element );
2305     } else {
2306       my $orig_best = $orig->[$best_candidate->{position}];
2307       # merge orig_best and b_element together and replace original with merged
2308       if (ref $orig_best ne 'HASH') {
2309         $orig->[$best_candidate->{position}] = $import_element;
2310       } elsif (ref $import_element eq 'HASH') {
2311         my ($key) = keys %{$orig_best};
2312         $orig->[$best_candidate->{position}] = { $key => $self->_merge_attr($orig_best->{$key}, $import_element->{$key}) };
2313       }
2314     }
2315     $seen_keys->{$import_key} = 1; # don't merge the same key twice
2316   }
2317
2318   return $orig;
2319 }
2320
2321 sub result_source {
2322     my $self = shift;
2323
2324     if (@_) {
2325         $self->_source_handle($_[0]->handle);
2326     } else {
2327         $self->_source_handle->resolve;
2328     }
2329 }
2330
2331 =head2 throw_exception
2332
2333 See L<DBIx::Class::Schema/throw_exception> for details.
2334
2335 =cut
2336
2337 sub throw_exception {
2338   my $self=shift;
2339   if (ref $self && $self->_source_handle->schema) {
2340     $self->_source_handle->schema->throw_exception(@_)
2341   } else {
2342     croak(@_);
2343   }
2344
2345 }
2346
2347 # XXX: FIXME: Attributes docs need clearing up
2348
2349 =head1 ATTRIBUTES
2350
2351 The resultset takes various attributes that modify its behavior. Here's an
2352 overview of them:
2353
2354 =head2 order_by
2355
2356 =over 4
2357
2358 =item Value: ($order_by | \@order_by)
2359
2360 =back
2361
2362 Which column(s) to order the results by. This is currently passed
2363 through directly to SQL, so you can give e.g. C<year DESC> for a
2364 descending order on the column `year'.
2365
2366 Please note that if you have C<quote_char> enabled (see
2367 L<DBIx::Class::Storage::DBI/connect_info>) you will need to do C<\'year DESC' > to
2368 specify an order. (The scalar ref causes it to be passed as raw sql to the DB,
2369 so you will need to manually quote things as appropriate.)
2370
2371 =head2 columns
2372
2373 =over 4
2374
2375 =item Value: \@columns
2376
2377 =back
2378
2379 Shortcut to request a particular set of columns to be retrieved.  Adds
2380 C<me.> onto the start of any column without a C<.> in it and sets C<select>
2381 from that, then auto-populates C<as> from C<select> as normal. (You may also
2382 use the C<cols> attribute, as in earlier versions of DBIC.)
2383
2384 =head2 include_columns
2385
2386 =over 4
2387
2388 =item Value: \@columns
2389
2390 =back
2391
2392 Shortcut to include additional columns in the returned results - for example
2393
2394   $schema->resultset('CD')->search(undef, {
2395     include_columns => ['artist.name'],
2396     join => ['artist']
2397   });
2398
2399 would return all CDs and include a 'name' column to the information
2400 passed to object inflation. Note that the 'artist' is the name of the
2401 column (or relationship) accessor, and 'name' is the name of the column
2402 accessor in the related table.
2403
2404 =head2 select
2405
2406 =over 4
2407
2408 =item Value: \@select_columns
2409
2410 =back
2411
2412 Indicates which columns should be selected from the storage. You can use
2413 column names, or in the case of RDBMS back ends, function or stored procedure
2414 names:
2415
2416   $rs = $schema->resultset('Employee')->search(undef, {
2417     select => [
2418       'name',
2419       { count => 'employeeid' },
2420       { sum => 'salary' }
2421     ]
2422   });
2423
2424 When you use function/stored procedure names and do not supply an C<as>
2425 attribute, the column names returned are storage-dependent. E.g. MySQL would
2426 return a column named C<count(employeeid)> in the above example.
2427
2428 =head2 +select
2429
2430 =over 4
2431
2432 Indicates additional columns to be selected from storage.  Works the same as
2433 L</select> but adds columns to the selection.
2434
2435 =back
2436
2437 =head2 +as
2438
2439 =over 4
2440
2441 Indicates additional column names for those added via L</+select>.
2442
2443 =back
2444
2445 =head2 as
2446
2447 =over 4
2448
2449 =item Value: \@inflation_names
2450
2451 =back
2452
2453 Indicates column names for object inflation. That is, C<as>
2454 indicates the name that the column can be accessed as via the
2455 C<get_column> method (or via the object accessor, B<if one already
2456 exists>).  It has nothing to do with the SQL code C<SELECT foo AS bar>.
2457
2458 The C<as> attribute is used in conjunction with C<select>,
2459 usually when C<select> contains one or more function or stored
2460 procedure names:
2461
2462   $rs = $schema->resultset('Employee')->search(undef, {
2463     select => [
2464       'name',
2465       { count => 'employeeid' }
2466     ],
2467     as => ['name', 'employee_count'],
2468   });
2469
2470   my $employee = $rs->first(); # get the first Employee
2471
2472 If the object against which the search is performed already has an accessor
2473 matching a column name specified in C<as>, the value can be retrieved using
2474 the accessor as normal:
2475
2476   my $name = $employee->name();
2477
2478 If on the other hand an accessor does not exist in the object, you need to
2479 use C<get_column> instead:
2480
2481   my $employee_count = $employee->get_column('employee_count');
2482
2483 You can create your own accessors if required - see
2484 L<DBIx::Class::Manual::Cookbook> for details.
2485
2486 Please note: This will NOT insert an C<AS employee_count> into the SQL
2487 statement produced, it is used for internal access only. Thus
2488 attempting to use the accessor in an C<order_by> clause or similar
2489 will fail miserably.
2490
2491 To get around this limitation, you can supply literal SQL to your
2492 C<select> attibute that contains the C<AS alias> text, eg:
2493
2494   select => [\'myfield AS alias']
2495
2496 =head2 join
2497
2498 =over 4
2499
2500 =item Value: ($rel_name | \@rel_names | \%rel_names)
2501
2502 =back
2503
2504 Contains a list of relationships that should be joined for this query.  For
2505 example:
2506
2507   # Get CDs by Nine Inch Nails
2508   my $rs = $schema->resultset('CD')->search(
2509     { 'artist.name' => 'Nine Inch Nails' },
2510     { join => 'artist' }
2511   );
2512
2513 Can also contain a hash reference to refer to the other relation's relations.
2514 For example:
2515
2516   package MyApp::Schema::Track;
2517   use base qw/DBIx::Class/;
2518   __PACKAGE__->table('track');
2519   __PACKAGE__->add_columns(qw/trackid cd position title/);
2520   __PACKAGE__->set_primary_key('trackid');
2521   __PACKAGE__->belongs_to(cd => 'MyApp::Schema::CD');
2522   1;
2523
2524   # In your application
2525   my $rs = $schema->resultset('Artist')->search(
2526     { 'track.title' => 'Teardrop' },
2527     {
2528       join     => { cd => 'track' },
2529       order_by => 'artist.name',
2530     }
2531   );
2532
2533 You need to use the relationship (not the table) name in  conditions, 
2534 because they are aliased as such. The current table is aliased as "me", so 
2535 you need to use me.column_name in order to avoid ambiguity. For example:
2536
2537   # Get CDs from 1984 with a 'Foo' track 
2538   my $rs = $schema->resultset('CD')->search(
2539     { 
2540       'me.year' => 1984,
2541       'tracks.name' => 'Foo'
2542     },
2543     { join => 'tracks' }
2544   );
2545   
2546 If the same join is supplied twice, it will be aliased to <rel>_2 (and
2547 similarly for a third time). For e.g.
2548
2549   my $rs = $schema->resultset('Artist')->search({
2550     'cds.title'   => 'Down to Earth',
2551     'cds_2.title' => 'Popular',
2552   }, {
2553     join => [ qw/cds cds/ ],
2554   });
2555
2556 will return a set of all artists that have both a cd with title 'Down
2557 to Earth' and a cd with title 'Popular'.
2558
2559 If you want to fetch related objects from other tables as well, see C<prefetch>
2560 below.
2561
2562 For more help on using joins with search, see L<DBIx::Class::Manual::Joining>.
2563
2564 =head2 prefetch
2565
2566 =over 4
2567
2568 =item Value: ($rel_name | \@rel_names | \%rel_names)
2569
2570 =back
2571
2572 Contains one or more relationships that should be fetched along with
2573 the main query (when they are accessed afterwards the data will
2574 already be available, without extra queries to the database).  This is
2575 useful for when you know you will need the related objects, because it
2576 saves at least one query:
2577
2578   my $rs = $schema->resultset('Tag')->search(
2579     undef,
2580     {
2581       prefetch => {
2582         cd => 'artist'
2583       }
2584     }
2585   );
2586
2587 The initial search results in SQL like the following:
2588
2589   SELECT tag.*, cd.*, artist.* FROM tag
2590   JOIN cd ON tag.cd = cd.cdid
2591   JOIN artist ON cd.artist = artist.artistid
2592
2593 L<DBIx::Class> has no need to go back to the database when we access the
2594 C<cd> or C<artist> relationships, which saves us two SQL statements in this
2595 case.
2596
2597 Simple prefetches will be joined automatically, so there is no need
2598 for a C<join> attribute in the above search. 
2599
2600 C<prefetch> can be used with the following relationship types: C<belongs_to>,
2601 C<has_one> (or if you're using C<add_relationship>, any relationship declared
2602 with an accessor type of 'single' or 'filter'). A more complex example that
2603 prefetches an artists cds, the tracks on those cds, and the tags associted 
2604 with that artist is given below (assuming many-to-many from artists to tags):
2605
2606  my $rs = $schema->resultset('Artist')->search(
2607    undef,
2608    {
2609      prefetch => [
2610        { cds => 'tracks' },
2611        { artist_tags => 'tags' }
2612      ]
2613    }
2614  );
2615  
2616
2617 B<NOTE:> If you specify a C<prefetch> attribute, the C<join> and C<select>
2618 attributes will be ignored.
2619
2620 =head2 page
2621
2622 =over 4
2623
2624 =item Value: $page
2625
2626 =back
2627
2628 Makes the resultset paged and specifies the page to retrieve. Effectively
2629 identical to creating a non-pages resultset and then calling ->page($page)
2630 on it.
2631
2632 If L<rows> attribute is not specified it defualts to 10 rows per page.
2633
2634 =head2 rows
2635
2636 =over 4
2637
2638 =item Value: $rows
2639
2640 =back
2641
2642 Specifes the maximum number of rows for direct retrieval or the number of
2643 rows per page if the page attribute or method is used.
2644
2645 =head2 offset
2646
2647 =over 4
2648
2649 =item Value: $offset
2650
2651 =back
2652
2653 Specifies the (zero-based) row number for the  first row to be returned, or the
2654 of the first row of the first page if paging is used.
2655
2656 =head2 group_by
2657
2658 =over 4
2659
2660 =item Value: \@columns
2661
2662 =back
2663
2664 A arrayref of columns to group by. Can include columns of joined tables.
2665
2666   group_by => [qw/ column1 column2 ... /]
2667
2668 =head2 having
2669
2670 =over 4
2671
2672 =item Value: $condition
2673
2674 =back
2675
2676 HAVING is a select statement attribute that is applied between GROUP BY and
2677 ORDER BY. It is applied to the after the grouping calculations have been
2678 done.
2679
2680   having => { 'count(employee)' => { '>=', 100 } }
2681
2682 =head2 distinct
2683
2684 =over 4
2685
2686 =item Value: (0 | 1)
2687
2688 =back
2689
2690 Set to 1 to group by all columns.
2691
2692 =head2 where
2693
2694 =over 4
2695
2696 Adds to the WHERE clause.
2697
2698   # only return rows WHERE deleted IS NULL for all searches
2699   __PACKAGE__->resultset_attributes({ where => { deleted => undef } }); )
2700
2701 Can be overridden by passing C<{ where => undef }> as an attribute
2702 to a resulset.
2703
2704 =back
2705
2706 =head2 cache
2707
2708 Set to 1 to cache search results. This prevents extra SQL queries if you
2709 revisit rows in your ResultSet:
2710
2711   my $resultset = $schema->resultset('Artist')->search( undef, { cache => 1 } );
2712
2713   while( my $artist = $resultset->next ) {
2714     ... do stuff ...
2715   }
2716
2717   $rs->first; # without cache, this would issue a query
2718
2719 By default, searches are not cached.
2720
2721 For more examples of using these attributes, see
2722 L<DBIx::Class::Manual::Cookbook>.
2723
2724 =head2 from
2725
2726 =over 4
2727
2728 =item Value: \@from_clause
2729
2730 =back
2731
2732 The C<from> attribute gives you manual control over the C<FROM> clause of SQL
2733 statements generated by L<DBIx::Class>, allowing you to express custom C<JOIN>
2734 clauses.
2735
2736 NOTE: Use this on your own risk.  This allows you to shoot off your foot!
2737
2738 C<join> will usually do what you need and it is strongly recommended that you
2739 avoid using C<from> unless you cannot achieve the desired result using C<join>.
2740 And we really do mean "cannot", not just tried and failed. Attempting to use
2741 this because you're having problems with C<join> is like trying to use x86
2742 ASM because you've got a syntax error in your C. Trust us on this.
2743
2744 Now, if you're still really, really sure you need to use this (and if you're
2745 not 100% sure, ask the mailing list first), here's an explanation of how this
2746 works.
2747
2748 The syntax is as follows -
2749
2750   [
2751     { <alias1> => <table1> },
2752     [
2753       { <alias2> => <table2>, -join_type => 'inner|left|right' },
2754       [], # nested JOIN (optional)
2755       { <table1.column1> => <table2.column2>, ... (more conditions) },
2756     ],
2757     # More of the above [ ] may follow for additional joins
2758   ]
2759
2760   <table1> <alias1>
2761   JOIN
2762     <table2> <alias2>
2763     [JOIN ...]
2764   ON <table1.column1> = <table2.column2>
2765   <more joins may follow>
2766
2767 An easy way to follow the examples below is to remember the following:
2768
2769     Anything inside "[]" is a JOIN
2770     Anything inside "{}" is a condition for the enclosing JOIN
2771
2772 The following examples utilize a "person" table in a family tree application.
2773 In order to express parent->child relationships, this table is self-joined:
2774
2775     # Person->belongs_to('father' => 'Person');
2776     # Person->belongs_to('mother' => 'Person');
2777
2778 C<from> can be used to nest joins. Here we return all children with a father,
2779 then search against all mothers of those children:
2780
2781   $rs = $schema->resultset('Person')->search(
2782       undef,
2783       {
2784           alias => 'mother', # alias columns in accordance with "from"
2785           from => [
2786               { mother => 'person' },
2787               [
2788                   [
2789                       { child => 'person' },
2790                       [
2791                           { father => 'person' },
2792                           { 'father.person_id' => 'child.father_id' }
2793                       ]
2794                   ],
2795                   { 'mother.person_id' => 'child.mother_id' }
2796               ],
2797           ]
2798       },
2799   );
2800
2801   # Equivalent SQL:
2802   # SELECT mother.* FROM person mother
2803   # JOIN (
2804   #   person child
2805   #   JOIN person father
2806   #   ON ( father.person_id = child.father_id )
2807   # )
2808   # ON ( mother.person_id = child.mother_id )
2809
2810 The type of any join can be controlled manually. To search against only people
2811 with a father in the person table, we could explicitly use C<INNER JOIN>:
2812
2813     $rs = $schema->resultset('Person')->search(
2814         undef,
2815         {
2816             alias => 'child', # alias columns in accordance with "from"
2817             from => [
2818                 { child => 'person' },
2819                 [
2820                     { father => 'person', -join_type => 'inner' },
2821                     { 'father.id' => 'child.father_id' }
2822                 ],
2823             ]
2824         },
2825     );
2826
2827     # Equivalent SQL:
2828     # SELECT child.* FROM person child
2829     # INNER JOIN person father ON child.father_id = father.id
2830
2831 =head2 for
2832
2833 =over 4
2834
2835 =item Value: ( 'update' | 'shared' )
2836
2837 =back
2838
2839 Set to 'update' for a SELECT ... FOR UPDATE or 'shared' for a SELECT
2840 ... FOR SHARED.
2841
2842 =cut
2843
2844 1;