1 package DBIx::Class::Row;
6 use base qw/DBIx::Class/;
8 __PACKAGE__->load_components(qw/AccessorGroup/);
10 __PACKAGE__->mk_group_accessors('simple' => 'result_source');
14 DBIx::Class::Row - Basic row methods
20 This class is responsible for defining and doing basic operations on rows
21 derived from L<DBIx::Class::Table> objects.
27 my $obj = My::Class->new($attrs);
29 Creates a new row object from column => value mappings passed as a hash ref
34 my ($class, $attrs) = @_;
35 $class = ref $class if ref $class;
36 my $new = bless({ _column_data => { } }, $class);
38 $new->throw("attrs must be a hashref" ) unless ref($attrs) eq 'HASH';
39 while (my ($k, $v) = each %{$attrs}) {
40 die "No such column $k on $class" unless $class->has_column($k);
41 $new->store_column($k => $v);
51 Inserts an object into the database if it isn't already in there. Returns
52 the object itself. Requires the object's result source to be set, or the
53 class to have a result_source_instance method.
59 return $self if $self->in_storage;
60 $self->{result_source} ||= $self->result_source_instance
61 if $self->can('result_source_instance');
62 my $source = $self->{result_source};
63 die "No result_source set on this object; can't insert" unless $source;
64 #use Data::Dumper; warn Dumper($self);
65 $source->storage->insert($source->from, { $self->get_columns });
67 $self->{_dirty_columns} = {};
73 $obj->in_storage; # Get value
74 $obj->in_storage(1); # Set value
76 Indicated whether the object exists as a row in the database or not
81 my ($self, $val) = @_;
82 $self->{_in_storage} = $val if @_ > 1;
83 return $self->{_in_storage};
90 Must be run on an object that is already in the database; issues an SQL
91 UPDATE query to commit any changes to the object to the db if required.
96 my ($self, $upd) = @_;
97 $self->throw( "Not in database" ) unless $self->in_storage;
98 my %to_update = $self->get_dirty_columns;
99 return $self unless keys %to_update;
100 my $rows = $self->result_source->storage->update(
101 $self->result_source->from, \%to_update, $self->ident_condition);
103 $self->throw( "Can't update ${self}: row not found" );
104 } elsif ($rows > 1) {
105 $self->throw("Can't update ${self}: updated more than one row");
107 $self->{_dirty_columns} = {};
115 Deletes the object from the database. The object is still perfectly usable
116 accessor-wise etc. but ->in_storage will now return 0 and the object must
117 be re ->insert'ed before it can be ->update'ed
124 $self->throw( "Not in database" ) unless $self->in_storage;
125 $self->result_source->storage->delete(
126 $self->result_source->from, $self->ident_condition);
127 $self->in_storage(undef);
129 die "Can't do class delete without a ResultSource instance"
130 unless $self->can('result_source_instance');
132 if (@_ > 1 && ref $_[$#_] eq 'HASH') {
133 $attrs = { %{ pop(@_) } };
135 my $query = (ref $_[0] eq 'HASH' ? $_[0] : {@_});
136 $self->result_source_instance->resultset->search(@_)->delete;
143 my $val = $obj->get_column($col);
145 Gets a column value from a row object. Currently, does not do
146 any queries; the column must have already been fetched from
147 the database and stored in the object.
152 my ($self, $column) = @_;
153 $self->throw( "Can't fetch data as class method" ) unless ref $self;
154 return $self->{_column_data}{$column}
155 if exists $self->{_column_data}{$column};
156 $self->throw( "No such column '${column}'" ) unless $self->has_column($column);
162 my %data = $obj->get_columns;
164 Does C<get_column>, for all column values at once.
170 return return %{$self->{_column_data}};
173 =head2 get_dirty_columns
175 my %data = $obj->get_dirty_columns;
177 Identical to get_columns but only returns those that have been changed.
181 sub get_dirty_columns {
183 return map { $_ => $self->{_column_data}{$_} }
184 keys %{$self->{_dirty_columns}};
189 $obj->set_column($col => $val);
191 Sets a column value. If the new value is different from the old one,
192 the column is marked as dirty for when you next call $obj->update.
199 my $old = $self->get_column($column);
200 my $ret = $self->store_column(@_);
201 $self->{_dirty_columns}{$column} = 1
202 if (defined $old ^ defined $ret) || (defined $old && $old ne $ret);
208 my $copy = $orig->set_columns({ $col => $val, ... });
210 Sets more than one column value at once.
215 my ($self,$data) = @_;
216 while (my ($col,$val) = each %$data) {
217 $self->set_column($col,$val);
224 my $copy = $orig->copy({ change => $to, ... });
226 Inserts a new row with the specified changes.
231 my ($self, $changes) = @_;
232 my $new = bless({ _column_data => { %{$self->{_column_data}}} }, ref $self);
233 $new->set_column($_ => $changes->{$_}) for keys %$changes;
239 $obj->store_column($col => $val);
241 Sets a column value without marking it as dirty.
246 my ($self, $column, $value) = @_;
247 $self->throw( "No such column '${column}'" )
248 unless exists $self->{_column_data}{$column} || $self->has_column($column);
249 $self->throw( "set_column called for ${column} without value" )
251 return $self->{_column_data}{$column} = $value;
254 =head2 inflate_result
256 Class->inflate_result($result_source, \%me, \%prefetch?)
258 Called by ResultSet to inflate a result from storage
263 my ($class, $source, $me, $prefetch) = @_;
264 #use Data::Dumper; print Dumper(@_);
265 my $new = bless({ result_source => $source,
269 ref $class || $class);
271 PRE: foreach my $pre (keys %{$prefetch||{}}) {
272 my $rel_obj = $class->relationship_info($pre);
273 die "Can't prefetch non-eistant relationship ${pre}" unless $rel_obj;
274 $schema ||= $source->schema;
275 my $pre_class = $schema->class($rel_obj->{class});
276 my $fetched = $pre_class->inflate_result(
277 $schema->source($pre_class), @{$prefetch->{$pre}});
278 $class->throw("No accessor for prefetched $pre")
279 unless defined $rel_obj->{attrs}{accessor};
280 PRIMARY: foreach my $pri ($rel_obj->{class}->primary_columns) {
281 unless (defined $fetched->get_column($pri)) {
286 if ($rel_obj->{attrs}{accessor} eq 'single') {
287 $new->{_relationship_data}{$pre} = $fetched;
288 } elsif ($rel_obj->{attrs}{accessor} eq 'filter') {
289 $new->{_inflated_column}{$pre} = $fetched;
291 $class->throw("Don't know how to store prefetched $pre");
297 =head2 insert_or_update
299 $obj->insert_or_update
301 Updates the object if it's already in the db, else inserts it.
305 sub insert_or_update {
307 return ($self->in_storage ? $self->update : $self->insert);
312 my @changed_col_names = $obj->is_changed
317 return keys %{shift->{_dirty_columns} || {}};
322 Accessor to the ResultSource this object was created from
330 Matt S. Trout <mst@shadowcatsystems.co.uk>
334 You may distribute this code under the same terms as Perl itself.