xref: /PHP-8.3/ext/mysqli/tests/mysqli_report.phpt (revision a21edc52)
1--TEST--
2mysqli_report()
3--EXTENSIONS--
4mysqli
5--SKIPIF--
6<?php
7require_once 'skipifconnectfailure.inc';
8?>
9--FILE--
10<?php
11    if (true !== ($tmp = mysqli_report(-1)))
12        printf("[002] Expecting boolean/true even for invalid flags, got %s/%s\n", gettype($tmp), $tmp);
13
14    if (true !== ($tmp = mysqli_report(MYSQLI_REPORT_ERROR)))
15        printf("[003] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
16
17    if (true !== ($tmp = mysqli_report(MYSQLI_REPORT_STRICT)))
18        printf("[004] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
19
20    if (true !== ($tmp = mysqli_report(MYSQLI_REPORT_INDEX)))
21        printf("[005] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
22
23    if (true !== ($tmp = mysqli_report(MYSQLI_REPORT_ALL)))
24        printf("[007] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
25
26    if (true !== ($tmp = mysqli_report(MYSQLI_REPORT_OFF)))
27        printf("[008] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
28
29    require_once 'table.inc';
30
31    /*
32    Internal macro MYSQL_REPORT_ERROR
33    */
34    mysqli_report(MYSQLI_REPORT_ERROR);
35
36    mysqli_multi_query($link, "BAR; FOO;");
37    mysqli_query($link, "FOO");
38    try {
39        mysqli_kill($link, -1);
40    } catch (\ValueError $e) {
41        echo $e->getMessage() . \PHP_EOL;
42    }
43
44    // mysqli_ping() cannot be tested, because one would need to cause an error inside the C function to test it
45    mysqli_prepare($link, "FOO");
46    mysqli_real_query($link, "FOO");
47    if (@mysqli_select_db($link, "Oh lord, let this be an unknown database name"))
48        printf("[009] select_db should have failed\n");
49    // mysqli_store_result() and mysqli_use_result() cannot be tested, because one would need to cause an error inside the C function to test it
50
51    mysqli_multi_query($link, "SELECT 1; FOO;");
52    mysqli_autocommit($link, true);
53    mysqli_commit($link);
54    mysqli_rollback($link);
55    $stmt = mysqli_stmt_init($link);
56    mysqli_stmt_prepare($stmt, "SELECT id FROM test WHERE id > ?");
57    while(mysqli_more_results($link)) {
58        mysqli_next_result($link);
59        $res = mysqli_store_result($link);
60    }
61    mysqli_next_result($link);
62
63    $stmt = mysqli_prepare($link, "SELECT 1");
64    mysqli_stmt_attr_set($stmt, MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_FOR_UPDATE);
65
66    // Check that none of the above would have caused any error messages if MYSQL_REPORT_ERROR would
67    // not have been set. If that would be the case, the test would be broken.
68    mysqli_report(MYSQLI_REPORT_OFF);
69
70    mysqli_multi_query($link, "BAR; FOO;");
71    mysqli_query($link, "FOO");
72    try {
73        mysqli_kill($link, -1);
74    } catch (\ValueError $e) {
75        echo $e->getMessage() . \PHP_EOL;
76    }
77    mysqli_prepare($link, "FOO");
78    mysqli_real_query($link, "FOO");
79    mysqli_select_db($link, "Oh lord, let this be an unknown database name");
80
81    mysqli_multi_query($link, "SELECT 1; FOO;");
82    mysqli_autocommit($link, true);
83    mysqli_commit($link);
84    mysqli_rollback($link);
85    $stmt = mysqli_stmt_init($link);
86    mysqli_stmt_prepare($stmt, "SELECT id FROM test WHERE id > ?");
87    while(mysqli_more_results($link)) {
88        mysqli_next_result($link);
89        $res = mysqli_store_result($link);
90    }
91    mysqli_next_result($link);
92
93    $stmt = mysqli_prepare($link, "SELECT 1");
94    mysqli_stmt_attr_set($stmt, MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_FOR_UPDATE);
95
96    /*
97    Internal macro MYSQL_REPORT_STMT_ERROR
98    */
99
100    mysqli_report(MYSQLI_REPORT_ERROR);
101
102    $stmt = mysqli_stmt_init($link);
103    mysqli_stmt_prepare($stmt, "FOO");
104
105    $stmt = mysqli_stmt_init($link);
106    mysqli_stmt_prepare($stmt, "SELECT id FROM test WHERE id > ?");
107    $id = 1;
108    mysqli_kill($link, mysqli_thread_id($link));
109    mysqli_stmt_bind_param($stmt, "i", $id);
110    mysqli_stmt_close($stmt);
111    mysqli_close($link);
112
113    /* mysqli_stmt_execute() = mysql_stmt_execute cannot be tested from PHP */
114    if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
115            printf("[008] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
116    $stmt = mysqli_stmt_init($link);
117    mysqli_stmt_prepare($stmt, "SELECT id FROM test WHERE id > ?");
118    $id = 1;
119    mysqli_stmt_bind_param($stmt, "i", $id);
120    // mysqli_kill($link, mysqli_thread_id($link));
121    mysqli_stmt_execute($stmt);
122    mysqli_stmt_close($stmt);
123    mysqli_close($link);
124
125    /* mysqli_kill() "trick" does not work for any of the following because of an E_COMMANDS_OUT_OF_SYNC */
126    /* mysqli_stmt_bind_result() = mysql_stmt_bind_result() cannot be tested from PHP */
127    /* mysqli_stmt_fetch() = mysql_stmt_fetch() cannot be tested from PHP */
128    /* mysqli_stmt_result_metadata() = mysql_stmt_result_metadata() cannot be tested from PHP */
129    /* mysqli_stmt_store_result() = mysql_stmt_store_result() cannot be tested from PHP */
130
131    // Check
132    mysqli_report(MYSQLI_REPORT_OFF);
133
134    if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
135        printf("[010] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
136    $stmt = mysqli_stmt_init($link);
137    mysqli_stmt_prepare($stmt, "FOO");
138
139    $stmt = mysqli_stmt_init($link);
140    mysqli_stmt_prepare($stmt, "SELECT id FROM test WHERE id > ?");
141    $id = 1;
142    mysqli_kill($link, mysqli_thread_id($link));
143    mysqli_stmt_bind_param($stmt, "i", $id);
144    mysqli_stmt_close($stmt);
145    mysqli_close($link);
146
147    if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
148        printf("[011] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
149    $stmt = mysqli_stmt_init($link);
150    mysqli_stmt_prepare($stmt, "SELECT id FROM test WHERE id > ?");
151    $id = 1;
152    mysqli_stmt_bind_param($stmt, "i", $id);
153    mysqli_kill($link, mysqli_thread_id($link));
154    mysqli_stmt_execute($stmt);
155    mysqli_stmt_close($stmt);
156    mysqli_close($link);
157
158    /*
159    MYSQLI_REPORT_STRICT
160
161    MYSQLI_REPORT_STRICT --->
162    php_mysqli_report_error() ->
163        MYSQLI_REPORT_MYSQL_ERROR,
164        MYSQLI_REPORT_STMT_ERROR ->
165            already tested
166
167    php_mysqli_throw_sql_exception() ->
168        my_mysqli_real_connect()
169        my_mysqli_connect()
170
171    can't be tested: mysqli_query() via mysql_use_result()/mysql_store_result()
172    */
173    mysqli_report(MYSQLI_REPORT_OFF);
174    mysqli_report(MYSQLI_REPORT_STRICT);
175
176    try {
177
178        if ($link = my_mysqli_connect($host, $user . 'unknown_really', $passwd . 'non_empty', $db, $port, $socket))
179            printf("[012] Can connect to the server using host=%s, user=%s, passwd=***non_empty, dbname=%s, port=%s, socket=%s\n",
180                $host, $user . 'unknown_really', $db, $port, $socket);
181        mysqli_close($link);
182
183    } catch (mysqli_sql_exception $e) {
184        printf("[013] %s\n", $e->getMessage());
185    }
186
187    try {
188        if (!$link = mysqli_init())
189            printf("[014] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
190
191        if ($link = my_mysqli_real_connect($link, $host, $user . 'unknown_really', $passwd . 'non_empty', $db, $port, $socket))
192            printf("[015] Can connect to the server using host=%s, user=%s, passwd=***non_empty, dbname=%s, port=%s, socket=%s\n",
193                $host, $user . 'unknown_really', $db, $port, $socket);
194        mysqli_close($link);
195    } catch (mysqli_sql_exception $e) {
196        printf("[016] %s\n", $e->getMessage());
197    }
198
199    /*
200    MYSQLI_REPORT_INDEX --->
201    mysqli_query()
202    mysqli_stmt_execute()
203    mysqli_prepare()
204    mysqli_real_query()
205    mysqli_store_result()
206    mysqli_use_result()
207
208    No test, because of to many prerequisites:
209        - Server needs to be started with and
210            --log-slow-queries --log-queries-not-using-indexes
211        - query must cause the warning on all MySQL versions
212
213    TODO:
214    */
215    $log_slow_queries = false;
216    $log_queries_not_using_indexes = false;
217    mysqli_report(MYSQLI_REPORT_OFF);
218    mysqli_report(MYSQLI_REPORT_INDEX);
219
220    if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
221        printf("[017] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
222
223    if (mysqli_get_server_version($link) <= 50600) {
224        // this might cause a warning - no index used
225        if (!$res = @mysqli_query($link, "SHOW VARIABLES LIKE 'log_slow_queries'"))
226            printf("[018] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
227
228        if (!$row = mysqli_fetch_assoc($res))
229            printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
230
231        $log_slow_query = ('ON' == $row['Value']);
232
233        if (mysqli_get_server_version($link) >= 50111) {
234            // this might cause a warning - no index used
235            if (!$res = @mysqli_query($link, "SHOW VARIABLES LIKE 'log_queries_not_using_indexes'"))
236                printf("[020] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
237
238            if (!$row = mysqli_fetch_assoc($res))
239                printf("[021] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
240
241            $log_queries_not_using_indexes = ('ON' == $row['Value']);
242
243            if ($log_slow_queries && $log_queries_not_using_indexes) {
244
245                for ($i = 100; $i < 20000; $i++) {
246                    if (!mysqli_query($link, "INSERT INTO test(id, label) VALUES ($i, 'z')"))
247                        printf("[022 - %d] [%d] %s\n", $i - 99, mysqli_errno($link), mysqli_error($link));
248                }
249
250                // this might cause a warning - no index used
251                if (!$res = @mysqli_query($link, "SELECT id, label FROM test WHERE id = 1323"))
252                    printf("[023] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
253
254                mysqli_free_result($res);
255            }
256        }
257    }
258
259    // Maybe we've provoked an index message, maybe not.
260    // All we can do is make a few dummy calls to ensure that all codes gets executed which
261    // checks the flag. Functions to check: mysqli_query() - done above,
262    // mysqli_stmt_execute(), mysqli_prepare(), mysqli_real_query(), mysqli_store_result()
263    // mysqli_use_result(), mysqli_thread_safe(), mysqli_thread_id()
264    mysqli_report(MYSQLI_REPORT_OFF);
265    mysqli_close($link);
266    if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
267        printf("[024] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
268
269    if (!$stmt = mysqli_stmt_init($link))
270        printf("[025] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
271
272    if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test'))
273        printf("[026] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
274
275    if (!mysqli_stmt_execute($stmt))
276        printf("[027] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
277
278    mysqli_stmt_close($stmt);
279
280    if (!mysqli_real_query($link, 'SELECT label, id FROM test'))
281        printf("[028] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
282
283    if (!$res = mysqli_use_result($link))
284        printf("[029] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
285
286    mysqli_free_result($res);
287
288    if (!mysqli_real_query($link, 'SELECT label, id FROM test'))
289        printf("[030]  [%d] %s\n", mysqli_errno($link), mysqli_error($link));
290
291    if (!$res = mysqli_store_result($link))
292        printf("[031]  [%d] %s\n", mysqli_errno($link), mysqli_error($link));
293
294    mysqli_free_result($res);
295
296    if (!$stmt = mysqli_prepare($link, 'SELECT id * 3 FROM test'))
297        printf("[032] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
298    else
299        mysqli_stmt_close($stmt);
300
301    if (!mysqli_query($link, "INSERT INTO test(id, label) VALUES (100, 'z')", MYSQLI_USE_RESULT) ||
302            !mysqli_query($link, 'DELETE FROM test WHERE id > 50', MYSQLI_USE_RESULT))
303        printf("[033] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
304
305    $tmp = mysqli_thread_id($link);
306
307    mysqli_close($link);
308    print "done!";
309?>
310--CLEAN--
311<?php
312require_once 'clean_table.inc';
313?>
314--EXPECTF--
315Warning: mysqli_multi_query(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near 'BAR; FOO' at line 1 in %s on line %d
316
317Warning: mysqli_query(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
318mysqli_kill(): Argument #2 ($process_id) must be greater than 0
319
320Warning: mysqli_prepare(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
321
322Warning: mysqli_real_query(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
323
324Warning: mysqli_autocommit(): (%s/%d): Commands out of sync; you can't run this command now in %s on line %d
325
326Warning: mysqli_commit(): (%s/%d): Commands out of sync; you can't run this command now in %s on line %d
327
328Warning: mysqli_rollback(): (%s/%d): Commands out of sync; you can't run this command now in %s on line %d
329
330Warning: mysqli_stmt_prepare(): (%s/%d): Commands out of sync; you can't run this command now in %s on line %d
331
332Warning: mysqli_next_result(): (%s/%d): You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
333
334Warning: mysqli_store_result(): (%s/%d): You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
335
336Warning: mysqli_stmt_attr_set(): (%s/%d): Not implemented in %s on line %d
337mysqli_kill(): Argument #2 ($process_id) must be greater than 0
338
339Warning: mysqli_stmt_prepare(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
340[013] Access denied for user '%s'@'%s'%r( \(using password: \w+\)){0,1}%r
341[016] Access denied for user '%s'@'%s'%r( \(using password: \w+\)){0,1}%r
342done!
343