# Copyright (C) 2020 The Psycopg Team
from cpython.ref cimport Py_INCREF
-from cpython.dict cimport PyDict_GetItem
+from cpython.dict cimport PyDict_GetItem, PyDict_SetItem
from cpython.list cimport PyList_New, PyList_GET_ITEM, PyList_SET_ITEM
from cpython.tuple cimport PyTuple_New, PyTuple_SET_ITEM
from cpython.object cimport PyObject, PyObject_CallFunctionObjArgs
cdef readonly object connection
cdef readonly object adapters
+ # TODO: the dumpers should have the same tweaking of the loaders
+ cdef dict _adapters_loaders
+ cdef dict _adapters_dumpers
cdef dict _dumpers_cache
cdef dict _text_loaders
cdef dict _binary_loaders
self.adapters = global_adapters
self.connection = None
+ self._adapters_loaders = self.adapters._loaders
+ self._adapters_dumpers = self.adapters._dumpers
+
# mapping class, fmt -> Dumper instance
self._dumpers_cache: Dict[Tuple[type, Format], "Dumper"] = {}
Py_INCREF(tmp)
PyList_SET_ITEM(formats, i, tmp)
- self._c_set_row_types(types, formats)
+ self._c_set_row_types(self._nfields, types, formats)
- def set_row_types(self, types: Sequence[int], formats: Sequence[Format]) -> None:
- self._c_set_row_types(types, formats)
+ def set_row_types(self,
+ types: Sequence[int], formats: Sequence[Format]) -> None:
+ self._c_set_row_types(len(types), types, formats)
- cdef void _c_set_row_types(self, list types, list formats):
+ cdef void _c_set_row_types(self, int ntypes, list types, list formats):
+ cdef list loaders = PyList_New(ntypes)
+ cdef object loader
cdef dict text_loaders = {}
cdef dict binary_loaders = {}
- cdef list loaders = PyList_New(len(types))
- cdef object loader
- cdef libpq.Oid oid
- cdef int fmt
- cdef int i
- for i in range(len(types)):
- oid = types[i]
- fmt = formats[i]
+
+ # these are used more as Python object than C
+ cdef object oid
+ cdef object fmt
+ cdef PyObject *ptr
+ for i in range(ntypes):
+ oid = <object>PyList_GET_ITEM(types, i)
+ fmt = <object>PyList_GET_ITEM(formats, i)
if fmt == 0:
- if oid in text_loaders:
- loader = text_loaders[oid]
+ ptr = PyDict_GetItem(text_loaders, oid)
+ if ptr != NULL:
+ loader = <object>ptr
else:
- loader = text_loaders[oid] = self._get_row_loader(oid, fmt)
+ loader = self._get_row_loader(oid, fmt)
+ PyDict_SetItem(text_loaders, oid, loader)
else:
- if oid in binary_loaders:
- loader = binary_loaders[oid]
+ ptr = PyDict_GetItem(binary_loaders, oid)
+ if ptr != NULL:
+ loader = <object>ptr
else:
- loader = binary_loaders[oid] = self._get_row_loader(oid, fmt)
+ loader = self._get_row_loader(oid, fmt)
+ PyDict_SetItem(binary_loaders, oid, loader)
Py_INCREF(loader)
PyList_SET_ITEM(loaders, i, loader)
self._row_loaders = loaders
- cdef RowLoader _get_row_loader(self, libpq.Oid oid, int fmt):
+ cdef RowLoader _get_row_loader(self, object oid, object fmt):
cdef RowLoader row_loader = RowLoader()
loader = self._c_get_loader(oid, fmt)
row_loader.pyloader = loader.load
def get_loader(self, oid: int, format: Format) -> "Loader":
return self._c_get_loader(oid, format)
- cdef object _c_get_loader(self, libpq.Oid oid, int format):
+ cdef object _c_get_loader(self, object oid, object format):
cdef dict cache
- cdef object pyoid = oid
+ cdef PyObject *ptr
if format == 0:
cache = self._text_loaders
else:
cache = self._binary_loaders
- cdef PyObject *ptr = PyDict_GetItem(cache, pyoid)
+ ptr = PyDict_GetItem(cache, oid)
if ptr != NULL:
return <object>ptr
- loader_cls = self.adapters._loaders.get((pyoid, format))
- if loader_cls is None:
- loader_cls = self.adapters._loaders[oids.INVALID_OID, format]
- loader = cache[pyoid] = loader_cls(pyoid, self)
+ key = (oid, format)
+ ptr = PyDict_GetItem(self._adapters_loaders, (oid, format))
+ if ptr != NULL:
+ loader_cls = <object>ptr
+ else:
+ ptr = PyDict_GetItem(
+ self.adapters._loaders, (oids.INVALID_OID, format))
+ if ptr == NULL:
+ raise e.InterfaceError(f"unknown oid loader not found")
+ loader_cls = <object>ptr
+ loader = loader_cls(oid, self)
+ PyDict_SetItem(cache, oid, loader)
return loader