X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FResultSet.pm;h=28b2f9a5fe63f6276f55229ed07983694f56fe52;hb=dfb45ec431de0598c0222aa067b9b9380143d7f8;hp=f71743573d39fd109343b0ddace5c796c2ff9c9d;hpb=c7a9d1027d40e6b3275cb26db68141b152f3bd13;p=dbsrgits%2FDBIx-Class-Historic.git diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index f717435..28b2f9a 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -19,38 +19,122 @@ __PACKAGE__->mk_group_accessors('simple' => qw/_result_class _source_handle/); =head1 NAME -DBIx::Class::ResultSet - Responsible for fetching and creating resultset. +DBIx::Class::ResultSet - Represents a query used for fetching a set of results. =head1 SYNOPSIS - my $rs = $schema->resultset('User')->search({ registered => 1 }); - my @rows = $schema->resultset('CD')->search({ year => 2005 })->all(); + my $users_rs = $schema->resultset('User'); + my $registered_users_rs = $schema->resultset('User')->search({ registered => 1 }); + my @cds_in_2005 = $schema->resultset('CD')->search({ year => 2005 })->all(); =head1 DESCRIPTION -The resultset is also known as an iterator. It is responsible for handling -queries that may return an arbitrary number of rows, e.g. via L -or a C relationship. +A ResultSet is an object which stores a set of conditions representing +a query. It is the backbone of DBIx::Class (i.e. the really +important/useful bit). -In the examples below, the following table classes are used: +No SQL is executed on the database when a ResultSet is created, it +just stores all the conditions needed to create the query. - package MyApp::Schema::Artist; - use base qw/DBIx::Class/; - __PACKAGE__->load_components(qw/Core/); - __PACKAGE__->table('artist'); - __PACKAGE__->add_columns(qw/artistid name/); - __PACKAGE__->set_primary_key('artistid'); - __PACKAGE__->has_many(cds => 'MyApp::Schema::CD'); - 1; +A basic ResultSet representing the data of an entire table is returned +by calling C on a L and passing in a +L name. - package MyApp::Schema::CD; - use base qw/DBIx::Class/; - __PACKAGE__->load_components(qw/Core/); - __PACKAGE__->table('cd'); - __PACKAGE__->add_columns(qw/cdid artist title year/); - __PACKAGE__->set_primary_key('cdid'); - __PACKAGE__->belongs_to(artist => 'MyApp::Schema::Artist'); - 1; + my $users_rs = $schema->resultset('User'); + +A new ResultSet is returned from calling L on an existing +ResultSet. The new one will contain all the conditions of the +original, plus any new conditions added in the C call. + +A ResultSet is also an iterator. L is used to return all the +Ls the ResultSet represents. + +The query that the ResultSet represents is B executed against +the database when these methods are called: + +=over + +=item L + +=item L + +=item L + +=item L + +=item L + +=item L + +=back + +=head1 EXAMPLES + +=head2 Chaining resultsets + +Let's say you've got a query that needs to be run to return some data +to the user. But, you have an authorization system in place that +prevents certain users from seeing certain information. So, you want +to construct the basic query in one method, but add constraints to it in +another. + + sub get_data { + my $self = shift; + my $request = $self->get_request; # Get a request object somehow. + my $schema = $self->get_schema; # Get the DBIC schema object somehow. + + my $cd_rs = $schema->resultset('CD')->search({ + title => $request->param('title'), + year => $request->param('year'), + }); + + $self->apply_security_policy( $cd_rs ); + + return $cd_rs->all(); + } + + sub apply_security_policy { + my $self = shift; + my ($rs) = @_; + + return $rs->search({ + subversive => 0, + }); + } + +=head2 Multiple queries + +Since a resultset just defines a query, you can do all sorts of +things with it with the same object. + + # Don't hit the DB yet. + my $cd_rs = $schema->resultset('CD')->search({ + title => 'something', + year => 2009, + }); + + # Each of these hits the DB individually. + my $count = $cd_rs->count; + my $most_recent = $cd_rs->get_column('date_released')->max(); + my @records = $cd_rs->all; + +And it's not just limited to SELECT statements. + + $cd_rs->delete(); + +This is even cooler: + + $cd_rs->create({ artist => 'Fred' }); + +Which is the same as: + + $schema->resultset('CD')->create({ + title => 'something', + year => 2009, + artist => 'Fred' + }); + +See: L, L, L, L, L. =head1 OVERLOADING @@ -607,6 +691,10 @@ of the resultset. sub single { my ($self, $where) = @_; + if(@_ > 2) { + $self->throw_exception('single() only takes search conditions, no attributes. You want ->search( $cond, $attrs )->single()'); + } + my $attrs = { %{$self->_resolved_attrs} }; if ($where) { if (defined $attrs->{where}) { @@ -1109,7 +1197,11 @@ is returned in list context. =cut sub all { - my ($self) = @_; + my $self = shift; + if(@_) { + $self->throw_exception("all() doesn't take any arguments, you probably wanted ->search(...)->all()"); + } + return @{ $self->get_cache } if $self->get_cache; my @obj; @@ -1261,6 +1353,11 @@ sub update { $self->throw_exception("Values for update must be a hash") unless ref $values eq 'HASH'; + carp( 'WARNING! Currently $rs->update() does not generate proper SQL' + . ' on joined resultsets, and may affect rows well outside of the' + . ' contents of $rs. Use at your own risk' ) + if ( $self->{attrs}{seen_join} ); + my $cond = $self->_cond_for_update_delete; return $self->result_source->storage->update( @@ -1721,56 +1818,11 @@ sub _remove_alias { Returns the SQL query and bind vars associated with the invocant. -=cut - -sub as_query { return shift->cursor->as_query(@_) } - -=head2 as_subselect - -=over 4 - -=item Arguments: none - -=item Return Value: \[ $sql, @bind ] - -=back - -Returns the SQL query and bind vars associated with the invocant. - -The SQL will be wrapped in parentheses, ready for use as a subselect. +This is generally used as the RHS for a subquery. =cut -sub as_subselect { - my $self = shift; - my $arr = ${$self->as_query(@_)}; - $arr->[0] = '( ' . $arr->[0] . ' )'; - return \$arr; -} - -=head2 as_query - -=over 4 - -=item Arguments: none - -=item Return Value: $sql - -=back - -Returns the SQL query associated with the invocant. All bind vars -will have been bound using C<< DBI->quote() >>. - -=cut - -sub as_sql { - my $self = shift; - my $arr = ${$self->as_query(@_)}; - my $sql = shift @$arr; - my $dbh = $self->result_source->schema->storage->dbh; - $sql =~ s/\?/$dbh->quote((shift @$arr)->[1])/eg; - return $sql -} +sub as_query { return shift->cursor->as_query(@_) } =head2 find_or_new @@ -1853,7 +1905,7 @@ Example of creating a new row. $person_rs->create({ name=>"Some Person", - email=>"somebody@someplace.com" + email=>"somebody@someplace.com" }); Example of creating a new row and also creating rows in a related C @@ -1872,10 +1924,10 @@ Cresultset. Note Hashref. $cd_rs->create({ title=>"Music for Silly Walks", - year=>2000, - artist => { - name=>"Silly Musician", - } + year=>2000, + artist => { + name=>"Silly Musician", + } }); =cut @@ -2272,7 +2324,7 @@ sub _resolved_attrs { push(@{$attrs->{as}}, @$adds); } - $attrs->{from} ||= [ { 'me' => $source->from } ]; + $attrs->{from} ||= [ { $self->{attrs}{alias} => $source->from } ]; if (exists $attrs->{join} || exists $attrs->{prefetch}) { my $join = delete $attrs->{join} || {}; @@ -2305,7 +2357,7 @@ sub _resolved_attrs { if (my $prefetch = delete $attrs->{prefetch}) { $prefetch = $self->_merge_attr({}, $prefetch); my @pre_order; - my $seen = $attrs->{seen_join} || {}; + my $seen = { %{ $attrs->{seen_join} || {} } }; foreach my $p (ref $prefetch eq 'ARRAY' ? @$prefetch : ($prefetch)) { # bring joins back to level of current class my @prefetch = $source->resolve_prefetch( @@ -2461,8 +2513,12 @@ sub throw_exception { =head1 ATTRIBUTES -The resultset takes various attributes that modify its behavior. Here's an -overview of them: +Attributes are used to refine a ResultSet in various ways when +searching for data. They can be passed to any method which takes an +C<\%attrs> argument. See L, L, L, +L. + +These are in no particular order: =head2 order_by @@ -2555,7 +2611,7 @@ L but adds columns to the selection. =over 4 -Indicates additional column names for those added via L. +Indicates additional column names for those added via L. See L. =back