]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Added Transformer.types_sequence
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Thu, 6 Aug 2020 01:09:35 +0000 (02:09 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 23 Aug 2020 18:24:01 +0000 (19:24 +0100)
Not entirely sure yet if it will be needed, but this allows to free
dump_sequence() from returning the oids as second argument.

Dropped Transformer.get_dump_function() too.

psycopg3/psycopg3/proto.py
psycopg3/psycopg3/transform.py
psycopg3/psycopg3/utils/queries.py
psycopg3_c/psycopg3_c/_psycopg3.pyi
psycopg3_c/psycopg3_c/transform.pyx

index 9b84e28d4c69969c2e5f25468750d6612014213c..9ae326aadfccee1f279915dc1745f792fb54639d 100644 (file)
@@ -82,10 +82,10 @@ class Transformer(Protocol):
     ) -> Tuple[List[Optional[bytes]], List[int]]:
         ...
 
-    def dump(self, obj: None, format: Format = Format.TEXT) -> MaybeOid:
+    def types_sequence(self) -> List[int]:
         ...
 
-    def get_dump_function(self, src: type, format: Format) -> DumpFunc:
+    def dump(self, obj: None, format: Format = Format.TEXT) -> MaybeOid:
         ...
 
     def lookup_dumper(self, src: type, format: Format) -> DumperType:
index e8a1c714c9268f0d602328ebe549f23e7974d591..95c714082b081b19cf76a04b6b16c57670cd5b80 100644 (file)
@@ -6,15 +6,19 @@ Helper object to transform values between Python and PostgreSQL
 
 import codecs
 from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple
+from typing import TYPE_CHECKING
 
 from . import errors as e
 from . import pq
-from .proto import AdaptContext, DumpFunc, DumpersMap, DumperType
+from .proto import AdaptContext, DumpersMap, DumperType
 from .proto import LoadFunc, LoadersMap, LoaderType, MaybeOid
 from .cursor import BaseCursor
 from .connection import BaseConnection
 from .types.oids import builtins, INVALID_OID
 
+if TYPE_CHECKING:
+    from .adapt import Dumper
+
 Format = pq.Format
 TEXT_OID = builtins["text"].oid
 
@@ -36,8 +40,10 @@ class Transformer:
         self._setup_context(context)
         self.pgresult = None
 
-        # mapping class, fmt -> dump function
-        self._dump_funcs: Dict[Tuple[type, Format], DumpFunc] = {}
+        # mapping class, fmt -> Dumper instance
+        self._dumpers_cache: Dict[Tuple[type, Format], "Dumper"] = {}
+
+        self._oids: List[int] = []
 
         # mapping oid, fmt -> load function
         self._load_funcs: Dict[Tuple[int, Format], LoadFunc] = {}
@@ -136,46 +142,50 @@ class Transformer:
         for oid, fmt in types:
             rc.append(self.get_load_function(oid, fmt))
 
+    # TODO: drop?
     def dump_sequence(
         self, objs: Iterable[Any], formats: Iterable[Format]
     ) -> Tuple[List[Optional[bytes]], List[int]]:
-        out = []
-        types = []
+        out: List[Optional[bytes]] = []
+        oids = self._oids = []
 
         for var, fmt in zip(objs, formats):
-            data = self.dump(var, fmt)
-            if isinstance(data, tuple):
-                oid = data[1]
-                data = data[0]
+            if var is not None:
+                dumper = self.get_dumper(type(var), fmt)
+                data = dumper.dump(var)
+                if isinstance(data, tuple):
+                    data = data[0]
+
+                out.append(data)
+                oids.append(dumper.oid)
             else:
-                oid = TEXT_OID
+                out.append(None)
+                oids.append(TEXT_OID)
 
-            out.append(data)
-            types.append(oid)
+        return out, self._oids
 
-        return out, types
+    # TODO: drop?
+    def types_sequence(self) -> List[int]:
+        return self._oids
 
+    # TODO: drop?
     def dump(self, obj: None, format: Format = Format.TEXT) -> MaybeOid:
         if obj is None:
             return None, TEXT_OID
 
-        src = type(obj)
-        func = self.get_dump_function(src, format)
-        return func(obj)
+        dumper = self.get_dumper(type(obj), format)
+        return dumper.dump(obj)
 
-    def get_dump_function(self, src: type, format: Format) -> DumpFunc:
+    def get_dumper(self, src: type, format: Format) -> "Dumper":
         key = (src, format)
         try:
-            return self._dump_funcs[key]
+            return self._dumpers_cache[key]
         except KeyError:
             pass
 
-        dumper = self.lookup_dumper(src, format)
-        func: DumpFunc
-        func = dumper(src, self).dump
-
-        self._dump_funcs[key] = func
-        return func
+        dumper_cls = self.lookup_dumper(src, format)
+        self._dumpers_cache[key] = dumper = dumper_cls(src, self)
+        return dumper
 
     def lookup_dumper(self, src: type, format: Format) -> DumperType:
         key = (src, format)
