1 package DBIx::Class::ResultSet;
12 DBIX::Class::ResultSet - Responsible for fetching and creating resultset.
16 $rs=MyApp::DB::Class->search(registered=>1);
20 The resultset is also known as an iterator.
26 =item new <db_class> <attrs>
28 The resultset constructor. Takes a db class and an
29 attribute hash (see below for more info on attributes)
34 my ($class, $db_class, $attrs) = @_;
35 #use Data::Dumper; warn Dumper(@_);
36 $class = ref $class if ref $class;
37 $attrs = { %{ $attrs || {} } };
39 $attrs->{cols} ||= [ map { "me.$_" } $db_class->_select_columns ];
40 $attrs->{from} ||= [ { 'me' => $db_class->_table_name } ];
42 foreach my $j (ref $attrs->{join} eq 'ARRAY'
43 ? (@{$attrs->{join}}) : ($attrs->{join})) {
44 if (ref $j eq 'HASH') {
45 $seen{$_} = 1 foreach keys %$j;
50 push(@{$attrs->{from}}, $db_class->_resolve_join($attrs->{join}, 'me'));
52 foreach my $pre (@{$attrs->{prefetch} || []}) {
53 push(@{$attrs->{from}}, $db_class->_resolve_join($pre, 'me'))
55 push(@{$attrs->{cols}},
57 $db_class->_relationships->{$pre}->{class}->_select_columns);
61 cols => $attrs->{cols},
62 cond => $attrs->{where},
63 from => $attrs->{from},
68 $new->pager if ($attrs->{page});
74 Runs a search against the current resultset.
81 my $attrs = { %{$self->{attrs}} };
82 if (@_ > 1 && ref $_[$#_] eq 'HASH') {
83 $attrs = { %{ pop(@_) } };
86 my $where = (@_ == 1 || ref $_[0] eq "HASH" ? shift: {@_});
88 $where = (defined $attrs->{where}
89 ? { '-and' => [ $where, $attrs->{where} ] }
91 $attrs->{where} = $where;
94 my $rs = $self->new($self->{source}, $attrs);
96 return (wantarray ? $rs->all : $rs);
102 Return a storage driven cursor to the given resultset.
108 my ($source, $attrs) = @{$self}{qw/source attrs/};
109 if ($attrs->{page}) {
110 $attrs->{rows} = $self->pager->entries_per_page;
111 $attrs->{offset} = $self->pager->skipped;
113 return $self->{cursor}
114 ||= $source->storage->select($self->{from}, $self->{cols},
115 $attrs->{where},$attrs);
118 =item slice <first> <last>
120 return a number of elements from the given resultset.
125 my ($self, $min, $max) = @_;
126 my $attrs = { %{ $self->{attrs} || {} } };
127 $self->{source}->throw("Can't slice without where") unless $attrs->{where};
128 $attrs->{offset} = $min;
129 $attrs->{rows} = ($max ? ($max - $min + 1) : 1);
130 my $slice = $self->new($self->{source}, $attrs);
131 return (wantarray ? $slice->all : $slice);
136 Returns the next element in this resultset.
142 my @row = $self->cursor->next;
143 return unless (@row);
144 return $self->_construct_object(@row);
147 sub _construct_object {
148 my ($self, @row) = @_;
149 my @cols = @{ $self->{attrs}{cols} };
151 @cols = grep { /\(/ or ! /\./ } @cols;
153 unless ($self->{attrs}{prefetch}) {
154 $new = $self->{source}->_row_to_object(\@cols, \@row);
156 my @main = splice(@row, 0, scalar @cols);
157 $new = $self->{source}->_row_to_object(\@cols, \@main);
158 PRE: foreach my $pre (@{$self->{attrs}{prefetch}}) {
159 my $rel_obj = $self->{source}->_relationships->{$pre};
160 my $pre_class = $self->{source}->resolve_class($rel_obj->{class});
161 my @pre_cols = $pre_class->_select_columns;
162 my @vals = splice(@row, 0, scalar @pre_cols);
163 my $fetched = $pre_class->_row_to_object(\@pre_cols, \@vals);
164 $self->{source}->throw("No accessor for prefetched $pre")
165 unless defined $rel_obj->{attrs}{accessor};
166 if ($rel_obj->{attrs}{accessor} eq 'single') {
167 foreach my $pri ($rel_obj->{class}->primary_columns) {
168 unless (defined $fetched->get_column($pri)) {
173 $new->{_relationship_data}{$pre} = $fetched;
174 } elsif ($rel_obj->{attrs}{accessor} eq 'filter') {
175 $new->{_inflated_column}{$pre} = $fetched;
177 $self->{source}->throw("Don't know how to store prefetched $pre");
181 $new = $self->{attrs}{record_filter}->($new)
182 if exists $self->{attrs}{record_filter};
188 Performs an SQL count with the same query as the resultset was built
189 with to find the number of elements.
196 my $attrs = { %{ $self->{attrs} } };
197 unless ($self->{count}) {
198 # offset and order by are not needed to count
199 delete $attrs->{$_} for qw/offset order_by/;
201 my @cols = 'COUNT(*)';
202 $self->{count} = $self->{source}->storage->select_single(
203 $self->{from}, \@cols, $self->{cond}, $attrs);
205 return 0 unless $self->{count};
206 return $self->{pager}->entries_on_this_page if ($self->{pager});
207 return ( $attrs->{rows} && $attrs->{rows} < $self->{count} )
214 Returns all elements in the resultset. Is called implictly if the search
215 method is used in list context.
221 return map { $self->_construct_object(@$_); }
227 Reset this resultset's cursor, so you can iterate through the elements again.
233 $self->cursor->reset;
239 resets the resultset and returns the first element.
244 return $_[0]->reset->next;
249 Deletes all elements in the resultset.
255 $_->delete for $self->all;
259 *delete_all = \&delete; # Yeah, yeah, yeah ...
263 Returns a L<Data::Page> object for the current resultset. Only makes
264 sense for queries with page turned on.
270 my $attrs = $self->{attrs};
271 delete $attrs->{offset};
272 my $rows_per_page = delete $attrs->{rows} || 10;
273 $self->{pager} ||= Data::Page->new(
274 $self->count, $rows_per_page, $attrs->{page} || 1);
275 $attrs->{rows} = $rows_per_page;
276 return $self->{pager};
281 Returns a new resultset representing a given page.
286 my ($self, $page) = @_;
287 my $attrs = $self->{attrs};
288 $attrs->{page} = $page;
289 return $self->new($self->{source}, $attrs);
296 The resultset is responsible for handling the various attributes that
297 can be passed in with the search functions. Here's an overview of them:
303 Which column to order the results by.
307 Which cols should be retrieved on the first search.
311 Contains a list of relations that should be joined for this query. Can also
312 contain a hash referece to refer to that relation's relations.
316 This attribute can contain a arrayref of elements. each element can be another
317 arrayref, to nest joins, or it can be a hash which represents the two sides
320 *NOTE* Use this on your own risk. This allows you to shoot your foot off!
324 Should the resultset be paged? This can also be enabled by using the
329 For paged resultsset, how many rows per page
333 For paged resultsset, which page to start on.