+# returns DBIx::Class::ResultSource::column_info as a hash indexed by column accessor || name
+sub _get_columns_by_accessor {
+ my $self = shift;
+ my $source = $self->result_source;
+ my %columns;
+ for my $name ( $source->columns ) {
+ my $info = $source->column_info($name);
+ $info->{name} = $name;
+ $columns{ $info->{accessor} || $name } = $info;
+ }
+ return %columns;
+}
+
+# Arguments: $rs, $name, $updates, $row, $if_not_submitted
+
+sub _update_relation {
+ my ( $self, $name, $updates, $object, $if_not_submitted ) = @_;
+
+ # this should never happen because we're checking the paramters passed to
+ # recursive_update, but just to be sure...
+ $object->throw_exception("No such relationship '$name'")
+ unless $object->has_relationship($name);
+
+ #warn "_update_relation $name: OBJ: " . ref($object) . " IN STOR: " . $object->in_storage . "\n";
+
+ my $info = $object->result_source->relationship_info($name);
+
+ # get a related resultset without a condition
+ my $related_resultset =
+ $self->related_resultset($name)->result_source->resultset;
+ my $resolved;
+ if ( $self->result_source->can('_resolve_condition') ) {
+ $resolved =
+ $self->result_source->_resolve_condition( $info->{cond}, $name,
+ $object );
+ }
+
+ # warn "$name resolved: " . Dumper( $resolved ); use Data::Dumper;
+ $resolved = {}
+ if defined $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION
+ && $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION
+ == $resolved;
+
+ my $rel_col_cnt = scalar keys %{ $info->{cond} };
+ use Data::Dumper;
+ warn "RELINFO for $name: " . Dumper($info);
+ warn "REL_COL_CNT: $rel_col_cnt";
+
+ #warn "REV RELINFO for $name: " . Dumper($revrelinfo);
+
+ # the only valid datatype for a has_many rels is an arrayref
+ if ( $info->{attrs}{accessor} eq 'multi' ) {
+ $self->throw_exception(
+ "data for has_many relationship '$name' must be an arrayref")
+ unless ref $updates eq 'ARRAY';
+
+ my @updated_ids;
+ for my $sub_updates ( @{$updates} ) {
+ my $sub_object = recursive_update(
+ resultset => $related_resultset,
+ updates => $sub_updates,
+ resolved => $resolved
+ );
+ push @updated_ids, $sub_object->id;
+ }
+ my @related_pks = $related_resultset->result_source->primary_columns;
+ if ( defined $if_not_submitted && $if_not_submitted eq 'delete' ) {
+
+ # only handles related result classes with single primary keys
+ if ( 1 == scalar @related_pks ) {
+ $object->$name->search(
+ { $related_pks[0] => { -not_in => \@updated_ids } } )
+ ->delete;
+ }
+ }
+ elsif ( defined $if_not_submitted
+ && $if_not_submitted eq 'set_to_null' )
+ {
+
+ # only handles related result classes with single primary keys
+ if ( 1 == scalar @related_pks ) {
+ my @fk = keys %$resolved;
+ $object->$name->search(
+ { $related_pks[0] => { -not_in => \@updated_ids } } )
+ ->update( { $fk[0] => undef } );
+ }
+ }
+ }
+ elsif ($info->{attrs}{accessor} eq 'single'
+ || $info->{attrs}{accessor} eq 'filter' )
+ {
+ #warn "\tupdating rel '$name': $if_not_submitted\n";
+ my $sub_object;
+ if ( ref $updates ) {
+
+ # for might_have relationship
+ if ( $info->{attrs}{accessor} eq 'single'
+ && defined $object->$name )
+ {
+ $sub_object = recursive_update(
+ resultset => $related_resultset,
+ updates => $updates,
+ object => $object->$name
+ );
+ }
+ else {
+ $sub_object = recursive_update(
+ resultset => $related_resultset,
+ updates => $updates,
+ resolved => $resolved
+ );
+ }
+ }
+ else {
+ $sub_object = $related_resultset->find($updates)
+ unless (
+ !$updates
+ && ( exists $info->{attrs}{join_type}
+ && $info->{attrs}{join_type} eq 'LEFT' )
+ );
+ }
+ $object->set_from_related( $name, $sub_object )
+ unless (
+ !$sub_object
+ && !$updates
+ && ( exists $info->{attrs}{join_type}
+ && $info->{attrs}{join_type} eq 'LEFT' )
+ );
+ }
+ else {
+ $self->throw_exception(
+ "recursive_update doesn't now how to handle relationship '$name' with accessor "
+ . $info->{attrs}{accessor} );
+ }