From: Daniele Varrazzo Date: Thu, 7 Jan 2021 23:07:56 +0000 (+0100) Subject: Don't deal with the python-level connection in C adapters X-Git-Tag: 3.0.dev0~199 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dc702fb95a803cd5e8314952d269127984be3be1;p=thirdparty%2Fpsycopg.git Don't deal with the python-level connection in C adapters Use the libpq-level connection to shed some overhead. --- diff --git a/psycopg3_c/psycopg3_c/_psycopg3/adapt.pyx b/psycopg3_c/psycopg3_c/_psycopg3/adapt.pyx index afa44ad31..daf434b96 100644 --- a/psycopg3_c/psycopg3_c/_psycopg3/adapt.pyx +++ b/psycopg3_c/psycopg3_c/_psycopg3/adapt.pyx @@ -34,15 +34,12 @@ logger = logging.getLogger("psycopg3.adapt") cdef class CDumper: cdef object cls cdef public libpq.Oid oid - cdef readonly object connection cdef pq.PGconn _pgconn def __init__(self, cls: type, context: Optional[AdaptContext] = None): self.cls = cls - self.connection = context.connection if context is not None else None - self._pgconn = ( - self.connection.pgconn if self.connection is not None else None - ) + conn = context.connection if context is not None else None + self._pgconn = conn.pgconn if conn is not None else None # default oid is implicitly set to 0, subclasses may override it # PG 9.6 goes a bit bonker sending unknown oids, so use text instead @@ -145,11 +142,12 @@ cdef class CDumper: @cython.freelist(8) cdef class CLoader: cdef public libpq.Oid oid - cdef readonly connection + cdef pq.PGconn _pgconn def __init__(self, int oid, context: Optional[AdaptContext] = None): self.oid = oid - self.connection = context.connection if context is not None else None + conn = context.connection if context is not None else None + self._pgconn = conn.pgconn if conn is not None else None cdef object cload(self, const char *data, size_t length): raise NotImplementedError() diff --git a/psycopg3_c/psycopg3_c/_psycopg3/transform.pyx b/psycopg3_c/psycopg3_c/_psycopg3/transform.pyx index e24b2f917..57e8dc4a6 100644 --- a/psycopg3_c/psycopg3_c/_psycopg3/transform.pyx +++ b/psycopg3_c/psycopg3_c/_psycopg3/transform.pyx @@ -85,6 +85,9 @@ cdef class Transformer: @pgresult.setter def pgresult(self, result: Optional[PGresult]) -> None: + self.set_pgresult(result) + + cdef void set_pgresult(self, pq.PGresult result): self._pgresult = result if result is None: diff --git a/psycopg3_c/psycopg3_c/types/text.pyx b/psycopg3_c/psycopg3_c/types/text.pyx index bb7d83f9d..5070f5aae 100644 --- a/psycopg3_c/psycopg3_c/types/text.pyx +++ b/psycopg3_c/psycopg3_c/types/text.pyx @@ -17,6 +17,7 @@ from cpython.unicode cimport ( ) from psycopg3_c.pq cimport libpq, Escaping, _buffer_as_string_and_size +from psycopg3.encodings import pg2py cdef extern from "Python.h": const char *PyUnicode_AsUTF8AndSize(unicode obj, Py_ssize_t *size) @@ -32,16 +33,18 @@ cdef class _StringDumper(CDumper): self.is_utf8 = 0 self.encoding = "utf-8" + cdef const char *pgenc - conn = self.connection - if conn is not None: - self._bytes_encoding = conn.client_encoding.encode("utf-8") - self.encoding = PyBytes_AsString(self._bytes_encoding) - if ( - self._bytes_encoding == b"utf-8" - or self._bytes_encoding == b"ascii" - ): + if self._pgconn is not None: + pgenc = libpq.PQparameterStatus(self._pgconn.pgconn_ptr, b"client_encoding") + if pgenc == NULL or pgenc == b"UTF8": + self._bytes_encoding = b"utf-8" self.is_utf8 = 1 + else: + self._bytes_encoding = pg2py(pgenc).encode("utf-8") + if self._bytes_encoding == b"ascii": + self.is_utf8 = 1 + self.encoding = PyBytes_AsString(self._bytes_encoding) cdef Py_ssize_t cdump(self, obj, bytearray rv, Py_ssize_t offset) except -1: # the server will raise DataError subclass if the string contains 0x00 @@ -105,15 +108,20 @@ cdef class _TextLoader(CLoader): self.is_utf8 = 0 self.encoding = "utf-8" + cdef const char *pgenc - conn = self.connection - if conn is not None: - self._bytes_encoding = conn.client_encoding.encode("utf-8") - self.encoding = PyBytes_AsString(self._bytes_encoding) - if self._bytes_encoding == b"utf-8": + if self._pgconn is not None: + pgenc = libpq.PQparameterStatus(self._pgconn.pgconn_ptr, b"client_encoding") + if pgenc == NULL or pgenc == b"UTF8": + self._bytes_encoding = b"utf-8" self.is_utf8 = 1 - elif self._bytes_encoding == b"ascii": + else: + self._bytes_encoding = pg2py(pgenc).encode("utf-8") + + if pgenc == b"SQL_ASCII": self.encoding = NULL + else: + self.encoding = PyBytes_AsString(self._bytes_encoding) cdef object cload(self, const char *data, size_t length): if self.is_utf8: