php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #77855 PG: rowCount returns 0 when using CURSOR_SCROLL
Submitted: 2019-04-05 12:50 UTC Modified: -
Votes:2
Avg. Score:4.0 ± 1.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: php at bohwaz dot net Assigned:
Status: Open Package: PDO PgSQL
PHP Version: 7.3.4 OS: All
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: php at bohwaz dot net
New email:
PHP Version: OS:

 

 [2019-04-05 12:50 UTC] php at bohwaz dot net
Description:
------------
When using the "PDO::ATTR_CURSOR" attribute set to "PDO::CURSOR_SCROLL" on a pgSQL PDO statement, subsequent calls to rowCount will return 0.

That's because in Postgre a cursor has no way to tell how many lines it will have.

I did change the PHP documentation of rowCount, but having a more explicit way would be better, perhaps by throwing an error.

Another solution would be to do as described here: https://github.com/MagicStack/asyncpg/issues/359#issuecomment-420266185

For example rowCount() could execute:

-- Move to the end of the cursor
MOVE FORWARD ALL IN my_cursor;
-- Will return the number of rows in the result cursor as "MOVE xxx", should store it to return it later
-- Move back to the beginning
MOVE ABSOLUTE 0 IN my_cursor;

But because of the way rowCount is implemented in PDO, it cannot be done in a driver-specific way. We would have to do that MOVE FORWARD / MOVE back to 0 inside the pgsql_stmt_execute function and store it in statement->row_count. 

This might have a performance impact though, but I'm not sure as I'm not very familiar with postgre internals.

Test script:
---------------
--TEST--
PDO PgSQL bug with CURSOR_SCROLL and rowCount
--SKIPIF--
<?php # vim:se ft=php:
if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
require dirname(__FILE__) . '/config.inc';
require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
PDOTest::skip();
?>
--FILE--
<?php
require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$st = $pdo->prepare('SELECT NOW();');
$st->execute();
var_dump($st->rowCount());

$st = $pdo->prepare('SELECT NOW();', [PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL]);
$st->execute();
var_dump($st->rowCount());
?>
--EXPECT--
int(1)
int(1)

Expected result:
----------------
int(1)
int(1)

Actual result:
--------------
int(1)
int(0)

Patches

Pull Requests

 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Wed Dec 04 18:01:31 2024 UTC