X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FRow.pm;h=19b1a767cd20d8d2149a2f9264a86c2052969c2a;hb=8a89a03cad87b903e938825ec45b6b2c48db53c5;hp=24575f7d9bf66fb311eb568a3d37e5aa8ea0a171;hpb=af2d42c04edc254f8b83010a8feadc31d0ac3860;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Row.pm b/lib/DBIx/Class/Row.pm index 24575f7..19b1a76 100644 --- a/lib/DBIx/Class/Row.pm +++ b/lib/DBIx/Class/Row.pm @@ -44,19 +44,27 @@ passed objects. ## tests! sub new { - my ($class, $attrs, $source) = @_; + my ($class, $attrs) = @_; $class = ref $class if ref $class; my $new = { _column_data => {} }; bless $new, $class; - $new->_source_handle($source) if $source; + if (my $handle = delete $attrs->{-source_handle}) { + $new->_source_handle($handle); + } + if (my $source = delete $attrs->{-result_source}) { + $new->result_source($source); + } if ($attrs) { $new->throw_exception("attrs must be a hashref") unless ref($attrs) eq 'HASH'; my ($related,$inflated); + ## Pretend all the rels are actual objects, unset below if not, for insert() to fix + $new->{_rel_in_storage} = 1; + foreach my $key (keys %$attrs) { if (ref $attrs->{$key}) { ## Can we extract this lot to use with update(_or .. ) ? @@ -64,49 +72,48 @@ sub new { if ($info && $info->{attrs}{accessor} && $info->{attrs}{accessor} eq 'single') { - my $rel_obj = $attrs->{$key}; - $new->{_rel_in_storage} = 1; + my $rel_obj = delete $attrs->{$key}; if(!Scalar::Util::blessed($rel_obj)) { - $rel_obj = $new->new_related($key, $rel_obj); - $new->{_rel_in_storage} = 0; + $rel_obj = $new->find_or_new_related($key, $rel_obj); + $new->{_rel_in_storage} = 0 unless ($rel_obj->in_storage); } - $new->set_from_related($key, $attrs->{$key}); - $related->{$key} = $attrs->{$key}; + $new->set_from_related($key, $rel_obj); + $related->{$key} = $rel_obj; next; } elsif ($info && $info->{attrs}{accessor} && $info->{attrs}{accessor} eq 'multi' && ref $attrs->{$key} eq 'ARRAY') { - my $others = delete $attrs->{$key}; - $new->{_rel_in_storage} = 1; - foreach my $rel_obj (@$others) { - if(!Scalar::Util::blessed($rel_obj)) { - $rel_obj = $new->new_related($key, $rel_obj); - $new->{_rel_in_storage} = 0; - } + my $others = delete $attrs->{$key}; + foreach my $rel_obj (@$others) { + if(!Scalar::Util::blessed($rel_obj)) { + $rel_obj = $new->new_related($key, $rel_obj); + $new->{_rel_in_storage} = 0; } - $related->{$key} = $others; - next; - } elsif ($class->has_column($key) - && exists $class->column_info($key)->{_inflate_info}) + } + $related->{$key} = $others; + next; + } elsif ($info && $info->{attrs}{accessor} + && $info->{attrs}{accessor} eq 'filter') { ## 'filter' should disappear and get merged in with 'single' above! - my $rel_obj = $attrs->{$key}; - $new->{_rel_in_storage} = 1; + my $rel_obj = delete $attrs->{$key}; if(!Scalar::Util::blessed($rel_obj)) { - $rel_obj = $new->new_related($key, $rel_obj); - $new->{_rel_in_storage} = 0; + $rel_obj = $new->find_or_new_related($key, $rel_obj); + $new->{_rel_in_storage} = 0 unless ($rel_obj->in_storage); } $inflated->{$key} = $rel_obj; next; + } elsif ($class->has_column($key) + && $class->column_info($key)->{_inflate_info}) { + $inflated->{$key} = $attrs->{$key}; + next; } } + use Data::Dumper; $new->throw_exception("No such column $key on $class") unless $class->has_column($key); $new->store_column($key => $attrs->{$key}); } - if (my $source = delete $attrs->{-result_source}) { - $new->result_source($source); - } $new->{_relationship_data} = $related if $related; $new->{_inflated_column} = $inflated if $inflated; @@ -137,18 +144,21 @@ sub insert { unless $source; # Check if we stored uninserted relobjs here in new() - $source->storage->txn_begin if(!$self->{_rel_in_storage}); - my %related_stuff = (%{$self->{_relationship_data} || {}}, %{$self->{_inflated_column} || {}}); - ## Should all be in relationship_data, but we need to get rid of the - ## 'filter' reltype.. - ## These are the FK rels, need their IDs for the insert. - foreach my $relname (keys %related_stuff) { - my $relobj = $related_stuff{$relname}; - if(ref $relobj ne 'ARRAY') { - $relobj->insert() if(!$relobj->in_storage); - $self->set_from_related($relname, $relobj); + if(!$self->{_rel_in_storage}) + { + $source->storage->txn_begin; + + ## Should all be in relationship_data, but we need to get rid of the + ## 'filter' reltype.. + ## These are the FK rels, need their IDs for the insert. + foreach my $relname (keys %related_stuff) { + my $rel_obj = $related_stuff{$relname}; + if(Scalar::Util::blessed($rel_obj) && $rel_obj->isa('DBIx::Class::Row')) { + $rel_obj->insert(); + $self->set_from_related($relname, $rel_obj); + } } } @@ -169,20 +179,23 @@ sub insert { $self->store_column($pri => $id); } - ## Now do the has_many rels, that need $selfs ID. - foreach my $relname (keys %related_stuff) { - my $relobj = $related_stuff{$relname}; - if(ref $relobj eq 'ARRAY') { - foreach my $obj (@$relobj) { - my $info = $self->relationship_info($relname); - ## What about multi-col FKs ? - my $key = $1 if($info && (keys %{$info->{cond}})[0] =~ /^foreign\.(\w+)/); - $obj->set_from_related($key, $self); - $obj->insert() if(!$obj->in_storage); + if(!$self->{_rel_in_storage}) + { + ## Now do the has_many rels, that need $selfs ID. + foreach my $relname (keys %related_stuff) { + my $relobj = $related_stuff{$relname}; + if(ref $relobj eq 'ARRAY') { + foreach my $obj (@$relobj) { + my $info = $self->relationship_info($relname); + ## What about multi-col FKs ? + my $key = $1 if($info && (keys %{$info->{cond}})[0] =~ /^foreign\.(\w+)/); + $obj->set_from_related($key, $self); + $obj->insert() if(!$obj->in_storage); + } } } + $source->storage->txn_commit; } - $source->storage->txn_commit if(!$self->{_rel_in_storage}); $self->in_storage(1); $self->{_dirty_columns} = {}; @@ -208,12 +221,16 @@ sub in_storage { =head2 update - $obj->update; + $obj->update \%columns?; 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. +Also takes an options hashref of C<< column_name => value> pairs >> to update +first. But be aware that this hashref might be edited in place, so dont rely on +it being the same after a call to C. + =cut sub update { @@ -385,6 +402,22 @@ sub get_dirty_columns { keys %{$self->{_dirty_columns}}; } +=head2 get_inflated_columns + + my $inflated_data = $obj->get_inflated_columns; + +Similar to get_columns but objects are returned for inflated columns instead of their raw non-inflated values. + +=cut + +sub get_inflated_columns { + my $self = shift; + return map { + my $accessor = $self->column_info($_)->{'accessor'} || $_; + ($_ => $self->$accessor); + } $self->columns; +} + =head2 set_column $obj->set_column($col => $val); @@ -525,6 +558,7 @@ sub inflate_result { $fetched = $pre_source->result_class->inflate_result( $pre_source, @{$pre_val}); } + $new->related_resultset($pre)->set_cache([ $fetched ]); my $accessor = $source->relationship_info($pre)->{attrs}{accessor}; $class->throw_exception("No accessor for prefetched $pre") unless defined $accessor;