diff --git a/NEWS b/NEWS index 8947af2542f..c866e22c7fb 100644 --- a/NEWS +++ b/NEWS @@ -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) diff --git a/ext/pdo_pgsql/config.m4 b/ext/pdo_pgsql/config.m4 index 775fc39723d..1137a911c81 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 55759133864..8f3dd5237b5 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 @@ 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); }