1 package DBIx::Class::ResultSet;
12 use base qw/DBIx::Class/;
13 __PACKAGE__->load_components(qw/AccessorGroup/);
14 __PACKAGE__->mk_group_accessors('simple' => 'result_source');
18 DBIx::Class::ResultSet - Responsible for fetching and creating resultset.
22 my $rs = $schema->resultset('User')->search(registered => 1);
23 my @rows = $schema->resultset('Foo')->search(bar => 'baz');
27 The resultset is also known as an iterator. It is responsible for handling
28 queries that may return an arbitrary number of rows, e.g. via L</search>
29 or a C<has_many> relationship.
31 In the examples below, the following table classes are used:
33 package MyApp::Schema::Artist;
34 use base qw/DBIx::Class/;
35 __PACKAGE__->table('artist');
36 __PACKAGE__->add_columns(qw/artistid name/);
37 __PACKAGE__->set_primary_key('artistid');
38 __PACKAGE__->has_many(cds => 'MyApp::Schema::CD');
41 package MyApp::Schema::CD;
42 use base qw/DBIx::Class/;
43 __PACKAGE__->table('artist');
44 __PACKAGE__->add_columns(qw/cdid artist title year/);
45 __PACKAGE__->set_primary_key('cdid');
46 __PACKAGE__->belongs_to(artist => 'MyApp::Schema::Artist');
51 =head2 new($source, \%$attrs)
53 The resultset constructor. Takes a source object (usually a
54 L<DBIx::Class::ResultSourceProxy::Table>) and an attribute hash (see L</ATRRIBUTES>
55 below). Does not perform any queries -- these are executed as needed by the
58 Generally you won't need to construct a resultset manually. You'll
59 automatically get one from e.g. a L</search> called in scalar context:
61 my $rs = $schema->resultset('CD')->search({ title => '100th Window' });
67 return $class->new_result(@_) if ref $class;
68 my ($source, $attrs) = @_;
69 #use Data::Dumper; warn Dumper($attrs);
70 $attrs = Storable::dclone($attrs || {}); # { %{ $attrs || {} } };
72 my $alias = ($attrs->{alias} ||= 'me');
73 if ($attrs->{cols} || !$attrs->{select}) {
74 delete $attrs->{as} if $attrs->{cols};
75 my @cols = ($attrs->{cols}
76 ? @{delete $attrs->{cols}}
78 $attrs->{select} = [ map { m/\./ ? $_ : "${alias}.$_" } @cols ];
80 $attrs->{as} ||= [ map { m/^$alias\.(.*)$/ ? $1 : $_ } @{$attrs->{select}} ];
81 if (my $include = delete $attrs->{include_columns}) {
82 push(@{$attrs->{select}}, @$include);
83 push(@{$attrs->{as}}, map { m/([^\.]+)$/; $1; } @$include);
85 #use Data::Dumper; warn Dumper(@{$attrs}{qw/select as/});
86 $attrs->{from} ||= [ { $alias => $source->from } ];
87 if (my $join = delete $attrs->{join}) {
88 foreach my $j (ref $join eq 'ARRAY'
89 ? (@{$join}) : ($join)) {
90 if (ref $j eq 'HASH') {
91 $seen{$_} = 1 foreach keys %$j;
96 push(@{$attrs->{from}}, $source->resolve_join($join, $attrs->{alias}));
98 $attrs->{group_by} ||= $attrs->{select} if delete $attrs->{distinct};
100 if (my $prefetch = delete $attrs->{prefetch}) {
101 foreach my $p (ref $prefetch eq 'ARRAY'
102 ? (@{$prefetch}) : ($prefetch)) {
103 if( ref $p eq 'HASH' ) {
104 foreach my $key (keys %$p) {
105 push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
110 push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
113 my @prefetch = $source->resolve_prefetch($p, $attrs->{alias});
115 push(@{$attrs->{select}}, map { $_->[0] } @prefetch);
116 push(@{$attrs->{as}}, map { $_->[1] } @prefetch);
120 if ($attrs->{page}) {
121 $attrs->{rows} ||= 10;
122 $attrs->{offset} ||= 0;
123 $attrs->{offset} += ($attrs->{rows} * ($attrs->{page} - 1));
126 result_source => $source,
127 cond => $attrs->{where},
128 from => $attrs->{from},
130 page => delete $attrs->{page},
133 bless ($new, $class);
139 my @obj = $rs->search({ foo => 3 }); # "... WHERE foo = 3"
140 my $new_rs = $rs->search({ foo => 3 });
142 If you need to pass in additional attributes but no additional condition,
143 call it as C<search({}, \%attrs);>.
145 # "SELECT foo, bar FROM $class_table"
146 my @all = $class->search({}, { cols => [qw/foo bar/] });
153 #use Data::Dumper;warn Dumper(@_);
155 my $attrs = { %{$self->{attrs}} };
156 if (@_ > 1 && ref $_[$#_] eq 'HASH') {
157 $attrs = { %$attrs, %{ pop(@_) } };
160 my $where = (@_ ? ((@_ == 1 || ref $_[0] eq "HASH") ? shift : {@_}) : undef());
161 if (defined $where) {
162 $where = (defined $attrs->{where}
164 [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
165 $where, $attrs->{where} ] }
167 $attrs->{where} = $where;
170 my $rs = (ref $self)->new($self->result_source, $attrs);
172 return (wantarray ? $rs->all : $rs);
175 =head2 search_literal
177 my @obj = $rs->search_literal($literal_where_cond, @bind);
178 my $new_rs = $rs->search_literal($literal_where_cond, @bind);
180 Pass a literal chunk of SQL to be added to the conditional part of the
186 my ($self, $cond, @vals) = @_;
187 my $attrs = (ref $vals[$#vals] eq 'HASH' ? { %{ pop(@vals) } } : {});
188 $attrs->{bind} = [ @{$self->{attrs}{bind}||[]}, @vals ];
189 return $self->search(\$cond, $attrs);
192 =head2 find(@colvalues), find(\%cols, \%attrs?)
194 Finds a row based on its primary key or unique constraint. For example:
196 my $cd = $schema->resultset('CD')->find(5);
198 Also takes an optional C<key> attribute, to search by a specific key or unique
199 constraint. For example:
201 my $cd = $schema->resultset('CD')->find_or_create(
203 artist => 'Massive Attack',
204 title => 'Mezzanine',
206 { key => 'artist_title' }
209 See also L</find_or_create> and L</update_or_create>.
214 my ($self, @vals) = @_;
215 my $attrs = (@vals > 1 && ref $vals[$#vals] eq 'HASH' ? pop(@vals) : {});
217 my @cols = $self->result_source->primary_columns;
218 if (exists $attrs->{key}) {
219 my %uniq = $self->result_source->unique_constraints;
220 $self->( "Unknown key " . $attrs->{key} . " on " . $self->name )
221 unless exists $uniq{$attrs->{key}};
222 @cols = @{ $uniq{$attrs->{key}} };
224 #use Data::Dumper; warn Dumper($attrs, @vals, @cols);
225 $self->throw_exception( "Can't find unless a primary key or unique constraint is defined" )
229 if (ref $vals[0] eq 'HASH') {
230 $query = { %{$vals[0]} };
231 } elsif (@cols == @vals) {
233 @{$query}{@cols} = @vals;
237 foreach (keys %$query) {
239 $query->{$self->{attrs}{alias}.'.'.$_} = delete $query->{$_};
241 #warn Dumper($query);
242 return $self->search($query,$attrs)->next;
245 =head2 search_related
247 $rs->search_related('relname', $cond?, $attrs?);
249 Search the specified relationship. Optionally specify a condition for matching
255 my ($self, $rel, @rest) = @_;
256 my $rel_obj = $self->result_source->relationship_info($rel);
257 $self->throw_exception(
258 "No such relationship ${rel} in search_related")
260 my $rs = $self->search(undef, { join => $rel });
261 return $self->result_source->schema->resultset($rel_obj->{class}
272 Returns a storage-driven cursor to the given resultset.
278 my ($attrs) = $self->{attrs};
279 $attrs = { %$attrs };
280 return $self->{cursor}
281 ||= $self->result_source->storage->select($self->{from}, $attrs->{select},
282 $attrs->{where},$attrs);
287 Perform a search, but use C<LIKE> instead of equality as the condition. Note
288 that this is simply a convenience method; you most likely want to use
289 L</search> with specific operators.
291 For more information, see L<DBIx::Class::Manual::Cookbook>.
298 if (@_ > 1 && ref $_[$#_] eq 'HASH') {
301 my $query = ref $_[0] eq "HASH" ? { %{shift()} }: {@_};
302 $query->{$_} = { 'like' => $query->{$_} } for keys %$query;
303 return $class->search($query, { %$attrs });
306 =head2 slice($first, $last)
308 Returns a subset of elements from the resultset.
313 my ($self, $min, $max) = @_;
314 my $attrs = { %{ $self->{attrs} || {} } };
315 $attrs->{offset} ||= 0;
316 $attrs->{offset} += $min;
317 $attrs->{rows} = ($max ? ($max - $min + 1) : 1);
318 my $slice = (ref $self)->new($self->result_source, $attrs);
319 return (wantarray ? $slice->all : $slice);
324 Returns the next element in the resultset (C<undef> is there is none).
326 Can be used to efficiently iterate over records in the resultset:
328 my $rs = $schema->resultset('CD')->search({});
329 while (my $cd = $rs->next) {
337 my @row = $self->cursor->next;
338 # warn Dumper(\@row); use Data::Dumper;
339 return unless (@row);
340 return $self->_construct_object(@row);
343 sub _construct_object {
344 my ($self, @row) = @_;
345 my @as = @{ $self->{attrs}{as} };
346 #warn "@cols -> @row";
347 my $info = [ {}, {} ];
348 foreach my $as (@as) {
350 my @parts = split(/\./, $as);
351 my $col = pop(@parts);
352 foreach my $p (@parts) {
353 $target = $target->[1]->{$p} ||= [];
355 $target->[0]->{$col} = shift @row;
357 #use Data::Dumper; warn Dumper(\@as, $info);
358 my $new = $self->result_source->result_class->inflate_result(
359 $self->result_source, @$info);
360 $new = $self->{attrs}{record_filter}->($new)
361 if exists $self->{attrs}{record_filter};
367 Returns a reference to the result source for this recordset.
374 Performs an SQL C<COUNT> with the same query as the resultset was built
375 with to find the number of elements. If passed arguments, does a search
376 on the resultset and counts the results of that.
378 Note: When using C<count> with C<group_by>, L<DBIX::Class> emulates C<GROUP BY>
379 using C<COUNT( DISTINCT( columns ) )>. Some databases (notably SQLite) do
380 not support C<DISTINCT> with multiple columns. If you are using such a
381 database, you should only use columns from the main table in your C<group_by>
388 return $self->search(@_)->count if @_ && defined $_[0];
389 unless (defined $self->{count}) {
391 my $select = { 'count' => '*' };
392 if( $group_by = delete $self->{attrs}{group_by} ) {
393 my @distinct = @$group_by;
394 # todo: try CONCAT for multi-column pk
395 my @pk = $self->result_source->primary_columns;
396 if( scalar(@pk) == 1 ) {
398 my $alias = $self->{attrs}{alias};
399 my $re = qr/^($alias\.)?$pk$/;
400 foreach my $column ( @$group_by ) {
401 if( $column =~ $re ) {
402 @distinct = ( $column );
408 $select = { count => { 'distinct' => \@distinct } };
409 #use Data::Dumper; die Dumper $select;
412 my $attrs = { %{ $self->{attrs} },
415 # offset, order by and page are not needed to count. record_filter is cdbi
416 delete $attrs->{$_} for qw/rows offset order_by page pager record_filter/;
418 ($self->{count}) = (ref $self)->new($self->result_source, $attrs)->cursor->next;
419 $self->{attrs}{group_by} = $group_by;
421 return 0 unless $self->{count};
422 my $count = $self->{count};
423 $count -= $self->{attrs}{offset} if $self->{attrs}{offset};
424 $count = $self->{attrs}{rows} if
425 ($self->{attrs}{rows} && $self->{attrs}{rows} < $count);
431 Calls L</search_literal> with the passed arguments, then L</count>.
435 sub count_literal { shift->search_literal(@_)->count; }
439 Returns all elements in the resultset. Called implictly if the resultset
440 is returned in list context.
446 return map { $self->_construct_object(@$_); }
452 Resets the resultset's cursor, so you can iterate through the elements again.
458 $self->cursor->reset;
464 Resets the resultset and returns the first element.
469 return $_[0]->reset->next;
472 =head2 update(\%values)
474 Sets the specified columns in the resultset to the supplied values.
479 my ($self, $values) = @_;
480 $self->throw_exception("Values for update must be a hash") unless ref $values eq 'HASH';
481 return $self->result_source->storage->update(
482 $self->result_source->from, $values, $self->{cond});
485 =head2 update_all(\%values)
487 Fetches all objects and updates them one at a time. Note that C<update_all>
488 will run cascade triggers while L</update> will not.
493 my ($self, $values) = @_;
494 $self->throw_exception("Values for update must be a hash") unless ref $values eq 'HASH';
495 foreach my $obj ($self->all) {
496 $obj->set_columns($values)->update;
503 Deletes the contents of the resultset from its result source.
509 $self->result_source->storage->delete($self->result_source->from, $self->{cond});
515 Fetches all objects and deletes them one at a time. Note that C<delete_all>
516 will run cascade triggers while L</delete> will not.
522 $_->delete for $self->all;
528 Returns a L<Data::Page> object for the current resultset. Only makes
529 sense for queries with a C<page> attribute.
535 my $attrs = $self->{attrs};
536 $self->throw_exception("Can't create pager for non-paged rs") unless $self->{page};
537 $attrs->{rows} ||= 10;
539 return $self->{pager} ||= Data::Page->new(
540 $self->{count}, $attrs->{rows}, $self->{page});
543 =head2 page($page_num)
545 Returns a new resultset for the specified page.
550 my ($self, $page) = @_;
551 my $attrs = { %{$self->{attrs}} };
552 $attrs->{page} = $page;
553 return (ref $self)->new($self->result_source, $attrs);
556 =head2 new_result(\%vals)
558 Creates a result in the resultset's result class.
563 my ($self, $values) = @_;
564 $self->throw_exception( "new_result needs a hash" )
565 unless (ref $values eq 'HASH');
566 $self->throw_exception( "Can't abstract implicit construct, condition not a hash" )
567 if ($self->{cond} && !(ref $self->{cond} eq 'HASH'));
569 my $alias = $self->{attrs}{alias};
570 foreach my $key (keys %{$self->{cond}||{}}) {
571 $new{$1} = $self->{cond}{$key} if ($key =~ m/^(?:$alias\.)?([^\.]+)$/);
573 my $obj = $self->result_source->result_class->new(\%new);
574 $obj->result_source($self->result_source) if $obj->can('result_source');
578 =head2 create(\%vals)
580 Inserts a record into the resultset and returns the object.
582 Effectively a shortcut for C<< ->new_result(\%vals)->insert >>.
587 my ($self, $attrs) = @_;
588 $self->throw_exception( "create needs a hashref" ) unless ref $attrs eq 'HASH';
589 return $self->new_result($attrs)->insert;
592 =head2 find_or_create(\%vals, \%attrs?)
594 $class->find_or_create({ key => $val, ... });
596 Searches for a record matching the search condition; if it doesn't find one,
597 creates one and returns that instead.
599 my $cd = $schema->resultset('CD')->find_or_create({
601 artist => 'Massive Attack',
602 title => 'Mezzanine',
606 Also takes an optional C<key> attribute, to search by a specific key or unique
607 constraint. For example:
609 my $cd = $schema->resultset('CD')->find_or_create(
611 artist => 'Massive Attack',
612 title => 'Mezzanine',
614 { key => 'artist_title' }
617 See also L</find> and L</update_or_create>.
623 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
624 my $hash = ref $_[0] eq "HASH" ? shift : {@_};
625 my $exists = $self->find($hash, $attrs);
626 return defined($exists) ? $exists : $self->create($hash);
629 =head2 update_or_create
631 $class->update_or_create({ key => $val, ... });
633 First, search for an existing row matching one of the unique constraints
634 (including the primary key) on the source of this resultset. If a row is
635 found, update it with the other given column values. Otherwise, create a new
638 Takes an optional C<key> attribute to search on a specific unique constraint.
641 # In your application
642 my $cd = $schema->resultset('CD')->update_or_create(
644 artist => 'Massive Attack',
645 title => 'Mezzanine',
648 { key => 'artist_title' }
651 If no C<key> is specified, it searches on all unique constraints defined on the
652 source, including the primary key.
654 If the C<key> is specified as C<primary>, search only on the primary key.
656 See also L</find> and L</find_or_create>.
660 sub update_or_create {
663 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
664 my $hash = ref $_[0] eq "HASH" ? shift : {@_};
666 my %unique_constraints = $self->result_source->unique_constraints;
667 my @constraint_names = (exists $attrs->{key}
669 : keys %unique_constraints);
672 foreach my $name (@constraint_names) {
673 my @unique_cols = @{ $unique_constraints{$name} };
675 map { $_ => $hash->{$_} }
676 grep { exists $hash->{$_} }
679 push @unique_hashes, \%unique_hash
680 if (scalar keys %unique_hash == scalar @unique_cols);
684 if (@unique_hashes) {
685 $row = $self->search(\@unique_hashes, { rows => 1 })->first;
687 $row->set_columns($hash);
693 $row = $self->create($hash);
699 =head2 throw_exception
701 See Schema's throw_exception
705 sub throw_exception {
707 $self->result_source->schema->throw_exception(@_);
712 The resultset takes various attributes that modify its behavior. Here's an
717 Which column(s) to order the results by. This is currently passed through
718 directly to SQL, so you can give e.g. C<foo DESC> for a descending order.
720 =head2 cols (arrayref)
722 Shortcut to request a particular set of columns to be retrieved. Adds
723 C<me.> onto the start of any column without a C<.> in it and sets C<select>
724 from that, then auto-populates C<as> from C<select> as normal.
726 =head2 include_columns (arrayref)
728 Shortcut to include additional columns in the returned results - for example
730 { include_columns => ['foo.name'], join => ['foo'] }
732 would add a 'name' column to the information passed to object inflation
734 =head2 select (arrayref)
736 Indicates which columns should be selected from the storage. You can use
737 column names, or in the case of RDBMS back ends, function or stored procedure
740 $rs = $schema->resultset('Foo')->search(
745 { count => 'column_to_count' },
746 { sum => 'column_to_sum' }
751 When you use function/stored procedure names and do not supply an C<as>
752 attribute, the column names returned are storage-dependent. E.g. MySQL would
753 return a column named C<count(column_to_count)> in the above example.
757 Indicates column names for object inflation. This is used in conjunction with
758 C<select>, usually when C<select> contains one or more function or stored
761 $rs = $schema->resultset('Foo')->search(
766 { count => 'column2' }
768 as => [qw/ column1 column2_count /]
772 my $foo = $rs->first(); # get the first Foo
774 If the object against which the search is performed already has an accessor
775 matching a column name specified in C<as>, the value can be retrieved using
776 the accessor as normal:
778 my $column1 = $foo->column1();
780 If on the other hand an accessor does not exist in the object, you need to
781 use C<get_column> instead:
783 my $column2_count = $foo->get_column('column2_count');
785 You can create your own accessors if required - see
786 L<DBIx::Class::Manual::Cookbook> for details.
790 Contains a list of relationships that should be joined for this query. For
793 # Get CDs by Nine Inch Nails
794 my $rs = $schema->resultset('CD')->search(
795 { 'artist.name' => 'Nine Inch Nails' },
799 Can also contain a hash reference to refer to the other relation's relations.
802 package MyApp::Schema::Track;
803 use base qw/DBIx::Class/;
804 __PACKAGE__->table('track');
805 __PACKAGE__->add_columns(qw/trackid cd position title/);
806 __PACKAGE__->set_primary_key('trackid');
807 __PACKAGE__->belongs_to(cd => 'MyApp::Schema::CD');
810 # In your application
811 my $rs = $schema->resultset('Artist')->search(
812 { 'track.title' => 'Teardrop' },
814 join => { cd => 'track' },
815 order_by => 'artist.name',
819 If you want to fetch columns from related tables as well, see C<prefetch>
822 =head2 prefetch arrayref/hashref
824 Contains one or more relationships that should be fetched along with the main
825 query (when they are accessed afterwards they will have already been
826 "prefetched"). This is useful for when you know you will need the related
827 objects, because it saves at least one query:
829 my $rs = $schema->resultset('Tag')->search(
838 The initial search results in SQL like the following:
840 SELECT tag.*, cd.*, artist.* FROM tag
841 JOIN cd ON tag.cd = cd.cdid
842 JOIN artist ON cd.artist = artist.artistid
844 L<DBIx::Class> has no need to go back to the database when we access the
845 C<cd> or C<artist> relationships, which saves us two SQL statements in this
848 Any prefetched relationship will be joined automatically, so there is no need
849 for a C<join> attribute in the above search.
851 C<prefetch> can be used with the following relationship types: C<belongs_to>,
854 =head2 from (arrayref)
856 The C<from> attribute gives you manual control over the C<FROM> clause of SQL
857 statements generated by L<DBIx::Class>, allowing you to express custom C<JOIN>
860 NOTE: Use this on your own risk. This allows you to shoot off your foot!
861 C<join> will usually do what you need and it is strongly recommended that you
862 avoid using C<from> unless you cannot achieve the desired result using C<join>.
864 In simple terms, C<from> works as follows:
867 { <alias> => <table>, -join-type => 'inner|left|right' }
868 [] # nested JOIN (optional)
869 { <table.column> = <foreign_table.foreign_key> }
875 ON <table.column> = <foreign_table.foreign_key>
877 An easy way to follow the examples below is to remember the following:
879 Anything inside "[]" is a JOIN
880 Anything inside "{}" is a condition for the enclosing JOIN
882 The following examples utilize a "person" table in a family tree application.
883 In order to express parent->child relationships, this table is self-joined:
885 # Person->belongs_to('father' => 'Person');
886 # Person->belongs_to('mother' => 'Person');
888 C<from> can be used to nest joins. Here we return all children with a father,
889 then search against all mothers of those children:
891 $rs = $schema->resultset('Person')->search(
894 alias => 'mother', # alias columns in accordance with "from"
896 { mother => 'person' },
899 { child => 'person' },
901 { father => 'person' },
902 { 'father.person_id' => 'child.father_id' }
905 { 'mother.person_id' => 'child.mother_id' }
912 # SELECT mother.* FROM person mother
916 # ON ( father.person_id = child.father_id )
918 # ON ( mother.person_id = child.mother_id )
920 The type of any join can be controlled manually. To search against only people
921 with a father in the person table, we could explicitly use C<INNER JOIN>:
923 $rs = $schema->resultset('Person')->search(
926 alias => 'child', # alias columns in accordance with "from"
928 { child => 'person' },
930 { father => 'person', -join-type => 'inner' },
931 { 'father.id' => 'child.father_id' }
938 # SELECT child.* FROM person child
939 # INNER JOIN person father ON child.father_id = father.id
943 For a paged resultset, specifies which page to retrieve. Leave unset
944 for an unpaged resultset.
948 For a paged resultset, how many rows per page:
952 Can also be used to simulate an SQL C<LIMIT>.
954 =head2 group_by (arrayref)
956 A arrayref of columns to group by. Can include columns of joined tables.
958 group_by => [qw/ column1 column2 ... /]
962 Set to 1 to group by all columns.
964 For more examples of using these attributes, see
965 L<DBIx::Class::Manual::Cookbook>.