X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FResultSet.pm;h=c2b045cf332a9f244bfba837832e2c3f189aa81a;hb=0ed8d3b659c714c617fa211f32f34879c5b224f0;hp=b4219442c060013f9a189ece199eed366e65e55b;hpb=01d59a6a6cb21f4701777531b349dce6832e5b6a;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index b421944..c2b045c 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -11,6 +11,7 @@ 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/); @@ -95,6 +96,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 +141,8 @@ L. For more examples of using this function, see L. For a complete documentation for the first argument, see L. +For more help on using joins with search, see L. + =cut sub search { @@ -164,18 +169,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 +277,13 @@ sub search_rs { Pass a literal chunk of SQL to be added to the conditional part of the resultset query. +CAVEAT: C is provided for Class::DBI compatibility and should +only be used in that context. There are known problems using C +in chained queries; it can result in bind values in the wrong order. See +L and +L for searching techniques that do not +require C. + =cut sub search_literal { @@ -918,7 +938,7 @@ Performs an SQL C 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 with C, L emulates C +Note: When using C with C, L emulates C using C. Some databases (notably SQLite) do not support C with multiple columns. If you are using such a database, you should only use columns from the main table in your C @@ -1251,7 +1271,7 @@ Pass an arrayref of hashrefs. Each hashref should be a structure suitable for submitting to a $resultset->create(...) method. In void context, C in L 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, and a arrayref of the resulting row @@ -1288,6 +1308,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 in +L this will skip any component that is overriding +c. So if you are using something like L 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 @@ -1422,7 +1450,12 @@ sub page { =back -Creates an object in the resultset's result class and returns it. +Creates a new row object in the resultset's result class and returns +it. The row is not inserted into the database at this point, call +L to do that. Calling L +will tell you whether the row object has been inserted or not. + +Passes the hashref of input on to L. =cut @@ -1436,9 +1469,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 ); @@ -1536,14 +1572,63 @@ sub find_or_new { =item Arguments: \%vals -=item Return Value: $object +=item Return Value: a L $object =back -Inserts a record into the resultset and returns the object representing it. +Attempt to create a single new row or a row with multiple related rows +in the table represented by the resultset (and related tables). This +will not check for duplicate rows before inserting, use +L to do that. + +To create one row for this resultset, pass a hashref of key/value +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. + +To create related objects, pass a hashref for the value if the related +item is a foreign key relationship (L), +and use the name of the relationship as the key. (NOT the name of the field, +necessarily). For C and C relationships, pass an arrayref +of hashrefs containing the data for each of the rows to create in the foreign +tables, again using the relationship name as the key. + +Instead of hashrefs of plain related data (key/value pairs), you may +also pass new or inserted objects. New objects (not inserted yet, see +L), 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 +or C resultset. Note Arrayref. + + $artist_rs->create( + { artistid => 4, name => 'Manufactured Crap', cds => [ + { title => 'My First CD', year => 2006 }, + { title => 'Yet More Tweeny-Pop crap', year => 2007 }, + ], + }, + ); + +Example of creating a new row and also creating a row in a related +Cresultset. Note Hashref. + + $cd_rs->create({ + title=>"Music for Silly Walks", + year=>2000, + artist => { + name=>"Silly Musician", + } + }); + =cut sub create { @@ -2002,10 +2087,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') { @@ -2015,6 +2100,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; @@ -2127,7 +2213,7 @@ return a column named C in the above example. =over 4 Indicates additional columns to be selected from storage. Works the same as -L but adds columns to the selection. =back @@ -2135,7 +2221,7 @@ L. -The C< as > attribute is used in conjunction with C, usually when C