Skip to content

Instantly share code, notes, and snippets.

@will
Created April 14, 2016 23:01
Show Gist options
  • Save will/1ce086413f2b6048460878563829b4d0 to your computer and use it in GitHub Desktop.
Save will/1ce086413f2b6048460878563829b4d0 to your computer and use it in GitHub Desktop.
require "./src/pg"
# require "../hexdump/hex.cr"
require "big_int"
struct Numeric
property ndigits
property weight
property sign
property dscale
property digits
TenK = BigInt.new(10000)
enum Sign
Pos = 0x0000
Neg = 0x4000
Nan = 0xC000
end
def initialize(bytes)
int_d = PG::Decoder::Int2Decoder.new
@ndigits = int_d.decode(bytes[0, 2])
@weight = int_d.decode(bytes[2, 2])
@sign = int_d.decode(bytes[4, 2])
@dscale = int_d.decode(bytes[6, 2])
@digits = (0...(bytes.size - 8)/2).map { |i| int_d.decode(bytes[i*2 + 8, 2]) }
end
def integer_part
digits_to_bigint @digits[0..weight]
end
def fractional_part
digits_to_bigint @digits[weight + 1..-1]
end
def to_s
p sign
if sign == Sign::Nan.value
"NaN"
else
"#{"-" if sign == Sign::Neg.value}#{integer_part}#{".#{fractional_part.to_s[0..dscale - 1]}" if dscale > 0}"
end
end
private def digits_to_bigint(digit_arr)
digit_arr.reduce(BigInt.new(0)) { |a, i| a*TenK + BigInt.new(i) }
end
end
class NumericDecoder < PG::Decoder::Decoder
def decode(bytes)
# puts bytes.hexdump
Numeric.new(bytes)
end
end
PG::Decoder.register_decoder NumericDecoder.new, 1700
DB = PG.connect(ENV["DATABASE_URL"]? || "postgres:///")
def try(n)
p n
r = DB.exec({Numeric}, "select #{n}::numeric")
n = r.rows[0].first
p ({ndigits: n.ndigits, weight: n.weight, sign: n.sign, dscale: n.dscale, digits: n.digits})
p n.to_s
puts
end
try "1"
try "1.1"
try "1.10"
try "11.11"
try "12.3456789"
try "123.456789"
try "12345.6789"
try "123451234523498293847982374987342987.987654321"
try "1.23451234523498293847982374987342987987654321"
try "99999999999999999999999.99999999999999999999"
try "0.000000000000000000000000000000000000009999999999999999999"
try "-1"
try "'nan'"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment