1--TEST-- 2mysqli_poll() & INSERT SELECT 3--SKIPIF-- 4<?php 5require_once('skipif.inc'); 6require_once('connect.inc'); 7require_once('skipifconnectfailure.inc'); 8 9if (!$IS_MYSQLND) 10 die("skip mysqlnd only feature, compile PHP using --with-mysqli=mysqlnd"); 11?> 12--FILE-- 13<?php 14 require_once('table.inc'); 15 16 function get_connection() { 17 global $host, $user, $passwd, $db, $port, $socket; 18 19 if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) 20 printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); 21 return $link; 22 } 23 24 25 // Note: some queries will fail! They are supposed to fail. 26 $queries = array( 27 'CREATE TABLE IF NOT EXISTS bogus(id INT)', 28 'SET @a = 1', 29 'SELECT * FROM test ORDER BY id ASC LIMIT 2', 30 "INSERT INTO test(id, label) VALUES (100, 'z')", 31 'SELECT * FROM test ORDER BY id ASC LIMIT 2', 32 'SELECT', 33 'UPDATE test SET id = 101 WHERE id > 3', 34 'UPDATE_FIX test SET id = 101 WHERE id > 3', 35 'DROP TABLE IF EXISTS bogus', 36 'DELETE FROM test WHERE id = @a', 37 'DELETE FROM test WHERE id = 1', 38 ); 39 40 $link = get_connection(); 41 $have_proc = false; 42 mysqli_real_query($link, "DROP PROCEDURE IF EXISTS p"); 43 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;')) { 44 $have_proc = true; 45 $queries[] = "CALL p('myversion', @version)"; 46 } 47 mysqli_close($link); 48 49 $links = array(); 50 for ($i = 0; $i < count($queries); $i++) { 51 52 $link = get_connection(); 53 54 if (true !== ($tmp = mysqli_query($link, $queries[$i], MYSQLI_ASYNC | MYSQLI_USE_RESULT))) 55 printf("[002] Expecting true got %s/%s\n", gettype($tmp), var_export($tmp, true)); 56 57 // WARNING KLUDGE NOTE 58 // Add a tiny delay to ensure that queries get executed in a certain order 59 // If your MySQL server is very slow the test may randomly fail! 60 usleep(20000); 61 62 $links[mysqli_thread_id($link)] = array( 63 'query' => $queries[$i], 64 'link' => $link, 65 'processed' => false, 66 ); 67 } 68 69 $saved_errors = array(); 70 do { 71 $poll_links = $poll_errors = $poll_reject = array(); 72 foreach ($links as $thread_id => $link) { 73 if (!$link['processed']) { 74 $poll_links[] = $link['link']; 75 $poll_errors[] = $link['link']; 76 $poll_reject[] = $link['link']; 77 } 78 } 79 if (0 == count($poll_links)) 80 break; 81 82 if (0 === ($num_ready = mysqli_poll($poll_links, $poll_errors, $poll_reject, 0, 200000))) 83 continue; 84 85 if (!empty($poll_errors)) { 86 die(var_dump($poll_errors)); 87 } 88 89 if (FALSE === $num_ready) { 90 die("Some mysqli indicated error"); 91 } 92 93 foreach ($poll_links as $link) { 94 $thread_id = mysqli_thread_id($link); 95 $links[$thread_id]['processed'] = true; 96 97 if (is_object($res = mysqli_reap_async_query($link))) { 98 // result set object 99 while ($row = mysqli_fetch_assoc($res)) { 100 // eat up all results 101 ; 102 } 103 mysqli_free_result($res); 104 } else { 105 // either there is no result (no SELECT) or there is an error 106 if (mysqli_errno($link) > 0) { 107 $saved_errors[$thread_id] = mysqli_errno($link); 108 } 109 } 110 } 111 112 } while (true); 113 114 // Checking if all lines are still usable 115 foreach ($links as $thread_id => $link) { 116 if (isset($saved_errors[$thread_id])) { 117 printf("[003] '%s' caused %d\n", 118 $links[$thread_id]['query'], $saved_errors[$thread_id]); 119 if ($saved_errors[$thread_id] != mysqli_errno($link['link'])) { 120 printf("[004] Error state not saved for query '%s', %d != %d\n", $link['query'], 121 $saved_errors[$thread_id], mysqli_errno($link['link'])); 122 } 123 } 124 125 if (!$res = mysqli_query($link['link'], 'SELECT * FROM test WHERE id = 100')) 126 printf("[005] Expecting true got %s/%s\n", gettype($tmp), var_export($tmp, true)); 127 if (!$row = mysqli_fetch_row($res)) 128 printf("[006] Expecting true got %s/%s\n", gettype($tmp), var_export($tmp, true)); 129 130 mysqli_free_result($res); 131 } 132 133 if ($res = mysqli_query($link['link'], "SELECT * FROM test WHERE id = 100")) { 134 $row = mysqli_fetch_assoc($res); 135 var_dump($row); 136 mysqli_free_result($res); 137 } 138 139 if ($have_proc && ($res = mysqli_query($link['link'], "SELECT @version as _version"))) { 140 $row = mysqli_fetch_assoc($res); 141 if ($row['_version'] != 'myversion') { 142 printf("[007] Check procedures\n"); 143 } 144 mysqli_free_result($res); 145 } 146 147 foreach ($links as $link) 148 mysqli_close($link['link']); 149 150 $link = get_connection(); 151 if (!mysqli_query($link, 'SELECT 1', MYSQLI_ASYNC)) 152 printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); 153 154 if (!mysqli_query($link, 'SELECT 1', MYSQLI_ASYNC)) 155 printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); 156 157 mysqli_close($link); 158 159 print "done!"; 160?> 161--CLEAN-- 162<?php 163require_once("connect.inc"); 164if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) 165 printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); 166 167if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) 168 printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link)); 169 170if (!mysqli_query($link, "DROP TABLE IF EXISTS bogus")) 171 printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link)); 172 173mysqli_query($link, "DROP PROCEDURE IF EXISTS p"); 174 175mysqli_close($link); 176?> 177--EXPECTF-- 178[003] 'SELECT' caused 1064 179[003] 'UPDATE test SET id = 101 WHERE id > 3' caused 1062 180[003] 'UPDATE_FIX test SET id = 101 WHERE id > 3' caused 1064 181array(2) { 182 ["id"]=> 183 string(3) "100" 184 ["label"]=> 185 string(1) "z" 186} 187[009] [2014] %s 188done! 189