From 89ea64d9a13f5a702de024b902d433b94af56c46 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 3 Feb 2024 12:43:08 +0000 Subject: [PATCH] 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 ` query is used which free entirely the statement's resources. --- ext/pdo_pgsql/config.m4 | 6 ++++++ ext/pdo_pgsql/pgsql_statement.c | 15 ++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/ext/pdo_pgsql/config.m4 b/ext/pdo_pgsql/config.m4 index 775fc39723dbc..1137a911c8116 100644 --- a/ext/pdo_pgsql/config.m4 +++ b/ext/pdo_pgsql/config.m4 @@ -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], diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c index 55759133864fa..8f3dd5237b5a1 100644 --- a/ext/pdo_pgsql/pgsql_statement.c +++ b/ext/pdo_pgsql/pgsql_statement.c @@ -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 @@ static int pgsql_stmt_execute(pdo_stmt_t *stmt) * 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); }