__PACKAGE__->belongs_to(artist => 'MyApp::Schema::Artist');
1;
+=head1 DISCUSSION
+
+When you create a resultset (usually as a result of calling search()), DBIx::Class
+B<doesn't> make a DB call. Not yet. A resultset is (in simplistic terms) a set of
+where conditions, join conditions, and other metadata that would be needed to execute
+a SELECT statement. This has several big implications:
+
+=over 4
+
+=item * You can chain resultsets
+
+=item * You can run multiple queries using the same resultset
+
+=back
+
+=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 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 $rs = $schema->resultset('some_data')->search({
+ foo => $request->param('foo'),
+ bar => $request->param('bar'),
+ });
+
+ $self->apply_security_policy( $rs );
+
+ return $rs->all;
+ }
+
+ sub apply_security_policy {
+ my $self = shift;
+ my ($rs) = @_;
+
+ return $rs->search({
+ hidden_data => 0,
+ });
+ }
+
+=head2 Multiple queries
+
+Since a resultset hasn't hit the database yet, you can do all sorts of things with it.
+
+ # Don't hit the DB yet.
+ my $rs = $schema->resultset('some_table')->search({
+ foo => 1,
+ bar => 2,
+ });
+
+ # Each of these hits the DB individually.
+ my $count = $rs->count;
+ my $max_baz = $rs->get_column('baz')->max;
+ my @records = $rs->all;
+
+And it's not just limited to SELECT statements.
+
+ $rs->delete;
+
+This is even cooler
+
+ $rs->create({ baz => 20 });
+
+That is equivalent to
+
+ $schema->resultset('some_table')->create({
+ foo => 1,
+ bar => 2,
+ baz => 20,
+ });
+
+Note that C<get_column()> returns a ResultSetColumn object. This will behave almost
+exactly like a resultset, except it has methods tuned for working with columns.
+
=head1 OVERLOADING
If a resultset is used in a numeric context it returns the L</count>.
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}) {
=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;
$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(
=head2 _normalize_populate_args ($args)
-Private method used by L</populate> to normalize it's incoming arguments. Factored
+Private method used by L</populate> to normalize its incoming arguments. Factored
out in case you want to subclass and accept new argument structures to the
L</populate> method.
return \%unaliased;
}
+=head2 as_query
+
+=over 4
+
+=item Arguments: none
+
+=item Return Value: \[ $sql, @bind ]
+
+=back
+
+Returns the SQL query and bind vars associated with the invocant.
+
+This is generally used as the RHS for a subquery.
+
+=cut
+
+sub as_query { return shift->cursor->as_query(@_) }
+
=head2 find_or_new
=over 4
$cd->cd_to_producer->find_or_new({ producer => $producer },
{ key => 'primary });
-Find an existing record from this resultset, based on it's primary
+Find an existing record from this resultset, based on its primary
key, or a unique constraint. If none exists, instantiate a new result
object and return it. The object will not be saved into your storage
until you call L<DBIx::Class::Row/insert> on it.
pairs representing the columns of the table and the values you wish to
store. If the appropriate relationships are set up, foreign key fields
can also be passed an object representing the foreign row, and the
-value will be set to it's primary key.
+value will be set to its primary key.
To create related objects, pass a hashref for the value if the related
item is a foreign key relationship (L<DBIx::Class::Relationship/belongs_to>),
$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<has_many>
$cd_rs->create({
title=>"Music for Silly Walks",
- year=>2000,
- artist => {
- name=>"Silly Musician",
- }
+ year=>2000,
+ artist => {
+ name=>"Silly Musician",
+ }
});
=cut
=back
-Returns the current alias of the result source that corrensponds to the result
-set (this alias will eventually be used as the SQL table alias in the SQL
-query). Usually it is C<me>.
+Returns the current table alias for the result source this resultset is built
+on, that will be used in the SQL query. Usually it is C<me>.
Currently the source alias that refers to the result set returned by a
L</search>/L</find> family method depends on how you got to the resultset: it's
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(
=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</search>, L</search_rs>, L</find>,
+L</count>.
+
+These are in no particular order:
=head2 order_by
specify an order. (The scalar ref causes it to be passed as raw sql to the DB,
so you will need to manually quote things as appropriate.)
+If your L<SQL::Abstract> version supports it (>=1.50), you can also use
+C<{-desc => 'year'}>, which takes care of the quoting for you. This is the
+recommended syntax.
+
=head2 columns
=over 4
=over 4
-Indicates additional column names for those added via L</+select>.
+Indicates additional column names for those added via L</+select>. See L</as>.
=back