Subject: | Sometimes floats persist as Int |
It turns out that if you take a scalar that holds a float, use it as an int, store it
as the value for a Moose attribute, insert the value of the Moose attribute into
Mongo, then it's stored as a NumberLong instead of a float inside Mongo.
All those steps cause the about-to-be-inserted scalar to look like this according to
Devel::Peek:
SV = PVMG(0x21b8630) at 0x21abf98
REFCNT = 1
FLAGS = (PADMY,NOK,pIOK,pNOK)
IV = 1
NV = 1.25
PV = 0
Apparently, under these circumstances MongoDB is choosing to pass the IV to Mongo
instead of the NV. This seems like the wrong choice.
The attached code carries out the steps described and demonstrates the bug.
Subject: | example.pl |
use strict;
use v5.10;
use Devel::Peek;
use MongoDB;
{
package Foo;
use Moose;
has x => ( is => 'ro' );
}
my $y = 1.25;
Dump($y); # y is a NV: NV = 1.25
my $y = 1.25;
int $y;
Dump($y); # y is a PVNV: NV = 1.25, IV = 1
my $foo = Foo->new(x => $y);
my $x = $foo->x;
Dump($x); # y is a PVMG: NV = 1.25, IV = 1
my $c = MongoDB::Connection->new;
$c->testdb->testcol->update(
{ name => 'foo' },
{
name => 'foo',
v => $x,
},
{ upsert => 1, safe => 1},
);
my $result =$c->testdb->testcol->find_one(
{ name => 'foo' },
);
say "result: $result->{v}"; # prints 1 not 1.25!