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