Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP PDO multiple select query consistently dropping last rowset

Tags:

php

mysql

pdo

I'm experiencing what appears to be a bug using a PDO statement to make multiple selects.

I'm building a SQL query that has many SELECTs, and regardless of how many SELECT statements it makes, the last rowset is dropped.

Here's a truncated example of whats happening

$pdo = /* connection stuff here */
$sql = "select 1; select 2; select 3; select 4;";
$statement = $pdo->query($sql);

do {
    $rowset = $statement->fetchAll();
    if($rowset) {               
        // Do stuff with $rowset
    }       
} while($statement->nextRowset());

Doing the above, 1-3 are successfully retrieved as rowsets, but 4 is not.
I cannot explain why that is the case. Making any subsequent queries with the same PDO object results in an error:

PDO::query(): SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. 
Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.

The above do ... while ... routine was based off of what can be found in PHP's documentation on the nextRowset() function at http://us1.php.net/manual/en/pdostatement.nextrowset.php

Calling $statement->closeCursor() at the end doesn't seem to work

The routines I'm using are significantly more complex, but I can confirm that the sql behaves as expected (by plugging it into MySQL directly using PHPMyAdmin and running it using mysqli->multi_query(), both of which return the expected results)

I found someone who had a similar issue and issued a PHP bug ticket, which was apparently marked as fixed: https://bugs.php.net/bug.php?id=61207&edit=1

Can anyone please explain to me what is causing the last rowset to be dropped? Thanks!

Versions: PHP 5.4.12, MySQL 5.6.12

Edit 1: I attempted to use MYSQL_ATTR_USE_BUFFERED_QUERY by changing the code to...

$pdo = /* connection stuff here */
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); // added code
$sql = "select 1; select 2; select 3; select 4;";
$statement = $pdo->query($sql);

do {
    $rowset = $statement->fetchAll();
    if($rowset) {               
        // Do stuff with $rowset
    }       
} while($statement->nextRowset());

This didn't solve the problem

like image 295
Kyle Avatar asked Jan 31 '14 17:01

Kyle


2 Answers

I think you are over complicating things with your do/while loop.

Try a simple while loop instead:

$pdo = /* connection stuff here */
$sql = "select 1; select 2; select 3; select 4;";
$statement = $pdo->query($sql);

while($rowset = $statement->fetchAll()){
    //do stuff

    $statement->nextRowset();
}

This will continue looping while rowset does not have a false value which should then work exactly as you expect.

like image 93
edmondscommerce Avatar answered Oct 21 '22 00:10

edmondscommerce


To avoid that PDOException just use columnCount:

while ($statment->columnCount()) {
     $rowset = $statment->fetchAll(PDO::FETCH_ASSOC);
     $statment->nextRowset();
}
like image 26
Heykel Avatar answered Oct 20 '22 23:10

Heykel