5

I ran in to this problem in one of my live web apps. It seems that if you issue a multi-statement query to MySQL via PHP PDO, and the first statement is an insert statement, and the second statement is an update statement, the PDO::nextRowset() function doesn't return the right number of result sets. (Note that PDO supposedly supports multiple statements per MySQL query since PHP 5.3.)

Here's an example:

SQL:

create database `test`character set utf8 collate utf8_general_ci;
create table `test`.`testtable`( `id` int ); 

PHP:

<?php
$link = new \PDO('mysql:host=localhost;dbname=test', 'username', 'password');

//Run one of the 4 $handle assignments at a time (comment out all but one). 
//Run #4 on an empty table to compare the results of #1 and #4.

//WORKS: INSERT, followed by SELECT, followed UPDATE
//Output: 
//Rowset 1
//Rowset 2
//Results detected
$handle = $link->prepare(' insert into testtable(id) values(1);
                           select * from testtable where id = ?;
                           update testtable set id = 2 where id = ?;');


//WORKS: SELECT, followed by UPDATE
//Output: 
//Rowset 1
//Results detected
$handle = $link->prepare('select * from testtable where id = ?; 
                          update testtable set id = 2 where id = ?;');

//WORKS: UPDATE, followed by SELECT
//Output: 
//Rowset 1
//Rowset 2
//Results detected
$handle = $link->prepare('select * from testtable where id = ?; 
                         update testtable set id = 2 where id = ?;');


//DOESN'T WORK: INSERT, followed by UPDATE, followed by SELECT
//Output: 
//Rowset 1
//Expected output: same as examples 1 and 3
$handle = $link->prepare('insert into testtable(id) values(1);
                          update testtable set id = 2 where id = ?;
                          select * from testtable where id = ?;');

$handle->bindValue('1', '1');
$handle->bindValue('2', '2');

$handle->execute();

$i = 1;
do{
    print('Rowset ' . $i++ . "\n");
    if($handle->columnCount() > 0)
     print("Results detected\n");
}while($handle->nextRowset());
?>

Does anyone have any idea as to what I'm doing wrong? Why can't I put my select statement at the end?

PHP 5.3.5

MySQL 5.1.54

Alex Cabal
  • 91
  • 7
  • should one be using \PDO – Lawrence Cherone Feb 22 '12 at 04:06
  • 3
    You shouldn't be doing multiple queries in a single query call to begin with. The mysql client libraries for PHP, which PDO uses, do not support this as an sql injection prevention defense. – Marc B Feb 22 '12 at 04:07
  • 2
    @LawrenceCherone One should, if one is developing within a namespace – Phil Feb 22 '12 at 04:09
  • 1
    PDO supports multiple statements per query as of PHP 5.3, so the question isn't whether or not one should do that, but why the above example is giving strange results. – Alex Cabal Feb 22 '12 at 04:10
  • 1
    @MarcB this is interesting. apparently pdo switched mysql drivers in php 5.3: http://stackoverflow.com/questions/6346674/pdo-support-for-multiple-queries-pdo-mysql-pdo-mysqlnd – dqhendricks Feb 22 '12 at 05:11
  • @AlexCabal : Would you please mention the links where its is written that multiple query is supported by PDO – xkeshav Feb 22 '12 at 07:09
  • @diEcho see above comments for the links. – Alex Cabal Feb 22 '12 at 20:50

2 Answers2

4

I submitted a PHP bug report about this problem and a possible patch has been submitted. So it looks like this was a PHP bug.

Alex Cabal
  • 91
  • 7
0
  1. First , you have to figure out what will nextRowset() returns regarding of a non-select operation . I have tried to var_dump it after an update ,and I got bool(false), which can explain why you only get one output with :

    $handle = $link->prepare('insert into testtable(id) values(1);
                      update testtable set id = 2 where id = ?;
                      select * from testtable where id = ?;');
    
  2. Second, I replaced the following codes:

    var_dump($h->nextRowset());
    var_dump($h->nextRowset());
    

    with your do-while segment,I got bool(false) bool(true), witch means that it just goes once in the loop.

    I don't know whether it is right to explain your question as above, may it will help you.

shengfengli
  • 126
  • 1
  • 8