From: Peter Rabbitson Date: Wed, 10 Jun 2009 17:57:04 +0000 (+0000) Subject: Datatype aware update works X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=8f9eff7531d8f4b32008ed94c492c23603d15267;p=dbsrgits%2FDBIx-Class-Historic.git Datatype aware update works --- diff --git a/lib/DBIx/Class/Row.pm b/lib/DBIx/Class/Row.pm index c08c00d..e583f2b 100644 --- a/lib/DBIx/Class/Row.pm +++ b/lib/DBIx/Class/Row.pm @@ -769,8 +769,39 @@ sub set_column { my $old_value = $self->get_column($column); $self->store_column($column, $new_value); - $self->{_dirty_columns}{$column} = 1 - if (defined $old_value xor defined $new_value) || (defined $old_value && $old_value ne $new_value); + + my $dirty; + if (defined $old_value xor defined $new_value) { + $dirty = 1; + } + elsif (not defined $old_value) { # both undef + $dirty = 0; + } + elsif ($old_value eq $new_value) { + $dirty = 0; + } + else { # do a numeric comparison if datatype allows it + my $colinfo = $self->column_info ($column); + + # cache for speed + if (not defined $colinfo->{is_numeric}) { + $colinfo->{is_numeric} = + $self->result_source->schema->storage->is_datatype_numeric ($colinfo->{data_type}) + ? 1 + : 0 + ; + } + + if ($colinfo->{is_numeric}) { + $dirty = $old_value <=> $new_value; + } + else { + $dirty = 1; + } + } + + # sadly the update code just checks for keys, not for their value + $self->{_dirty_columns}{$column} = 1 if $dirty; # XXX clear out the relation cache for this column delete $self->{related_resultsets}{$column}; diff --git a/lib/DBIx/Class/Storage/DBI.pm b/lib/DBIx/Class/Storage/DBI.pm index f70384d..584b514 100644 --- a/lib/DBIx/Class/Storage/DBI.pm +++ b/lib/DBIx/Class/Storage/DBI.pm @@ -1559,6 +1559,27 @@ sub bind_attribute_by_data_type { return; } +=head2 is_datatype_numeric + +Given a datatype from column_info, returns a boolean value indicating if +the current RDBMS considers it a numeric value. This controls how +L<< DBIx::Class::Row/set_column >> decides whether to mark the column as +dirty - when the datatype is deemed numeric a C<< <=> >> comparison will +be performed instead of the usual C. + +=cut + +sub is_datatype_numeric { + my ($self, $dt) = @_; + + return 0 unless $dt; + + return $dt =~ /^ (?: + numeric | int(?:eger)? | (?:tiny|small|medium|big)int | dec(?:imal)? | real | float | double (?: \s+ precision)? | (?:big)?serial + ) $/ix; +} + + =head2 create_ddl_dir (EXPERIMENTAL) =over 4