attempt to fix weird overload '0+' bug, modify tests to make sure it works
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / ResultSet.pm
1 package DBIx::Class::ResultSet;
2
3 use strict;
4 use warnings;
5 use overload
6         '0+'     => \&count,
7         'bool'   => sub { 1; },
8         fallback => 1;
9 use Data::Page;
10 use Storable;
11
12 use base qw/DBIx::Class/;
13 __PACKAGE__->load_components(qw/AccessorGroup/);
14 __PACKAGE__->mk_group_accessors('simple' => 'result_source');
15
16 =head1 NAME
17
18 DBIx::Class::ResultSet - Responsible for fetching and creating resultset.
19
20 =head1 SYNOPSIS
21
22   my $rs   = $schema->resultset('User')->search(registered => 1);
23   my @rows = $schema->resultset('Foo')->search(bar => 'baz');
24
25 =head1 DESCRIPTION
26
27 The resultset is also known as an iterator. It is responsible for handling
28 queries that may return an arbitrary number of rows, e.g. via L</search>
29 or a C<has_many> relationship.
30
31 In the examples below, the following table classes are used:
32
33   package MyApp::Schema::Artist;
34   use base qw/DBIx::Class/;
35   __PACKAGE__->load_components(qw/Core/);
36   __PACKAGE__->table('artist');
37   __PACKAGE__->add_columns(qw/artistid name/);
38   __PACKAGE__->set_primary_key('artistid');
39   __PACKAGE__->has_many(cds => 'MyApp::Schema::CD');
40   1;
41
42   package MyApp::Schema::CD;
43   use base qw/DBIx::Class/;
44   __PACKAGE__->load_components(qw/Core/);
45   __PACKAGE__->table('cd');
46   __PACKAGE__->add_columns(qw/cdid artist title year/);
47   __PACKAGE__->set_primary_key('cdid');
48   __PACKAGE__->belongs_to(artist => 'MyApp::Schema::Artist');
49   1;
50
51 =head1 METHODS
52
53 =head2 new
54
55 =head3 Arguments: ($source, \%$attrs)
56
57 The resultset constructor. Takes a source object (usually a
58 L<DBIx::Class::ResultSourceProxy::Table>) and an attribute hash (see L</ATRRIBUTES>
59 below).  Does not perform any queries -- these are executed as needed by the
60 other methods.
61
62 Generally you won't need to construct a resultset manually.  You'll
63 automatically get one from e.g. a L</search> called in scalar context:
64
65   my $rs = $schema->resultset('CD')->search({ title => '100th Window' });
66
67 =cut
68
69 sub new {
70   my $class = shift;
71   return $class->new_result(@_) if ref $class;
72   my ($source, $attrs) = @_;
73   #use Data::Dumper; warn Dumper($attrs);
74   $attrs = Storable::dclone($attrs || {}); # { %{ $attrs || {} } };
75   my %seen;
76   my $alias = ($attrs->{alias} ||= 'me');
77   if ($attrs->{cols} || !$attrs->{select}) {
78     delete $attrs->{as} if $attrs->{cols};
79     my @cols = ($attrs->{cols}
80                  ? @{delete $attrs->{cols}}
81                  : $source->columns);
82     $attrs->{select} = [ map { m/\./ ? $_ : "${alias}.$_" } @cols ];
83   }
84   $attrs->{as} ||= [ map { m/^$alias\.(.*)$/ ? $1 : $_ } @{$attrs->{select}} ];
85   if (my $include = delete $attrs->{include_columns}) {
86     push(@{$attrs->{select}}, @$include);
87     push(@{$attrs->{as}}, map { m/([^\.]+)$/; $1; } @$include);
88   }
89   #use Data::Dumper; warn Dumper(@{$attrs}{qw/select as/});
90   $attrs->{from} ||= [ { $alias => $source->from } ];
91   $attrs->{seen_join} ||= {};
92   if (my $join = delete $attrs->{join}) {
93     foreach my $j (ref $join eq 'ARRAY'
94               ? (@{$join}) : ($join)) {
95       if (ref $j eq 'HASH') {
96         $seen{$_} = 1 foreach keys %$j;
97       } else {
98         $seen{$j} = 1;
99       }
100     }
101     push(@{$attrs->{from}}, $source->resolve_join($join, $attrs->{alias}, $attrs->{seen_join}));
102   }
103   $attrs->{group_by} ||= $attrs->{select} if delete $attrs->{distinct};
104
105   if (my $prefetch = delete $attrs->{prefetch}) {
106     foreach my $p (ref $prefetch eq 'ARRAY'
107               ? (@{$prefetch}) : ($prefetch)) {
108       if( ref $p eq 'HASH' ) {
109         foreach my $key (keys %$p) {
110           push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
111             unless $seen{$key};
112         }
113       }
114       else {
115         push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
116             unless $seen{$p};
117       }
118       my @prefetch = $source->resolve_prefetch($p, $attrs->{alias});
119       #die Dumper \@cols;
120       push(@{$attrs->{select}}, map { $_->[0] } @prefetch);
121       push(@{$attrs->{as}}, map { $_->[1] } @prefetch);
122     }
123   }
124
125   if ($attrs->{page}) {
126     $attrs->{rows} ||= 10;
127     $attrs->{offset} ||= 0;
128     $attrs->{offset} += ($attrs->{rows} * ($attrs->{page} - 1));
129   }
130   my $new = {
131     result_source => $source,
132     cond => $attrs->{where},
133     from => $attrs->{from},
134     count => undef,
135     page => delete $attrs->{page},
136     pager => undef,
137     attrs => $attrs };
138   bless ($new, $class);
139   return $new;
140 }
141
142 =head2 search
143
144   my @obj    = $rs->search({ foo => 3 }); # "... WHERE foo = 3"
145   my $new_rs = $rs->search({ foo => 3 });
146
147 If you need to pass in additional attributes but no additional condition,
148 call it as C<search({}, \%attrs);>.
149
150   # "SELECT foo, bar FROM $class_table"
151   my @all = $class->search({}, { cols => [qw/foo bar/] });
152
153 =cut
154
155 sub search {
156   my $self = shift;
157
158   #use Data::Dumper;warn Dumper(@_);
159
160   my $attrs = { %{$self->{attrs}} };
161   if (@_ > 1 && ref $_[$#_] eq 'HASH') {
162     $attrs = { %$attrs, %{ pop(@_) } };
163   }
164
165   my $where = (@_ ? ((@_ == 1 || ref $_[0] eq "HASH") ? shift : {@_}) : undef());
166   if (defined $where) {
167     $where = (defined $attrs->{where}
168                 ? { '-and' =>
169                     [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
170                         $where, $attrs->{where} ] }
171                 : $where);
172     $attrs->{where} = $where;
173   }
174
175   my $rs = (ref $self)->new($self->result_source, $attrs);
176
177   return (wantarray ? $rs->all : $rs);
178 }
179
180 =head2 search_literal
181
182   my @obj    = $rs->search_literal($literal_where_cond, @bind);
183   my $new_rs = $rs->search_literal($literal_where_cond, @bind);
184
185 Pass a literal chunk of SQL to be added to the conditional part of the
186 resultset.
187
188 =cut
189                                                          
190 sub search_literal {
191   my ($self, $cond, @vals) = @_;
192   my $attrs = (ref $vals[$#vals] eq 'HASH' ? { %{ pop(@vals) } } : {});
193   $attrs->{bind} = [ @{$self->{attrs}{bind}||[]}, @vals ];
194   return $self->search(\$cond, $attrs);
195 }
196
197 =head2 find
198
199 =head3 Arguments: (@colvalues) | (\%cols, \%attrs?)
200
201 Finds a row based on its primary key or unique constraint. For example:
202
203   my $cd = $schema->resultset('CD')->find(5);
204
205 Also takes an optional C<key> attribute, to search by a specific key or unique
206 constraint. For example:
207
208   my $cd = $schema->resultset('CD')->find_or_create(
209     {
210       artist => 'Massive Attack',
211       title  => 'Mezzanine',
212     },
213     { key => 'artist_title' }
214   );
215
216 See also L</find_or_create> and L</update_or_create>.
217
218 =cut
219
220 sub find {
221   my ($self, @vals) = @_;
222   my $attrs = (@vals > 1 && ref $vals[$#vals] eq 'HASH' ? pop(@vals) : {});
223
224   my @cols = $self->result_source->primary_columns;
225   if (exists $attrs->{key}) {
226     my %uniq = $self->result_source->unique_constraints;
227     $self->( "Unknown key " . $attrs->{key} . " on " . $self->name )
228       unless exists $uniq{$attrs->{key}};
229     @cols = @{ $uniq{$attrs->{key}} };
230   }
231   #use Data::Dumper; warn Dumper($attrs, @vals, @cols);
232   $self->throw_exception( "Can't find unless a primary key or unique constraint is defined" )
233     unless @cols;
234
235   my $query;
236   if (ref $vals[0] eq 'HASH') {
237     $query = { %{$vals[0]} };
238   } elsif (@cols == @vals) {
239     $query = {};
240     @{$query}{@cols} = @vals;
241   } else {
242     $query = {@vals};
243   }
244   foreach (keys %$query) {
245     next if m/\./;
246     $query->{$self->{attrs}{alias}.'.'.$_} = delete $query->{$_};
247   }
248   #warn Dumper($query);
249   return $self->search($query,$attrs)->next;
250 }
251
252 =head2 search_related
253
254   $rs->search_related('relname', $cond?, $attrs?);
255
256 Search the specified relationship. Optionally specify a condition for matching
257 records.
258
259 =cut
260
261 sub search_related {
262   my ($self, $rel, @rest) = @_;
263   my $rel_obj = $self->result_source->relationship_info($rel);
264   $self->throw_exception(
265     "No such relationship ${rel} in search_related")
266       unless $rel_obj;
267   my $rs = $self->search(undef, { join => $rel });
268   my $alias = ($rs->{attrs}{seen_join}{$rel} > 1
269                 ? join('_', $rel, $rs->{attrs}{seen_join}{$rel})
270                 : $rel);
271   return $self->result_source->schema->resultset($rel_obj->{class}
272            )->search( undef,
273              { %{$rs->{attrs}},
274                alias => $alias,
275                select => undef(),
276                as => undef() }
277            )->search(@rest);
278 }
279
280 =head2 cursor
281
282 Returns a storage-driven cursor to the given resultset.
283
284 =cut
285
286 sub cursor {
287   my ($self) = @_;
288   my ($attrs) = $self->{attrs};
289   $attrs = { %$attrs };
290   return $self->{cursor}
291     ||= $self->result_source->storage->select($self->{from}, $attrs->{select},
292           $attrs->{where},$attrs);
293 }
294
295 =head2 search_like
296
297 Perform a search, but use C<LIKE> instead of equality as the condition. Note
298 that this is simply a convenience method; you most likely want to use
299 L</search> with specific operators.
300
301 For more information, see L<DBIx::Class::Manual::Cookbook>.
302
303 =cut
304
305 sub search_like {
306   my $class    = shift;
307   my $attrs = { };
308   if (@_ > 1 && ref $_[$#_] eq 'HASH') {
309     $attrs = pop(@_);
310   }
311   my $query    = ref $_[0] eq "HASH" ? { %{shift()} }: {@_};
312   $query->{$_} = { 'like' => $query->{$_} } for keys %$query;
313   return $class->search($query, { %$attrs });
314 }
315
316 =head2 slice
317
318 =head3 Arguments: ($first, $last)
319
320 Returns a subset of elements from the resultset.
321
322 =cut
323
324 sub slice {
325   my ($self, $min, $max) = @_;
326   my $attrs = { %{ $self->{attrs} || {} } };
327   $attrs->{offset} ||= 0;
328   $attrs->{offset} += $min;
329   $attrs->{rows} = ($max ? ($max - $min + 1) : 1);
330   my $slice = (ref $self)->new($self->result_source, $attrs);
331   return (wantarray ? $slice->all : $slice);
332 }
333
334 =head2 next
335
336 Returns the next element in the resultset (C<undef> is there is none).
337
338 Can be used to efficiently iterate over records in the resultset:
339
340   my $rs = $schema->resultset('CD')->search({});
341   while (my $cd = $rs->next) {
342     print $cd->title;
343   }
344
345 =cut
346
347 sub next {
348   my ($self) = @_;
349   my @row = $self->cursor->next;
350 #  warn Dumper(\@row); use Data::Dumper;
351   return unless (@row);
352   return $self->_construct_object(@row);
353 }
354
355 sub _construct_object {
356   my ($self, @row) = @_;
357   my @as = @{ $self->{attrs}{as} };
358   #warn "@cols -> @row";
359   my $info = [ {}, {} ];
360   foreach my $as (@as) {
361     my $target = $info;
362     my @parts = split(/\./, $as);
363     my $col = pop(@parts);
364     foreach my $p (@parts) {
365       $target = $target->[1]->{$p} ||= [];
366     }
367     $target->[0]->{$col} = shift @row;
368   }
369   #use Data::Dumper; warn Dumper(\@as, $info);
370   my $new = $self->result_source->result_class->inflate_result(
371               $self->result_source, @$info);
372   $new = $self->{attrs}{record_filter}->($new)
373     if exists $self->{attrs}{record_filter};
374   return $new;
375 }
376
377 =head2 result_source
378
379 Returns a reference to the result source for this recordset.
380
381 =cut
382
383
384 =head2 count
385
386 Performs an SQL C<COUNT> with the same query as the resultset was built
387 with to find the number of elements. If passed arguments, does a search
388 on the resultset and counts the results of that.
389
390 Note: When using C<count> with C<group_by>, L<DBIX::Class> emulates C<GROUP BY>
391 using C<COUNT( DISTINCT( columns ) )>. Some databases (notably SQLite) do
392 not support C<DISTINCT> with multiple columns. If you are using such a
393 database, you should only use columns from the main table in your C<group_by>
394 clause.
395
396 =cut
397
398 sub count {
399   my $self = shift;
400   return $self->search(@_)->count if @_ && defined $_[0];
401   unless (defined $self->{count}) {
402     my $group_by;
403     my $select = { 'count' => '*' };
404     if( $group_by = delete $self->{attrs}{group_by} ) {
405       my @distinct = (ref $group_by ?  @$group_by : ($group_by));
406       # todo: try CONCAT for multi-column pk
407       my @pk = $self->result_source->primary_columns;
408       if( scalar(@pk) == 1 ) {
409         my $pk = shift(@pk);
410         my $alias = $self->{attrs}{alias};
411         my $re = qr/^($alias\.)?$pk$/;
412         foreach my $column ( @distinct) {
413           if( $column =~ $re ) {
414             @distinct = ( $column );
415             last;
416           }
417         } 
418       }
419
420       $select = { count => { 'distinct' => \@distinct } };
421       #use Data::Dumper; die Dumper $select;
422     }
423
424     my $attrs = { %{ $self->{attrs} },
425                   select => $select,
426                   as => [ 'count' ] };
427     # offset, order by and page are not needed to count. record_filter is cdbi
428     delete $attrs->{$_} for qw/rows offset order_by page pager record_filter/;
429         
430     ($self->{count}) = (ref $self)->new($self->result_source, $attrs)->cursor->next;
431     $self->{attrs}{group_by} = $group_by;
432   }
433   return 0 unless $self->{count};
434   my $count = $self->{count};
435   $count -= $self->{attrs}{offset} if $self->{attrs}{offset};
436   $count = $self->{attrs}{rows} if
437     ($self->{attrs}{rows} && $self->{attrs}{rows} < $count);
438   return $count;
439 }
440
441 =head2 count_literal
442
443 Calls L</search_literal> with the passed arguments, then L</count>.
444
445 =cut
446
447 sub count_literal { shift->search_literal(@_)->count; }
448
449 =head2 all
450
451 Returns all elements in the resultset. Called implictly if the resultset
452 is returned in list context.
453
454 =cut
455
456 sub all {
457   my ($self) = @_;
458   return map { $self->_construct_object(@$_); }
459            $self->cursor->all;
460 }
461
462 =head2 reset
463
464 Resets the resultset's cursor, so you can iterate through the elements again.
465
466 =cut
467
468 sub reset {
469   my ($self) = @_;
470   $self->cursor->reset;
471   return $self;
472 }
473
474 =head2 first
475
476 Resets the resultset and returns the first element.
477
478 =cut
479
480 sub first {
481   return $_[0]->reset->next;
482 }
483
484 =head2 update
485
486 =head3 Arguments: (\%values)
487
488 Sets the specified columns in the resultset to the supplied values.
489
490 =cut
491
492 sub update {
493   my ($self, $values) = @_;
494   $self->throw_exception("Values for update must be a hash") unless ref $values eq 'HASH';
495   return $self->result_source->storage->update(
496            $self->result_source->from, $values, $self->{cond});
497 }
498
499 =head2 update_all
500
501 =head3 Arguments: (\%values)
502
503 Fetches all objects and updates them one at a time.  Note that C<update_all>
504 will run cascade triggers while L</update> will not.
505
506 =cut
507
508 sub update_all {
509   my ($self, $values) = @_;
510   $self->throw_exception("Values for update must be a hash") unless ref $values eq 'HASH';
511   foreach my $obj ($self->all) {
512     $obj->set_columns($values)->update;
513   }
514   return 1;
515 }
516
517 =head2 delete
518
519 Deletes the contents of the resultset from its result source.
520
521 =cut
522
523 sub delete {
524   my ($self) = @_;
525   my $del = {};
526   $self->throw_exception("Can't delete on resultset with condition unless hash or array")
527     unless (ref($self->{cond}) eq 'HASH' || ref($self->{cond}) eq 'ARRAY');
528   if (ref $self->{cond} eq 'ARRAY') {
529     $del = [ map { my %hash;
530       foreach my $key (keys %{$_}) {
531         $key =~ /([^\.]+)$/;
532         $hash{$1} = $_->{$key};
533       }; \%hash; } @{$self->{cond}} ];
534   } elsif ((keys %{$self->{cond}})[0] eq '-and') {
535     $del->{-and} = [ map { my %hash;
536       foreach my $key (keys %{$_}) {
537         $key =~ /([^\.]+)$/;
538         $hash{$1} = $_->{$key};
539       }; \%hash; } @{$self->{cond}{-and}} ];
540   } else {
541     foreach my $key (keys %{$self->{cond}}) {
542       $key =~ /([^\.]+)$/;
543       $del->{$1} = $self->{cond}{$key};
544     }
545   }
546   $self->result_source->storage->delete($self->result_source->from, $del);
547   return 1;
548 }
549
550 =head2 delete_all
551
552 Fetches all objects and deletes them one at a time.  Note that C<delete_all>
553 will run cascade triggers while L</delete> will not.
554
555 =cut
556
557 sub delete_all {
558   my ($self) = @_;
559   $_->delete for $self->all;
560   return 1;
561 }
562
563 =head2 pager
564
565 Returns a L<Data::Page> object for the current resultset. Only makes
566 sense for queries with a C<page> attribute.
567
568 =cut
569
570 sub pager {
571   my ($self) = @_;
572   my $attrs = $self->{attrs};
573   $self->throw_exception("Can't create pager for non-paged rs") unless $self->{page};
574   $attrs->{rows} ||= 10;
575   $self->count;
576   return $self->{pager} ||= Data::Page->new(
577     $self->{count}, $attrs->{rows}, $self->{page});
578 }
579
580 =head2 page
581
582 =head3 Arguments: ($page_num)
583
584 Returns a new resultset for the specified page.
585
586 =cut
587
588 sub page {
589   my ($self, $page) = @_;
590   my $attrs = { %{$self->{attrs}} };
591   $attrs->{page} = $page;
592   return (ref $self)->new($self->result_source, $attrs);
593 }
594
595 =head2 new_result
596
597 =head3 Arguments: (\%vals)
598
599 Creates a result in the resultset's result class.
600
601 =cut
602
603 sub new_result {
604   my ($self, $values) = @_;
605   $self->throw_exception( "new_result needs a hash" )
606     unless (ref $values eq 'HASH');
607   $self->throw_exception( "Can't abstract implicit construct, condition not a hash" )
608     if ($self->{cond} && !(ref $self->{cond} eq 'HASH'));
609   my %new = %$values;
610   my $alias = $self->{attrs}{alias};
611   foreach my $key (keys %{$self->{cond}||{}}) {
612     $new{$1} = $self->{cond}{$key} if ($key =~ m/^(?:$alias\.)?([^\.]+)$/);
613   }
614   my $obj = $self->result_source->result_class->new(\%new);
615   $obj->result_source($self->result_source) if $obj->can('result_source');
616   $obj;
617 }
618
619 =head2 create
620
621 =head3 Arguments: (\%vals)
622
623 Inserts a record into the resultset and returns the object.
624
625 Effectively a shortcut for C<< ->new_result(\%vals)->insert >>.
626
627 =cut
628
629 sub create {
630   my ($self, $attrs) = @_;
631   $self->throw_exception( "create needs a hashref" ) unless ref $attrs eq 'HASH';
632   return $self->new_result($attrs)->insert;
633 }
634
635 =head2 find_or_create
636
637 =head3 Arguments: (\%vals, \%attrs?)
638
639   $class->find_or_create({ key => $val, ... });
640
641 Searches for a record matching the search condition; if it doesn't find one,    
642 creates one and returns that instead.                                       
643
644   my $cd = $schema->resultset('CD')->find_or_create({
645     cdid   => 5,
646     artist => 'Massive Attack',
647     title  => 'Mezzanine',
648     year   => 2005,
649   });
650
651 Also takes an optional C<key> attribute, to search by a specific key or unique
652 constraint. For example:
653
654   my $cd = $schema->resultset('CD')->find_or_create(
655     {
656       artist => 'Massive Attack',
657       title  => 'Mezzanine',
658     },
659     { key => 'artist_title' }
660   );
661
662 See also L</find> and L</update_or_create>.
663
664 =cut
665
666 sub find_or_create {
667   my $self     = shift;
668   my $attrs    = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
669   my $hash     = ref $_[0] eq "HASH" ? shift : {@_};
670   my $exists   = $self->find($hash, $attrs);
671   return defined($exists) ? $exists : $self->create($hash);
672 }
673
674 =head2 update_or_create
675
676   $class->update_or_create({ key => $val, ... });
677
678 First, search for an existing row matching one of the unique constraints
679 (including the primary key) on the source of this resultset.  If a row is
680 found, update it with the other given column values.  Otherwise, create a new
681 row.
682
683 Takes an optional C<key> attribute to search on a specific unique constraint.
684 For example:
685
686   # In your application
687   my $cd = $schema->resultset('CD')->update_or_create(
688     {
689       artist => 'Massive Attack',
690       title  => 'Mezzanine',
691       year   => 1998,
692     },
693     { key => 'artist_title' }
694   );
695
696 If no C<key> is specified, it searches on all unique constraints defined on the
697 source, including the primary key.
698
699 If the C<key> is specified as C<primary>, search only on the primary key.
700
701 See also L</find> and L</find_or_create>.
702
703 =cut
704
705 sub update_or_create {
706   my $self = shift;
707
708   my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
709   my $hash  = ref $_[0] eq "HASH" ? shift : {@_};
710
711   my %unique_constraints = $self->result_source->unique_constraints;
712   my @constraint_names   = (exists $attrs->{key}
713                             ? ($attrs->{key})
714                             : keys %unique_constraints);
715
716   my @unique_hashes;
717   foreach my $name (@constraint_names) {
718     my @unique_cols = @{ $unique_constraints{$name} };
719     my %unique_hash =
720       map  { $_ => $hash->{$_} }
721       grep { exists $hash->{$_} }
722       @unique_cols;
723
724     push @unique_hashes, \%unique_hash
725       if (scalar keys %unique_hash == scalar @unique_cols);
726   }
727
728   my $row;
729   if (@unique_hashes) {
730     $row = $self->search(\@unique_hashes, { rows => 1 })->first;
731     if ($row) {
732       $row->set_columns($hash);
733       $row->update;
734     }
735   }
736
737   unless ($row) {
738     $row = $self->create($hash);
739   }
740
741   return $row;
742 }
743
744 =head2 throw_exception
745
746 See Schema's throw_exception
747
748 =cut
749
750 sub throw_exception {
751   my $self=shift;
752   $self->result_source->schema->throw_exception(@_);
753 }
754
755 =head1 ATTRIBUTES
756
757 The resultset takes various attributes that modify its behavior. Here's an
758 overview of them:
759
760 =head2 order_by
761
762 Which column(s) to order the results by. This is currently passed through
763 directly to SQL, so you can give e.g. C<foo DESC> for a descending order.
764
765 =head2 cols
766
767 =head3 Arguments: (arrayref)
768
769 Shortcut to request a particular set of columns to be retrieved.  Adds
770 C<me.> onto the start of any column without a C<.> in it and sets C<select>
771 from that, then auto-populates C<as> from C<select> as normal.
772
773 =head2 include_columns
774
775 =head3 Arguments: (arrayref)
776
777 Shortcut to include additional columns in the returned results - for example
778
779   { include_columns => ['foo.name'], join => ['foo'] }
780
781 would add a 'name' column to the information passed to object inflation
782
783 =head2 select
784
785 =head3 Arguments: (arrayref)
786
787 Indicates which columns should be selected from the storage. You can use
788 column names, or in the case of RDBMS back ends, function or stored procedure
789 names:
790
791   $rs = $schema->resultset('Foo')->search(
792     {},
793     {
794       select => [
795         'column_name',
796         { count => 'column_to_count' },
797         { sum => 'column_to_sum' }
798       ]
799     }
800   );
801
802 When you use function/stored procedure names and do not supply an C<as>
803 attribute, the column names returned are storage-dependent. E.g. MySQL would
804 return a column named C<count(column_to_count)> in the above example.
805
806 =head2 as
807
808 =head3 Arguments: (arrayref)
809
810 Indicates column names for object inflation. This is used in conjunction with
811 C<select>, usually when C<select> contains one or more function or stored
812 procedure names:
813
814   $rs = $schema->resultset('Foo')->search(
815     {},
816     {
817       select => [
818         'column1',
819         { count => 'column2' }
820       ],
821       as => [qw/ column1 column2_count /]
822     }
823   );
824
825   my $foo = $rs->first(); # get the first Foo
826
827 If the object against which the search is performed already has an accessor
828 matching a column name specified in C<as>, the value can be retrieved using
829 the accessor as normal:
830
831   my $column1 = $foo->column1();
832
833 If on the other hand an accessor does not exist in the object, you need to
834 use C<get_column> instead:
835
836   my $column2_count = $foo->get_column('column2_count');
837
838 You can create your own accessors if required - see
839 L<DBIx::Class::Manual::Cookbook> for details.
840
841 =head2 join
842
843 Contains a list of relationships that should be joined for this query.  For
844 example:
845
846   # Get CDs by Nine Inch Nails
847   my $rs = $schema->resultset('CD')->search(
848     { 'artist.name' => 'Nine Inch Nails' },
849     { join => 'artist' }
850   );
851
852 Can also contain a hash reference to refer to the other relation's relations.
853 For example:
854
855   package MyApp::Schema::Track;
856   use base qw/DBIx::Class/;
857   __PACKAGE__->table('track');
858   __PACKAGE__->add_columns(qw/trackid cd position title/);
859   __PACKAGE__->set_primary_key('trackid');
860   __PACKAGE__->belongs_to(cd => 'MyApp::Schema::CD');
861   1;
862
863   # In your application
864   my $rs = $schema->resultset('Artist')->search(
865     { 'track.title' => 'Teardrop' },
866     {
867       join     => { cd => 'track' },
868       order_by => 'artist.name',
869     }
870   );
871
872 If the same join is supplied twice, it will be aliased to <rel>_2 (and
873 similarly for a third time). For e.g.
874
875   my $rs = $schema->resultset('Artist')->search(
876     { 'cds.title'   => 'Foo',
877       'cds_2.title' => 'Bar' },
878     { join => [ qw/cds cds/ ] });
879
880 will return a set of all artists that have both a cd with title Foo and a cd
881 with title Bar.
882
883 If you want to fetch related objects from other tables as well, see C<prefetch>
884 below.
885
886 =head2 prefetch
887
888 =head3 Arguments: arrayref/hashref
889
890 Contains one or more relationships that should be fetched along with the main 
891 query (when they are accessed afterwards they will have already been
892 "prefetched").  This is useful for when you know you will need the related
893 objects, because it saves at least one query:
894
895   my $rs = $schema->resultset('Tag')->search(
896     {},
897     {
898       prefetch => {
899         cd => 'artist'
900       }
901     }
902   );
903
904 The initial search results in SQL like the following:
905
906   SELECT tag.*, cd.*, artist.* FROM tag
907   JOIN cd ON tag.cd = cd.cdid
908   JOIN artist ON cd.artist = artist.artistid
909
910 L<DBIx::Class> has no need to go back to the database when we access the
911 C<cd> or C<artist> relationships, which saves us two SQL statements in this
912 case.
913
914 Simple prefetches will be joined automatically, so there is no need
915 for a C<join> attribute in the above search. If you're prefetching to
916 depth (e.g. { cd => { artist => 'label' } or similar), you'll need to
917 specify the join as well.
918
919 C<prefetch> can be used with the following relationship types: C<belongs_to>,
920 C<has_one> (or if you're using C<add_relationship>, any relationship declared
921 with an accessor type of 'single' or 'filter').
922
923 =head2 from
924
925 =head3 Arguments: (arrayref)
926
927 The C<from> attribute gives you manual control over the C<FROM> clause of SQL
928 statements generated by L<DBIx::Class>, allowing you to express custom C<JOIN>
929 clauses.
930
931 NOTE: Use this on your own risk.  This allows you to shoot off your foot!
932 C<join> will usually do what you need and it is strongly recommended that you
933 avoid using C<from> unless you cannot achieve the desired result using C<join>.
934
935 In simple terms, C<from> works as follows:
936
937     [
938         { <alias> => <table>, -join-type => 'inner|left|right' }
939         [] # nested JOIN (optional)
940         { <table.column> = <foreign_table.foreign_key> }
941     ]
942
943     JOIN
944         <alias> <table>
945         [JOIN ...]
946     ON <table.column> = <foreign_table.foreign_key>
947
948 An easy way to follow the examples below is to remember the following:
949
950     Anything inside "[]" is a JOIN
951     Anything inside "{}" is a condition for the enclosing JOIN
952
953 The following examples utilize a "person" table in a family tree application.
954 In order to express parent->child relationships, this table is self-joined:
955
956     # Person->belongs_to('father' => 'Person');
957     # Person->belongs_to('mother' => 'Person');
958
959 C<from> can be used to nest joins. Here we return all children with a father,
960 then search against all mothers of those children:
961
962   $rs = $schema->resultset('Person')->search(
963       {},
964       {
965           alias => 'mother', # alias columns in accordance with "from"
966           from => [
967               { mother => 'person' },
968               [
969                   [
970                       { child => 'person' },
971                       [
972                           { father => 'person' },
973                           { 'father.person_id' => 'child.father_id' }
974                       ]
975                   ],
976                   { 'mother.person_id' => 'child.mother_id' }
977               ],                
978           ]
979       },
980   );
981
982   # Equivalent SQL:
983   # SELECT mother.* FROM person mother
984   # JOIN (
985   #   person child
986   #   JOIN person father
987   #   ON ( father.person_id = child.father_id )
988   # )
989   # ON ( mother.person_id = child.mother_id )
990
991 The type of any join can be controlled manually. To search against only people
992 with a father in the person table, we could explicitly use C<INNER JOIN>:
993
994     $rs = $schema->resultset('Person')->search(
995         {},
996         {
997             alias => 'child', # alias columns in accordance with "from"
998             from => [
999                 { child => 'person' },
1000                 [
1001                     { father => 'person', -join-type => 'inner' },
1002                     { 'father.id' => 'child.father_id' }
1003                 ],
1004             ]
1005         },
1006     );
1007
1008     # Equivalent SQL:
1009     # SELECT child.* FROM person child
1010     # INNER JOIN person father ON child.father_id = father.id
1011
1012 =head2 page
1013
1014 For a paged resultset, specifies which page to retrieve.  Leave unset
1015 for an unpaged resultset.
1016
1017 =head2 rows
1018
1019 For a paged resultset, how many rows per page:
1020
1021   rows => 10
1022
1023 Can also be used to simulate an SQL C<LIMIT>.
1024
1025 =head2 group_by
1026
1027 =head3 Arguments: (arrayref)
1028
1029 A arrayref of columns to group by. Can include columns of joined tables.
1030
1031   group_by => [qw/ column1 column2 ... /]
1032
1033 =head2 distinct
1034
1035 Set to 1 to group by all columns.
1036
1037 For more examples of using these attributes, see
1038 L<DBIx::Class::Manual::Cookbook>.
1039
1040 =cut
1041
1042 1;