[php-src] Issue #10110: mysqli_error() after mysqli_stmt_execute() gets unset at the end of the function
Issue: https://github.com/php/php-src/issues/10110
Author: weary-adventurer
### Description
Given this MySQL table:
```sql
CREATE TABLE test (
id int(10) unsigned NOT NULL AUTO_INCREMENT,
foo varchar(256) NOT NULL,
PRIMARY KEY (id)
);
```
This code sets up a MySQLi connection and runs two SQL queries:
```php
<?php
define("DB_HOSTNAME", "localhost");
define("DB_USERNAME", "root");
define("DB_PASSWORD", "");
define("DB_DATABASE", "my_database_name");
function db_init() : ?mysqli {
mysqli_report(MYSQLI_REPORT_OFF);
$db = @mysqli_connect(DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE);
return $db === false ? null : $db;
}
function db_query(mysqli &$db, string $query, ?string $types = null, ...$values) {
$stmt = mysqli_prepare($db, $query);
if (!$stmt) {
echo "| mysqli_prepare failed\n";
echo "| mysqli_error() = '" . mysqli_error($db) . "'\n";
return null;
}
if (!mysqli_stmt_bind_param($stmt, $types, ...$values)) {
echo "| mysqli_stmt_bind_param failed\n";
echo "| mysqli_error() = '" . mysqli_error($db) . "'\n";
return null;
}
if (!mysqli_stmt_execute($stmt)) {
echo "| mysqli_stmt_execute failed\n";
echo "| mysqli_error() = '" . mysqli_error($db) . "'\n";
return null;
}
$result = mysqli_stmt_get_result($stmt);
echo "| db_query succeeded\n";
echo "| result = '" . print_r($result, true) . "'\n";
echo "| mysqli_error() = '" . mysqli_error($db) . "'\n";
return $result;
}
function main() {
echo "connecting...\n";
echo "| phpversion() = " . phpversion() . "\n";
$db = db_init();
if (!$db) {
echo "| mysqli_connect_error() = " . mysqli_connect_error($db) . "\n";
return;
}
echo "\n";
echo "connected\n";
echo "| mysqli_error() = '" . mysqli_error($db) . "'\n";
echo "\n";
echo "trying to fail mysqli_prepare ...\n";
db_query($db, "INSERT INTO non_existent (foo) VALUES (?)", "s", null);
echo "\n";
echo "state after mysqli_prepare is:\n";
echo "| mysqli_error() = '" . mysqli_error($db) . "'\n";
echo "\n";
echo "trying to fail mysqli_stmt_execute ...\n";
db_query($db, "INSERT INTO test (foo) VALUES (?)", "s", null);
echo "\n";
echo "state after mysqli_stmt_execute is:\n";
echo "| mysqli_error() = '" . mysqli_error($db) . "'\n";
}
echo "<pre>";
main();
echo "</pre>";
exit;
?>
```
The following output is produced:
```
connecting...
| phpversion() = 8.2.0
connected
| mysqli_error() = ''
trying to fail mysqli_prepare ...
| mysqli_prepare failed
| mysqli_error() = 'Table 'my_database_name.non_existent' doesn't exist'
state after mysqli_prepare is:
| mysqli_error() = 'Table 'my_database_name.non_existent' doesn't exist'
trying to fail mysqli_stmt_execute ...
| mysqli_stmt_execute failed
| mysqli_error() = 'Column 'foo' cannot be null'
state after mysqli_stmt_execute is:
| mysqli_error() = ''
```
What this does:
* The first query tries to insert a row in a non-existing table, which fails the
mysqli_prepare() call.
* The second query tries to insert a row with a NULL value, which fails the
mysqli_stmt_execute() call.
In both cases a MySQLi error is generated and the message can be obtained with
mysqli_error().
But this error gets unset after the db_query function exits, and it only happens if the
failing function was mysqli_stmt_execute().
### PHP Version
PHP 8.2.0
### Operating System
Windows 10.0.19043
Thread (1 message)
- weary-adventurer