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