X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FRow.pm;h=a5e0e120360f2823124426f8da1e4a29f4573509;hb=82f0e0aa75e07eeb3395c5dd2854073708450b96;hp=a5f7eaa114a4991fdaa12d45b8458582e1bc7c04;hpb=0c11ad0ee5c8407f6b87d6e15c62a1b445076dc0;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Row.pm b/lib/DBIx/Class/Row.pm index a5f7eaa..a5e0e12 100644 --- a/lib/DBIx/Class/Row.pm +++ b/lib/DBIx/Class/Row.pm @@ -5,7 +5,6 @@ use warnings; use base qw/DBIx::Class/; -use DBIx::Class::Exception; use Scalar::Util 'blessed'; use List::Util 'first'; use Try::Tiny; @@ -34,14 +33,31 @@ DBIx::Class::Row - Basic row methods This class is responsible for defining and doing basic operations on rows derived from L objects. -Row objects are returned from Ls using the +Result objects are returned from Ls using the L, L, L and L methods, as well as invocations of 'single' ( L, L or L) -relationship accessors of L objects. +relationship accessors of L objects. + +=head1 NOTE + +All "Row objects" derived from a Schema-attached L +object (such as a typical C<< L->L >> call) are actually Result +instances, based on your application's +L. + +L implements most of the row-based communication with the +underlying storage, but a Result class B. +Usually, Result classes inherit from L, which in turn +combines the methods from several classes, one of them being +L. Therefore, while many of the methods available to a +L-derived Result class are described in the following +documentation, it does not detail all of the methods available to Result +objects. Refer to L for more info. =head1 METHODS @@ -55,11 +71,11 @@ relationship accessors of L objects. =item Arguments: \%attrs or \%colsandvalues -=item Returns: A Row object +=item Return Value: L<$result|DBIx::Class::Manual::ResultClass> =back -While you can create a new row object by calling C directly on +While you can create a new result object by calling C directly on this class, you are better off calling it on a L object. @@ -243,7 +259,7 @@ sub new { next; } } - $new->throw_exception("No such column $key on $class") + $new->throw_exception("No such column '$key' on $class") unless $class->has_column($key); $new->store_column($key => $attrs->{$key}); } @@ -255,6 +271,42 @@ sub new { return $new; } +=head2 $column_accessor + + # Each pair does the same thing + + # (un-inflated, regular column) + my $val = $row->get_column('first_name'); + my $val = $row->first_name; + + $row->set_column('first_name' => $val); + $row->first_name($val); + + # (inflated column via DBIx::Class::InflateColumn::DateTime) + my $val = $row->get_inflated_column('last_modified'); + my $val = $row->last_modified; + + $row->set_inflated_column('last_modified' => $val); + $row->last_modified($val); + +=over + +=item Arguments: $value? + +=item Return Value: $value + +=back + +A column accessor method is created for each column, which is used for +getting/setting the value for that column. + +The actual method name is based on the +L name given during the +L L. Like L, this +will not store the data in the database until L or L +is called on the row. + =head2 insert $row->insert; @@ -263,7 +315,7 @@ sub new { =item Arguments: none -=item Returns: The Row object +=item Return Value: L<$result|DBIx::Class::Manual::ResultClass> =back @@ -271,8 +323,8 @@ Inserts an object previously created by L into the database if it isn't already in there. Returns the object itself. To insert an entirely new row into the database, use L. -To fetch an uninserted row object, call -L on a resultset. +To fetch an uninserted result object, call +L on a resultset. This will also insert any uninserted, related objects held inside this one, see L for more details. @@ -416,7 +468,7 @@ sub insert { =item Arguments: none or 1|0 -=item Returns: 1|0 +=item Return Value: 1|0 =back @@ -425,8 +477,8 @@ not. This is set to true when L, L or L are used. -Creating a row object using L, or calling -L on one, sets it to false. +Creating a result object using L, or +calling L on one, sets it to false. =cut @@ -444,11 +496,11 @@ sub in_storage { =item Arguments: none or a hashref -=item Returns: The Row object +=item Return Value: L<$result|DBIx::Class::Manual::ResultClass> =back -Throws an exception if the row object is not yet in the database, +Throws an exception if the result object is not yet in the database, according to L. This method issues an SQL UPDATE query to commit any changes to the @@ -473,7 +525,7 @@ contain scalar references, e.g.: $row->update({ last_modified => \'NOW()' }); The update will pass the values verbatim into SQL. (See -L docs). The values in your Row object will NOT change +L docs). The values in your Result object will NOT change as a result of the update call, if you want the object to be updated with the actual values from the database, call L after the update. @@ -522,7 +574,7 @@ sub update { =item Arguments: none -=item Returns: The Row object +=item Return Value: L<$result|DBIx::Class::Manual::ResultClass> =back @@ -546,7 +598,7 @@ main row first> and only then attempts to delete any remaining related rows. If you delete an object within a txn_do() (see L) -and the transaction subsequently fails, the row object will remain marked as +and the transaction subsequently fails, the result object will remain marked as not being in storage. If you know for a fact that the object is still in storage (i.e. by inspecting the cause of the transaction's failure), you can use C<< $obj->in_storage(1) >> to restore consistency between the object and @@ -588,14 +640,14 @@ sub delete { =item Arguments: $columnname -=item Returns: The value of the column +=item Return Value: The value of the column =back Throws an exception if the column name given doesn't exist according to L. -Returns a raw column value from the row object, if it has already +Returns a raw column value from the result object, if it has already been fetched from the database or set by an accessor. If an L has been set, it @@ -632,7 +684,7 @@ sub get_column { =item Arguments: $columnname -=item Returns: 0|1 +=item Return Value: 0|1 =back @@ -656,7 +708,7 @@ sub has_column_loaded { =item Arguments: none -=item Returns: A hash of columnname, value pairs. +=item Return Value: A hash of columnname, value pairs. =back @@ -686,7 +738,7 @@ sub get_columns { =item Arguments: none -=item Returns: A hash of column, value pairs +=item Return Value: A hash of column, value pairs =back @@ -711,7 +763,7 @@ sub get_dirty_columns { =item Arguments: $columnname -=item Returns: undefined +=item Return Value: not defined =back @@ -751,7 +803,7 @@ sub make_column_dirty { =item Arguments: none -=item Returns: A hash of column, object|value pairs +=item Return Value: A hash of column, object|value pairs =back @@ -814,7 +866,7 @@ sub _is_column_numeric { =item Arguments: $columnname, $value -=item Returns: $value +=item Return Value: $value =back @@ -824,7 +876,7 @@ the column is marked as dirty for when you next call L. If passed an object or reference as a value, this method will happily attempt to store it, and a later L or L will try and stringify/numify as appropriate. To set an object to be deflated -instead, see L. +instead, see L, or better yet, use L. =cut @@ -924,7 +976,7 @@ sub _track_storage_value { =item Arguments: \%columndata -=item Returns: The Row object +=item Return Value: L<$result|DBIx::Class::Manual::ResultClass> =back @@ -950,16 +1002,16 @@ sub set_columns { =item Arguments: \%columndata -=item Returns: The Row object +=item Return Value: L<$result|DBIx::Class::Manual::ResultClass> =back Sets more than one column value at once. Any inflated values are deflated and the raw values stored. -Any related values passed as Row objects, using the relation name as a +Any related values passed as Result objects, using the relation name as a key, are reduced to the appropriate foreign key values and stored. If -instead of related row objects, a hashref of column, value data is +instead of related result objects, a hashref of column, value data is passed, will create the related object first then store. Will even accept arrayrefs of data as a value to a @@ -1007,7 +1059,7 @@ sub set_inflated_columns { =item Arguments: \%replacementdata -=item Returns: The Row object copy +=item Return Value: L<$result|DBIx::Class::Manual::ResultClass> copy =back @@ -1078,7 +1130,7 @@ sub copy { =item Arguments: $columnname, $value -=item Returns: The value sent to storage +=item Return Value: The value sent to storage =back @@ -1086,7 +1138,7 @@ Set a raw value for a column without marking it as changed. This method is used internally by L which you should probably be using. -This is the lowest level at which data is set on a row object, +This is the lowest level at which data is set on a result object, extend this method to catch all data setting methods. =cut @@ -1106,14 +1158,14 @@ sub store_column { =over -=item Arguments: $result_source, \%columndata, \%prefetcheddata +=item Arguments: L<$result_source|DBIx::Class::ResultSource>, \%columndata, \%prefetcheddata -=item Returns: A Row object +=item Return Value: L<$result|DBIx::Class::Manual::ResultClass> =back All L methods that retrieve data from the -database and turn it into row objects call this method. +database and turn it into result objects call this method. Extend this method in your Result classes to hook into this process, for example to rebless the result into a different class. @@ -1139,56 +1191,28 @@ sub inflate_result { foreach my $pre (keys %{$prefetch||{}}) { - my (@pre_vals, $is_multi); - if (ref $prefetch->{$pre}[0] eq 'ARRAY') { - $is_multi = 1; - @pre_vals = @{$prefetch->{$pre}}; - } - else { - @pre_vals = $prefetch->{$pre}; - } - - my $pre_source = try { - $source->related_source($pre) - } - catch { - $class->throw_exception(sprintf + my @pre_vals; + @pre_vals = (ref $prefetch->{$pre}[0] eq 'ARRAY') + ? @{$prefetch->{$pre}} : $prefetch->{$pre} + if @{$prefetch->{$pre}}; - "Can't inflate manual prefetch into non-existent relationship '%s' from '%s', " - . "check the inflation specification (columns/as) ending in '%s.%s'.", - - $pre, - $source->source_name, - $pre, - (keys %{$pre_vals[0][0]})[0] || 'something.something...', - ); - }; + my $pre_source = $source->related_source($pre); my $accessor = $source->relationship_info($pre)->{attrs}{accessor} - or $class->throw_exception("No accessor type declared for prefetched $pre"); - - if (! $is_multi and $accessor eq 'multi') { - $class->throw_exception("Manual prefetch (via select/columns) not supported with accessor 'multi'"); - } + or $class->throw_exception("No accessor type declared for prefetched relationship '$pre'"); my @pre_objects; for my $me_pref (@pre_vals) { - # FIXME - this should not be necessary - # the collapser currently *could* return bogus elements with all - # columns set to undef - my $has_def; - for (values %{$me_pref->[0]}) { - if (defined $_) { - $has_def++; - last; - } - } - next unless $has_def; + # FIXME SUBOPTIMAL - the new row parsers can very well optimize + # this away entirely, and *never* return such empty rows. + # For now we maintain inflate_result API backcompat, see + # t/resultset/inflate_result_api.t + next unless defined first { defined $_ } values %{$me_pref->[0]}; - push @pre_objects, $pre_source->result_class->inflate_result( - $pre_source, @$me_pref - ); + push @pre_objects, $pre_source->result_class->inflate_result( + $pre_source, @$me_pref + ); } if ($accessor eq 'single') { @@ -1213,7 +1237,7 @@ sub inflate_result { =item Arguments: none -=item Returns: Result of update or insert operation +=item Return Value: Result of update or insert operation =back @@ -1244,7 +1268,7 @@ sub update_or_insert { =item Arguments: none -=item Returns: 0|1 or @columnnames +=item Return Value: 0|1 or @columnnames =back @@ -1266,7 +1290,7 @@ sub is_changed { =item Arguments: $columname -=item Returns: 0|1 +=item Return Value: 0|1 =back @@ -1285,9 +1309,9 @@ sub is_column_changed { =over -=item Arguments: $result_source_instance +=item Arguments: L<$result_source?|DBIx::Class::ResultSource> -=item Returns: a ResultSource instance +=item Return Value: L<$result_source|DBIx::Class::ResultSource> =back @@ -1323,7 +1347,7 @@ sub result_source { =item Arguments: $columnname, \%columninfo -=item Returns: undefined +=item Return Value: not defined =back @@ -1354,11 +1378,11 @@ sub register_column { =item Arguments: \%attrs -=item Returns: A Row object +=item Return Value: A Result object =back -Fetches a fresh copy of the Row object from the database and returns it. +Fetches a fresh copy of the Result object from the database and returns it. Throws an exception if a proper WHERE clause identifying the database row can not be constructed (i.e. if the original object does not contain its entire @@ -1366,11 +1390,11 @@ entire ). If passed the \%attrs argument, will first apply these attributes to the resultset used to find the row. -This copy can then be used to compare to an existing row object, to +This copy can then be used to compare to an existing result object, to determine if any changes have been made in the database since it was created. -To just update your Row object with any latest changes from the +To just update your Result object with any latest changes from the database, use L instead. The \%attrs argument should be compatible with @@ -1390,7 +1414,7 @@ sub get_from_storage { return $resultset->find($self->_storage_ident_condition); } -=head2 discard_changes ($attrs?) +=head2 discard_changes $row->discard_changes @@ -1398,7 +1422,7 @@ sub get_from_storage { =item Arguments: none or $attrs -=item Returns: self (updates object in-place) +=item Return Value: self (updates object in-place) =back