X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FResultSet.pm;h=e03a16d2a489fbcaf51e1bc6a6ee12b1e2f30a97;hb=a0638a7bb719844a0d5c264265a3a13b18d3318f;hp=7109e39ec1f42d70edf9b05909c40df3e7d7db36;hpb=555af3d91a033d10e1f20c802ded7bf209dd7058;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index 7109e39..e03a16d 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -8,6 +8,7 @@ use overload fallback => 1; use Data::Page; use Storable; +use Scalar::Util qw/weaken/; use base qw/DBIx::Class/; __PACKAGE__->load_components(qw/AccessorGroup/); @@ -20,7 +21,7 @@ DBIx::Class::ResultSet - Responsible for fetching and creating resultset. =head1 SYNOPSIS my $rs = $schema->resultset('User')->search(registered => 1); - my @rows = $schema->resultset('Foo')->search(bar => 'baz'); + my @rows = $schema->resultset('CD')->search(year => 2005); =head1 DESCRIPTION @@ -69,29 +70,30 @@ automatically get one from e.g. a L called in scalar context: sub new { my $class = shift; return $class->new_result(@_) if ref $class; + my ($source, $attrs) = @_; - #use Data::Dumper; warn Dumper($attrs); + weaken $source; $attrs = Storable::dclone($attrs || {}); # { %{ $attrs || {} } }; - my %seen; + #use Data::Dumper; warn Dumper($attrs); my $alias = ($attrs->{alias} ||= 'me'); - if ($attrs->{cols} || !$attrs->{select}) { - delete $attrs->{as} if $attrs->{cols}; - my @cols = ($attrs->{cols} - ? @{delete $attrs->{cols}} - : $source->columns); - $attrs->{select} = [ map { m/\./ ? $_ : "${alias}.$_" } @cols ]; - } - $attrs->{as} ||= [ map { m/^$alias\.(.*)$/ ? $1 : $_ } @{$attrs->{select}} ]; + + $attrs->{columns} ||= delete $attrs->{cols} if $attrs->{cols}; + delete $attrs->{as} if $attrs->{columns}; + $attrs->{columns} ||= [ $source->columns ] unless $attrs->{select}; + $attrs->{select} = [ map { m/\./ ? $_ : "${alias}.$_" } @{delete $attrs->{columns}} ] + if $attrs->{columns}; + $attrs->{as} ||= [ map { m/^\Q$alias.\E(.+)$/ ? $1 : $_ } @{$attrs->{select}} ]; if (my $include = delete $attrs->{include_columns}) { push(@{$attrs->{select}}, @$include); - push(@{$attrs->{as}}, map { m/([^\.]+)$/; $1; } @$include); + push(@{$attrs->{as}}, map { m/([^.]+)$/; $1; } @$include); } #use Data::Dumper; warn Dumper(@{$attrs}{qw/select as/}); + $attrs->{from} ||= [ { $alias => $source->from } ]; $attrs->{seen_join} ||= {}; + my %seen; if (my $join = delete $attrs->{join}) { - foreach my $j (ref $join eq 'ARRAY' - ? (@{$join}) : ($join)) { + foreach my $j (ref $join eq 'ARRAY' ? @$join : ($join)) { if (ref $j eq 'HASH') { $seen{$_} = 1 foreach keys %$j; } else { @@ -100,38 +102,33 @@ sub new { } push(@{$attrs->{from}}, $source->resolve_join($join, $attrs->{alias}, $attrs->{seen_join})); } + $attrs->{group_by} ||= $attrs->{select} if delete $attrs->{distinct}; - - $attrs->{order_by} = [ $attrs->{order_by} ] - if $attrs->{order_by} && !ref($attrs->{order_by}); + $attrs->{order_by} = [ $attrs->{order_by} ] if $attrs->{order_by} and !ref($attrs->{order_by}); $attrs->{order_by} ||= []; my $collapse = $attrs->{collapse} || {}; - if (my $prefetch = delete $attrs->{prefetch}) { my @pre_order; - foreach my $p (ref $prefetch eq 'ARRAY' - ? (@{$prefetch}) : ($prefetch)) { - if( ref $p eq 'HASH' ) { + foreach my $p (ref $prefetch eq 'ARRAY' ? @$prefetch : ($prefetch)) { + if ( ref $p eq 'HASH' ) { foreach my $key (keys %$p) { push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias})) unless $seen{$key}; } - } - else { + } else { push(@{$attrs->{from}}, $source->resolve_join($p, $attrs->{alias})) unless $seen{$p}; } my @prefetch = $source->resolve_prefetch( $p, $attrs->{alias}, {}, \@pre_order, $collapse); - #die Dumper \@cols; push(@{$attrs->{select}}, map { $_->[0] } @prefetch); push(@{$attrs->{as}}, map { $_->[1] } @prefetch); } push(@{$attrs->{order_by}}, @pre_order); } - $attrs->{collapse} = $collapse; +# use Data::Dumper; warn Dumper($collapse) if keys %{$collapse}; if ($attrs->{page}) { $attrs->{rows} ||= 10; @@ -139,11 +136,7 @@ sub new { $attrs->{offset} += ($attrs->{rows} * ($attrs->{page} - 1)); } -#if (keys %{$collapse}) { -# use Data::Dumper; warn Dumper($collapse); -#} - - my $new = { + bless { result_source => $source, result_class => $attrs->{result_class} || $source->result_class, cond => $attrs->{where}, @@ -152,21 +145,22 @@ sub new { count => undef, page => delete $attrs->{page}, pager => undef, - attrs => $attrs }; - bless ($new, $class); - return $new; + attrs => $attrs + }, $class; } =head2 search - my @obj = $rs->search({ foo => 3 }); # "... WHERE foo = 3" - my $new_rs = $rs->search({ foo => 3 }); + my @cds = $rs->search({ year => 2001 }); # "... WHERE year = 2001" + my $new_rs = $rs->search({ year => 2005 }); If you need to pass in additional attributes but no additional condition, -call it as C. +call it as C. - # "SELECT foo, bar FROM $class_table" - my @all = $class->search({}, { cols => [qw/foo bar/] }); + # "SELECT name, artistid FROM $artist_table" + my @all_artists = $schema->resultset('Artist')->search(undef, { + columns => [qw/name artistid/], + }); =cut @@ -178,9 +172,7 @@ sub search { my $attrs = { %{$self->{attrs}} }; my $having = delete $attrs->{having}; - if (@_ > 1 && ref $_[$#_] eq 'HASH') { - $attrs = { %$attrs, %{ pop(@_) } }; - } + $attrs = { %$attrs, %{ pop(@_) } } if @_ > 1 and ref $_[$#_] eq 'HASH'; my $where = (@_ ? ((@_ == 1 || ref $_[0] eq "HASH") @@ -191,28 +183,26 @@ sub search { : {@_})) : undef()); if (defined $where) { - $where = (defined $attrs->{where} + $attrs->{where} = (defined $attrs->{where} ? { '-and' => [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ } $where, $attrs->{where} ] } : $where); - $attrs->{where} = $where; } if (defined $having) { - $having = (defined $attrs->{having} + $attrs->{having} = (defined $attrs->{having} ? { '-and' => [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ } $having, $attrs->{having} ] } : $having); - $attrs->{having} = $having; } $rs = (ref $self)->new($self->result_source, $attrs); } else { $rs = $self; - $rs->reset(); + $rs->reset; } return (wantarray ? $rs->all : $rs); } @@ -264,7 +254,7 @@ sub find { my @cols = $self->result_source->primary_columns; if (exists $attrs->{key}) { my %uniq = $self->result_source->unique_constraints; - $self->( "Unknown key " . $attrs->{key} . " on " . $self->name ) + $self->throw_exception( "Unknown key $attrs->{key} on '" . $self->result_source->name . "'" ) unless exists $uniq{$attrs->{key}}; @cols = @{ $uniq{$attrs->{key}} }; } @@ -281,9 +271,8 @@ sub find { } else { $query = {@vals}; } - foreach (keys %$query) { - next if m/\./; - $query->{$self->{attrs}{alias}.'.'.$_} = delete $query->{$_}; + foreach my $key (grep { ! m/\./ } keys %$query) { + $query->{"$self->{attrs}{alias}.$key"} = delete $query->{$key}; } #warn Dumper($query); @@ -316,8 +305,7 @@ Returns a storage-driven cursor to the given resultset. sub cursor { my ($self) = @_; - my ($attrs) = $self->{attrs}; - $attrs = { %$attrs }; + my $attrs = { %{$self->{attrs}} }; return $self->{cursor} ||= $self->result_source->storage->select($self->{from}, $attrs->{select}, $attrs->{where},$attrs); @@ -330,18 +318,17 @@ Inflates the first result without creating a cursor =cut sub single { - my ($self, $extra) = @_; - my ($attrs) = $self->{attrs}; - $attrs = { %$attrs }; - if ($extra) { + my ($self, $where) = @_; + my $attrs = { %{$self->{attrs}} }; + if ($where) { if (defined $attrs->{where}) { $attrs->{where} = { - '-and' - => [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ } - delete $attrs->{where}, $extra ] + '-and' => + [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ } + $where, delete $attrs->{where} ] }; } else { - $attrs->{where} = $extra; + $attrs->{where} = $where; } } my @data = $self->result_source->storage->select_single( @@ -362,12 +349,9 @@ For more information, see L. =cut sub search_like { - my $class = shift; - my $attrs = { }; - if (@_ > 1 && ref $_[$#_] eq 'HASH') { - $attrs = pop(@_); - } - my $query = ref $_[0] eq "HASH" ? { %{shift()} }: {@_}; + my $class = shift; + my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {}); + my $query = ref $_[0] eq 'HASH' ? { %{shift()} }: {@_}; $query->{$_} = { 'like' => $query->{$_} } for keys %$query; return $class->search($query, { %$attrs }); } @@ -396,7 +380,7 @@ Returns the next element in the resultset (C is there is none). Can be used to efficiently iterate over records in the resultset: - my $rs = $schema->resultset('CD')->search({}); + my $rs = $schema->resultset('CD')->search; while (my $cd = $rs->next) { print $cd->title; } @@ -405,12 +389,9 @@ Can be used to efficiently iterate over records in the resultset: sub next { my ($self) = @_; - my $cache; - if( @{$cache = $self->{all_cache} || []}) { + if (@{$self->{all_cache} || []}) { $self->{all_cache_position} ||= 0; - my $obj = $cache->[$self->{all_cache_position}]; - $self->{all_cache_position}++; - return $obj; + return $self->{all_cache}->[$self->{all_cache_position}++]; } if ($self->{attrs}{cache}) { $self->{all_cache_position} = 1; @@ -427,14 +408,13 @@ sub next { sub _construct_object { my ($self, @row) = @_; my @as = @{ $self->{attrs}{as} }; - + my $info = $self->_collapse_result(\@as, \@row); - + my $new = $self->result_class->inflate_result($self->result_source, @$info); - + $new = $self->{attrs}{record_filter}->($new) if exists $self->{attrs}{record_filter}; - return $new; } @@ -449,11 +429,11 @@ sub _collapse_result { if (defined $prefix) { if ($this_as =~ m/^\Q${prefix}.\E(.+)$/) { my $remain = $1; - $remain =~ /^(?:(.*)\.)?([^\.]+)$/; + $remain =~ /^(?:(.*)\.)?([^.]+)$/; $const{$1||''}{$2} = $val; } } else { - $this_as =~ /^(?:(.*)\.)?([^\.]+)$/; + $this_as =~ /^(?:(.*)\.)?([^.]+)$/; $const{$1||''}{$2} = $val; } } @@ -497,7 +477,7 @@ sub _collapse_result { $tree = $self->_collapse_result($as, $row, $c_prefix); #warn Data::Dumper::Dumper($tree, $row); } - @{$target} = @final; + @$target = @final; } return $info; @@ -526,46 +506,47 @@ clause. sub count { my $self = shift; - return $self->search(@_)->count if @_ && defined $_[0]; - unless (defined $self->{count}) { - return scalar @{ $self->get_cache } - if @{ $self->get_cache }; - my $group_by; - my $select = { 'count' => '*' }; - my $attrs = { %{ $self->{attrs} } }; - if( $group_by = delete $attrs->{group_by} ) { - delete $attrs->{having}; - my @distinct = (ref $group_by ? @$group_by : ($group_by)); - # todo: try CONCAT for multi-column pk - my @pk = $self->result_source->primary_columns; - if( scalar(@pk) == 1 ) { - my $pk = shift(@pk); - my $alias = $attrs->{alias}; - my $re = qr/^($alias\.)?$pk$/; - foreach my $column ( @distinct) { - if( $column =~ $re ) { - @distinct = ( $column ); - last; - } - } - } + return $self->search(@_)->count if @_ and defined $_[0]; + return scalar @{ $self->get_cache } if @{ $self->get_cache }; - $select = { count => { 'distinct' => \@distinct } }; - #use Data::Dumper; die Dumper $select; - } + my $count = $self->_count; + return 0 unless $count; - $attrs->{select} = $select; - $attrs->{as} = [ 'count' ]; - # offset, order by and page are not needed to count. record_filter is cdbi - delete $attrs->{$_} for qw/rows offset order_by page pager record_filter/; - - ($self->{count}) = (ref $self)->new($self->result_source, $attrs)->cursor->next; - } - return 0 unless $self->{count}; - my $count = $self->{count}; $count -= $self->{attrs}{offset} if $self->{attrs}{offset}; $count = $self->{attrs}{rows} if - ($self->{attrs}{rows} && $self->{attrs}{rows} < $count); + $self->{attrs}{rows} and $self->{attrs}{rows} < $count; + return $count; +} + +sub _count { # Separated out so pager can get the full count + my $self = shift; + my $select = { count => '*' }; + my $attrs = { %{ $self->{attrs} } }; + if (my $group_by = delete $attrs->{group_by}) { + delete $attrs->{having}; + my @distinct = (ref $group_by ? @$group_by : ($group_by)); + # todo: try CONCAT for multi-column pk + my @pk = $self->result_source->primary_columns; + if (@pk == 1) { + foreach my $column (@distinct) { + if ($column =~ qr/^(?:\Q$attrs->{alias}.\E)?$pk[0]$/) { + @distinct = ($column); + last; + } + } + } + + $select = { count => { distinct => \@distinct } }; + #use Data::Dumper; die Dumper $select; + } + + $attrs->{select} = $select; + $attrs->{as} = [qw/count/]; + + # offset, order by and page are not needed to count. record_filter is cdbi + delete $attrs->{$_} for qw/rows offset order_by page pager record_filter/; + + my ($count) = (ref $self)->new($self->result_source, $attrs)->cursor->next; return $count; } @@ -586,8 +567,7 @@ is returned in list context. sub all { my ($self) = @_; - return @{ $self->get_cache } - if @{ $self->get_cache }; + return @{ $self->get_cache } if @{ $self->get_cache }; my @obj; @@ -596,20 +576,19 @@ sub all { # If we're collapsing has_many prefetches it probably makes # very little difference, and this is cleaner than hacking # _construct_object to survive the approach - my @row; $self->cursor->reset; - while (@row = $self->cursor->next) { + my @row = $self->cursor->next; + while (@row) { push(@obj, $self->_construct_object(@row)); + @row = (exists $self->{stashed_row} + ? @{delete $self->{stashed_row}} + : $self->cursor->next); } } else { - @obj = map { $self->_construct_object(@$_); } - $self->cursor->all; - } - - if( $self->{attrs}->{cache} ) { - $self->set_cache( \@obj ); + @obj = map { $self->_construct_object(@$_) } $self->cursor->all; } + $self->set_cache(\@obj) if $self->{attrs}{cache}; return @obj; } @@ -678,26 +657,41 @@ Deletes the contents of the resultset from its result source. sub delete { my ($self) = @_; my $del = {}; - $self->throw_exception("Can't delete on resultset with condition unless hash or array") - unless (ref($self->{cond}) eq 'HASH' || ref($self->{cond}) eq 'ARRAY'); - if (ref $self->{cond} eq 'ARRAY') { + + if (!ref($self->{cond})) { + + # No-op. No condition, we're deleting everything + + } elsif (ref $self->{cond} eq 'ARRAY') { + $del = [ map { my %hash; foreach my $key (keys %{$_}) { - $key =~ /([^\.]+)$/; + $key =~ /([^.]+)$/; $hash{$1} = $_->{$key}; }; \%hash; } @{$self->{cond}} ]; - } elsif ((keys %{$self->{cond}})[0] eq '-and') { - $del->{-and} = [ map { my %hash; - foreach my $key (keys %{$_}) { - $key =~ /([^\.]+)$/; - $hash{$1} = $_->{$key}; - }; \%hash; } @{$self->{cond}{-and}} ]; - } else { - foreach my $key (keys %{$self->{cond}}) { - $key =~ /([^\.]+)$/; - $del->{$1} = $self->{cond}{$key}; + + } elsif (ref $self->{cond} eq 'HASH') { + + if ((keys %{$self->{cond}})[0] eq '-and') { + + $del->{-and} = [ map { my %hash; + foreach my $key (keys %{$_}) { + $key =~ /([^.]+)$/; + $hash{$1} = $_->{$key}; + }; \%hash; } @{$self->{cond}{-and}} ]; + + } else { + + foreach my $key (keys %{$self->{cond}}) { + $key =~ /([^.]+)$/; + $del->{$1} = $self->{cond}{$key}; + } } + } else { + $self->throw_exception( + "Can't delete on resultset with condition unless hash or array"); } + $self->result_source->storage->delete($self->result_source->from, $del); return 1; } @@ -727,9 +721,8 @@ sub pager { my $attrs = $self->{attrs}; $self->throw_exception("Can't create pager for non-paged rs") unless $self->{page}; $attrs->{rows} ||= 10; - $self->count; return $self->{pager} ||= Data::Page->new( - $self->{count}, $attrs->{rows}, $self->{page}); + $self->_count, $attrs->{rows}, $self->{page}); } =head2 page @@ -764,11 +757,11 @@ sub new_result { my %new = %$values; my $alias = $self->{attrs}{alias}; foreach my $key (keys %{$self->{cond}||{}}) { - $new{$1} = $self->{cond}{$key} if ($key =~ m/^(?:$alias\.)?([^\.]+)$/); + $new{$1} = $self->{cond}{$key} if ($key =~ m/^(?:\Q${alias}.\E)?([^.]+)$/); } my $obj = $self->result_class->new(\%new); $obj->result_source($self->result_source) if $obj->can('result_source'); - $obj; + return $obj; } =head2 create @@ -821,9 +814,9 @@ See also L and L. sub find_or_create { my $self = shift; my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {}); - my $hash = ref $_[0] eq "HASH" ? shift : {@_}; + my $hash = ref $_[0] eq 'HASH' ? shift : {@_}; my $exists = $self->find($hash, $attrs); - return defined($exists) ? $exists : $self->create($hash); + return defined $exists ? $exists : $self->create($hash); } =head2 update_or_create @@ -859,9 +852,8 @@ See also L and L. sub update_or_create { my $self = shift; - my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {}); - my $hash = ref $_[0] eq "HASH" ? shift : {@_}; + my $hash = ref $_[0] eq 'HASH' ? shift : {@_}; my %unique_constraints = $self->result_source->unique_constraints; my @constraint_names = (exists $attrs->{key} @@ -880,20 +872,16 @@ sub update_or_create { if (scalar keys %unique_hash == scalar @unique_cols); } - my $row; if (@unique_hashes) { - $row = $self->search(\@unique_hashes, { rows => 1 })->first; - if ($row) { + my $row = $self->single(\@unique_hashes); + if (defined $row) { $row->set_columns($hash); $row->update; + return $row; } } - unless ($row) { - $row = $self->create($hash); - } - - return $row; + return $self->create($hash); } =head2 get_cache @@ -903,8 +891,7 @@ Gets the contents of the cache for the resultset. =cut sub get_cache { - my $self = shift; - return $self->{all_cache} || []; + shift->{all_cache} || []; } =head2 set_cache @@ -932,51 +919,42 @@ Clears the cache for the resultset. =cut sub clear_cache { - my $self = shift; - $self->set_cache([]); + shift->set_cache([]); } =head2 related_resultset Returns a related resultset for the supplied relationship name. - $rs = $rs->related_resultset('foo'); + $artist_rs = $schema->resultset('CD')->related_resultset('Artist'); =cut sub related_resultset { my ( $self, $rel, @rest ) = @_; $self->{related_resultsets} ||= {}; - my $resultsets = $self->{related_resultsets}; - if( !exists $resultsets->{$rel} ) { - #warn "fetching related resultset for rel '$rel'"; - my $rel_obj = $self->result_source->relationship_info($rel); - $self->throw_exception( - "search_related: result source '" . $self->result_source->name . - "' has no such relationship ${rel}") - unless $rel_obj; #die Dumper $self->{attrs}; - my $rs = $self->search(undef, { join => $rel }); - #if( $self->{attrs}->{cache} ) { - # $rs = $self->search(undef); - #} - #else { - #} - #use Data::Dumper; die Dumper $rs->{attrs};#$rs = $self->search( undef ); - #use Data::Dumper; warn Dumper $self->{attrs}, Dumper $rs->{attrs}; - my $alias = (defined $rs->{attrs}{seen_join}{$rel} - && $rs->{attrs}{seen_join}{$rel} > 1 - ? join('_', $rel, $rs->{attrs}{seen_join}{$rel}) - : $rel); - $resultsets->{$rel} = + return $self->{related_resultsets}{$rel} ||= do { + #warn "fetching related resultset for rel '$rel'"; + my $rel_obj = $self->result_source->relationship_info($rel); + $self->throw_exception( + "search_related: result source '" . $self->result_source->name . + "' has no such relationship ${rel}") + unless $rel_obj; #die Dumper $self->{attrs}; + + my $rs = $self->search(undef, { join => $rel }); + my $alias = defined $rs->{attrs}{seen_join}{$rel} + && $rs->{attrs}{seen_join}{$rel} > 1 + ? join('_', $rel, $rs->{attrs}{seen_join}{$rel}) + : $rel; + $self->result_source->schema->resultset($rel_obj->{class} )->search( undef, { %{$rs->{attrs}}, alias => $alias, - select => undef(), - as => undef() } - )->search(@rest); - } - return $resultsets->{$rel}; + select => undef, + as => undef } + )->search(@rest); + }; } =head2 throw_exception @@ -997,16 +975,18 @@ overview of them: =head2 order_by -Which column(s) to order the results by. This is currently passed through -directly to SQL, so you can give e.g. C for a descending order. +Which column(s) to order the results by. This is currently passed +through directly to SQL, so you can give e.g. C for a +descending order on the column `year'. -=head2 cols +=head2 columns =head3 Arguments: (arrayref) Shortcut to request a particular set of columns to be retrieved. Adds C onto the start of any column without a C<.> in it and sets C as normal. +from that, then auto-populates C from C as normal. Shortcut to include additional columns in the returned results - for example - { include_columns => ['foo.name'], join => ['foo'] } + $schema->resultset('CD')->search(undef, { + include_columns => ['artist.name'], + join => ['artist'] + }); -would add a 'name' column to the information passed to object inflation +would return all CDs and include a 'name' column to the information +passed to object inflation =head2 select @@ -1026,20 +1010,17 @@ Indicates which columns should be selected from the storage. You can use column names, or in the case of RDBMS back ends, function or stored procedure names: - $rs = $schema->resultset('Foo')->search( - {}, - { - select => [ - 'column_name', - { count => 'column_to_count' }, - { sum => 'column_to_sum' } - ] - } - ); + $rs = $schema->resultset('Employee')->search(undef, { + select => [ + 'name', + { count => 'employeeid' }, + { sum => 'salary' } + ] + }); When you use function/stored procedure names and do not supply an C attribute, the column names returned are storage-dependent. E.g. MySQL would -return a column named C in the above example. +return a column named C in the above example. =head2 as @@ -1049,29 +1030,26 @@ Indicates column names for object inflation. This is used in conjunction with C contains one or more function or stored procedure names: - $rs = $schema->resultset('Foo')->search( - {}, - { - select => [ - 'column1', - { count => 'column2' } - ], - as => [qw/ column1 column2_count /] - } - ); + $rs = $schema->resultset('Employee')->search(undef, { + select => [ + 'name', + { count => 'employeeid' } + ], + as => ['name', 'employee_count'], + }); - my $foo = $rs->first(); # get the first Foo + my $employee = $rs->first(); # get the first Employee If the object against which the search is performed already has an accessor matching a column name specified in C, the value can be retrieved using the accessor as normal: - my $column1 = $foo->column1(); + my $name = $employee->name(); If on the other hand an accessor does not exist in the object, you need to use C instead: - my $column2_count = $foo->get_column('column2_count'); + my $employee_count = $employee->get_column('employee_count'); You can create your own accessors if required - see L for details. @@ -1110,13 +1088,15 @@ For example: If the same join is supplied twice, it will be aliased to _2 (and similarly for a third time). For e.g. - my $rs = $schema->resultset('Artist')->search( - { 'cds.title' => 'Foo', - 'cds_2.title' => 'Bar' }, - { join => [ qw/cds cds/ ] }); + my $rs = $schema->resultset('Artist')->search({ + 'cds.title' => 'Down to Earth', + 'cds_2.title' => 'Popular', + }, { + join => [ qw/cds cds/ ], + }); -will return a set of all artists that have both a cd with title Foo and a cd -with title Bar. +will return a set of all artists that have both a cd with title 'Down +to Earth' and a cd with title 'Popular'. If you want to fetch related objects from other tables as well, see C below. @@ -1131,7 +1111,7 @@ query (when they are accessed afterwards they will have already been objects, because it saves at least one query: my $rs = $schema->resultset('Tag')->search( - {}, + undef, { prefetch => { cd => 'artist' @@ -1198,7 +1178,7 @@ C can be used to nest joins. Here we return all children with a father, then search against all mothers of those children: $rs = $schema->resultset('Person')->search( - {}, + undef, { alias => 'mother', # alias columns in accordance with "from" from => [ @@ -1230,7 +1210,7 @@ The type of any join can be controlled manually. To search against only people with a father in the person table, we could explicitly use C: $rs = $schema->resultset('Person')->search( - {}, + undef, { alias => 'child', # alias columns in accordance with "from" from => [