DBIx-DataModel
view release on metacpan or search on metacpan
lib/DBIx/DataModel/Source/Table.pm view on Meta::CPAN
croak "update() as instance method: too many arguments";
}
}
return ($to_set, $where);
}
sub _apply_handlers_for_update {
my ($self, $to_set, $where) = @_;
# class of the invocant
my $class = ref $self || $self;
# apply no_update and auto_update
my %no_update_column = $self->metadm->no_update_column;
delete $to_set->{$_} foreach keys %no_update_column;
my %auto_update_column = $self->metadm->auto_update_column;
while (my ($col, $handler) = each %auto_update_column) {
$to_set->{$col} = $handler->($to_set, $class);
}
# apply 'to_DB' handlers. Need temporary bless as an object
my $schema = $self->schema;
$to_set->{__schema} = $schema; # in case the handlers need it
bless $to_set, $class;
$to_set->apply_column_handler('to_DB');
delete $to_set->{__schema};
$schema->unbless($to_set);
# detect references to foreign objects
my $sqla = $schema->sql_abstract;
my @sub_refs;
foreach my $key (keys %$to_set) {
my $val = $to_set->{$key};
next if !ref $val;
push @sub_refs, $key
if does($val, 'HASH')
||( does($val, 'ARRAY')
&& !$sqla->{array_datatypes}
&& !$sqla->is_bind_value_with_type($val) );
# reftypes SCALAR or REF are OK; they are used by SQLA for verbatim SQL
}
# remove references to foreign objects
if (@sub_refs) {
carp "data passed to update() contained nested references : ",
CORE::join ", ", sort @sub_refs;
delete @{$to_set}{@sub_refs};
}
# THINK : instead of removing references to foreign objects, one could
# maybe perform recursive updates (including insert/update/delete of child
# objects)
}
sub update {
my $self = shift;
# prepare datastructures for generating the SQL
my ($to_set, $where) = $self->_parse_update_args(@_);
$self->_apply_handlers_for_update($to_set, $where);
# database request
my $schema = $self->schema;
my $sqla = $schema->sql_abstract;
my ($sql, @bind) = $sqla->update(
-table => $self->db_from,
-set => $to_set,
-where => $where,
);
$schema->_debug(do {no warnings 'uninitialized';
$sql . " / " . CORE::join(", ", @bind);});
my $prepare_method = $schema->dbi_prepare_method;
my $sth = $schema->dbh->$prepare_method($sql);
$sqla->bind_params($sth, @bind);
return $sth->execute(); # will return the number of updated records
}
#------------------------------------------------------------
# utility methods
#------------------------------------------------------------
sub db_from {
my $self = shift;
my $db_from = $self->metadm->db_from;
my $db_schema = $self->schema->db_schema;
# prefix table with $db_schema if non-empty and there is no hardwired db_schema
return $db_schema && $db_from !~ /\./ ? "$db_schema.$db_from" : $db_from;
}
sub has_invalid_columns {
my ($self) = @_;
my $results = $self->apply_column_handler('validate');
my @invalid; # names of invalid columns
while (my ($k, $v) = each %$results) {
push @invalid, $k if defined($v) and not $v;
}
return @invalid ? \@invalid : undef;
}
sub _parse_ending_options {
my ($class_or_self, $args_ref, $regex) = @_;
# end of list may contain options, recognized because option name is a
# scalar matching the given regex
my %options;
while (@$args_ref >= 2 && !ref $args_ref->[-2]
&& $args_ref->[-2] && $args_ref->[-2] =~ $regex) {
my ($opt_val, $opt_name) = (pop @$args_ref, pop @$args_ref);
$options{$opt_name} = $opt_val;
}
return \%options;
}
( run in 3.140 seconds using v1.01-cache-2.11-cpan-5735350b133 )