diff --git a/spec/pg/numeric_spec.cr b/spec/pg/numeric_spec.cr index b9049a5d..56821cff 100644 --- a/spec/pg/numeric_spec.cr +++ b/spec/pg/numeric_spec.cr @@ -1,5 +1,6 @@ require "../spec_helper" require "../../src/pg_ext/big_rational" +require "../../src/pg_ext/big_decimal" private def n(nd, w, s, ds, d) PG::Numeric.new(nd.to_i16, w.to_i16, s.to_i16, ds.to_i16, d.map(&.to_i16)) @@ -9,6 +10,10 @@ private def br(n, d) BigRational.new(n, d) end +private def bd(d) + BigDecimal.new(d) +end + private def ex(which) case which when "nan" @@ -82,6 +87,24 @@ describe PG::Numeric do end end + it "to_big_d" do + [ + {"nan", bd(0)}, + {"0", bd(0)}, + {"0.0", bd(0)}, + {"1", bd(1)}, + {"-1", bd(-1)}, + {"1.30", bd(1.3)}, + {"12345.6789123", bd(12345.6789123)}, + {"-0.00009", bd(-0.00009)}, + {"-0.000009", bd(-0.000009)}, + {"-0.0000009", bd(-0.0000009)}, + {"-0.00000009", bd(-0.00000009)}, + ].each do |x| + ex(x[0]).to_big_d.should eq(x[1]) + end + end + it "#to_s" do [ {"nan", "NaN"}, diff --git a/src/pg_ext/big_decimal.cr b/src/pg_ext/big_decimal.cr new file mode 100644 index 00000000..732cd947 --- /dev/null +++ b/src/pg_ext/big_decimal.cr @@ -0,0 +1,23 @@ +require "big" + +module PG + struct Numeric + # Returns a BigDecimal representation of the numeric. This retains all precision. + def to_big_d + return BigDecimal.new("0") if nan? || ndigits == 0 + + # Since BigDecimal allows initialaztion from String, why should one reinvent the wheel? + BigDecimal.new(to_s) + end + end + + class ResultSet + def read(t : BigDecimal.class) + read(PG::Numeric).to_big_d + end + + def read(t : BigDecimal?.class) + read(PG::Numeric?).try &.to_big_d + end + end +end