ID: 46144 Updated by: u...@php.net Reported By: Progman2002 at gmx dot de Status: Open Bug Type: MySQLi related Operating System: Linux PHP Version: 5.2CVS-2009-01-25 (snap) New Comment:
I don't know what to do with this report because in a way it is a user error. The problem can easily be avoided by calling the destructor of the mysql_statement class before assigning false to it. A simple $stmt->close() before the second $stmt = $db->prepare() will fix it. What happens is: $stmt = ... <valid_sql> $stmt = $mysqli->prepare('wrong_sql'); <switch into php /> <function_enter> C API: mysql_stmt_init() C API: mysql_stmt_prepare() -> error copy error, because mysql_stmt_close() will clean it C API: mysql_stmt_close() RETURN false </function_enter> <evaluate assignment to $stmt> $stmt is a Prepared Statement for <valid_sql> destruct $stmt, because user did not clean it up! C API: mysql_stmt_close() !!! previously saved error message gets cleaned !!! </evaluate assignment to $stmt> <assign return value to $stmt /> <give control back to PHP script /> var_dump($mysqli->error) -> no error message One way to fix on the C level would be to blow up the MY_MYSQL struct and copy the error message into some safe place. But I wonder how we would know when to return the message copied into a safe place and when not... currently I can't think of a way how we would know. It may be possible to hack something with mysqlnd and make mysqlnd behave different to libmysql (not clean/preserve error message in mysqlnd' stmt dtor) but that would be just the wrong place and really hackish.... Maybe we should set the status to "Won't fix". Previous Comments: ------------------------------------------------------------------------ [2009-05-18 14:43:14] Progman2002 at gmx dot de Sure I can call close() by myself (which I normally do), but it doesn't solve the bug itself. The point is you get an error situation and don't know why. ------------------------------------------------------------------------ [2009-05-18 02:17:56] felix9x at yahoo dot com It's because the first $stmt object is destroyed by the second assignment (which clears the last error message). $sql = 'INSERT INTO SomeTest(UserID, RechtID) WHERE (?,?)'; if (!$stmt = $db->prepare($sql)) { die($db->error."-".$db->errno."-".$db->info); } Its equivalent to doing this: $stmt = false; The destructor of the Mysqli_stmt class resets the Last error. Its possible to call $stmt->close() explicitly. Probably best to use this syntax: $sql = 'INSERT INTO t(i) WHERE (?)'; $stmt = $db->stmt_init(); if(!$stmt->prepare($sql) ){ die( $stmt->error ); } ------------------------------------------------------------------------ [2009-01-25 10:50:41] Progman2002 at gmx dot de The bug is still not fixed. Maybe it has something to do with an uncalled destructor since I use the same variable $stmt. Actual result: -------------- PHP-Version: 5.2.9-dev MySQL-Server-Version: 50060 MySQL-Protocol: 10 -0- Expected result: ---------------- PHP-Version: 5.2.9-dev MySQL-Server-Version: 50060 MySQL-Protocol: 10 (Showing a MySQL error which says "Syntax error near WHERE (?,?)" or says sth. like "unfinished prepare statement before") ------------------------------------------------------------------------ [2008-11-29 10:59:24] Progman2002 at gmx dot de As the paste on the pasteboard is gone I'll add the code here. ----------- <?php error_reporting(E_ALL); ini_set('display_errors', 1); $db = @new MySQLi('localhost', '', '', 'test'); if (mysqli_connect_errno()) { die('Konnte keine Verbindung zu Datenbank aufbauen, MySQL meldete: '.mysqli_connect_error()); } echo 'PHP-Version: '.PHP_VERSION."\n"; echo 'MySQL-Server-Version: '.$db->server_version."\n"; echo 'MySQL-Protocol: '.$db->protocol_version."\n"; $sql = 'CREATE TEMPORARY TABLE SomeTest(UserID INT NOT NULL, RechtID INT NOT NULL)'; if (!$db->query($sql)) { die($db->error); } $sql = 'DELETE FROM SomeTest WHERE UserID = ?'; if (!$stmt = $db->prepare($sql)) { die($db->error); } // note the missing $stmt->close() here $sql = 'INSERT INTO SomeTest(UserID, RechtID) WHERE (?,?)'; if (!$stmt = $db->prepare($sql)) { die($db->error."-".$db->errno."-".$db->info); } echo "done"; ?> ------------------------------------------------------------------------ [2008-09-21 13:49:28] Progman2002 at gmx dot de Description: ------------ If you create a prepared statement with a DELETE query and tries to create a second prepared statement with an INSERT query on the same table without closing the first one the MySQLi::prepare() method failed, but the fields $error and $errno (and all other related to them) aren't filled with the error message. This is strange as the prepare() failed but you dont know why. The mysql error is shown if I save the second statement into another variable (like if (!$stmt2 = $db->prepare($sql))) (maybe its related to bug #44766) Reproduce code: --------------- Code is at http://nopaste.php-quake.net/51976 Expected result: ---------------- PHP-Version: 5.2.6-pl7-gentoo MySQL-Server-Version: 50042 MySQL-Protocol: 10 {Showing a MySQL error which says "Syntax error near WHERE (?,?)" or says sth. like "unfinished prepare statement before") Actual result: -------------- PHP-Version: 5.2.6-pl7-gentoo MySQL-Server-Version: 50042 MySQL-Protocol: 10 -0- (so the values are all empty strings or zero) ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=46144&edit=1