]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
RowLoader moved from adapt to transform module
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Thu, 14 May 2020 17:57:02 +0000 (05:57 +1200)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 17 May 2020 09:29:34 +0000 (21:29 +1200)
It's only used by the Transformer and it doesn't need to be exposed.

psycopg3/adapt.pxd
psycopg3/adapt.pyx
psycopg3/transform.pyx

index 4d372a3367d686a86936b943af32fe49dc8c5fb0..3c8a8772a31c262417464fb9f2f026597ebb4f1d 100644 (file)
@@ -1,10 +1,14 @@
+"""
+C definitions of the adaptation system.
+"""
+
+# Copyright (C) 2020 The Psycopg Team
+
 from cpython.object cimport PyObject
 
+# The type of a function reading a result from the database and returning
+# a Python object.
 ctypedef object (*cloader_func)(const char *data, size_t length, void *context)
-ctypedef void * (*get_context_func)(object conn)
 
-
-cdef struct RowLoader:
-    PyObject *pyloader  # borrowed
-    cloader_func cloader
-    void *context
+# Take in input a Loader instance and return a context for a `cloader_func`.
+ctypedef void * (*get_context_func)(object conn)
index d16881b786d328923f414d423ca72c09e73ef748..0cd43da6874b1ca07ae821840836a9c29ec51fcf 100644 (file)
@@ -1,5 +1,19 @@
-from psycopg3.adapt cimport cloader_func, get_context_func, RowLoader
+"""
+C implementation of the adaptation system.
 
+This module maps each Python adaptation function to a C adaptation function.
+Notice that C adaptation functions have a different signature because they can
+avoid making a memory copy, however this makes impossible to expose them to
+Python.
+
+This module exposes facilities to map the builtin adapters in python to
+equivalent C implementations.
+
+"""
+
+# Copyright (C) 2020 The Psycopg Team
+
+from psycopg3.adapt cimport cloader_func, get_context_func
 
 import logging
 logger = logging.getLogger("psycopg3.adapt")
@@ -31,21 +45,14 @@ cdef void register_c_loader(
     cloaders[pyloader] = cl
 
 
-cdef void fill_row_loader(RowLoader *loader, object pyloader):
-    loader.pyloader = <PyObject *>pyloader
-
-    cdef CLoader cloader
-    cloader = cloaders.get(pyloader)
-    if cloader is not None:
-        loader.cloader = cloader.cloader
-    else:
-        cloader = cloaders.get(getattr(pyloader, '__func__', None))
-        if cloader is not None and cloader.get_context is not NULL:
-            loader.cloader = cloader.cloader
-            loader.context = cloader.get_context(pyloader.__self__)
+def register_builtin_c_loaders():
+    """
+    Register all the builtin optimized methods.
 
+    This function is supposed to be called only once, after the Python loaders
+    are registered.
 
-def register_builtin_c_loaders():
+    """
     if cloaders:
         logger.warning("c loaders already registered")
         return
index 36fc99031b266b0cce695873b079246b323e587f..c5dc3368e7a83b4f2dd7279af3bed4591cccacbb 100644 (file)
@@ -1,3 +1,13 @@
+"""
+Helper object to transform values between Python and PostgreSQL
+
+Cython implementation: can access to lower level C features without creating
+too many temporary Python objects and performing less memory copying.
+
+"""
+
+# Copyright (C) 2020 The Psycopg Team
+
 from libc.string cimport memset
 from cpython.object cimport PyObject
 from cpython.ref cimport Py_INCREF
@@ -9,7 +19,6 @@ from typing import Any, Dict, Iterable, List, Optional, Sequence, Tuple
 
 from psycopg3.pq cimport libpq
 from psycopg3.pq.pq_cython cimport PGresult
-from psycopg3.adapt cimport RowLoader
 
 from psycopg3 import errors as e
 from psycopg3.pq.enums import Format
@@ -18,6 +27,12 @@ from psycopg3.pq.enums import Format
 TEXT_OID = 25
 
 
+cdef struct RowLoader:
+    PyObject *pyloader  # borrowed
+    cloader_func cloader
+    void *context
+
+
 cdef class Transformer:
     """
     An object that can adapt efficiently between Python and PostgreSQL.
@@ -154,10 +169,24 @@ cdef class Transformer:
             loader = self._set_loader(i, oid, fmt)
 
     cdef void _set_loader(self, int col, libpq.Oid oid, int fmt):
+        pyloader = self._pyloaders[col] = self.get_load_function(oid, fmt)
+
         cdef RowLoader *loader = self._row_loaders + col
+        loader.pyloader = <PyObject *>pyloader
 
-        pyloader = self._pyloaders[col] = self.get_load_function(oid, fmt)
-        fill_row_loader(loader, pyloader)
+        cdef CLoader cloader = cloaders.get(pyloader)
+
+        if cloader is not None:
+            # The cloader is a normal Python function
+            loader.cloader = cloader.cloader
+            return
+
+        cloader = cloaders.get(getattr(pyloader, '__func__', None))
+        if cloader is not None and cloader.get_context is not NULL:
+            # The cloader is the load() method of a Loader class
+            # Extract the context from the Loader instance
+            loader.cloader = cloader.cloader
+            loader.context = cloader.get_context(pyloader.__self__)
 
     def dump_sequence(
         self, objs: Iterable[Any], formats: Iterable[Format]