_oid = builtins["numeric"].oid
+ def dump(self, obj: Decimal) -> bytes:
+ if obj.is_nan():
+ # cover NaN and sNaN
+ return b"NaN"
+ else:
+ return str(obj).encode("utf8")
+
_special = {
b"Infinity": b"'Infinity'::numeric",
b"-Infinity": b"'-Infinity'::numeric",
def dump(self, obj: Decimal) -> Union[bytearray, bytes]:
sign, digits, exp = obj.as_tuple()
- if exp == "n": # type: ignore[comparison-overlap]
+ if exp == "n" or exp == "N": # type: ignore[comparison-overlap]
return NUMERIC_NAN_BIN
elif exp == "F": # type: ignore[comparison-overlap]
return NUMERIC_NINF_BIN if sign else NUMERIC_PINF_BIN
def make_Decimal(self, spec):
if random() >= 0.99:
if self.conn.info.server_version >= 140000:
- return Decimal(choice(["NaN", "Inf", "-Inf"]))
+ return Decimal(choice(["NaN", "sNaN", "Inf", "-Inf"]))
else:
- return Decimal("NaN")
+ return Decimal(choice(["NaN", "sNaN"]))
sign = choice("+-")
num = choice(["0.zd", "d", "d.d"])
"val",
[
"0",
+ "-0",
"0.0",
"0.000000000000000000001",
"-0.000000000000000000001",
"nan",
+ "snan",
],
)
-def test_roundtrip_numeric(conn, val):
- cur = conn.cursor()
+@pytest.mark.parametrize("fmt_in", [Format.TEXT, Format.BINARY])
+@pytest.mark.parametrize("fmt_out", [pq.Format.TEXT, pq.Format.BINARY])
+def test_roundtrip_numeric(conn, val, fmt_in, fmt_out):
+ cur = conn.cursor(binary=fmt_out)
val = Decimal(val)
- cur.execute("select %s", (val,))
+ cur.execute(f"select %{fmt_in}", (val,))
result = cur.fetchone()[0]
assert isinstance(result, Decimal)
if val.is_nan():
("0.00000000000000001", b"1E-17"),
("-0.00000000000000001", b" -1E-17"),
("nan", b"'NaN'::numeric"),
+ ("snan", b"'NaN'::numeric"),
],
)
def test_quote_numeric(conn, val, expr):