index 3b0550cf35093883a53a46f045d0a414cc4c4d52..c2625ddcbf91e8571ec7417a21ca4ff1e3d502cb 100644 (file)
@@ -69,9 +69,9 @@ class PostgresQuery:
             params = _validate_and_reorder_params(
                 self._parts, vars, self._order
             )
-            self.params, self.types = self._tx.dump_sequence(
-                params, self.formats or ()
-            )
+            self.params, _ = self._tx.dump_sequence(params, self.formats or ())
+            if self.types is None:
+                self.types = self._tx.types_sequence()
         else:
             self.params = self.types = None
 
index aaa29883400b2310f24bcc656b1d845f70a5b3de..1a9e1d596d0ba97a6fa1f526a5dadf77b314792d 100644 (file)
@@ -35,10 +35,10 @@ class Transformer:
     def dump_sequence(
         self, objs: Iterable[Any], formats: Iterable[pq.Format]
     ) -> Tuple[List[Optional[bytes]], List[int]]: ...
+    def types_sequence(self) -> List[int]: ...
     def dump(
         self, obj: None, format: pq.Format = pq.Format.TEXT
     ) -> MaybeOid: ...
-    def get_dump_function(self, src: type, format: pq.Format) -> DumpFunc: ...
     def lookup_dumper(self, src: type, format: pq.Format) -> DumperType: ...
     def load_row(self, row: int) -> Optional[Tuple[Any, ...]]: ...
     def load_sequence(
index 7b438fb6c38b619d05853ec0082a480d04ed473d..adae62a7b50979fc316a1b8dd84ed45e5cc5aced 100644 (file)
@@ -42,8 +42,8 @@ cdef class Transformer:
     state so adapting several values of the same type can use optimisations.
     """
 
-    cdef list _dumpers_maps, _loaders_maps
-    cdef dict _dumpers, _loaders, _dump_funcs, _load_funcs
+    cdef list _dumpers_maps, _loaders_maps, _oids
+    cdef dict _dumpers, _loaders, _dumpers_cache, _load_funcs
     cdef object _connection, _codec
     cdef PGresult _pgresult
     cdef int _nfields, _ntuples
@@ -57,8 +57,10 @@ cdef class Transformer:
         self._loaders_maps: List["LoadersMap"] = []
         self._setup_context(context)
 
-        # mapping class, fmt -> dump function
-        self._dump_funcs: Dict[Tuple[type, Format], "DumpFunc"] = {}
+        # mapping class, fmt -> Dumper instance
+        self._dumpers_cache: Dict[Tuple[type, Format], "Dumper"] = {}
+
+        self._oids: List[int] = []
 
         # mapping oid, fmt -> load function
         self._load_funcs: Dict[Tuple[int, Format], "LoadFunc"] = {}
@@ -220,41 +222,44 @@ cdef class Transformer:
     def dump_sequence(
         self, objs: Iterable[Any], formats: Iterable[Format]
     ) -> Tuple[List[Optional[bytes]], List[int]]:
-        out = []
-        types = []
+        out: List[Optional[bytes]] = []
+        oids = self._oids = []
 
         for var, fmt in zip(objs, formats):
-            data = self.dump(var, fmt)
-            if isinstance(data, tuple):
-                oid = data[1]
-                data = data[0]
+            if var is not None:
+                dumper = self.get_dumper(type(var), fmt)
+                data = dumper.dump(var)
+                if isinstance(data, tuple):
+                    data = data[0]
+
+                out.append(data)
+                oids.append(dumper.oid)
             else:
-                oid = TEXT_OID
+                out.append(None)
+                oids.append(TEXT_OID)
 
-            out.append(data)
-            types.append(oid)
+        return out, oids
 
-        return out, types
+    def types_sequence(self) -> List[int]:
+        return self._oids
 
     def dump(self, obj: None, format: Format = 0) -> "MaybeOid":
         if obj is None:
             return None, TEXT_OID
 
-        src = type(obj)
-        func = self.get_dump_function(src, format)
-        return func(obj)
+        dumper = self.get_dumper(type(obj), format)
+        return dumper.dump(obj)
 
-    def get_dump_function(self, src: type, format: Format) -> "DumpFunc":
+    def get_dumper(self, src: type, format: Format) -> "Dumper":
         key = (src, format)
         try:
-            return self._dump_funcs[key]
+            return self._dumpers_cache[key]
         except KeyError:
             pass
 
-        dumper = self.lookup_dumper(src, format)
-        func = dumper(src, self).dump
-        self._dump_funcs[key] = func
-        return func
+        dumper_cls = self.lookup_dumper(src, format)
+        self._dumpers_cache[key] = dumper = dumper_cls(src, self)
+        return dumper
 
     def lookup_dumper(self, src: type, format: Format) -> "DumperType":
         key = (src, format)