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
 [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: Thu Oct 31 22:01:27 2024 UTC