From: Daniele Varrazzo Date: Sat, 26 Dec 2020 18:09:17 +0000 (+0100) Subject: Release the gil around the exec/send libpq functions X-Git-Tag: 3.0.dev0~240 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7cc9cc2228fd935d4276f29c6d7047c089b75637;p=thirdparty%2Fpsycopg.git Release the gil around the exec/send libpq functions --- diff --git a/psycopg3_c/psycopg3_c/pq/libpq.pxd b/psycopg3_c/psycopg3_c/pq/libpq.pxd index d4498c4c6..6bd9fa1f9 100644 --- a/psycopg3_c/psycopg3_c/pq/libpq.pxd +++ b/psycopg3_c/psycopg3_c/pq/libpq.pxd @@ -128,7 +128,7 @@ cdef extern from "libpq-fe.h": # TODO: PQsslAttribute, PQsslAttributeNames, PQsslStruct, PQgetssl # 33.3. Command Execution Functions - PGresult *PQexec(PGconn *conn, const char *command) + PGresult *PQexec(PGconn *conn, const char *command) nogil PGresult *PQexecParams(PGconn *conn, const char *command, int nParams, @@ -136,19 +136,19 @@ cdef extern from "libpq-fe.h": const char * const *paramValues, const int *paramLengths, const int *paramFormats, - int resultFormat) + int resultFormat) nogil PGresult *PQprepare(PGconn *conn, const char *stmtName, const char *query, int nParams, - const Oid *paramTypes) + const Oid *paramTypes) nogil PGresult *PQexecPrepared(PGconn *conn, const char *stmtName, int nParams, const char * const *paramValues, const int *paramLengths, const int *paramFormats, - int resultFormat) + int resultFormat) nogil PGresult *PQdescribePrepared(PGconn *conn, const char *stmtName) PGresult *PQdescribePortal(PGconn *conn, const char *portalName) ExecStatusType PQresultStatus(const PGresult *res) @@ -200,7 +200,7 @@ cdef extern from "libpq-fe.h": # 33.4. Asynchronous Command Processing - int PQsendQuery(PGconn *conn, const char *command) + int PQsendQuery(PGconn *conn, const char *command) nogil int PQsendQueryParams(PGconn *conn, const char *command, int nParams, @@ -208,19 +208,19 @@ cdef extern from "libpq-fe.h": const char * const *paramValues, const int *paramLengths, const int *paramFormats, - int resultFormat) + int resultFormat) nogil int PQsendPrepare(PGconn *conn, const char *stmtName, const char *query, int nParams, - const Oid *paramTypes) + const Oid *paramTypes) nogil int PQsendQueryPrepared(PGconn *conn, const char *stmtName, int nParams, const char * const *paramValues, const int *paramLengths, const int *paramFormats, - int resultFormat) + int resultFormat) nogil int PQsendDescribePrepared(PGconn *conn, const char *stmtName) int PQsendDescribePortal(PGconn *conn, const char *portalName) PGresult *PQgetResult(PGconn *conn) diff --git a/psycopg3_c/psycopg3_c/pq/pgconn.pyx b/psycopg3_c/psycopg3_c/pq/pgconn.pyx index e13ffd551..4431f5162 100644 --- a/psycopg3_c/psycopg3_c/pq/pgconn.pyx +++ b/psycopg3_c/psycopg3_c/pq/pgconn.pyx @@ -183,7 +183,10 @@ cdef class PGconn: def exec_(self, command: bytes) -> PGresult: self._ensure_pgconn() - cdef libpq.PGresult *pgresult = libpq.PQexec(self.pgconn_ptr, command) + cdef const char *ccommand = command + cdef libpq.PGresult *pgresult + with nogil: + pgresult = libpq.PQexec(self.pgconn_ptr, ccommand) if pgresult is NULL: raise MemoryError("couldn't allocate PGresult") @@ -191,7 +194,11 @@ cdef class PGconn: def send_query(self, command: bytes) -> None: self._ensure_pgconn() - if not libpq.PQsendQuery(self.pgconn_ptr, command): + cdef const char *ccommand = command + cdef int rv + with nogil: + rv = libpq.PQsendQuery(self.pgconn_ptr, ccommand) + if not rv: raise PQerror(f"sending query failed: {error_message(self)}") def exec_params( @@ -209,12 +216,16 @@ cdef class PGconn: cdef char *const *cvalues cdef int *clengths cdef int *cformats + cdef const char *ccommand = command + cdef int cresformat = result_format cnparams, ctypes, cvalues, clengths, cformats = _query_params_args( param_values, param_types, param_formats) - cdef libpq.PGresult *pgresult = libpq.PQexecParams( - self.pgconn_ptr, command, cnparams, ctypes, - cvalues, clengths, cformats, result_format) + cdef libpq.PGresult *pgresult + with nogil: + pgresult = libpq.PQexecParams( + self.pgconn_ptr, ccommand, cnparams, ctypes, + cvalues, clengths, cformats, cresformat) _clear_query_params(ctypes, cvalues, clengths, cformats) if pgresult is NULL: raise MemoryError("couldn't allocate PGresult") @@ -235,13 +246,16 @@ cdef class PGconn: cdef char *const *cvalues cdef int *clengths cdef int *cformats + cdef const char *ccommand = command + cdef int cresformat = result_format cnparams, ctypes, cvalues, clengths, cformats = _query_params_args( param_values, param_types, param_formats) - cdef int rv = libpq.PQsendQueryParams( - self.pgconn_ptr, command, cnparams, ctypes, - cvalues, - clengths, cformats, result_format) + cdef int rv + with nogil: + rv = libpq.PQsendQueryParams( + self.pgconn_ptr, ccommand, cnparams, ctypes, + cvalues, clengths, cformats, cresformat) _clear_query_params(ctypes, cvalues, clengths, cformats) if not rv: raise PQerror( @@ -264,9 +278,13 @@ cdef class PGconn: for i in range(nparams): atypes[i] = param_types[i] - cdef int rv = libpq.PQsendPrepare( - self.pgconn_ptr, name, command, nparams, atypes - ) + cdef int rv + cdef const char *cname = name + cdef const char *ccommand = command + with nogil: + rv = libpq.PQsendPrepare( + self.pgconn_ptr, cname, ccommand, nparams, atypes + ) PyMem_Free(atypes) if not rv: raise PQerror( @@ -287,13 +305,16 @@ cdef class PGconn: cdef char *const *cvalues cdef int *clengths cdef int *cformats + cdef const char *cname = name + cdef int cresformat = result_format cnparams, ctypes, cvalues, clengths, cformats = _query_params_args( param_values, None, param_formats) - cdef int rv = libpq.PQsendQueryPrepared( - self.pgconn_ptr, name, cnparams, - cvalues, - clengths, cformats, result_format) + cdef int rv + with nogil: + rv = libpq.PQsendQueryPrepared( + self.pgconn_ptr, cname, cnparams, cvalues, + clengths, cformats, cresformat) _clear_query_params(ctypes, cvalues, clengths, cformats) if not rv: raise PQerror( @@ -316,8 +337,12 @@ cdef class PGconn: for i in range(nparams): atypes[i] = param_types[i] - cdef libpq.PGresult *rv = libpq.PQprepare( - self.pgconn_ptr, name, command, nparams, atypes) + cdef const char *cname = name + cdef const char *ccommand = command + cdef libpq.PGresult *rv + with nogil: + rv = libpq.PQprepare( + self.pgconn_ptr, cname, ccommand, nparams, atypes) PyMem_Free(atypes) if rv is NULL: raise MemoryError("couldn't allocate PGresult") @@ -340,10 +365,14 @@ cdef class PGconn: cnparams, ctypes, cvalues, clengths, cformats = _query_params_args( param_values, None, param_formats) - cdef libpq.PGresult *rv = libpq.PQexecPrepared( - self.pgconn_ptr, name, cnparams, - cvalues, - clengths, cformats, result_format) + cdef const char *cname = name + cdef int cresformat = result_format + cdef libpq.PGresult *rv + with nogil: + rv = libpq.PQexecPrepared( + self.pgconn_ptr, cname, cnparams, + cvalues, + clengths, cformats, cresformat) _clear_query_params(ctypes, cvalues, clengths, cformats) if rv is NULL: