Make throw_exception in RS a bit more forgiving too
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / ResultSet.pm
index a56166f..011d7da 100644 (file)
@@ -3,14 +3,15 @@ package DBIx::Class::ResultSet;
 use strict;
 use warnings;
 use overload
-        '0+'     => \&count,
-        'bool'   => sub { 1; },
+        '0+'     => "count",
+        'bool'   => "_bool",
         fallback => 1;
 use Carp::Clan qw/^DBIx::Class/;
 use Data::Page;
 use Storable;
 use DBIx::Class::ResultSetColumn;
 use DBIx::Class::ResultSourceHandle;
+use List::Util ();
 use base qw/DBIx::Class/;
 
 __PACKAGE__->mk_group_accessors('simple' => qw/result_class _source_handle/);
@@ -50,6 +51,10 @@ In the examples below, the following table classes are used:
   __PACKAGE__->belongs_to(artist => 'MyApp::Schema::Artist');
   1;
 
+=head1 OVERLOADING
+
+If a resultset is used as a number it returns the C<count()>.  However, if it is used as a boolean it is always true.  So if you want to check if a result set has any results use C<if $rs != 0>.  C<if $rs> will always be true.
+
 =head1 METHODS
 
 =head2 new
@@ -95,6 +100,8 @@ sub new {
 
   $attrs->{alias} ||= 'me';
 
+  # Creation of {} and bless separated to mitigate RH perl bug
+  # see https://bugzilla.redhat.com/show_bug.cgi?id=196836
   my $self = {
     _source_handle => $source,
     result_class => $attrs->{result_class} || $source->resolve->result_class,
@@ -138,6 +145,8 @@ L</ATTRIBUTES>. For more examples of using this function, see
 L<Searching|DBIx::Class::Manual::Cookbook/Searching>. For a complete
 documentation for the first argument, see L<SQL::Abstract>.
 
+For more help on using joins with search, see L<DBIx::Class::Manual::Joining>.
+
 =cut
 
 sub search {
@@ -164,18 +173,26 @@ always return a resultset, even in list context.
 sub search_rs {
   my $self = shift;
 
-  my $rows;
-
-  unless (@_) {                 # no search, effectively just a clone
-    $rows = $self->get_cache;
-  }
-
   my $attrs = {};
   $attrs = pop(@_) if @_ > 1 and ref $_[$#_] eq 'HASH';
   my $our_attrs = { %{$self->{attrs}} };
   my $having = delete $our_attrs->{having};
   my $where = delete $our_attrs->{where};
 
+  my $rows;
+
+  my %safe = (alias => 1, cache => 1);
+
+  unless (
+    (@_ && defined($_[0])) # @_ == () or (undef)
+    || 
+    (keys %$attrs # empty attrs or only 'safe' attrs
+    && List::Util::first { !$safe{$_} } keys %$attrs)
+  ) {
+    # no search, effectively just a clone
+    $rows = $self->get_cache;
+  }
+
   my $new_attrs = { %{$our_attrs}, %{$attrs} };
 
   # merge new attrs into inherited
@@ -264,6 +281,13 @@ sub search_rs {
 Pass a literal chunk of SQL to be added to the conditional part of the
 resultset query.
 
+CAVEAT: C<search_literal> is provided for Class::DBI compatibility and should
+only be used in that context. There are known problems using C<search_literal>
+in chained queries; it can result in bind values in the wrong order.  See
+L<DBIx::Class::Manual::Cookbook/Searching> and
+L<DBIx::Class::Manual::FAQ/Searching> for searching techniques that do not
+require C<search_literal>.
+
 =cut
 
 sub search_literal {
@@ -918,7 +942,7 @@ Performs an SQL C<COUNT> with the same query as the resultset was built
 with to find the number of elements. If passed arguments, does a search
 on the resultset and counts the results of that.
 
-Note: When using C<count> with C<group_by>, L<DBIX::Class> emulates C<GROUP BY>
+Note: When using C<count> with C<group_by>, L<DBIx::Class> emulates C<GROUP BY>
 using C<COUNT( DISTINCT( columns ) )>. Some databases (notably SQLite) do
 not support C<DISTINCT> with multiple columns. If you are using such a
 database, you should only use columns from the main table in your C<group_by>
@@ -976,6 +1000,10 @@ sub _count { # Separated out so pager can get the full count
   return $count;
 }
 
+sub _bool {
+  return 1;
+}
+
 =head2 count_literal
 
 =over 4
@@ -1251,7 +1279,7 @@ Pass an arrayref of hashrefs. Each hashref should be a structure suitable for
 submitting to a $resultset->create(...) method.
 
 In void context, C<insert_bulk> in L<DBIx::Class::Storage::DBI> is used
-to insert the data, as this is a faster method.
+to insert the data, as this is a faster method.  
 
 Otherwise, each set of data is inserted into the database using
 L<DBIx::Class::ResultSet/create>, and a arrayref of the resulting row
@@ -1288,6 +1316,14 @@ Example:  Assuming an Artist Class that has many CDs Classes relating:
   
   print $ArtistOne->name; ## response is 'Artist One'
   print $ArtistThree->cds->count ## reponse is '2'
+  
+Please note an important effect on your data when choosing between void and
+wantarray context. Since void context goes straight to C<insert_bulk> in 
+L<DBIx::Class::Storage::DBI> this will skip any component that is overriding
+c<insert>.  So if you are using something like L<DBIx-Class-UUIDColumns> to 
+create primary keys for you, you will find that your PKs are empty.  In this 
+case you will have to use the wantarray context in order to create those 
+values.
 
 =cut
 
@@ -1441,9 +1477,12 @@ sub new_result {
 
   my $alias = $self->{attrs}{alias};
   my $collapsed_cond = $self->{cond} ? $self->_collapse_cond($self->{cond}) : {};
+
+  # precendence must be given to passed values over values inherited from the cond, 
+  # so the order here is important.
   my %new = (
-    %{ $self->_remove_alias($values, $alias) },
     %{ $self->_remove_alias($collapsed_cond, $alias) },
+    %{ $self->_remove_alias($values, $alias) },
     -source_handle => $self->_source_handle,
     -result_source => $self->result_source, # DO NOT REMOVE THIS, REQUIRED
   );
@@ -1541,7 +1580,7 @@ sub find_or_new {
 
 =item Arguments: \%vals
 
-=item Return Value: $object
+=item Return Value: a L<DBIx::Class::Row> $object
 
 =back
 
@@ -1569,6 +1608,16 @@ L</new>), will be inserted into their appropriate tables.
 
 Effectively a shortcut for C<< ->new_result(\%vals)->insert >>.
 
+Example of creating a new row.
+
+  $person_rs->create({
+    name=>"Some Person",
+       email=>"somebody@someplace.com"
+  });
+  
+Example of creating a new row and also creating rows in a related C<has_many>
+or C<has_one> resultset.  Note Arrayref.
+
   $artist_rs->create(
      { artistid => 4, name => 'Manufactured Crap', cds => [ 
         { title => 'My First CD', year => 2006 },
@@ -1577,6 +1626,17 @@ Effectively a shortcut for C<< ->new_result(\%vals)->insert >>.
      },
   );
 
+Example of creating a new row and also creating a row in a related
+C<belongs_to>resultset. Note Hashref.
+
+  $cd_rs->create({
+    title=>"Music for Silly Walks",
+       year=>2000,
+       artist => {
+         name=>"Silly Musician",
+       }
+  });
+
 =cut
 
 sub create {
@@ -2035,10 +2095,10 @@ sub _merge_attr {
       $position++;
     }
     my ($b_key) = ( ref $b_element eq 'HASH' ) ? keys %{$b_element} : ($b_element);
+
     if ($best_candidate->{score} == 0 || exists $seen_keys->{$b_key}) {
       push( @{$a}, $b_element );
     } else {
-      $seen_keys->{$b_key} = 1; # don't merge the same key twice
       my $a_best = $a->[$best_candidate->{position}];
       # merge a_best and b_element together and replace original with merged
       if (ref $a_best ne 'HASH') {
@@ -2048,6 +2108,7 @@ sub _merge_attr {
         $a->[$best_candidate->{position}] = { $key => $self->_merge_attr($a_best->{$key}, $b_element->{$key}) };
       }
     }
+    $seen_keys->{$b_key} = 1; # don't merge the same key twice
   }
 
   return $a;
@@ -2071,7 +2132,12 @@ See L<DBIx::Class::Schema/throw_exception> for details.
 
 sub throw_exception {
   my $self=shift;
-  $self->_source_handle->schema->throw_exception(@_);
+  if (ref $self && $self->_source_handle->schema) {
+    $self->_source_handle->schema->throw_exception(@_)
+  } else {
+    croak(@_);
+  }
+
 }
 
 # XXX: FIXME: Attributes docs need clearing up
@@ -2160,7 +2226,7 @@ return a column named C<count(employeeid)> in the above example.
 =over 4
 
 Indicates additional columns to be selected from storage.  Works the same as
-L<select> but adds columns to the selection.
+L</select> but adds columns to the selection.
 
 =back
 
@@ -2168,7 +2234,7 @@ L<select> but adds columns to the selection.
 
 =over 4
 
-Indicates additional column names for those added via L<+select>.
+Indicates additional column names for those added via L</+select>.
 
 =back
 
@@ -2180,11 +2246,10 @@ Indicates additional column names for those added via L<+select>.
 
 =back
 
-Indicates column names for object inflation. That is, c< as >
+Indicates column names for object inflation. That is, C<as>
 indicates the name that the column can be accessed as via the
 C<get_column> method (or via the object accessor, B<if one already
-exists>).  It has nothing to do with the SQL code C< SELECT foo AS bar
->.
+exists>).  It has nothing to do with the SQL code C<SELECT foo AS bar>.
 
 The C<as> attribute is used in conjunction with C<select>,
 usually when C<select> contains one or more function or stored
@@ -2290,6 +2355,8 @@ to Earth' and a cd with title 'Popular'.
 If you want to fetch related objects from other tables as well, see C<prefetch>
 below.
 
+For more help on using joins with search, see L<DBIx::Class::Manual::Joining>.
+
 =head2 prefetch
 
 =over 4