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 cond => $attrs->{where},
73 from => $attrs->{from},
78 $new->pager if $attrs->{page};
84 my @obj = $rs->search({ foo => 3 }); # "... WHERE foo = 3"
85 my $new_rs = $rs->search({ foo => 3 });
87 If you need to pass in additional attributes but no additional condition,
88 call it as ->search(undef, \%attrs);
90 my @all = $class->search({}, { cols => [qw/foo bar/] }); # "SELECT foo, bar FROM $class_table"
97 #use Data::Dumper;warn Dumper(@_);
99 my $attrs = { %{$self->{attrs}} };
100 if (@_ > 1 && ref $_[$#_] eq 'HASH') {
101 $attrs = { %{ pop(@_) } };
104 my $where = ((@_ == 1 || ref $_[0] eq "HASH") ? shift : {@_});
105 if (defined $where) {
106 $where = (defined $attrs->{where}
107 ? { '-and' => [ $where, $attrs->{where} ] }
109 $attrs->{where} = $where;
112 my $rs = $self->new($self->{source}, $attrs);
114 return (wantarray ? $rs->all : $rs);
117 =head2 search_literal
118 my @obj = $rs->search_literal($literal_where_cond, @bind);
119 my $new_rs = $rs->search_literal($literal_where_cond, @bind);
121 Pass a literal chunk of SQL to be added to the conditional part of the
127 my ($self, $cond, @vals) = @_;
128 my $attrs = (ref $vals[$#vals] eq 'HASH' ? { %{ pop(@vals) } } : {});
129 $attrs->{bind} = [ @{$self->{attrs}{bind}||[]}, @vals ];
130 return $self->search(\$cond, $attrs);
135 Returns a storage-driven cursor to the given resultset.
141 my ($source, $attrs) = @{$self}{qw/source attrs/};
142 if ($attrs->{page}) {
143 $attrs->{rows} = $self->pager->entries_per_page;
144 $attrs->{offset} = $self->pager->skipped;
146 return $self->{cursor}
147 ||= $source->storage->select($self->{from}, $attrs->{select},
148 $attrs->{where},$attrs);
153 Identical to search except defaults to 'LIKE' instead of '=' in condition
160 if (@_ > 1 && ref $_[$#_] eq 'HASH') {
163 my $query = ref $_[0] eq "HASH" ? { %{shift()} }: {@_};
164 $query->{$_} = { 'like' => $query->{$_} } for keys %$query;
165 return $class->search($query, { %$attrs });
168 =head2 slice($first, $last)
170 Returns a subset of elements from the resultset.
175 my ($self, $min, $max) = @_;
176 my $attrs = { %{ $self->{attrs} || {} } };
177 $self->{source}->result_class->throw("Can't slice without where") unless $attrs->{where};
178 $attrs->{offset} = $min;
179 $attrs->{rows} = ($max ? ($max - $min + 1) : 1);
180 my $slice = $self->new($self->{source}, $attrs);
181 return (wantarray ? $slice->all : $slice);
186 Returns the next element in the resultset (undef is there is none).
192 my @row = $self->cursor->next;
193 return unless (@row);
194 return $self->_construct_object(@row);
197 sub _construct_object {
198 my ($self, @row) = @_;
199 my @cols = @{ $self->{attrs}{as} };
200 #warn "@cols -> @row";
201 @cols = grep { /\(/ or ! /\./ } @cols;
203 unless ($self->{attrs}{prefetch}) {
204 $new = $self->{source}->result_class->_row_to_object(\@cols, \@row);
206 my @main = splice(@row, 0, scalar @cols);
207 $new = $self->{source}->result_class->_row_to_object(\@cols, \@main);
208 PRE: foreach my $pre (@{$self->{attrs}{prefetch}}) {
209 my $rel_obj = $self->{source}->result_class->_relationships->{$pre};
210 my $pre_class = $self->{source}->result_class->resolve_class($rel_obj->{class});
211 my @pre_cols = $pre_class->_select_columns;
212 my @vals = splice(@row, 0, scalar @pre_cols);
213 my $fetched = $pre_class->_row_to_object(\@pre_cols, \@vals);
214 $self->{source}->result_class->throw("No accessor for prefetched $pre")
215 unless defined $rel_obj->{attrs}{accessor};
216 if ($rel_obj->{attrs}{accessor} eq 'single') {
217 foreach my $pri ($rel_obj->{class}->primary_columns) {
218 unless (defined $fetched->get_column($pri)) {
223 $new->{_relationship_data}{$pre} = $fetched;
224 } elsif ($rel_obj->{attrs}{accessor} eq 'filter') {
225 $new->{_inflated_column}{$pre} = $fetched;
227 $self->{source}->result_class->throw("Don't know how to store prefetched $pre");
231 $new = $self->{attrs}{record_filter}->($new)
232 if exists $self->{attrs}{record_filter};
238 Performs an SQL C<COUNT> with the same query as the resultset was built
239 with to find the number of elements. If passed arguments, does a search
240 on the resultset and counts the results of that.
246 return $self->search(@_)->count if @_ && defined $_[0];
247 unless ($self->{count}) {
248 my $attrs = { %{ $self->{attrs} },
249 select => [ 'COUNT(*)' ], as => [ 'count' ] };
250 # offset and order by are not needed to count, page, join and prefetch
251 # will get in the way (add themselves to from again ...)
252 delete $attrs->{$_} for qw/offset order_by page join prefetch/;
254 my @cols = 'COUNT(*)';
255 ($self->{count}) = $self->search(undef, $attrs)->cursor->next;
257 return 0 unless $self->{count};
258 return $self->{pager}->entries_on_this_page if ($self->{pager});
259 return ( $self->{attrs}->{rows} && $self->{attrs}->{rows} < $self->{count} )
260 ? $self->{attrs}->{rows}
266 Calls search_literal with the passed arguments, then count.
270 sub count_literal { shift->search_literal(@_)->count; }
274 Returns all elements in the resultset. Called implictly if the resultset
275 is returned in list context.
281 return map { $self->_construct_object(@$_); }
287 Resets the resultset's cursor, so you can iterate through the elements again.
293 $self->cursor->reset;
299 Resets the resultset and returns the first element.
304 return $_[0]->reset->next;
309 Deletes all elements in the resultset.
315 $_->delete for $self->all;
319 *delete_all = \&delete; # Yeah, yeah, yeah ...
323 Returns a L<Data::Page> object for the current resultset. Only makes
324 sense for queries with page turned on.
330 my $attrs = $self->{attrs};
331 delete $attrs->{offset};
332 my $rows_per_page = delete $attrs->{rows} || 10;
333 $self->{pager} ||= Data::Page->new(
334 $self->count, $rows_per_page, $attrs->{page} || 1);
335 $attrs->{rows} = $rows_per_page;
336 return $self->{pager};
339 =head2 page($page_num)
341 Returns a new resultset for the specified page.
346 my ($self, $page) = @_;
347 my $attrs = $self->{attrs};
348 $attrs->{page} = $page;
349 return $self->new($self->{source}, $attrs);
354 The resultset takes various attributes that modify its behavior.
355 Here's an overview of them:
359 Which column(s) to order the results by. This is currently passed
360 through directly to SQL, so you can give e.g. C<foo DESC> for a
363 =head2 cols (arrayref)
365 Shortcut to request a particular set of columns to be retrieved - adds
366 'me.' onto the start of any column without a '.' in it and sets 'select'
367 from that, then auto-populates 'as' from 'select' as normal
369 =head2 select (arrayref)
371 Indicates which columns should be selected from the storage
375 Indicates column names for object inflation
379 Contains a list of relationships that should be joined for this query. Can also
380 contain a hash reference to refer to that relation's relations. So, if one column
381 in your class C<belongs_to> foo and another C<belongs_to> bar, you can do
382 C<< join => [qw/ foo bar /] >> to join both (and e.g. use them for C<order_by>).
383 If a foo contains many margles and you want to join those too, you can do
384 C<< join => { foo => 'margle' } >>. If you want to fetch the columns from the
385 related table as well, see C<prefetch> below.
389 Contains a list of relationships that should be fetched along with the main
390 query (when they are accessed afterwards they will have already been
391 "prefetched"). This is useful for when you know you will need the related
392 object(s), because it saves a query. Currently limited to prefetching
393 one relationship deep, so unlike C<join>, prefetch must be an arrayref.
397 This attribute can contain a arrayref of elements. Each element can be another
398 arrayref, to nest joins, or it can be a hash which represents the two sides
401 NOTE: Use this on your own risk. This allows you to shoot your foot off!
405 For a paged resultset, specifies which page to retrieve. Leave unset
406 for an unpaged resultset.
410 For a paged resultset, how many rows per page