--TEST--
mysqli_poll() & INSERT SELECT
--SKIPIF--
<?php
require_once('skipif.inc');
require_once(
'skipifemb.inc');
require_once(
'connect.inc');
require_once(
'skipifconnectfailure.inc');

if (!
$IS_MYSQLND)
    die(
"skip mysqlnd only feature, compile PHP using --with-mysqli=mysqlnd");
?>
--FILE--
<?php
    
require_once('table.inc');

    function 
get_connection() {
        global 
$host$user$passwd$db$port$socket;

        if (!
$link my_mysqli_connect($host$user$passwd$db$port$socket))
            
printf("[001] [%d] %s\n"mysqli_connect_errno(), mysqli_connect_error());
        return 
$link;
    }


    
// Note: some queries will fail! They are supposed to fail.
    
$queries = array(
            
'CREATE TABLE IF NOT EXISTS bogus(id INT)',
            
'SET @a = 1',
            
'SELECT * FROM test ORDER BY id ASC LIMIT 2',
            
"INSERT INTO test(id, label) VALUES (100, 'z')",
            
'SELECT * FROM test ORDER BY id ASC LIMIT 2',
            
'SELECT',
            
'UPDATE test SET id = 101 WHERE id > 3',
            
'UPDATE_FIX test SET id = 101 WHERE id > 3',
            
'DROP TABLE IF EXISTS bogus',
            
'DELETE FROM test WHERE id = @a',
            
'DELETE FROM test WHERE id = 1',
    );

    
$link get_connection();
    
$have_proc false;
    
mysqli_real_query($link"DROP PROCEDURE IF EXISTS p");
    if (
mysqli_real_query($link'CREATE PROCEDURE p(IN ver_in VARCHAR(25), OUT ver_out VARCHAR(25)) BEGIN SELECT ver_in INTO ver_out; END;')) {
            
$have_proc true;
            
$queries[] = "CALL p('myversion', @version)";
    }
    
mysqli_close($link);

    
$links = array();
    for (
$i 0$i count($queries); $i++) {

        
$link get_connection();

        if (
true !== ($tmp mysqli_query($link$queries[$i], MYSQLI_ASYNC |  MYSQLI_USE_RESULT)))
            
printf("[002] Expecting true got %s/%s\n"gettype($tmp), var_export($tmptrue));

        
// WARNING KLUDGE NOTE
        // Add a tiny delay to ensure that queries get executed in a certain order
        // If your MySQL server is very slow the test may randomly fail!
        
usleep(20000);

        
$links[mysqli_thread_id($link)] = array(
            
'query' => $queries[$i],
            
'link' => $link,
            
'processed' => false,
        );
    }

    
$saved_errors = array();
    do {
        
$poll_links $poll_errors $poll_reject = array();
        foreach (
$links as $thread_id => $link) {
            if (!
$link['processed']) {
                
$poll_links[] = $link['link'];
                
$poll_errors[] = $link['link'];
                
$poll_reject[] = $link['link'];
            }
        }
        if (
== count($poll_links))
            break;

        if (
== ($num_ready mysqli_poll($poll_links$poll_errors$poll_reject0200000)))
            continue;

        if (!empty(
$poll_errors)) {
            die(
var_dump($poll_errors));
        }

        foreach (
$poll_links as $link) {
            
$thread_id mysqli_thread_id($link);
            
$links[$thread_id]['processed'] = true;

            if (
is_object($res mysqli_reap_async_query($link))) {
                
// result set object
                
while ($row mysqli_fetch_assoc($res)) {
                    
// eat up all results
                    
;
                }
                
mysqli_free_result($res);
            } else {
                
// either there is no result (no SELECT) or there is an error
                
if (mysqli_errno($link) > 0) {
                    
$saved_errors[$thread_id] = mysqli_errno($link);
                    
printf("[003] '%s' caused %d\n"$links[$thread_id]['query'],    mysqli_errno($link));
                }
            }
        }

    } while (
true);

    
// Checking if all lines are still usable
    
foreach ($links as $thread_id => $link) {
        if (isset(
$saved_errors[$thread_id]) &&
            
$saved_errors[$thread_id] != mysqli_errno($link['link'])) {
            
printf("[004] Error state not saved for query '%s', %d != %d\n"$link['query'],
                    
$saved_errors[$thread_id], mysqli_errno($link['link']));
        }

        if (!
$res mysqli_query($link['link'], 'SELECT * FROM test WHERE id = 100'))
            
printf("[005] Expecting true got %s/%s\n"gettype($tmp), var_export($tmptrue));
        if (!
$row mysqli_fetch_row($res))
            
printf("[006] Expecting true got %s/%s\n"gettype($tmp), var_export($tmptrue));

        
mysqli_free_result($res);
    }

    if (
$res mysqli_query($link['link'], "SELECT * FROM test WHERE id = 100")) {
        
$row mysqli_fetch_assoc($res);
        
var_dump($row);
        
mysqli_free_result($res);
    }

    if (
$have_proc && ($res mysqli_query($link['link'], "SELECT @version as _version"))) {
        
$row mysqli_fetch_assoc($res);
        if (
$row['_version'] != 'myversion') {
            
printf("[007] Check procedures\n");
        }
        
mysqli_free_result($res);
    }

    foreach (
$links as $link)
        
mysqli_close($link['link']);

    
$link get_connection();
    if (!
mysqli_query($link'SELECT 1'MYSQLI_ASYNC))
        
printf("[008] [%d] %s\n"mysqli_errno($link), mysqli_error($link));

    if (!
mysqli_query($link'SELECT 1'MYSQLI_ASYNC))
        
printf("[009] [%d] %s\n"mysqli_errno($link), mysqli_error($link));

    
mysqli_close($link);

    print 
"done!";
?>
--CLEAN--
<?php
require_once("connect.inc");
if (!
$link my_mysqli_connect($host$user$passwd$db$port$socket))
   
printf("[c001] [%d] %s\n"mysqli_connect_errno(), mysqli_connect_error());

if (!
mysqli_query($link"DROP TABLE IF EXISTS test"))
    
printf("[c002] Cannot drop table, [%d] %s\n"mysqli_errno($link), mysqli_error($link));

if (!
mysqli_query($link"DROP TABLE IF EXISTS bogus"))
    
printf("[c002] Cannot drop table, [%d] %s\n"mysqli_errno($link), mysqli_error($link));

mysqli_query($link"DROP PROCEDURE IF EXISTS p");

mysqli_close($link);
?>

--EXPECTF--
[003] 'SELECT' caused 1064
[003] 'UPDATE test SET id = 101 WHERE id > 3' caused 1062
[003] 'UPDATE_FIX test SET id = 101 WHERE id > 3' caused 1064
array(2) {
  [%u|b%"id"]=>
  %unicode|string%(3) "100"
  [%u|b%"label"]=>
  %unicode|string%(1) "z"
}
[009] [2014] %s
done!