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: None
 [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

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-07-03 13:32 UTC] [email protected]
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] [email protected]
I can't reproduce it.
 [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] [email protected]
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] [email protected]
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] [email protected]
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] [email protected]
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-2025 The PHP Group
All rights reserved.
Last updated: Wed Dec 31 10:00:02 2025 UTC