X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FRow.pm;h=d35d299a26202c0ef9bfdd3a07f12772faae39ae;hb=c00b00deb4354de9c59e46bd83f4a2b23b953425;hp=f7b33ccbea43f0b266feef59421d5b8a72f7a47d;hpb=1d0057bd70e7846100004b3fd918168a852ac6f6;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Row.pm b/lib/DBIx/Class/Row.pm index f7b33cc..d35d299 100644 --- a/lib/DBIx/Class/Row.pm +++ b/lib/DBIx/Class/Row.pm @@ -21,13 +21,42 @@ 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 +L, L, +L and L methods, +as well as invocations of 'single' ( +L, +L or +L) +relationship accessors of L objects. + =head1 METHODS =head2 new - my $obj = My::Class->new($attrs); + my $row = My::Class->new(\%attrs); + + my $row = $schema->resultset('MySource')->new(\%colsandvalues); + +=over + +=item Arguments: \%attrs or \%colsandvalues + +=item Returns: A Row object -Creates a new row object from column => value mappings passed as a hash ref +=back + +While you can create a new row object by calling C directly on +this class, you are better off calling it on a +L object. + +When calling it directly, you will not get a complete, usable row +object until you pass or set the C attribute, to a +L instance that is attached to a +L with a valid connection. + +C<$attrs> is a hashref of column name, value data. It can also contain +some other attributes such as the C. Passing an object, or an arrayref of objects as a value will call L for you. When @@ -49,17 +78,21 @@ For a more involved explanation, see L. sub __new_related_find_or_new_helper { my ($self, $relname, $data) = @_; if ($self->__their_pk_needs_us($relname, $data)) { +# print STDERR "PK needs us\n"; +# print STDERR "Data: ", Data::Dumper::Dumper($data); return $self->result_source ->related_source($relname) ->resultset ->new_result($data); } if ($self->result_source->pk_depends_on($relname, $data)) { +# print STDERR "PK depends on\n"; return $self->result_source ->related_source($relname) ->resultset ->find_or_create($data); } +# print STDERR "Neither, find_or_new\n"; return $self->find_or_new_related($relname, $data); } @@ -67,12 +100,20 @@ sub __their_pk_needs_us { # this should maybe be in resultsource. my ($self, $relname, $data) = @_; my $source = $self->result_source; my $reverse = $source->reverse_relationship_info($relname); +# print STDERR "Found reverse rel info: ", Data::Dumper::Dumper($reverse); my $rel_source = $source->related_source($relname); my $us = { $self->get_columns }; +# print STDERR "Test on self cols: ", Data::Dumper::Dumper($us); foreach my $key (keys %$reverse) { # if their primary key depends on us, then we have to # just create a result and we'll fill it out afterwards - return 1 if $rel_source->pk_depends_on($key, $us); + my $dep = $rel_source->pk_depends_on($key, $us); + if($dep) { +# print STDERR "Assigning $self to $key\n"; + $data->{$key} = $self; + return 1; + } +# return 1 if $rel_source->pk_depends_on($key, $us); } return 0; } @@ -95,6 +136,7 @@ sub new { $new->result_source($source); } +# print "Source ", $source->source_name, " is $new\n"; if ($attrs) { $new->throw_exception("attrs must be a hashref") unless ref($attrs) eq 'HASH'; @@ -111,6 +153,8 @@ sub new { if ($info && $info->{attrs}{accessor} && $info->{attrs}{accessor} eq 'single') { +# print STDERR "Single $key ", Data::Dumper::Dumper($attrs); +# print STDERR "from $class to: $info->{class}\n"; my $rel_obj = delete $attrs->{$key}; if(!Scalar::Util::blessed($rel_obj)) { $rel_obj = $new->__new_related_find_or_new_helper($key, $rel_obj); @@ -120,10 +164,13 @@ sub new { $new->set_from_related($key, $rel_obj) if $rel_obj->in_storage; $related->{$key} = $rel_obj; +# print STDERR "Related :", join(", ", keys %$related), "\n"; next; } elsif ($info && $info->{attrs}{accessor} && $info->{attrs}{accessor} eq 'multi' && ref $attrs->{$key} eq 'ARRAY') { +# print STDERR "Multi $key ", Data::Dumper::Dumper($attrs); +# print STDERR "from $class to: $info->{class}\n"; my $others = delete $attrs->{$key}; foreach my $rel_obj (@$others) { if(!Scalar::Util::blessed($rel_obj)) { @@ -134,6 +181,7 @@ sub new { $new->set_from_related($key, $rel_obj) if $rel_obj->in_storage; } $related->{$key} = $others; +# print STDERR "Related :", join(", ", keys %$related), "\n"; next; } elsif ($info && $info->{attrs}{accessor} && $info->{attrs}{accessor} eq 'filter') @@ -151,6 +199,7 @@ sub new { $inflated->{$key} = $attrs->{$key}; next; } +# print STDERR "Done :", join(", ", keys %$related), "\n"; } $new->throw_exception("No such column $key on $class") unless $class->has_column($key); @@ -166,13 +215,21 @@ sub new { =head2 insert - $obj->insert; + $row->insert; -Inserts an object into the database if it isn't already in -there. Returns the object itself. Requires the object's result source to -be set, or the class to have a result_source_instance method. To insert -an entirely new object into the database, use C (see -L). +=over + +=item Arguments: none + +=item Returns: The Row object + +=back + +Inserts an object previously created by L into the database if +it isn't already in there. Returns the object itself. Requires the +object's result source to be set, or the class to have a +result_source_instance method. To insert an entirely new row into +the database, use C (see L). To fetch an uninserted row object, call L on a resultset. @@ -209,24 +266,33 @@ sub insert { my @pri = $self->primary_columns; REL: foreach my $relname (keys %related_stuff) { - +# print STDERR "Looking at: $relname\n"; my $rel_obj = $related_stuff{$relname}; next REL unless (Scalar::Util::blessed($rel_obj) && $rel_obj->isa('DBIx::Class::Row')); +# print STDERR "Check pk: from ", $source->source_name, " to $relname\n"; +# print STDERR "With ", Data::Dumper::Dumper({ $rel_obj->get_columns }); next REL unless $source->pk_depends_on( $relname, { $rel_obj->get_columns } ); - +# print STDERR "$rel_obj\n"; +# print STDERR "in_storage: ", $rel_obj->in_storage, "\n"; +# print STDERR "Inserting $relname\n"; $rel_obj->insert(); $self->set_from_related($relname, $rel_obj); delete $related_stuff{$relname}; } } +# print STDERR "self $self\n"; +# print STDERR "self in_storage ", $self->in_storage, "\n"; +# print STDERR "Ran out of rels, insert ", $source->source_name, "\n"; my $updated_cols = $source->storage->insert($source, { $self->get_columns }); $self->set_columns($updated_cols); + $self->in_storage(1); +# print STDERR "$self\n"; ## PK::Auto my @auto_pri = grep { @@ -265,10 +331,15 @@ sub insert { my $reverse = $source->reverse_relationship_info($relname); foreach my $obj (@cands) { $obj->set_from_related($_, $self) for keys %$reverse; +# my $them = { %{$obj->{_relationship_data} || {} }, $obj->get_inflated_columns }; my $them = { $obj->get_inflated_columns }; +# print STDERR "Does $relname need our PK?\n"; if ($self->__their_pk_needs_us($relname, $them)) { - $obj = $self->find_or_create_related($relname, $them); +# print STDERR "Yes\n"; + # $obj = $self->find_or_create_related($relname, $them); + $obj->insert(); } else { +# print STDERR "No\n"; $obj->insert(); } } @@ -277,15 +348,23 @@ sub insert { $rollback_guard->commit; } - $self->in_storage(1); +# $self->in_storage(1); undef $self->{_orig_ident}; return $self; } =head2 in_storage - $obj->in_storage; # Get value - $obj->in_storage(1); # Set value + $row->in_storage; # Get value + $row->in_storage(1); # Set value + +=over + +=item Arguments: none or 1|0 + +=item Returns: 1|0 + +=back Indicates whether the object exists as a row in the database or not. This is set to true when L, @@ -305,24 +384,35 @@ sub in_storage { =head2 update - $obj->update \%columns?; + $row->update(\%columns?) + +=over + +=item Arguments: none or a hashref + +=item Returns: The Row object + +=back + +Throws an exception if the row object is not yet in the database, +according to L. -Must be run on an object that is already in the database; issues an SQL -UPDATE query to commit any changes to the object to the database if -required. +This method issues an SQL UPDATE query to commit any changes to the +object to the database if required. -Also takes an options hashref of C<< column_name => value> pairs >> to update -first. But be aware that the hashref will be passed to -C, which might edit it in place, so dont rely on it being -the same after a call to C. If you need to preserve the hashref, it is -sufficient to pass a shallow copy to C, e.g. ( { %{ $href } } ) +Also takes an optional hashref of C<< column_name => value> >> pairs +to update on the object first. Be aware that the hashref will be +passed to C, which might edit it in place, so +don't rely on it being the same after a call to C. If you +need to preserve the hashref, it is sufficient to pass a shallow copy +to C, e.g. ( { %{ $href } } ) If the values passed or any of the column values set on the object contain scalar references, eg: - $obj->last_modified(\'NOW()'); + $row->last_modified(\'NOW()'); # OR - $obj->update({ last_modified => \'NOW()' }); + $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 @@ -330,7 +420,15 @@ 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. - $obj->update()->discard_changes(); + $row->update()->discard_changes(); + +To determine before calling this method, which column values have +changed and will be updated, call L. + +To check if any columns will be updated, call L. + +To force a column to be updated, call L before +this method. =cut @@ -361,16 +459,32 @@ sub update { =head2 delete - $obj->delete + $row->delete + +=over + +=item Arguments: none + +=item Returns: The Row object + +=back + +Throws an exception if the object is not in the database according to +L. Runs an SQL DELETE statement using the primary key +values to locate the row. + +The object is still perfectly usable, but L will +now return 0 and the object must be reinserted using L +before it can be used to L the row again. -Deletes the object from the database. The object is still perfectly -usable, but C<< ->in_storage() >> will now return 0 and the object must -reinserted using C<< ->insert() >> before C<< ->update() >> can be used -on it. If you delete an object in a class with a C -relationship, all the related objects will be deleted as well. To turn -this behavior off, pass C<< cascade_delete => 0 >> in the C<$attr> -hashref. Any database-level cascade or restrict will take precedence -over a DBIx-Class-based cascading delete. See also L. +If you delete an object in a class with a C relationship, an +attempt is made to delete all the related objects as well. To turn +this behaviour off, pass C<< cascade_delete => 0 >> in the C<$attr> +hashref of the relationship, see L. Any +database-level cascade or restrict will take precedence over a +DBIx-Class-based cascading delete. + +See also L. =cut @@ -400,7 +514,18 @@ sub delete { =head2 get_column - my $val = $obj->get_column($col); + my $val = $row->get_column($col); + +=over + +=item Arguments: $columnname + +=item Returns: 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 been fetched from the database or set by an accessor. @@ -408,6 +533,13 @@ been fetched from the database or set by an accessor. If an L has been set, it will be deflated and returned. +Note that if you used the C or the C