1 package DBIx::Class::ResultSet;
12 DBIx::Class::ResultSet - Responsible for fetching and creating resultset.
16 my $rs = MyApp::DB::Class->search(registered => 1);
17 my @rows = MyApp::DB::Class->search(foo => 'bar');
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.
27 =head2 new($source, \%$attrs)
29 The resultset constructor. Takes a source object (usually a DBIx::Class::Table)
30 and an attribute hash (see below for more information on attributes). Does
31 not perform any queries -- these are executed as needed by the other methods.
36 my ($class, $source, $attrs) = @_;
37 #use Data::Dumper; warn Dumper(@_);
38 $class = ref $class if ref $class;
39 $attrs = { %{ $attrs || {} } };
41 if (!$attrs->{select}) {
42 my @cols = ($attrs->{cols}
43 ? @{delete $attrs->{cols}}
44 : $source->result_class->_select_columns);
45 $attrs->{select} = [ map { m/\./ ? $_ : "me.$_" } @cols ];
47 $attrs->{as} ||= [ map { m/^me\.(.*)$/ ? $1 : $_ } @{$attrs->{select}} ];
48 #use Data::Dumper; warn Dumper(@{$attrs}{qw/select as/});
49 $attrs->{from} ||= [ { 'me' => $source->name } ];
51 foreach my $j (ref $attrs->{join} eq 'ARRAY'
52 ? (@{$attrs->{join}}) : ($attrs->{join})) {
53 if (ref $j eq 'HASH') {
54 $seen{$_} = 1 foreach keys %$j;
59 push(@{$attrs->{from}}, $source->result_class->_resolve_join($attrs->{join}, 'me'));
61 foreach my $pre (@{$attrs->{prefetch} || []}) {
62 push(@{$attrs->{from}}, $source->result_class->_resolve_join($pre, 'me'))
66 $source->result_class->_relationships->{$pre}->{class}->columns;
67 push(@{$attrs->{select}}, @pre);
68 push(@{$attrs->{as}}, @pre);
72 result_class => $source->result_class,
73 cond => $attrs->{where},
74 from => $attrs->{from},
79 $new->pager if $attrs->{page};
85 my @obj = $rs->search({ foo => 3 }); # "... WHERE foo = 3"
86 my $new_rs = $rs->search({ foo => 3 });
88 If you need to pass in additional attributes but no additional condition,
89 call it as ->search(undef, \%attrs);
91 my @all = $class->search({}, { cols => [qw/foo bar/] }); # "SELECT foo, bar FROM $class_table"
98 #use Data::Dumper;warn Dumper(@_);
100 my $attrs = { %{$self->{attrs}} };
101 if (@_ > 1 && ref $_[$#_] eq 'HASH') {
102 $attrs = { %{ pop(@_) } };
105 my $where = ((@_ == 1 || ref $_[0] eq "HASH") ? shift : {@_});
106 if (defined $where) {
107 $where = (defined $attrs->{where}
108 ? { '-and' => [ $where, $attrs->{where} ] }
110 $attrs->{where} = $where;
113 my $rs = $self->new($self->{source}, $attrs);
115 return (wantarray ? $rs->all : $rs);
118 =head2 search_literal
119 my @obj = $rs->search_literal($literal_where_cond, @bind);
120 my $new_rs = $rs->search_literal($literal_where_cond, @bind);
122 Pass a literal chunk of SQL to be added to the conditional part of the
128 my ($self, $cond, @vals) = @_;
129 my $attrs = (ref $vals[$#vals] eq 'HASH' ? { %{ pop(@vals) } } : {});
130 $attrs->{bind} = [ @{$self->{attrs}{bind}||[]}, @vals ];
131 return $self->search(\$cond, $attrs);
136 Returns a storage-driven cursor to the given resultset.
142 my ($source, $attrs) = @{$self}{qw/source attrs/};
143 if ($attrs->{page}) {
144 $attrs->{rows} = $self->pager->entries_per_page;
145 $attrs->{offset} = $self->pager->skipped;
147 return $self->{cursor}
148 ||= $source->storage->select($self->{from}, $attrs->{select},
149 $attrs->{where},$attrs);
154 Identical to search except defaults to 'LIKE' instead of '=' in condition
161 if (@_ > 1 && ref $_[$#_] eq 'HASH') {
164 my $query = ref $_[0] eq "HASH" ? { %{shift()} }: {@_};
165 $query->{$_} = { 'like' => $query->{$_} } for keys %$query;
166 return $class->search($query, { %$attrs });
169 =head2 slice($first, $last)
171 Returns a subset of elements from the resultset.
176 my ($self, $min, $max) = @_;
177 my $attrs = { %{ $self->{attrs} || {} } };
178 $self->{source}->result_class->throw("Can't slice without where") unless $attrs->{where};
179 $attrs->{offset} = $min;
180 $attrs->{rows} = ($max ? ($max - $min + 1) : 1);
181 my $slice = $self->new($self->{source}, $attrs);
182 return (wantarray ? $slice->all : $slice);
187 Returns the next element in the resultset (undef is there is none).
193 my @row = $self->cursor->next;
194 return unless (@row);
195 return $self->_construct_object(@row);
198 sub _construct_object {
199 my ($self, @row) = @_;
200 my @cols = @{ $self->{attrs}{as} };
201 #warn "@cols -> @row";
202 @cols = grep { /\(/ or ! /\./ } @cols;
204 unless ($self->{attrs}{prefetch}) {
205 $new = $self->{source}->result_class->_row_to_object(\@cols, \@row);
207 my @main = splice(@row, 0, scalar @cols);
208 $new = $self->{source}->result_class->_row_to_object(\@cols, \@main);
209 PRE: foreach my $pre (@{$self->{attrs}{prefetch}}) {
210 my $rel_obj = $self->{source}->result_class->_relationships->{$pre};
211 my $pre_class = $self->{source}->result_class->resolve_class($rel_obj->{class});
212 my @pre_cols = $pre_class->_select_columns;
213 my @vals = splice(@row, 0, scalar @pre_cols);
214 my $fetched = $pre_class->_row_to_object(\@pre_cols, \@vals);
215 $self->{source}->result_class->throw("No accessor for prefetched $pre")
216 unless defined $rel_obj->{attrs}{accessor};
217 if ($rel_obj->{attrs}{accessor} eq 'single') {
218 foreach my $pri ($rel_obj->{class}->primary_columns) {
219 unless (defined $fetched->get_column($pri)) {
224 $new->{_relationship_data}{$pre} = $fetched;
225 } elsif ($rel_obj->{attrs}{accessor} eq 'filter') {
226 $new->{_inflated_column}{$pre} = $fetched;
228 $self->{source}->result_class->throw("Don't know how to store prefetched $pre");
232 $new = $self->{attrs}{record_filter}->($new)
233 if exists $self->{attrs}{record_filter};
239 Performs an SQL C<COUNT> with the same query as the resultset was built
240 with to find the number of elements. If passed arguments, does a search
241 on the resultset and counts the results of that.
247 return $self->search(@_)->count if @_ && defined $_[0];
248 unless ($self->{count}) {
249 my $attrs = { %{ $self->{attrs} },
250 select => [ 'COUNT(*)' ], as => [ 'count' ] };
251 # offset and order by are not needed to count, page, join and prefetch
252 # will get in the way (add themselves to from again ...)
253 delete $attrs->{$_} for qw/offset order_by page join prefetch/;
255 my @cols = 'COUNT(*)';
256 ($self->{count}) = $self->search(undef, $attrs)->cursor->next;
258 return 0 unless $self->{count};
259 return $self->{pager}->entries_on_this_page if ($self->{pager});
260 return ( $self->{attrs}->{rows} && $self->{attrs}->{rows} < $self->{count} )
261 ? $self->{attrs}->{rows}
267 Calls search_literal with the passed arguments, then count.
271 sub count_literal { shift->search_literal(@_)->count; }
275 Returns all elements in the resultset. Called implictly if the resultset
276 is returned in list context.
282 return map { $self->_construct_object(@$_); }
288 Resets the resultset's cursor, so you can iterate through the elements again.
294 $self->cursor->reset;
300 Resets the resultset and returns the first element.
305 return $_[0]->reset->next;
310 Deletes all elements in the resultset.
316 $_->delete for $self->all;
320 *delete_all = \&delete; # Yeah, yeah, yeah ...
324 Returns a L<Data::Page> object for the current resultset. Only makes
325 sense for queries with page turned on.
331 my $attrs = $self->{attrs};
332 delete $attrs->{offset};
333 my $rows_per_page = delete $attrs->{rows} || 10;
334 $self->{pager} ||= Data::Page->new(
335 $self->count, $rows_per_page, $attrs->{page} || 1);
336 $attrs->{rows} = $rows_per_page;
337 return $self->{pager};
340 =head2 page($page_num)
342 Returns a new resultset for the specified page.
347 my ($self, $page) = @_;
348 my $attrs = $self->{attrs};
349 $attrs->{page} = $page;
350 return $self->new($self->{source}, $attrs);
355 The resultset takes various attributes that modify its behavior.
356 Here's an overview of them:
360 Which column(s) to order the results by. This is currently passed
361 through directly to SQL, so you can give e.g. C<foo DESC> for a
364 =head2 cols (arrayref)
366 Shortcut to request a particular set of columns to be retrieved - adds
367 'me.' onto the start of any column without a '.' in it and sets 'select'
368 from that, then auto-populates 'as' from 'select' as normal
370 =head2 select (arrayref)
372 Indicates which columns should be selected from the storage
376 Indicates column names for object inflation
380 Contains a list of relationships that should be joined for this query. Can also
381 contain a hash reference to refer to that relation's relations. So, if one column
382 in your class C<belongs_to> foo and another C<belongs_to> bar, you can do
383 C<< join => [qw/ foo bar /] >> to join both (and e.g. use them for C<order_by>).
384 If a foo contains many margles and you want to join those too, you can do
385 C<< join => { foo => 'margle' } >>. If you want to fetch the columns from the
386 related table as well, see C<prefetch> below.
390 Contains a list of relationships that should be fetched along with the main
391 query (when they are accessed afterwards they will have already been
392 "prefetched"). This is useful for when you know you will need the related
393 object(s), because it saves a query. Currently limited to prefetching
394 one relationship deep, so unlike C<join>, prefetch must be an arrayref.
398 This attribute can contain a arrayref of elements. Each element can be another
399 arrayref, to nest joins, or it can be a hash which represents the two sides
402 NOTE: Use this on your own risk. This allows you to shoot your foot off!
406 For a paged resultset, specifies which page to retrieve. Leave unset
407 for an unpaged resultset.
411 For a paged resultset, how many rows per page