[Dbix-class] Getting numeric columns as numeric values

Darren Duncan darren at darrenduncan.net
Thu Feb 26 06:15:38 GMT 2015


I think the core issue is that Perl is not capable of losslessly representing 
all numbers that could come from a SQL database without using the string 
representation (or BigInt/BigRat/etc), and so using strings is a safe solution.

That being said, I think the best solution is for DBIx::Class to conditionally 
return as numbers.  Return a result $x as a Perl number if and only if both 
"(0+$x) eq $x" is true and $x is logically a number to the database.

Optionally auto-promote $x to a Math::BigInt/Rat/etc only when "(0+$x) ne $x".

Under this system, you get the most accurate semantics and performance without 
loss of precision.  (I assume the JSON modules deal with Math::BigInt/etc 
correctly.)

How does that work for people?

-- Darren Duncan

On 2015-02-25 3:30 PM, Augustus Saunders wrote:
> Seems a little backwards to create a helper to work around a core defect. This is something that should work transparently, and is very simple to do so.
>
> Augustus
>
>
> On Feb 25, 2015, at 2:53 PM, Dmitry L. <dim0xff at gmail.com> wrote:
>
>> Use DBIx::Class::Helper::Row::NumifyGet Luke
>>
>> On 26 February 2015 at 01:43, Lasse Makholm <lasse at unity3d.com> wrote:
>>>
>>>
>>> On Wed, Feb 25, 2015 at 10:59 PM, Darren Duncan <darren at darrenduncan.net>
>>> wrote:
>>>>
>>>> Augustus, what is the problem with DBIC stringifying numeric values?  That
>>>> ensures full precision and in particular when you want to use them as
>>>> numbers you can just do so, Perl does that automatically. -- Darren Duncan
>>>
>>>
>>> One example of it being a problem is when converting row objects to JSON.
>>> Javascripts === operator, for example, evaluates to false for for 42 ===
>>> "42".
>>>
>>> /L
>>>
>>>
>>>>
>>>>
>>>> On 2015-02-25 1:15 PM, Augustus Saunders wrote:
>>>>>
>>>>> For reasons unknown to us, DBIx is stringifying numeric values somewhere
>>>>> along the way. In order to ensure they come out numeric, we made this small
>>>>> patch:
>>>>>
>>>>> --- a/lib/perl5/DBIx/Class/Row.pm
>>>>> +++ b/lib/perl5/DBIx/Class/Row.pm
>>>>> @@ -661,10 +661,15 @@ To retrieve all loaded column values as a hash, use
>>>>> L</get_columns>.
>>>>>   sub get_column {
>>>>>     my ($self, $column) = @_;
>>>>>     $self->throw_exception( "Can't fetch data as class method" ) unless
>>>>> ref $self;
>>>>> -  return $self->{_column_data}{$column} if exists
>>>>> $self->{_column_data}{$column};
>>>>> +  if (exists $self->{_column_data}{$column}) {
>>>>> +    return 0 + $self->{_column_data}{$column} if
>>>>> $self->_is_column_numeric($column);
>>>>> +    return $self->{_column_data}{$column};
>>>>> +  }
>>>>>     if (exists $self->{_inflated_column}{$column}) {
>>>>> -    return $self->store_column($column,
>>>>> +    my $ret = $self->store_column($column,
>>>>>         $self->_deflated_column($column,
>>>>> $self->{_inflated_column}{$column}));
>>>>> +    return 0 + $ret if $self->_is_column_numeric($column);
>>>>> +    return $ret;
>>>>>     }
>>>>>     $self->throw_exception( "No such column '${column}'" ) unless
>>>>> $self->has_column($column);
>>>>>     return undef;
>>>>>
>>>>> If there's a better way to do this, or some way to prevent DBIx from
>>>>> stringifying the values in the first place, that would be nice to know too.
>>>>> Thanks-
>>>>>
>>>>> Augustus




More information about the DBIx-Class mailing list