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