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__->load_components(qw/Core/);
36 __PACKAGE__->table('artist');
37 __PACKAGE__->add_columns(qw/artistid name/);
38 __PACKAGE__->set_primary_key('artistid');
39 __PACKAGE__->has_many(cds => 'MyApp::Schema::CD');
42 package MyApp::Schema::CD;
43 use base qw/DBIx::Class/;
44 __PACKAGE__->load_components(qw/Core/);
45 __PACKAGE__->table('cd');
46 __PACKAGE__->add_columns(qw/cdid artist title year/);
47 __PACKAGE__->set_primary_key('cdid');
48 __PACKAGE__->belongs_to(artist => 'MyApp::Schema::Artist');
55 =head3 Arguments: ($source, \%$attrs)
57 The resultset constructor. Takes a source object (usually a
58 L<DBIx::Class::ResultSourceProxy::Table>) and an attribute hash (see L</ATTRIBUTES>
59 below). Does not perform any queries -- these are executed as needed by the
62 Generally you won't need to construct a resultset manually. You'll
63 automatically get one from e.g. a L</search> called in scalar context:
65 my $rs = $schema->resultset('CD')->search({ title => '100th Window' });
71 return $class->new_result(@_) if ref $class;
72 my ($source, $attrs) = @_;
73 #use Data::Dumper; warn Dumper($attrs);
74 $attrs = Storable::dclone($attrs || {}); # { %{ $attrs || {} } };
76 my $alias = ($attrs->{alias} ||= 'me');
77 if ($attrs->{cols} || !$attrs->{select}) {
78 delete $attrs->{as} if $attrs->{cols};
79 my @cols = ($attrs->{cols}
80 ? @{delete $attrs->{cols}}
82 $attrs->{select} = [ map { m/\./ ? $_ : "${alias}.$_" } @cols ];
84 $attrs->{as} ||= [ map { m/^$alias\.(.*)$/ ? $1 : $_ } @{$attrs->{select}} ];
85 if (my $include = delete $attrs->{include_columns}) {
86 push(@{$attrs->{select}}, @$include);
87 push(@{$attrs->{as}}, map { m/([^\.]+)$/; $1; } @$include);
89 #use Data::Dumper; warn Dumper(@{$attrs}{qw/select as/});
90 $attrs->{from} ||= [ { $alias => $source->from } ];
91 $attrs->{seen_join} ||= {};
92 if (my $join = delete $attrs->{join}) {
93 foreach my $j (ref $join eq 'ARRAY'
94 ? (@{$join}) : ($join)) {
95 if (ref $j eq 'HASH') {
96 $seen{$_} = 1 foreach keys %$j;
101 push(@{$attrs->{from}}, $source->resolve_join($join, $attrs->{alias}, $attrs->{seen_join}));
103 $attrs->{group_by} ||= $attrs->{select} if delete $attrs->{distinct};
105 if (my $prefetch = delete $attrs->{prefetch}) {
106 foreach my $p (ref $prefetch eq 'ARRAY'
107 ? (@{$prefetch}) : ($prefetch)) {
108 if( ref $p eq 'HASH' ) {
109 foreach my $key (keys %$p) {
110 push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
115 push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias}))
118 my @prefetch = $source->resolve_prefetch($p, $attrs->{alias});
120 push(@{$attrs->{select}}, map { $_->[0] } @prefetch);
121 push(@{$attrs->{as}}, map { $_->[1] } @prefetch);
125 if ($attrs->{page}) {
126 $attrs->{rows} ||= 10;
127 $attrs->{offset} ||= 0;
128 $attrs->{offset} += ($attrs->{rows} * ($attrs->{page} - 1));
131 result_source => $source,
132 cond => $attrs->{where},
133 from => $attrs->{from},
135 page => delete $attrs->{page},
138 bless ($new, $class);
144 my @obj = $rs->search({ foo => 3 }); # "... WHERE foo = 3"
145 my $new_rs = $rs->search({ foo => 3 });
147 If you need to pass in additional attributes but no additional condition,
148 call it as C<search({}, \%attrs);>.
150 # "SELECT foo, bar FROM $class_table"
151 my @all = $class->search({}, { cols => [qw/foo bar/] });
158 #use Data::Dumper;warn Dumper(@_);
160 my $attrs = { %{$self->{attrs}} };
161 if (@_ > 1 && ref $_[$#_] eq 'HASH') {
162 $attrs = { %$attrs, %{ pop(@_) } };
165 my $where = (@_ ? ((@_ == 1 || ref $_[0] eq "HASH") ? shift : {@_}) : undef());
166 if (defined $where) {
167 $where = (defined $attrs->{where}
169 [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
170 $where, $attrs->{where} ] }
172 $attrs->{where} = $where;
175 my $rs = (ref $self)->new($self->result_source, $attrs);
177 return (wantarray ? $rs->all : $rs);
180 =head2 search_literal
182 my @obj = $rs->search_literal($literal_where_cond, @bind);
183 my $new_rs = $rs->search_literal($literal_where_cond, @bind);
185 Pass a literal chunk of SQL to be added to the conditional part of the
191 my ($self, $cond, @vals) = @_;
192 my $attrs = (ref $vals[$#vals] eq 'HASH' ? { %{ pop(@vals) } } : {});
193 $attrs->{bind} = [ @{$self->{attrs}{bind}||[]}, @vals ];
194 return $self->search(\$cond, $attrs);
199 =head3 Arguments: (@colvalues) | (\%cols, \%attrs?)
201 Finds a row based on its primary key or unique constraint. For example:
203 my $cd = $schema->resultset('CD')->find(5);
205 Also takes an optional C<key> attribute, to search by a specific key or unique
206 constraint. For example:
208 my $cd = $schema->resultset('CD')->find(
210 artist => 'Massive Attack',
211 title => 'Mezzanine',
213 { key => 'artist_title' }
216 See also L</find_or_create> and L</update_or_create>.
221 my ($self, @vals) = @_;
222 my $attrs = (@vals > 1 && ref $vals[$#vals] eq 'HASH' ? pop(@vals) : {});
224 my @cols = $self->result_source->primary_columns;
225 if (exists $attrs->{key}) {
226 my %uniq = $self->result_source->unique_constraints;
227 $self->( "Unknown key " . $attrs->{key} . " on " . $self->name )
228 unless exists $uniq{$attrs->{key}};
229 @cols = @{ $uniq{$attrs->{key}} };
231 #use Data::Dumper; warn Dumper($attrs, @vals, @cols);
232 $self->throw_exception( "Can't find unless a primary key or unique constraint is defined" )
236 if (ref $vals[0] eq 'HASH') {
237 $query = { %{$vals[0]} };
238 } elsif (@cols == @vals) {
240 @{$query}{@cols} = @vals;
244 foreach (keys %$query) {
246 $query->{$self->{attrs}{alias}.'.'.$_} = delete $query->{$_};
248 #warn Dumper($query);
249 return $self->search($query,$attrs)->next;
252 =head2 search_related
254 $rs->search_related('relname', $cond?, $attrs?);
256 Search the specified relationship. Optionally specify a condition for matching
262 my ($self, $rel, @rest) = @_;
263 my $rel_obj = $self->result_source->relationship_info($rel);
264 $self->throw_exception(
265 "No such relationship ${rel} in search_related")
267 my $rs = $self->search(undef, { join => $rel });
268 my $alias = ($rs->{attrs}{seen_join}{$rel} > 1
269 ? join('_', $rel, $rs->{attrs}{seen_join}{$rel})
271 return $self->result_source->schema->resultset($rel_obj->{class}
282 Returns a storage-driven cursor to the given resultset.
288 my ($attrs) = $self->{attrs};
289 $attrs = { %$attrs };
290 return $self->{cursor}
291 ||= $self->result_source->storage->select($self->{from}, $attrs->{select},
292 $attrs->{where},$attrs);
297 Perform a search, but use C<LIKE> instead of equality as the condition. Note
298 that this is simply a convenience method; you most likely want to use
299 L</search> with specific operators.
301 For more information, see L<DBIx::Class::Manual::Cookbook>.
308 if (@_ > 1 && ref $_[$#_] eq 'HASH') {
311 my $query = ref $_[0] eq "HASH" ? { %{shift()} }: {@_};
312 $query->{$_} = { 'like' => $query->{$_} } for keys %$query;
313 return $class->search($query, { %$attrs });
318 =head3 Arguments: ($first, $last)
320 Returns a subset of elements from the resultset.
325 my ($self, $min, $max) = @_;
326 my $attrs = { %{ $self->{attrs} || {} } };
327 $attrs->{offset} ||= 0;
328 $attrs->{offset} += $min;
329 $attrs->{rows} = ($max ? ($max - $min + 1) : 1);
330 my $slice = (ref $self)->new($self->result_source, $attrs);
331 return (wantarray ? $slice->all : $slice);
336 Returns the next element in the resultset (C<undef> is there is none).
338 Can be used to efficiently iterate over records in the resultset:
340 my $rs = $schema->resultset('CD')->search({});
341 while (my $cd = $rs->next) {
349 my @row = $self->cursor->next;
350 # warn Dumper(\@row); use Data::Dumper;
351 return unless (@row);
352 return $self->_construct_object(@row);
355 sub _construct_object {
356 my ($self, @row) = @_;
357 my @as = @{ $self->{attrs}{as} };
358 #warn "@cols -> @row";
359 my $info = [ {}, {} ];
360 foreach my $as (@as) {
362 my @parts = split(/\./, $as);
363 my $col = pop(@parts);
364 foreach my $p (@parts) {
365 $target = $target->[1]->{$p} ||= [];
367 $target->[0]->{$col} = shift @row;
369 #use Data::Dumper; warn Dumper(\@as, $info);
370 my $new = $self->result_source->result_class->inflate_result(
371 $self->result_source, @$info);
372 $new = $self->{attrs}{record_filter}->($new)
373 if exists $self->{attrs}{record_filter};
379 Returns a reference to the result source for this recordset.
386 Performs an SQL C<COUNT> with the same query as the resultset was built
387 with to find the number of elements. If passed arguments, does a search
388 on the resultset and counts the results of that.
390 Note: When using C<count> with C<group_by>, L<DBIX::Class> emulates C<GROUP BY>
391 using C<COUNT( DISTINCT( columns ) )>. Some databases (notably SQLite) do
392 not support C<DISTINCT> with multiple columns. If you are using such a
393 database, you should only use columns from the main table in your C<group_by>
400 return $self->search(@_)->count if @_ && defined $_[0];
401 unless (defined $self->{count}) {
403 my $select = { 'count' => '*' };
404 if( $group_by = delete $self->{attrs}{group_by} ) {
405 my @distinct = (ref $group_by ? @$group_by : ($group_by));
406 # todo: try CONCAT for multi-column pk
407 my @pk = $self->result_source->primary_columns;
408 if( scalar(@pk) == 1 ) {
410 my $alias = $self->{attrs}{alias};
411 my $re = qr/^($alias\.)?$pk$/;
412 foreach my $column ( @distinct) {
413 if( $column =~ $re ) {
414 @distinct = ( $column );
420 $select = { count => { 'distinct' => \@distinct } };
421 #use Data::Dumper; die Dumper $select;
424 my $attrs = { %{ $self->{attrs} },
427 # offset, order by and page are not needed to count. record_filter is cdbi
428 delete $attrs->{$_} for qw/rows offset order_by page pager record_filter/;
430 ($self->{count}) = (ref $self)->new($self->result_source, $attrs)->cursor->next;
431 $self->{attrs}{group_by} = $group_by;
433 return 0 unless $self->{count};
434 my $count = $self->{count};
435 $count -= $self->{attrs}{offset} if $self->{attrs}{offset};
436 $count = $self->{attrs}{rows} if
437 ($self->{attrs}{rows} && $self->{attrs}{rows} < $count);
443 Calls L</search_literal> with the passed arguments, then L</count>.
447 sub count_literal { shift->search_literal(@_)->count; }
451 Returns all elements in the resultset. Called implictly if the resultset
452 is returned in list context.
458 return map { $self->_construct_object(@$_); }
464 Resets the resultset's cursor, so you can iterate through the elements again.
470 $self->cursor->reset;
476 Resets the resultset and returns the first element.
481 return $_[0]->reset->next;
486 =head3 Arguments: (\%values)
488 Sets the specified columns in the resultset to the supplied values.
493 my ($self, $values) = @_;
494 $self->throw_exception("Values for update must be a hash") unless ref $values eq 'HASH';
495 return $self->result_source->storage->update(
496 $self->result_source->from, $values, $self->{cond});
501 =head3 Arguments: (\%values)
503 Fetches all objects and updates them one at a time. Note that C<update_all>
504 will run cascade triggers while L</update> will not.
509 my ($self, $values) = @_;
510 $self->throw_exception("Values for update must be a hash") unless ref $values eq 'HASH';
511 foreach my $obj ($self->all) {
512 $obj->set_columns($values)->update;
519 Deletes the contents of the resultset from its result source.
526 $self->throw_exception("Can't delete on resultset with condition unless hash or array")
527 unless (ref($self->{cond}) eq 'HASH' || ref($self->{cond}) eq 'ARRAY');
528 if (ref $self->{cond} eq 'ARRAY') {
529 $del = [ map { my %hash;
530 foreach my $key (keys %{$_}) {
532 $hash{$1} = $_->{$key};
533 }; \%hash; } @{$self->{cond}} ];
534 } elsif ((keys %{$self->{cond}})[0] eq '-and') {
535 $del->{-and} = [ map { my %hash;
536 foreach my $key (keys %{$_}) {
538 $hash{$1} = $_->{$key};
539 }; \%hash; } @{$self->{cond}{-and}} ];
541 foreach my $key (keys %{$self->{cond}}) {
543 $del->{$1} = $self->{cond}{$key};
546 $self->result_source->storage->delete($self->result_source->from, $del);
552 Fetches all objects and deletes them one at a time. Note that C<delete_all>
553 will run cascade triggers while L</delete> will not.
559 $_->delete for $self->all;
565 Returns a L<Data::Page> object for the current resultset. Only makes
566 sense for queries with a C<page> attribute.
572 my $attrs = $self->{attrs};
573 $self->throw_exception("Can't create pager for non-paged rs") unless $self->{page};
574 $attrs->{rows} ||= 10;
576 return $self->{pager} ||= Data::Page->new(
577 $self->{count}, $attrs->{rows}, $self->{page});
582 =head3 Arguments: ($page_num)
584 Returns a new resultset for the specified page.
589 my ($self, $page) = @_;
590 my $attrs = { %{$self->{attrs}} };
591 $attrs->{page} = $page;
592 return (ref $self)->new($self->result_source, $attrs);
597 =head3 Arguments: (\%vals)
599 Creates a result in the resultset's result class.
604 my ($self, $values) = @_;
605 $self->throw_exception( "new_result needs a hash" )
606 unless (ref $values eq 'HASH');
607 $self->throw_exception( "Can't abstract implicit construct, condition not a hash" )
608 if ($self->{cond} && !(ref $self->{cond} eq 'HASH'));
610 my $alias = $self->{attrs}{alias};
611 foreach my $key (keys %{$self->{cond}||{}}) {
612 $new{$1} = $self->{cond}{$key} if ($key =~ m/^(?:$alias\.)?([^\.]+)$/);
614 my $obj = $self->result_source->result_class->new(\%new);
615 $obj->result_source($self->result_source) if $obj->can('result_source');
621 =head3 Arguments: (\%vals)
623 Inserts a record into the resultset and returns the object.
625 Effectively a shortcut for C<< ->new_result(\%vals)->insert >>.
630 my ($self, $attrs) = @_;
631 $self->throw_exception( "create needs a hashref" ) unless ref $attrs eq 'HASH';
632 return $self->new_result($attrs)->insert;
635 =head2 find_or_create
637 =head3 Arguments: (\%vals, \%attrs?)
639 $class->find_or_create({ key => $val, ... });
641 Searches for a record matching the search condition; if it doesn't find one,
642 creates one and returns that instead.
644 my $cd = $schema->resultset('CD')->find_or_create({
646 artist => 'Massive Attack',
647 title => 'Mezzanine',
651 Also takes an optional C<key> attribute, to search by a specific key or unique
652 constraint. For example:
654 my $cd = $schema->resultset('CD')->find_or_create(
656 artist => 'Massive Attack',
657 title => 'Mezzanine',
659 { key => 'artist_title' }
662 See also L</find> and L</update_or_create>.
668 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
669 my $hash = ref $_[0] eq "HASH" ? shift : {@_};
670 my $exists = $self->find($hash, $attrs);
671 return defined($exists) ? $exists : $self->create($hash);
674 =head2 update_or_create
676 $class->update_or_create({ key => $val, ... });
678 First, search for an existing row matching one of the unique constraints
679 (including the primary key) on the source of this resultset. If a row is
680 found, update it with the other given column values. Otherwise, create a new
683 Takes an optional C<key> attribute to search on a specific unique constraint.
686 # In your application
687 my $cd = $schema->resultset('CD')->update_or_create(
689 artist => 'Massive Attack',
690 title => 'Mezzanine',
693 { key => 'artist_title' }
696 If no C<key> is specified, it searches on all unique constraints defined on the
697 source, including the primary key.
699 If the C<key> is specified as C<primary>, search only on the primary key.
701 See also L</find> and L</find_or_create>.
705 sub update_or_create {
708 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
709 my $hash = ref $_[0] eq "HASH" ? shift : {@_};
711 my %unique_constraints = $self->result_source->unique_constraints;
712 my @constraint_names = (exists $attrs->{key}
714 : keys %unique_constraints);
717 foreach my $name (@constraint_names) {
718 my @unique_cols = @{ $unique_constraints{$name} };
720 map { $_ => $hash->{$_} }
721 grep { exists $hash->{$_} }
724 push @unique_hashes, \%unique_hash
725 if (scalar keys %unique_hash == scalar @unique_cols);
729 if (@unique_hashes) {
730 $row = $self->search(\@unique_hashes, { rows => 1 })->first;
732 $row->set_columns($hash);
738 $row = $self->create($hash);
744 =head2 throw_exception
746 See Schema's throw_exception
750 sub throw_exception {
752 $self->result_source->schema->throw_exception(@_);
757 The resultset takes various attributes that modify its behavior. Here's an
762 Which column(s) to order the results by. This is currently passed through
763 directly to SQL, so you can give e.g. C<foo DESC> for a descending order.
767 =head3 Arguments: (arrayref)
769 Shortcut to request a particular set of columns to be retrieved. Adds
770 C<me.> onto the start of any column without a C<.> in it and sets C<select>
771 from that, then auto-populates C<as> from C<select> as normal.
773 =head2 include_columns
775 =head3 Arguments: (arrayref)
777 Shortcut to include additional columns in the returned results - for example
779 { include_columns => ['foo.name'], join => ['foo'] }
781 would add a 'name' column to the information passed to object inflation
785 =head3 Arguments: (arrayref)
787 Indicates which columns should be selected from the storage. You can use
788 column names, or in the case of RDBMS back ends, function or stored procedure
791 $rs = $schema->resultset('Foo')->search(
796 { count => 'column_to_count' },
797 { sum => 'column_to_sum' }
802 When you use function/stored procedure names and do not supply an C<as>
803 attribute, the column names returned are storage-dependent. E.g. MySQL would
804 return a column named C<count(column_to_count)> in the above example.
808 =head3 Arguments: (arrayref)
810 Indicates column names for object inflation. This is used in conjunction with
811 C<select>, usually when C<select> contains one or more function or stored
814 $rs = $schema->resultset('Foo')->search(
819 { count => 'column2' }
821 as => [qw/ column1 column2_count /]
825 my $foo = $rs->first(); # get the first Foo
827 If the object against which the search is performed already has an accessor
828 matching a column name specified in C<as>, the value can be retrieved using
829 the accessor as normal:
831 my $column1 = $foo->column1();
833 If on the other hand an accessor does not exist in the object, you need to
834 use C<get_column> instead:
836 my $column2_count = $foo->get_column('column2_count');
838 You can create your own accessors if required - see
839 L<DBIx::Class::Manual::Cookbook> for details.
843 Contains a list of relationships that should be joined for this query. For
846 # Get CDs by Nine Inch Nails
847 my $rs = $schema->resultset('CD')->search(
848 { 'artist.name' => 'Nine Inch Nails' },
852 Can also contain a hash reference to refer to the other relation's relations.
855 package MyApp::Schema::Track;
856 use base qw/DBIx::Class/;
857 __PACKAGE__->table('track');
858 __PACKAGE__->add_columns(qw/trackid cd position title/);
859 __PACKAGE__->set_primary_key('trackid');
860 __PACKAGE__->belongs_to(cd => 'MyApp::Schema::CD');
863 # In your application
864 my $rs = $schema->resultset('Artist')->search(
865 { 'track.title' => 'Teardrop' },
867 join => { cd => 'track' },
868 order_by => 'artist.name',
872 If the same join is supplied twice, it will be aliased to <rel>_2 (and
873 similarly for a third time). For e.g.
875 my $rs = $schema->resultset('Artist')->search(
876 { 'cds.title' => 'Foo',
877 'cds_2.title' => 'Bar' },
878 { join => [ qw/cds cds/ ] });
880 will return a set of all artists that have both a cd with title Foo and a cd
883 If you want to fetch related objects from other tables as well, see C<prefetch>
888 =head3 Arguments: arrayref/hashref
890 Contains one or more relationships that should be fetched along with the main
891 query (when they are accessed afterwards they will have already been
892 "prefetched"). This is useful for when you know you will need the related
893 objects, because it saves at least one query:
895 my $rs = $schema->resultset('Tag')->search(
904 The initial search results in SQL like the following:
906 SELECT tag.*, cd.*, artist.* FROM tag
907 JOIN cd ON tag.cd = cd.cdid
908 JOIN artist ON cd.artist = artist.artistid
910 L<DBIx::Class> has no need to go back to the database when we access the
911 C<cd> or C<artist> relationships, which saves us two SQL statements in this
914 Simple prefetches will be joined automatically, so there is no need
915 for a C<join> attribute in the above search. If you're prefetching to
916 depth (e.g. { cd => { artist => 'label' } or similar), you'll need to
917 specify the join as well.
919 C<prefetch> can be used with the following relationship types: C<belongs_to>,
920 C<has_one> (or if you're using C<add_relationship>, any relationship declared
921 with an accessor type of 'single' or 'filter').
925 =head3 Arguments: (arrayref)
927 The C<from> attribute gives you manual control over the C<FROM> clause of SQL
928 statements generated by L<DBIx::Class>, allowing you to express custom C<JOIN>
931 NOTE: Use this on your own risk. This allows you to shoot off your foot!
932 C<join> will usually do what you need and it is strongly recommended that you
933 avoid using C<from> unless you cannot achieve the desired result using C<join>.
935 In simple terms, C<from> works as follows:
938 { <alias> => <table>, -join-type => 'inner|left|right' }
939 [] # nested JOIN (optional)
940 { <table.column> = <foreign_table.foreign_key> }
946 ON <table.column> = <foreign_table.foreign_key>
948 An easy way to follow the examples below is to remember the following:
950 Anything inside "[]" is a JOIN
951 Anything inside "{}" is a condition for the enclosing JOIN
953 The following examples utilize a "person" table in a family tree application.
954 In order to express parent->child relationships, this table is self-joined:
956 # Person->belongs_to('father' => 'Person');
957 # Person->belongs_to('mother' => 'Person');
959 C<from> can be used to nest joins. Here we return all children with a father,
960 then search against all mothers of those children:
962 $rs = $schema->resultset('Person')->search(
965 alias => 'mother', # alias columns in accordance with "from"
967 { mother => 'person' },
970 { child => 'person' },
972 { father => 'person' },
973 { 'father.person_id' => 'child.father_id' }
976 { 'mother.person_id' => 'child.mother_id' }
983 # SELECT mother.* FROM person mother
987 # ON ( father.person_id = child.father_id )
989 # ON ( mother.person_id = child.mother_id )
991 The type of any join can be controlled manually. To search against only people
992 with a father in the person table, we could explicitly use C<INNER JOIN>:
994 $rs = $schema->resultset('Person')->search(
997 alias => 'child', # alias columns in accordance with "from"
999 { child => 'person' },
1001 { father => 'person', -join-type => 'inner' },
1002 { 'father.id' => 'child.father_id' }
1009 # SELECT child.* FROM person child
1010 # INNER JOIN person father ON child.father_id = father.id
1014 For a paged resultset, specifies which page to retrieve. Leave unset
1015 for an unpaged resultset.
1019 For a paged resultset, how many rows per page:
1023 Can also be used to simulate an SQL C<LIMIT>.
1027 =head3 Arguments: (arrayref)
1029 A arrayref of columns to group by. Can include columns of joined tables.
1031 group_by => [qw/ column1 column2 ... /]
1035 Set to 1 to group by all columns.
1037 For more examples of using these attributes, see
1038 L<DBIx::Class::Manual::Cookbook>.