From 490081a4a87a2dfc122e3ed9e900d0fe2c07f895 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=B6rg=20Breitbart?= Date: Thu, 11 Sep 2025 17:08:42 +0200 Subject: [PATCH] last code version with page_size attribute --- psycopg_c/psycopg_c/_psycopg/transform.pyx | 44 ++++++++++++++++------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/psycopg_c/psycopg_c/_psycopg/transform.pyx b/psycopg_c/psycopg_c/_psycopg/transform.pyx index 22cab1348..c5d7df731 100644 --- a/psycopg_c/psycopg_c/_psycopg/transform.pyx +++ b/psycopg_c/psycopg_c/_psycopg/transform.pyx @@ -36,6 +36,7 @@ cdef extern from *: """ void* alloca(size_t size) +ctypedef object (*cload_ptr)(CLoader, const char *, size_t) NoneType = type(None) @@ -109,6 +110,8 @@ cdef class Transformer: cdef dict _oid_types + cdef public int _page_size + def __cinit__(self, context: "AdaptContext" | None = None): if context is not None: self.adapters = context.adapters @@ -120,6 +123,7 @@ cdef class Transformer: self.types = self.formats = None self._none_oid = -1 + self._page_size = 100 @classmethod def from_context(cls, context: "AdaptContext" | None): @@ -434,7 +438,7 @@ cdef class Transformer: self.formats = pqformats return out - def load_rows_(self, int row0, int row1, object make_row) -> list[Row]: + def load_rows(self, int row0, int row1, object make_row) -> list[Row]: if self._pgresult is None: raise e.InterfaceError("result not set") @@ -457,12 +461,11 @@ cdef class Transformer: cdef PyObject *loader # borrowed RowLoader cdef PyObject *brecord # borrowed - cdef int advance row_loaders = self._row_loaders # avoid an incref/decref per item - cdef int window = 100 - for pr0 in range(row0, row1, window): - pr1 = min(pr0 + window, row1) + cdef int page_size = self._page_size + for pr0 in range(row0, row1, page_size): + pr1 = min(pr0 + page_size, row1) for row in range(pr0, pr1): record = PyTuple_New(self._nfields) Py_INCREF(record) @@ -509,7 +512,7 @@ cdef class Transformer: Py_DECREF(brecord) return records - def load_rows(self, int row0, int row1, object make_row) -> list[Row]: + def load_rows_(self, int row0, int row1, object make_row) -> list[Row]: if self._pgresult is None: raise e.InterfaceError("result not set") @@ -530,9 +533,20 @@ cdef class Transformer: cdef object records = PyList_New(row1 - row0) # hacky but fastest access to loaders - cdef PyObject **loaders = alloca(self._nfields * sizeof(PyObject *)) + #cdef int32_t *has_cloader = alloca(self._nfields * sizeof(int32_t)) + cdef cload_ptr *cloads = alloca(self._nfields * sizeof(cload_ptr)) + cdef PyObject **loadfuncs = alloca(self._nfields * sizeof(PyObject *)) + cdef PyObject *loader for col in range(self._nfields): - loaders[col] = PyList_GET_ITEM(self._row_loaders, col) + #loaders[col] = PyList_GET_ITEM(self._row_loaders, col) + loader = PyList_GET_ITEM(self._row_loaders, col) + if (loader).cloader is not None: + #has_cloader[col] = 1 + cloads[col] = (loader).cloader.cload + else: + #has_cloader[col] = 0 + cloads[col] = NULL + loadfuncs[col] = (loader).loadfunc for row in range(row0, row1): record = PyTuple_New(self._nfields) @@ -541,18 +555,24 @@ cdef class Transformer: if attval.len == -1: # NULL_LEN pyval = None else: - if (loaders[col]).cloader is not None: - pyval = (loaders[col]).cloader.cload( - attval.value, attval.len) + if cloads[col]: + #if has_cloader[col]: + #if (loaders[col]).cloader is not None: + #pyval = (loaders[col]).cloader.cload( + # attval.value, attval.len) + pyval = cloads[col](None, attval.value, attval.len) else: + #loader = PyList_GET_ITEM(self._row_loaders, col) b = PyMemoryView_FromObject( ViewBuffer._from_buffer( self._pgresult, attval.value, attval.len )) + #pyval = PyObject_CallFunctionObjArgs( + # (loader).loadfunc, b, NULL) pyval = PyObject_CallFunctionObjArgs( - (loaders[col]).loadfunc, b, NULL) + loadfuncs[col], b, NULL) Py_INCREF(pyval) PyTuple_SET_ITEM(record, col, pyval) if make_row is not tuple: -- 2.47.3