GH-12940 ext/pdo_pgsql: using PQclosePrepared to free statement resources.

PQclosePrepared allows the statement's name to be reused thus allowing
cache solutions to work properly ; whereas, for now, the `DEALLOCATE
<statement>` query is used which free entirely the statement's resources.

close GH-13316
This commit is contained in:
David Carlier 2024-02-03 12:43:08 +00:00
parent 051c886bc3
commit f35ad560b4
No known key found for this signature in database
GPG key ID: 8486F847B4B94EF1
3 changed files with 20 additions and 3 deletions

2
NEWS
View file

@ -37,6 +37,8 @@ PHP NEWS
- PDO_PGSQL:
. Fixed GH-15986 (Double-free due to Pdo\Pgsql::setNoticeCallback()). (cmb,
nielsdos)
. Fixed GH-12940 (Using PQclosePrepared when available instead of
the DEALLOCATE command to free statements resources). (David Carlier)
- Reflection:
. Add missing ReflectionProperty::hasHook[s]() methods. (ilutov)

View file

@ -19,6 +19,12 @@ if test "$PHP_PDO_PGSQL" != "no"; then
or later).])],,
[$PGSQL_LIBS])
PHP_CHECK_LIBRARY([pq], [PQclosePrepared],
[AC_DEFINE([HAVE_PQCLOSEPREPARED], [1],
[Define to 1 if libpq has the 'PQclosePrepared' function (PostgreSQL 17
or later).])],,
[$PGSQL_LIBS])
PHP_CHECK_PDO_INCLUDES
PHP_NEW_EXTENSION([pdo_pgsql],

View file

@ -74,12 +74,17 @@ static int pgsql_stmt_dtor(pdo_stmt_t *stmt)
if (S->stmt_name) {
if (S->is_prepared && server_obj_usable) {
pdo_pgsql_db_handle *H = S->H;
char *q = NULL;
PGresult *res;
#ifndef HAVE_PQCLOSEPREPARED
// TODO (??) libpq does not support close statement protocol < postgres 17
// check if we can circumvent this.
char *q = NULL;
spprintf(&q, 0, "DEALLOCATE %s", S->stmt_name);
res = PQexec(H->server, q);
efree(q);
#else
res = PQclosePrepared(H->server, S->stmt_name);
#endif
if (res) {
PQclear(res);
}
@ -203,10 +208,14 @@ stmt_retry:
* deallocate it and retry ONCE (thies 2005.12.15)
*/
if (sqlstate && !strcmp(sqlstate, "42P05")) {
char buf[100]; /* stmt_name == "pdo_crsr_%08x" */
PGresult *res;
#ifndef HAVE_PQCLOSEPREPARED
char buf[100]; /* stmt_name == "pdo_crsr_%08x" */
snprintf(buf, sizeof(buf), "DEALLOCATE %s", S->stmt_name);
res = PQexec(H->server, buf);
#else
res = PQclosePrepared(H->server, S->stmt_name);
#endif
if (res) {
PQclear(res);
}