update cookbook and resultset docs
[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         fallback => 1;
8 use Data::Page;
9
10 =head1 NAME
11
12 DBIx::Class::ResultSet - Responsible for fetching and creating resultset.
13
14 =head1 SYNOPSIS
15
16 my $rs = MyApp::DB::Class->search(registered => 1);
17 my @rows = MyApp::DB::Class->search(foo => 'bar');
18
19 =head1 DESCRIPTION
20
21 The resultset is also known as an iterator. It is responsible for handling
22 queries that may return an arbitrary number of rows, e.g. via C<search>
23 or a C<has_many> relationship.
24
25 =head1 METHODS
26
27 =head2 new($db_class, \%$attrs)
28
29 The resultset constructor. Takes a table class and an attribute hash
30 (see below for more information on attributes). Does not perform
31 any queries -- these are executed as needed by the other methods.
32
33 =cut
34
35 sub new {
36   my ($it_class, $db_class, $attrs) = @_;
37   #use Data::Dumper; warn Dumper(@_);
38   $it_class = ref $it_class if ref $it_class;
39   $attrs = { %{ $attrs || {} } };
40   my %seen;
41   $attrs->{cols} ||= [ map { "me.$_" } $db_class->_select_columns ];
42   $attrs->{from} ||= [ { 'me' => $db_class->_table_name } ];
43   if ($attrs->{join}) {
44     foreach my $j (ref $attrs->{join} eq 'ARRAY'
45               ? (@{$attrs->{join}}) : ($attrs->{join})) {
46       if (ref $j eq 'HASH') {
47         $seen{$_} = 1 foreach keys %$j;
48       } else {
49         $seen{$j} = 1;
50       }
51     }
52     push(@{$attrs->{from}}, $db_class->_resolve_join($attrs->{join}, 'me'));
53   }
54   foreach my $pre (@{$attrs->{prefetch} || []}) {
55     push(@{$attrs->{from}}, $db_class->_resolve_join($pre, 'me'))
56       unless $seen{$pre};
57     push(@{$attrs->{cols}},
58       map { "$pre.$_" }
59       $db_class->_relationships->{$pre}->{class}->_select_columns);
60   }
61   my $new = {
62     class => $db_class,
63     cols => $attrs->{cols} || [ $db_class->_select_columns ],
64     cond => $attrs->{where},
65     from => $attrs->{from} || $db_class->_table_name,
66     count => undef,
67     pager => undef,
68     attrs => $attrs };
69   bless ($new, $it_class);
70   $new->pager if ($attrs->{page});
71   return $new;
72 }
73
74 =head2 cursor
75
76 Return a storage-driven cursor to the given resultset.
77
78 =cut
79
80 sub cursor {
81   my ($self) = @_;
82   my ($db_class, $attrs) = @{$self}{qw/class attrs/};
83   if ($attrs->{page}) {
84     $attrs->{rows} = $self->pager->entries_per_page;
85     $attrs->{offset} = $self->pager->skipped;
86   }
87   return $self->{cursor}
88     ||= $db_class->storage->select($self->{from}, $self->{cols},
89           $attrs->{where},$attrs);
90 }
91
92 =head2 slice($first, $last)
93
94 Returns a subset of elements from the resultset.
95
96 =cut
97
98 sub slice {
99   my ($self, $min, $max) = @_;
100   my $attrs = { %{ $self->{attrs} || {} } };
101   $self->{class}->throw("Can't slice without where") unless $attrs->{where};
102   $attrs->{offset} = $min;
103   $attrs->{rows} = ($max ? ($max - $min + 1) : 1);
104   my $slice = $self->new($self->{class}, $attrs);
105   return (wantarray ? $slice->all : $slice);
106 }
107
108 =head2 next 
109
110 Returns the next element in the resultset (undef is there is none).
111
112 =cut
113
114 sub next {
115   my ($self) = @_;
116   my @row = $self->cursor->next;
117   return unless (@row);
118   return $self->_construct_object(@row);
119 }
120
121 sub _construct_object {
122   my ($self, @row) = @_;
123   my @cols = @{ $self->{attrs}{cols} };
124   s/^me\.// for @cols;
125   @cols = grep { /\(/ or ! /\./ } @cols;
126   my $new;
127   unless ($self->{attrs}{prefetch}) {
128     $new = $self->{class}->_row_to_object(\@cols, \@row);
129   } else {
130     my @main = splice(@row, 0, scalar @cols);
131     $new = $self->{class}->_row_to_object(\@cols, \@main);
132     PRE: foreach my $pre (@{$self->{attrs}{prefetch}}) {
133       my $rel_obj = $self->{class}->_relationships->{$pre};
134       my $pre_class = $self->{class}->resolve_class($rel_obj->{class});
135       my @pre_cols = $pre_class->_select_columns;
136       my @vals = splice(@row, 0, scalar @pre_cols);
137       my $fetched = $pre_class->_row_to_object(\@pre_cols, \@vals);
138       $self->{class}->throw("No accessor for prefetched $pre")
139         unless defined $rel_obj->{attrs}{accessor};
140       if ($rel_obj->{attrs}{accessor} eq 'single') {
141         foreach my $pri ($rel_obj->{class}->primary_columns) {
142           unless (defined $fetched->get_column($pri)) {
143             undef $fetched;
144             last;
145           }
146         }
147         $new->{_relationship_data}{$pre} = $fetched;
148       } elsif ($rel_obj->{attrs}{accessor} eq 'filter') {
149         $new->{_inflated_column}{$pre} = $fetched;
150       } else {
151         $self->{class}->throw("Don't know how to store prefetched $pre");
152       }
153     }
154   }
155   $new = $self->{attrs}{record_filter}->($new)
156     if exists $self->{attrs}{record_filter};
157   return $new;
158 }
159
160 =head2 count
161
162 Performs an SQL C<COUNT> with the same query as the resultset was built
163 with to find the number of elements.
164
165 =cut
166
167 sub count {
168   my ($self) = @_;
169   my $db_class = $self->{class};
170   my $attrs = { %{ $self->{attrs} } };
171   unless ($self->{count}) {
172     # offset and order by are not needed to count
173     delete $attrs->{$_} for qw/offset order_by/;
174         
175     my @cols = 'COUNT(*)';
176     $self->{count} = $db_class->storage->select_single($self->{from}, \@cols,
177                                               $self->{cond}, $attrs);
178   }
179   return 0 unless $self->{count};
180   return $self->{pager}->entries_on_this_page if ($self->{pager});
181   return ( $attrs->{rows} && $attrs->{rows} < $self->{count} ) 
182     ? $attrs->{rows} 
183     : $self->{count};
184 }
185
186 =head2 all
187
188 Returns all elements in the resultset. Called implictly if the resultset
189 is returned in list context.
190
191 =cut
192
193 sub all {
194   my ($self) = @_;
195   return map { $self->_construct_object(@$_); }
196            $self->cursor->all;
197 }
198
199 =head2 reset
200
201 Resets the resultset's cursor, so you can iterate through the elements again.
202
203 =cut
204
205 sub reset {
206   my ($self) = @_;
207   $self->cursor->reset;
208   return $self;
209 }
210
211 =head2 first
212
213 Resets the resultset and returns the first element.
214
215 =cut
216
217 sub first {
218   return $_[0]->reset->next;
219 }
220
221 =head2 delete
222
223 Deletes all elements in the resultset.
224
225 =cut
226
227 sub delete {
228   my ($self) = @_;
229   $_->delete for $self->all;
230   return 1;
231 }
232
233 *delete_all = \&delete; # Yeah, yeah, yeah ...
234
235 =head2 pager
236
237 Returns a L<Data::Page> object for the current resultset. Only makes
238 sense for queries with page turned on.
239
240 =cut
241
242 sub pager {
243   my ($self) = @_;
244   my $attrs = $self->{attrs};
245   delete $attrs->{offset};
246   my $rows_per_page = delete $attrs->{rows} || 10;
247   $self->{pager} ||= Data::Page->new(
248     $self->count, $rows_per_page, $attrs->{page} || 1);
249   $attrs->{rows} = $rows_per_page;
250   return $self->{pager};
251 }
252
253 =head2 page($page_num)
254
255 Returns a new resultset for the specified page.
256
257 =cut
258
259 sub page {
260   my ($self, $page) = @_;
261   my $attrs = $self->{attrs};
262   $attrs->{page} = $page;
263   return $self->new($self->{class}, $attrs);
264 }
265
266 =head1 Attributes
267
268 The resultset takes various attributes that modify its behavior.
269 Here's an overview of them:
270
271 =head2 order_by
272
273 Which column(s) to order the results by. This is currently passed
274 through directly to SQL, so you can give e.g. C<foo DESC> for a 
275 descending order.
276
277 =head2 cols
278
279 Which columns should be retrieved.
280
281 =head2 join
282
283 Contains a list of relationships that should be joined for this query. Can also 
284 contain a hash reference to refer to that relation's relations. So, if one column
285 in your class C<belongs_to> foo and another C<belongs_to> bar, you can do
286 C<< join => [qw/ foo bar /] >> to join both (and e.g. use them for C<order_by>).
287 If a foo contains many margles and you want to join those too, you can do
288 C<< join => { foo => 'margle' } >>. If you want to fetch the columns from the
289 related table as well, see C<prefetch> below.
290
291 =head2 prefetch
292
293 Contains a list of relationships that should be fetched along with the main 
294 query (when they are accessed afterwards they will have already been
295 "prefetched"). This is useful for when you know you will need the related
296 object(s), because it saves a query. Currently limited to prefetching
297 one relationship deep, so unlike C<join>, prefetch must be an arrayref.
298
299 =head2 from 
300
301 This attribute can contain a arrayref of elements. Each element can be another
302 arrayref, to nest joins, or it can be a hash which represents the two sides
303 of the join. 
304
305 NOTE: Use this on your own risk. This allows you to shoot your foot off!
306
307 =head2 page
308
309 For a paged resultset, specifies which page to retrieve. Leave unset
310 for an unpaged resultset.
311
312 =head2 rows
313
314 For a paged resultset, how many rows per page
315
316 =cut
317
318 1;