DBIx-Class

 view release on metacpan or  search on metacpan

lib/DBIx/Class/Row.pm  view on Meta::CPAN

are invoked.

Creating a result object using L<DBIx::Class::ResultSet/new_result>, or
calling L</delete> on one, sets it to false.


=head2 update

  $result->update(\%columns?)

=over

=item Arguments: none or a hashref

=item Return Value: L<$result|DBIx::Class::Manual::ResultClass>

=back

Throws an exception if the result object is not yet in the database,
according to L</in_storage>. Returns the object itself.

This method issues an SQL UPDATE query to commit any changes to the
object to the database if required (see L</get_dirty_columns>).
It throws an exception if a proper WHERE clause uniquely identifying
the database row can not be constructed (see
L<significance of primary keys|DBIx::Class::Manual::Intro/The Significance and Importance of Primary Keys>
for more details).

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<set_inflated_columns>, which might edit it in place, so
don't rely on it being the same after a call to C<update>.  If you
need to preserve the hashref, it is sufficient to pass a shallow copy
to C<update>, e.g. ( { %{ $href } } )

If the values passed or any of the column values set on the object
contain scalar references, e.g.:

  $result->last_modified(\'NOW()')->update();
  # OR
  $result->update({ last_modified => \'NOW()' });

The update will pass the values verbatim into SQL. (See
L<SQL::Abstract::Classic> 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</discard_changes> after the
update.

  $result->update()->discard_changes();

To determine before calling this method, which column values have
changed and will be updated, call L</get_dirty_columns>.

To check if any columns will be updated, call L</is_changed>.

To force a column to be updated, call L</make_column_dirty> before
this method.

=cut

sub update {
  my ($self, $upd) = @_;

  $self->set_inflated_columns($upd) if $upd;

  my %to_update = $self->get_dirty_columns
    or return $self;

  $self->throw_exception( "Not in database" ) unless $self->in_storage;

  my $rows = $self->result_source->storage->update(
    $self->result_source, \%to_update, $self->_storage_ident_condition
  );
  if ($rows == 0) {
    $self->throw_exception( "Can't update ${self}: row not found" );
  } elsif ($rows > 1) {
    $self->throw_exception("Can't update ${self}: updated more than one row");
  }
  $self->{_dirty_columns} = {};
  $self->{related_resultsets} = {};
  delete $self->{_column_data_in_storage};
  return $self;
}

=head2 delete

  $result->delete

=over

=item Arguments: none

=item Return Value: L<$result|DBIx::Class::Manual::ResultClass>

=back

Throws an exception if the object is not in the database according to
L</in_storage>. Also throws an exception if a proper WHERE clause
uniquely identifying the database row can not be constructed (see
L<significance of primary keys|DBIx::Class::Manual::Intro/The Significance and Importance of Primary Keys>
for more details).

The object is still perfectly usable, but L</in_storage> will
now return 0 and the object must be reinserted using L</insert>
before it can be used to L</update> the row again.

If you delete an object in a class with a C<has_many> 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<DBIx::Class::Relationship>. Any
database-level cascade or restrict will take precedence over a
DBIx-Class-based cascading delete, since DBIx-Class B<deletes the
main row first> and only then attempts to delete any remaining related
rows.

If you delete an object within a txn_do() (see L<DBIx::Class::Storage/txn_do>)
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
the database. This would allow a subsequent C<< $obj->delete >> to work

lib/DBIx/Class/Row.pm  view on Meta::CPAN

          and
        ref($prefetch->{$rel_name}) ne $DBIx::Class::ResultSource::RowParser::Util::null_branch_class
      ) {

        if (ref $prefetch->{$rel_name}[0] eq 'ARRAY') {
          my $rel_rsrc = $rel_rs->result_source;
          my $rel_class = $rel_rs->result_class;
          my $rel_inflator = $rel_class->can('inflate_result');
          @rel_objects = map
            { $rel_class->$rel_inflator ( $rel_rsrc, @$_ ) }
            @{$prefetch->{$rel_name}}
          ;
        }
        else {
          @rel_objects = $rel_rs->result_class->inflate_result(
            $rel_rs->result_source, @{$prefetch->{$rel_name}}
          );
        }
      }

      if ($relinfo->{attrs}{accessor} eq 'single') {
        $new->{_relationship_data}{$rel_name} = $rel_objects[0];
      }
      elsif ($relinfo->{attrs}{accessor} eq 'filter') {
        $new->{_inflated_column}{$rel_name} = $rel_objects[0];
      }

      $rel_rs->set_cache(\@rel_objects);
    }
  }

  $new->in_storage (1);
  return $new;
}

=head2 update_or_insert

  $result->update_or_insert

=over

=item Arguments: none

=item Return Value: Result of update or insert operation

=back

L</update>s the object if it's already in the database, according to
L</in_storage>, else L</insert>s it.

=head2 insert_or_update

  $obj->insert_or_update

Alias for L</update_or_insert>

=cut

sub insert_or_update { shift->update_or_insert(@_) }

sub update_or_insert {
  my $self = shift;
  return ($self->in_storage ? $self->update : $self->insert);
}

=head2 is_changed

  my @changed_col_names = $result->is_changed();
  if ($result->is_changed()) { ... }

=over

=item Arguments: none

=item Return Value: 0|1 or @columnnames

=back

In list context returns a list of columns with uncommited changes, or
in scalar context returns a true value if there are uncommitted
changes.

=cut

sub is_changed {
  return keys %{shift->{_dirty_columns} || {}};
}

=head2 is_column_changed

  if ($result->is_column_changed('col')) { ... }

=over

=item Arguments: $columname

=item Return Value: 0|1

=back

Returns a true value if the column has uncommitted changes.

=cut

sub is_column_changed {
  my( $self, $col ) = @_;
  return exists $self->{_dirty_columns}->{$col};
}

=head2 result_source

  my $resultsource = $result->result_source;

=over

=item Arguments: L<$result_source?|DBIx::Class::ResultSource>

=item Return Value: L<$result_source|DBIx::Class::ResultSource>

=back



( run in 0.565 second using v1.01-cache-2.11-cpan-39bf76dae61 )