]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Trying to dump int as int8, added binary dumpers for int and float
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sat, 14 Nov 2020 02:24:43 +0000 (02:24 +0000)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sat, 14 Nov 2020 02:24:43 +0000 (02:24 +0000)
psycopg3/psycopg3/types/numeric.py
tests/types/test_numeric.py

index 2773975e67d3afdb298514a2ad9d890d0fc298ca..8281199e7a0dd98a1ad617f00e9cb53f2cdd28b5 100644 (file)
@@ -12,6 +12,7 @@ from ..oids import builtins
 from ..adapt import Dumper, Loader
 
 _PackInt = Callable[[int], bytes]
+_PackFloat = Callable[[float], bytes]
 _UnpackInt = Callable[[bytes], Tuple[int]]
 _UnpackFloat = Callable[[bytes], Tuple[float]]
 
@@ -19,6 +20,7 @@ _pack_int2 = cast(_PackInt, struct.Struct("!h").pack)
 _pack_int4 = cast(_PackInt, struct.Struct("!i").pack)
 _pack_uint4 = cast(_PackInt, struct.Struct("!I").pack)
 _pack_int8 = cast(_PackInt, struct.Struct("!q").pack)
+_pack_float8 = cast(_PackFloat, struct.Struct("!d").pack)
 _unpack_int2 = cast(_UnpackInt, struct.Struct("!h").unpack)
 _unpack_int4 = cast(_UnpackInt, struct.Struct("!i").unpack)
 _unpack_uint4 = cast(_UnpackInt, struct.Struct("!I").unpack)
@@ -66,18 +68,22 @@ class NumberDumper(Dumper):
         if value in self._special:
             return self._special[value]
 
-        return b" " + value if value.startswith(b"-") else value
+        return value if obj >= 0 else b" " + value
 
 
 @Dumper.text(int)
 class IntDumper(NumberDumper):
-    # We don't know the size of it, so we have to return a type big enough
-    oid = builtins["numeric"].oid
+    oid = builtins["int8"].oid
+
+
+@Dumper.binary(int)
+class IntBinaryDumper(IntDumper):
+    def dump(self, obj: int) -> bytes:
+        return _pack_int8(obj)
 
 
 @Dumper.text(float)
 class FloatDumper(NumberDumper):
-
     oid = builtins["float8"].oid
 
     _special = {
@@ -87,9 +93,14 @@ class FloatDumper(NumberDumper):
     }
 
 
+@Dumper.binary(float)
+class FloatBinaryDumper(NumberDumper):
+    def dump(self, obj: float) -> bytes:
+        return _pack_float8(obj)
+
+
 @Dumper.text(Decimal)
 class DecimalDumper(NumberDumper):
-
     oid = builtins["numeric"].oid
 
     _special = {
index a4bfe89edcdad9744d656cbf72b7f4d46408eee7..445b905dc887a94ec9d30d73ca76a6863d9b1a9e 100644 (file)
@@ -27,10 +27,12 @@ from psycopg3.types.numeric import FloatLoader
         (int(-(2 ** 63)), "'-9223372036854775808'::bigint"),
     ],
 )
-def test_dump_int(conn, val, expr):
+@pytest.mark.parametrize("fmt_in", [Format.TEXT, Format.BINARY])
+def test_dump_int(conn, val, expr, fmt_in):
+    ph = "%s" if fmt_in == Format.TEXT else "%b"
     assert isinstance(val, int)
     cur = conn.cursor()
-    cur.execute(f"select {expr} = %s", (val,))
+    cur.execute(f"select {expr} = {ph}", (val,))
     assert cur.fetchone()[0] is True
 
 
@@ -82,14 +84,6 @@ def test_quote_int(conn, val, expr):
     assert cur.fetchone() == (val, -val)
 
 
-@pytest.mark.xfail
-def test_dump_int_binary():
-    # TODO: int binary adaptation (must choose the fitting int2,4,8)
-    tx = Transformer()
-    n = 1
-    tx.get_dumper(n, Format.BINARY).dump(n)
-
-
 @pytest.mark.parametrize(
     "val, pgtype, want",
     [
@@ -146,10 +140,12 @@ def test_load_int(conn, val, pgtype, want, fmt_out):
         (float("-inf"), "'-Infinity'"),
     ],
 )
-def test_dump_float(conn, val, expr):
+@pytest.mark.parametrize("fmt_in", [Format.TEXT, Format.BINARY])
+def test_dump_float(conn, val, expr, fmt_in):
+    ph = "%s" if fmt_in == Format.TEXT else "%b"
     assert isinstance(val, float)
     cur = conn.cursor()
-    cur.execute(f"select %s = {expr}::float8", (val,))
+    cur.execute(f"select {ph} = {expr}::float8", (val,))
     assert cur.fetchone()[0] is True
 
 
@@ -208,14 +204,6 @@ def test_dump_float_approx(conn, val, expr):
     assert cur.fetchone()[0] is True
 
 
-@pytest.mark.xfail
-def test_dump_float_binary():
-    # TODO: float binary adaptation
-    tx = Transformer()
-    n = 1.0
-    tx.get_dumper(n, Format.BINARY).dump(n)
-
-
 @pytest.mark.parametrize(
     "val, pgtype, want",
     [