From b143c4987ee3f7e7f12fdafa80f03b145c2b17e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=AD=A6=E7=94=B0=20=E6=86=B2=E5=A4=AA=E9=83=8E?= Date: Tue, 25 Aug 2026 23:00:34 +0000 Subject: [PATCH] ext/pdo_pgsql: Fix PDO::CURSOR_SCROLL statements failing under lazy fetching --- NEWS | 4 +++ ext/pdo_pgsql/pgsql_driver.c | 17 +++++----- .../tests/cursor_scroll_lazy_fetch.phpt | 33 +++++++++++++++++++ 3 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 ext/pdo_pgsql/tests/cursor_scroll_lazy_fetch.phpt diff --git a/NEWS b/NEWS index 149fea347077..297a6127a82d 100644 --- a/NEWS +++ b/NEWS @@ -52,6 +52,10 @@ PHP NEWS . Fixed bug GH-23418 (Use-after-free when looking up mounted directories). (Weilin Du) +- PDO_PGSQL: + . Fixed PDO::CURSOR_SCROLL statements failing under lazy fetching + (PDO::ATTR_PREFETCH => 0). (KentarouTakeda) + - Readline: . Fixed the interactive shell not waiting for the pager process to exit. (Weilin Du) diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index 54b2e25f72f6..060b8d687765 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -287,7 +287,16 @@ static bool pgsql_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, pdo_stmt_t * scrollable = pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY) == PDO_CURSOR_SCROLL; + S->is_unbuffered = + driver_options + && (val = zend_hash_index_find(Z_ARRVAL_P(driver_options), PDO_ATTR_PREFETCH)) + && pdo_get_long_param(&lval, val) + ? !lval + : H->default_fetching_laziness + ; + if (scrollable) { + S->is_unbuffered = false; if (S->cursor_name) { efree(S->cursor_name); } @@ -312,14 +321,6 @@ static bool pgsql_handle_preparer(pdo_dbh_t *dbh, zend_string *sql, pdo_stmt_t * stmt->named_rewrite_template = "$%d"; } - S->is_unbuffered = - driver_options - && (val = zend_hash_index_find(Z_ARRVAL_P(driver_options), PDO_ATTR_PREFETCH)) - && pdo_get_long_param(&lval, val) - ? !lval - : H->default_fetching_laziness - ; - ret = pdo_parse_params(stmt, sql, &nsql); if (ret == -1) { diff --git a/ext/pdo_pgsql/tests/cursor_scroll_lazy_fetch.phpt b/ext/pdo_pgsql/tests/cursor_scroll_lazy_fetch.phpt new file mode 100644 index 000000000000..df4be41b8532 --- /dev/null +++ b/ext/pdo_pgsql/tests/cursor_scroll_lazy_fetch.phpt @@ -0,0 +1,33 @@ +--TEST-- +PDO PgSQL a scrollable cursor is unaffected by lazy fetching +--EXTENSIONS-- +pdo_pgsql +--SKIPIF-- + +--FILE-- +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + +$sql = "SELECT * FROM generate_series(1, 3)"; +$scrollable = [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]; + +$stmt = $pdo->prepare($sql, $scrollable + [PDO::ATTR_PREFETCH => 0]); +$stmt->execute(); +echo 'lazy on the statement: ', implode(',', $stmt->fetchAll(PDO::FETCH_COLUMN)), PHP_EOL; + +$pdo->setAttribute(PDO::ATTR_PREFETCH, 0); +$stmt = $pdo->prepare($sql, $scrollable); +$stmt->execute(); +echo 'lazy on the connection: ', implode(',', $stmt->fetchAll(PDO::FETCH_COLUMN)), PHP_EOL; + +?> +--EXPECT-- +lazy on the statement: 1,2,3 +lazy on the connection: 1,2,3