if ptr + length > bufend:
raise e.DataError("bad copy data: length exceeding data")
field = PyMemoryView_FromObject(
- ViewBuffer._from_buffer(ptr, length))
+ ViewBuffer._from_buffer(data, ptr, length))
ptr += length
Py_INCREF(field)
elif num_bs == 0:
# Nothing to unescape: we don't need a copy
field = PyMemoryView_FromObject(
- ViewBuffer._from_buffer(fstart, fend - fstart))
+ ViewBuffer._from_buffer(data, fstart, fend - fstart))
# This is a field containing backslashes
else:
# 10% of the innermost loop, so I'm willing to ask for forgiveness later...
ctypedef struct PGresAttValue:
- int len
- char *value
+ int len
+ char *value
ctypedef struct pg_result_int:
# NOTE: it would be advised that we don't know this structure's content
cdef int row
cdef int col
cdef PGresAttValue *attval
- cdef const char *val
cdef object record # not 'tuple' as it would check on assignment
cdef object records = PyList_New(row1 - row0)
brecord = PyList_GET_ITEM(records, row - row0)
attval = &(ires.tuples[row][col])
if attval.len == -1: # NULL_LEN
- Py_INCREF(None)
- PyTuple_SET_ITEM(<object>brecord, col, None)
- continue
+ pyval = None
+ else:
+ pyval = (<RowLoader>loader).cloader.cload(
+ attval.value, attval.len)
- pyval = (<RowLoader>loader).cloader.cload(
- attval.value, attval.len)
Py_INCREF(pyval)
PyTuple_SET_ITEM(<object>brecord, col, pyval)
brecord = PyList_GET_ITEM(records, row - row0)
attval = &(ires.tuples[row][col])
if attval.len == -1: # NULL_LEN
- Py_INCREF(None)
- PyTuple_SET_ITEM(<object>brecord, col, None)
- continue
+ pyval = None
+ else:
+ # TODO: no copy
+ b = attval.value[:attval.len]
+ pyval = PyObject_CallFunctionObjArgs(
+ (<RowLoader>loader).pyloader, <PyObject *>b, NULL)
- # TODO: no copy
- b = attval.value[:attval.len]
- pyval = PyObject_CallFunctionObjArgs(
- (<RowLoader>loader).pyloader, <PyObject *>b, NULL)
Py_INCREF(pyval)
PyTuple_SET_ITEM(<object>brecord, col, pyval)
cdef PyObject *loader # borrowed RowLoader
cdef int col
cdef PGresAttValue *attval
- cdef const char *val
cdef object record # not 'tuple' as it would check on assignment
record = PyTuple_New(self._nfields)
for col in range(self._nfields):
attval = &(ires.tuples[row][col])
if attval.len == -1: # NULL_LEN
- Py_INCREF(None)
- PyTuple_SET_ITEM(record, col, None)
- continue
-
- val = attval.value
- loader = PyList_GET_ITEM(row_loaders, col)
- if (<RowLoader>loader).cloader is not None:
- pyval = (<RowLoader>loader).cloader.cload(val, attval.len)
+ pyval = None
else:
- # TODO: no copy
- b = val[:attval.len]
- pyval = PyObject_CallFunctionObjArgs(
- (<RowLoader>loader).pyloader, <PyObject *>b, NULL)
+ loader = PyList_GET_ITEM(row_loaders, col)
+ if (<RowLoader>loader).cloader is not None:
+ pyval = (<RowLoader>loader).cloader.cload(
+ attval.value, attval.len)
+ else:
+ # TODO: no copy
+ b = attval.value[:attval.len]
+ pyval = PyObject_CallFunctionObjArgs(
+ (<RowLoader>loader).pyloader, <PyObject *>b, NULL)
Py_INCREF(pyval)
PyTuple_SET_ITEM(record, col, pyval)
# Copyright (C) 2020 The Psycopg Team
+cimport cython
from cpython.bytes cimport PyBytes_AsStringAndSize
from cpython.buffer cimport PyObject_CheckBuffer, PyBUF_SIMPLE
from cpython.buffer cimport PyObject_GetBuffer, PyBuffer_Release
+@cython.freelist(32)
cdef class PQBuffer:
"""
Wrap a chunk of memory allocated by the libpq and expose it as memoryview.
"""
@staticmethod
- cdef PQBuffer _from_buffer(unsigned char *buf, Py_ssize_t len):
+ cdef PQBuffer _from_buffer(unsigned char *buf, Py_ssize_t length):
cdef PQBuffer rv = PQBuffer.__new__(PQBuffer)
rv.buf = buf
- rv.len = len
+ rv.len = length
return rv
def __cinit__(self):
pass
+@cython.freelist(32)
cdef class ViewBuffer:
"""
- Wrap a chunk of memory for view only.
+ Wrap a chunk of memory owned by a different object.
"""
@staticmethod
- cdef ViewBuffer _from_buffer(unsigned char *buf, Py_ssize_t len):
+ cdef ViewBuffer _from_buffer(
+ object obj, unsigned char *buf, Py_ssize_t length
+ ):
cdef ViewBuffer rv = ViewBuffer.__new__(ViewBuffer)
+ rv.obj = obj
rv.buf = buf
- rv.len = len
+ rv.len = length
return rv
def __cinit__(self):