php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #45120 PDOStatement->execute() returns true then false for same statement
Submitted: 2008-05-28 20:53 UTC Modified: 2009-12-03 15:25 UTC
Votes:4
Avg. Score:4.2 ± 0.8
Reproduced:4 of 4 (100.0%)
Same Version:2 (50.0%)
Same OS:2 (50.0%)
From: morrisdavidd at gmail dot com Assigned:
Status: Closed Package: PDO related
PHP Version: 5.3 OS: Linux
Private report: No CVE-ID:
 [2008-05-28 20:53 UTC] morrisdavidd at gmail dot com
Description:
------------
The query is the exact same every time the statement is called. There are no parameters being bound. However, the function only returns true the first time the PDO->execute() is called.

As per:
http://us3.php.net/manual/en/pdostatement.execute.php


"Return Values

Returns TRUE on success or FALSE on failure."


I've run a test where I had it sleep after the first $stmt->execute() long enough for me to change the value of the data being selected from the database (And I output the data being selected to make sure it was retrieved in its changed form the second time around). It still returned FALSE.

However, the documentation for the function states: "Execute the prepared statement." ... "Returns TRUE on success or FALSE on failure."

So, the function returns FALSE when it executed the prepared statement successfully.

Reproduce code:
---------------
Obviously You'll have to change the database name, user, pass, table...
<?php
$table = "SystemInformation";
$pdoDb = new PDO("mysql:host=localhost;dbname=eta_manybodystate", DB_USER, DB_PWD);
$stmt = $pdoDb->prepare("SELECT * FROM `".$table."` LIMIT 1;");
$foo = $stmt->execute();
$stmt->closeCursor();
echo "foo: ";
var_dump($foo);
$bar = $stmt->execute();
$stmt->closeCursor();
echo "bar: ";
var_dump($bar);
$foo2 = $stmt->execute();
$stmt->closeCursor();
echo "foo2: ";
var_dump($foo2);
$bar2 = $stmt->execute();
$stmt->closeCursor();
echo "bar2: ";
var_dump($bar2);
?>

Expected result:
----------------
foo: bool(true)
bar: bool(true)
foo2: bool(true)
bar2: bool(true)

Actual result:
--------------
foo: bool(true)
bar: bool(false)
foo2: bool(false)
bar2: bool(false)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-07-03 13:32 UTC] uw@php.net
On the first look this seems to be a PDO not a PDO_MYSQL (or any other driver) bug. 

From pdo_stmt.c, static PHP_METHOD(PDOStatement, execute), around line 450:


if (PDO_PLACEHOLDER_NONE == stmt->supports_placeholders) {
		/* handle the emulated parameter binding,
         * stmt->active_query_string holds the query with binds expanded and 
		 * quoted.
         */

		ret = pdo_parse_params(stmt, stmt->query_string, stmt->query_stringlen,
			&stmt->active_query_string, &stmt->active_query_stringlen TSRMLS_CC);

[...]
}

For some drivers, PDO assigns the return value of its pdo_parse_params() function to ret. And then the code flow continues and eventually the driver gets called to execute the statement (depending on the driver features):

if (stmt->methods->executer(stmt TSRMLS_CC)) {
		if (stmt->active_query_string && stmt->active_query_string != stmt->query_string) {
			efree(stmt->active_query_string);
		}
		stmt->active_query_string = NULL;
		if (!stmt->executed) {
			/* this is the first execute */

			if (stmt->dbh->alloc_own_columns && !stmt->columns) {
				/* for "big boy" drivers, we need to allocate memory to fetch
				 * the results into, so lets do that now */
				ret = pdo_stmt_describe_columns(stmt TSRMLS_CC);
			}

			stmt->executed = 1;
		}

		if (ret && !dispatch_param_event(stmt, PDO_PARAM_EVT_EXEC_POST TSRMLS_CC)) {
			RETURN_FALSE;
		}
			
		RETURN_BOOL(ret);
	}

ret (returned ny pdo_parse_params()) will be overwritten only on the first execution. Upon subsequent executions the driver cannot set ret. You get a bool(false) because pdo_parse_params() has returned 0 (= success) and the return value of PDO_MYSQL has been ignored.

Maybe it should read like this:

if (ret = stmt->methods->executer(stmt TSRMLS_CC)) {


 [2008-10-14 13:06 UTC] felipe@php.net
I can't reproduce it.
 [2009-04-25 15:03 UTC] jani@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5.2-latest.tar.gz
 
For Windows:

  http://windows.php.net/snapshots/


 [2009-05-03 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 [2009-07-28 07:10 UTC] morrisdavidd at gmail dot com
Sorry for the late reply,

I just duplicated this bug in PHP 5.3

Cheers,
David)
 [2009-10-07 14:51 UTC] mbeccati@php.net
The bug is reproducible only with the MySQL driver when using emulated prepared queries, which is the default. I've tested PgSQL and Sqlite and both work as expected.

There's also a pdo_mysql test for it, already marked as XFAIL:
http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/pdo_mysql/tests/bug_45120.phpt?view=markup
 [2009-10-08 09:53 UTC] mbeccati@php.net
Looks like I was wrong. The exisitng test was passing with the pgsql because of bug #48764 (setAttribute wasn't working do disable native prepared statements). Once fixed, the test fails on pgsql too, suggesting a problem in PDO itself, like others already mentioned.
 [2009-12-03 15:24 UTC] svn@php.net
Automatic comment from SVN on behalf of pierrick
Revision: http://svn.php.net/viewvc/?view=revision&revision=291657
Log: Fixed bug #45120 (PDOStatement->execute() returns true then false for same statement).
 [2009-12-03 15:25 UTC] pierrick@php.net
This bug has been fixed in SVN.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Mon Apr 21 07:02:06 2014 UTC