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 } ];
50 if (my $join = delete $attrs->{join}) {
51 foreach my $j (ref $join eq 'ARRAY'
52 ? (@{$join}) : ($join)) {
53 if (ref $j eq 'HASH') {
54 $seen{$_} = 1 foreach keys %$j;
59 push(@{$attrs->{from}}, $source->result_class->_resolve_join($join, 'me'));
61 $attrs->{group_by} ||= $attrs->{select} if delete $attrs->{distinct};
62 foreach my $pre (@{delete $attrs->{prefetch} || []}) {
63 push(@{$attrs->{from}}, $source->result_class->_resolve_join($pre, 'me'))
67 $source->result_class->_relationships->{$pre}->{class}->columns;
68 push(@{$attrs->{select}}, @pre);
69 push(@{$attrs->{as}}, @pre);
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);
134 =head2 search_related
136 $rs->search_related('relname', $cond?, $attrs?);
140 sub search_related { }
144 Returns a storage-driven cursor to the given resultset.
150 my ($source, $attrs) = @{$self}{qw/source attrs/};
151 if ($attrs->{page}) {
152 $attrs->{rows} = $self->pager->entries_per_page;
153 $attrs->{offset} = $self->pager->skipped;
155 return $self->{cursor}
156 ||= $source->storage->select($self->{from}, $attrs->{select},
157 $attrs->{where},$attrs);
162 Identical to search except defaults to 'LIKE' instead of '=' in condition
169 if (@_ > 1 && ref $_[$#_] eq 'HASH') {
172 my $query = ref $_[0] eq "HASH" ? { %{shift()} }: {@_};
173 $query->{$_} = { 'like' => $query->{$_} } for keys %$query;
174 return $class->search($query, { %$attrs });
177 =head2 slice($first, $last)
179 Returns a subset of elements from the resultset.
184 my ($self, $min, $max) = @_;
185 my $attrs = { %{ $self->{attrs} || {} } };
186 $self->{source}->result_class->throw("Can't slice without where") unless $attrs->{where};
187 $attrs->{offset} = $min;
188 $attrs->{rows} = ($max ? ($max - $min + 1) : 1);
189 my $slice = $self->new($self->{source}, $attrs);
190 return (wantarray ? $slice->all : $slice);
195 Returns the next element in the resultset (undef is there is none).
201 my @row = $self->cursor->next;
202 return unless (@row);
203 return $self->_construct_object(@row);
206 sub _construct_object {
207 my ($self, @row) = @_;
208 my @cols = @{ $self->{attrs}{as} };
209 #warn "@cols -> @row";
211 foreach my $col (@cols) {
212 if ($col =~ /([^\.]+)\.([^\.]+)/) {
213 $pre{$1}{$2} = shift @row;
215 $me{$col} = shift @row;
218 my $new = $self->{source}->result_class->inflate_result(\%me, \%pre);
219 $new = $self->{attrs}{record_filter}->($new)
220 if exists $self->{attrs}{record_filter};
226 Performs an SQL C<COUNT> with the same query as the resultset was built
227 with to find the number of elements. If passed arguments, does a search
228 on the resultset and counts the results of that.
234 return $self->search(@_)->count if @_ && defined $_[0];
235 die "Unable to ->count with a GROUP BY" if defined $self->{attrs}{group_by};
236 unless ($self->{count}) {
237 my $attrs = { %{ $self->{attrs} },
238 select => { 'count' => '*' },
240 # offset and order by are not needed to count, page, join and prefetch
241 # will get in the way (add themselves to from again ...)
242 delete $attrs->{$_} for qw/offset order_by page join prefetch/;
244 my @cols = 'COUNT(*)';
245 ($self->{count}) = $self->search(undef, $attrs)->cursor->next;
247 return 0 unless $self->{count};
248 return $self->{pager}->entries_on_this_page if ($self->{pager});
249 return ( $self->{attrs}->{rows} && $self->{attrs}->{rows} < $self->{count} )
250 ? $self->{attrs}->{rows}
256 Calls search_literal with the passed arguments, then count.
260 sub count_literal { shift->search_literal(@_)->count; }
264 Returns all elements in the resultset. Called implictly if the resultset
265 is returned in list context.
271 return map { $self->_construct_object(@$_); }
277 Resets the resultset's cursor, so you can iterate through the elements again.
283 $self->cursor->reset;
289 Resets the resultset and returns the first element.
294 return $_[0]->reset->next;
299 Deletes all elements in the resultset.
305 $_->delete for $self->all;
309 *delete_all = \&delete; # Yeah, yeah, yeah ...
313 Returns a L<Data::Page> object for the current resultset. Only makes
314 sense for queries with page turned on.
320 my $attrs = $self->{attrs};
321 delete $attrs->{offset};
322 my $rows_per_page = delete $attrs->{rows} || 10;
323 $self->{pager} ||= Data::Page->new(
324 $self->count, $rows_per_page, $attrs->{page} || 1);
325 $attrs->{rows} = $rows_per_page;
326 return $self->{pager};
329 =head2 page($page_num)
331 Returns a new resultset for the specified page.
336 my ($self, $page) = @_;
337 my $attrs = $self->{attrs};
338 $attrs->{page} = $page;
339 return $self->new($self->{source}, $attrs);
344 The resultset takes various attributes that modify its behavior.
345 Here's an overview of them:
349 Which column(s) to order the results by. This is currently passed
350 through directly to SQL, so you can give e.g. C<foo DESC> for a
353 =head2 cols (arrayref)
355 Shortcut to request a particular set of columns to be retrieved - adds
356 'me.' onto the start of any column without a '.' in it and sets 'select'
357 from that, then auto-populates 'as' from 'select' as normal
359 =head2 select (arrayref)
361 Indicates which columns should be selected from the storage
365 Indicates column names for object inflation
369 Contains a list of relationships that should be joined for this query. Can also
370 contain a hash reference to refer to that relation's relations. So, if one column
371 in your class C<belongs_to> foo and another C<belongs_to> bar, you can do
372 C<< join => [qw/ foo bar /] >> to join both (and e.g. use them for C<order_by>).
373 If a foo contains many margles and you want to join those too, you can do
374 C<< join => { foo => 'margle' } >>. If you want to fetch the columns from the
375 related table as well, see C<prefetch> below.
379 Contains a list of relationships that should be fetched along with the main
380 query (when they are accessed afterwards they will have already been
381 "prefetched"). This is useful for when you know you will need the related
382 object(s), because it saves a query. Currently limited to prefetching
383 one relationship deep, so unlike C<join>, prefetch must be an arrayref.
387 This attribute can contain a arrayref of elements. Each element can be another
388 arrayref, to nest joins, or it can be a hash which represents the two sides
391 NOTE: Use this on your own risk. This allows you to shoot your foot off!
395 For a paged resultset, specifies which page to retrieve. Leave unset
396 for an unpaged resultset.
400 For a paged resultset, how many rows per page
404 A list of columns to group by (note that 'count' doesn't work on grouped
409 Set to 1 to group by all columns