Closed huuhait closed 3 years ago
Hope you will see this error
@huuhait Can you provide a numeric that has this problem? I tried the number in your text, then two of numbers in your screenshot, and haven't been able to reproduce it yet
require "pg"
def debug(ndigits, weight, sign, dscale, digits)
n = PG::Numeric.new(ndigits.to_i16, weight.to_i16, sign.to_i16, dscale.to_i16, digits.map(&.to_i16))
puts n
puts n.inspect
puts n.to_s
puts n.to_f
n
end
debug 2, -1, 0, 5, [3390, 8000]
debug 2, 0, 0, 1, [595, 8000]
debug 5, 0, 0, 14, [202, 238, 6399, 9999, 9700]
[0.33908, 2, -1, 0, 5, [3390, 8000]]
0.33908
0.33908
0.33908
0.33908
[595.8, 2, 0, 0, 1, [595, 8000]]
595.8
595.8
595.8
595.8
[202.02386399999997, 5, 0, 0, 14, [202, 238, 6399, 9999, 9700]]
202.02386399999997
202.02386399999997
202.02386399999997
202.02386399999997
To get the digits
, weight
, sign
, dscale
, and digits
, one possible way is to add a print here
diff --git i/src/pg/numeric.cr w/src/pg/numeric.cr
index 19e3bcd..aebe970 100644
--- i/src/pg/numeric.cr
+++ w/src/pg/numeric.cr
@@ -34,6 +34,7 @@ module PG
def initialize(@ndigits : Int16, @weight : Int16, sign, @dscale : Int16, @digits : Array(Int16))
@sign = Sign.from_value(sign)
+ p [self, ndigits, weight, sign, dscale, digits]
end
# Returns `true` if the numeric is not a number.
and that should print before the exception. But also if you can get a number you know always does it from a select
query, and can give it to me, I can try and figure it out.
For the above thing, you can either edit the code in lib
as a temporary test, or in your own code after you require "pg"
you could probably monkey patch over the numeric initializer
require "pg"
module PG
struct Numeric
def initialize(@ndigits : Int16, @weight : Int16, sign, @dscale : Int16, @digits : Array(Int16))
@sign = Sign.from_value(sign)
p [self, ndigits, weight, sign, dscale, digits] # maybe remove the self part if that also cause the problem
end
end
end
I haven't actually tested that, so there might be some mistakes
@will i've tested
here is results
value in database is 2566.1918905000002000
Playground: https://play.crystal-lang.org/#/r/a763
Thank you, I can reproduce with that number.
Looking into postgres itself it seems like maybe how they go from numeric to float is to generate a string then parse that string, which seems wasteful, but maybe that's the only way for certain https://github.com/postgres/postgres/blob/32d6287d2eef6b6a4dde07e0513f3e4f321792ad/src/backend/utils/adt/numeric.c#L4306-L4330
Looking into different solutions
Thanks for reporting this. I expect to do a release sometime next week.
For example
0.33908 * 595.8 = 202.02386399999997
in Crystal lang if db saved a data like202.02386399999997
with type numeric it'll working good but it can't read it againhttps://github.com/will/crystal-pg/blob/master/src/pg/numeric.cr#L60