Commit 810a9e58dc0 for php.net
commit 810a9e58dc03a93351d2ff093676871a0cc3ea03
Merge: 67135cb97b5 f3607f147fe
Author: David Carlier <devnexen@gmail.com>
Date: Sun Sep 6 21:00:54 2026 +0100
Merge branch 'PHP-8.5'
* PHP-8.5:
ext/pdo_pgsql: Fix CURSOR_SCROLL statements closing a nonexistent cursor
# Conflicts:
# ext/pdo_pgsql/config.m4
# ext/pdo_pgsql/pgsql_statement.c
diff --cc ext/pdo_pgsql/config.m4
index 406f08465e9,eb002e3f38a..b6e1ec6edb8
--- a/ext/pdo_pgsql/config.m4
+++ b/ext/pdo_pgsql/config.m4
@@@ -25,20 -25,12 +25,26 @@@ if test "$PHP_PDO_PGSQL" != "no"; the
or later).])],,
[$PGSQL_LIBS])
+ PHP_CHECK_LIBRARY([pq], [PQclosePortal],
+ [AC_DEFINE([HAVE_PQCLOSEPORTAL], [1],
+ [Define to 1 if libpq has the 'PQclosePortal' function (PostgreSQL 17
+ or later).])],,
+ [$PGSQL_LIBS])
+
+ old_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS $PGSQL_CFLAGS"
+
+ AC_CHECK_DECL([PGRES_TUPLES_CHUNK],
+ PHP_CHECK_LIBRARY([pq], [PQsetChunkedRowsMode],
+ [AC_DEFINE([HAVE_PG_SET_CHUNKED_ROWS_SIZE], [1],
+ [Define to 1 if libpq has the 'PQsetChunkedRowsMode' function (PostgreSQL
+ 17 or later).])],,
+ [$PGSQL_LIBS]),,
+ [#include <libpq-fe.h>]
+ )
+
+ CFLAGS=$old_CFLAGS
+
PHP_CHECK_PDO_INCLUDES
PHP_NEW_EXTENSION([pdo_pgsql],
diff --cc ext/pdo_pgsql/config.w32
index 87ad0a661b5,fcc60140d31..5739e3060ef
--- a/ext/pdo_pgsql/config.w32
+++ b/ext/pdo_pgsql/config.w32
@@@ -4,12 -4,15 +4,16 @@@ ARG_WITH("pdo-pgsql", "PostgreSQL suppo
if (PHP_PDO_PGSQL != "no") {
if (CHECK_LIB("libpq.lib", "pdo_pgsql", PHP_PDO_PGSQL) &&
- CHECK_HEADER_ADD_INCLUDE("libpq-fe.h", "CFLAGS_PDO_PGSQL", PHP_PDO_PGSQL + "\\include;" + PHP_PHP_BUILD + "\\include\\pgsql;" + PHP_PHP_BUILD + "\\include\\libpq;")) {
+ CHECK_HEADER("libpq-fe.h", "CFLAGS_PDO_PGSQL", PHP_PDO_PGSQL + "\\include;" + PHP_PHP_BUILD + "\\include\\pgsql;" + PHP_PHP_BUILD + "\\include\\libpq;")) {
EXTENSION("pdo_pgsql", "pdo_pgsql.c pgsql_driver.c pgsql_statement.c pgsql_sql_parser.c");
+ AC_DEFINE('HAVE_PG_RESULT_MEMORY_SIZE', 1, "Define to 1 if libpq has the 'PQresultMemorySize' function (PostgreSQL 12 or later).");
AC_DEFINE('HAVE_PDO_PGSQL', 1, "Define to 1 if the PHP extension 'pdo_pgsql' is available.");
+ if (GREP_HEADER("libpq-fe.h", "PQclosePortal", PHP_PDO_PGSQL + "\\include;" + PHP_PHP_BUILD + "\\include\\pgsql;" + PHP_PHP_BUILD + "\\include\\libpq;")) {
+ AC_DEFINE('HAVE_PQCLOSEPORTAL', 1, "Define to 1 if libpq has the 'PQclosePortal' function (PostgreSQL 17 or later).");
+ }
+
ADD_EXTENSION_DEP('pdo_pgsql', 'pdo');
ADD_MAKEFILE_FRAGMENT();
} else {
diff --cc ext/pdo_pgsql/pgsql_statement.c
index f6f87139958,b2af41a339b..2f072553493
--- a/ext/pdo_pgsql/pgsql_statement.c
+++ b/ext/pdo_pgsql/pgsql_statement.c
@@@ -58,21 -60,47 +58,62 @@@
#define FIN_CLOSE 0x2
#define FIN_ABORT 0x4
+static bool pgsql_result_status_ok(ExecStatusType status)
+{
+ switch (status) {
+ case PGRES_COMMAND_OK:
+ case PGRES_TUPLES_OK:
+ case PGRES_SINGLE_TUPLE:
+#ifdef HAVE_PG_SET_CHUNKED_ROWS_SIZE
+ case PGRES_TUPLES_CHUNK:
+#endif
+ return true;
+ default:
+ return false;
+ }
+}
+
+ #ifndef HAVE_PQCLOSEPORTAL
+ static bool pdo_pgsql_try_cmd(const char *cmd, const char *ok_sqlstate, pdo_pgsql_db_handle *H)
+ {
+ bool result = false;
+ char *q = NULL;
+ PGresult *res = NULL;
+
+ PGTransactionStatusType status = PQtransactionStatus(H->server);
+
+ switch (status) {
+ case PQTRANS_ACTIVE:
+ case PQTRANS_INERROR:
+ break;
+ case PQTRANS_INTRANS: /* failure must not abort the caller's transaction */
+ /* PQexec does not run the statements following a failed one */
+ spprintf(&q, 0, "SAVEPOINT pdo_pgsql_savepoint; %s; RELEASE SAVEPOINT pdo_pgsql_savepoint;", cmd);
+ res = PQexec(H->server, q);
+
+ if (PQresultStatus(res) != PGRES_COMMAND_OK) {
+ PQclear(PQexec(H->server, "ROLLBACK TO SAVEPOINT pdo_pgsql_savepoint; RELEASE SAVEPOINT pdo_pgsql_savepoint"));
+ }
+
+ break;
+ default:
+ res = PQexec(H->server, cmd);
+ }
+
+ if (PQresultStatus(res) == PGRES_COMMAND_OK) {
+ result = true;
+ } else if (res) {
+ const char *sqlstate = pdo_pgsql_sqlstate(res);
+
+ result = sqlstate && !strcmp(sqlstate, ok_sqlstate);
+ }
+
+ if (q) efree(q);
+ if (res) PQclear(res);
+
+ return result;
+ }
+ #endif
static void pgsql_stmt_finish(pdo_pgsql_stmt *S, int fin_mode)
diff --cc ext/pdo_pgsql/php_pdo_pgsql_int.h
index a9a09a24b70,60fa28bbcb6..dc71d5ae7a5
--- a/ext/pdo_pgsql/php_pdo_pgsql_int.h
+++ b/ext/pdo_pgsql/php_pdo_pgsql_int.h
@@@ -67,8 -68,8 +67,9 @@@ struct pdo_pgsql_stmt
int *param_formats;
Oid *param_types;
int current_row;
+ zend_long chunk_size;
bool is_prepared;
+ bool is_cursor_declared;
bool is_unbuffered;
bool is_running_unbuffered;
};