Bug #81494 [Ver]: Stopped unbuffered query does not throw error

From: Date: Fri, 08 Oct 2021 12:36:42 +0000
Subject: Bug #81494 [Ver]: Stopped unbuffered query does not throw error
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-237105@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=81494&edit=1

 ID:                 81494
 Updated by:         nikic@php.net
 Reported by:        madri2 at gmail dot com
 Summary:             Stopped unbuffered query does not throw error
 Status:             Verified
 Type:               Bug
 Package:            MySQLi related
 PHP Version:        Irrelevant
 Block user comment: N
 Private report:     N

 New Comment:

After looking a bit closer, I believe the key problem here is that this is calling a method on
mysqli_result, while the error is reported on the connection (or stmt) and the result doesn't
have access to the connection.

So either we need to store the connection object in the mysqli result object, or we need to recover
it from the underlying driver -- mysqlnd has a conn field, which stores a reference to the
connection data, so we could use the low level API to access the error information.


Previous Comments:
------------------------------------------------------------------------
[2021-10-04 12:35:28] nikic@php.net

Oops, some autocomplete messed things up. I only wanted to change the status to Verified...

------------------------------------------------------------------------
[2021-10-04 12:17:36] madri2 at gmail dot com

<?php
error_reporting(E_ALL);
set_time_limit(0);

ini_set('memory_limit','2000M'); 
ini_set('display_errors', true); 

$dbo = mysqli_connect('localhost', 'xxx', 'yyy', '');
$dbo2 = mysqli_connect('localhost', 'xxx', 'yyy', '');

mysqli_report(MYSQLI_REPORT_ALL & ~MYSQLI_REPORT_INDEX);


$req = $dbo->query("SELECT * FROM mustBeATableBigEnough", MYSQLI_USE_RESULT);
$numFound = 0;

while ($found = $req->fetch_assoc()) {
    $numFound++;

    $req2 = $dbo2->query("SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID =
'".$dbo->thread_id."'");
    if ($found2 = $req2->fetch_assoc()) {
        print_r($found2);
        $dbo2->query("KILL ".$found2['ID']);
    }
    $req2->free();
}
$req->free();

echo 'numFound : '.$numFound."\n";



it outputs :
Array
(
    [ID] => 2348965
    [USER] => yyyyy
    [HOST] => localhost
    [DB] => zzzzzz
    [COMMAND] => Query
    [TIME] => 0
    [STATE] => Sending data
    [INFO] => SELECT * FROM xxxx
    [TIME_MS] => 1.708
    [STAGE] => 0
    [MAX_STAGE] => 0
    [PROGRESS] => 0.000
    [MEMORY_USED] => 212672
    [MAX_MEMORY_USED] => 212672
    [EXAMINED_ROWS] => 0
    [QUERY_ID] => 554751313
    [INFO_BINARY] => SELECT * FROM xxxx
    [TID] => 3625133
)

Warning: mysqli_result::fetch_assoc(): Error while reading a row in ....testBug.php on line 54
numFound : 52


the table contains millions of entries

------------------------------------------------------------------------
[2021-10-01 14:24:34] nikic@php.net

Please provide a full reproducer.

------------------------------------------------------------------------
[2021-10-01 14:22:06] madri2 at gmail dot com

Description:
------------
Do an unbuffered mysqli query and do a while to read all results,
kill the mysql request in mysql, then php will only trigger a warning when doing fetch_assoc
Warning: mysqli_result::fetch_assoc(): Error while reading a row

while ($found = $req->fetch_assoc()) {

}

will only stop the loop when the mysql query is killed, instead of throwing an error

I've tried to set mysqli_report(MYSQLI_REPORT_ALL & ~MYSQLI_REPORT_INDEX);
but this doesn't change anything

Expected result:
----------------
An exception thrown

Actual result:
--------------
Warning: mysqli_result::fetch_assoc(): Error while reading a row


------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=81494&edit=1


Thread (9 messages)

« previous php.bugs (#237105) next »