cdef object _connection, _codec
cdef PGresult _pgresult
cdef int _nfields, _ntuples
+
+ cdef int _nloaders
cdef RowLoader *_row_loaders
cdef object _pyloaders # only used to keep a reference
# mapping oid, fmt -> load function
self._load_funcs: Dict[Tuple[int, Format], "LoadFunc"] = {}
+ self._nloaders = 0
self._row_loaders = NULL
self._pyloaders = []
self.pgresult = None
def __dealloc__(self):
+ self._clear_row_loaders()
+
+ def _clear_row_loaders(self):
+ cdef int i
+ for i in range(self._nloaders):
+ PyMem_Free(self._row_loaders[i].context)
PyMem_Free(self._row_loaders)
def _setup_context(self, context: "AdaptContext") -> None:
def set_row_types(self, types: Sequence[Tuple[int, Format]]) -> None:
cdef int ntypes = len(types)
- PyMem_Free(self._row_loaders)
+ self._clear_row_loaders()
self._row_loaders = <RowLoader *>PyMem_Malloc(ntypes * sizeof(RowLoader))
memset(self._row_loaders, 0, ntypes * sizeof(RowLoader))
self._pyloaders = [None] * ntypes
# Copyright (C) 2020 The Psycopg Team
from cpython.bytes cimport PyBytes_FromStringAndSize
+from cpython.mem cimport PyMem_Malloc
+from cpython.object cimport PyObject
from cpython.unicode cimport PyUnicode_DecodeUTF8
from psycopg3.pq cimport libpq
+ctypedef unicode (*decodefunc)(char *s, Py_ssize_t size, char *errors)
+
+cdef struct TextContext:
+ PyObject *pydecoder
+ decodefunc cdecoder
+
cdef object load_text(const char *data, size_t length, void *context):
- # TODO: optimize
+ cdef TextContext *tcontext = <TextContext *>context
+ if tcontext.cdecoder:
+ return tcontext.cdecoder(<char *>data, length, NULL)
+
b = PyBytes_FromStringAndSize(data, length)
- if context is not NULL:
- codec = <object>context
- # TODO: check if the refcount is right (but a DECREF here segfaults)
- return codec(b)[0]
+ decoder = <object>(tcontext.pydecoder)
+ if decoder is not None:
+ # TODO: check if the refcount is right
+ return decoder(b)[0]
else:
return b
cdef void *get_context_text(object loader):
- if loader.decode is not None:
- return <void *>loader.decode
- else:
- return NULL
+ cdef TextContext *rv = <TextContext *>PyMem_Malloc(sizeof(TextContext))
+ rv.pydecoder = <PyObject *>loader.decode
+ rv.cdecoder = NULL
+
+ if loader.connection is None or loader.connection.encoding == "UTF8":
+ rv.cdecoder = <decodefunc>PyUnicode_DecodeUTF8
+
+ return rv
cdef object load_bytea_text(const char *data, size_t length, void *context):