1--TEST--
2mysqli_get_client_stats()
3--SKIPIF--
4<?PHP
5require_once('skipif.inc');
6require_once('skipifemb.inc');
7require_once('skipifconnectfailure.inc');
8if (!function_exists('mysqli_get_client_stats')) {
9	die("skip only available with mysqlnd");
10}
11?>
12--INI--
13mysqlnd.collect_statistics=1
14mysqlnd.collect_memory_statistics=1
15--FILE--
16<?php
17	/*
18	TODO
19	no_index_used - difficult to simulate because server/engine dependent
20	bad_index_used - difficult to simulate because server/engine dependent
21	flushed_normal_sets
22	flushed_ps_sets
23	explicit_close
24	implicit_close
25	disconnect_close
26	in_middle_of_command_close
27	explicit_free_result
28	implicit_free_result
29	explicit_stmt_close
30	implicit_stmt_close
31	*/
32
33	function mysqli_get_client_stats_assert_eq($field, $current, $expected, &$test_counter, $desc = "") {
34
35		$test_counter++;
36		if (is_array($current) && is_array($expected)) {
37			if ($current[$field] !== $expected[$field]) {
38				printf("[%03d] %s Expecting %s = %s/%s, got %s/%s\n",
39					$test_counter, $desc,
40					$field, $expected[$field], gettype($expected[$field]),
41					$current[$field], gettype($current[$field]));
42			}
43		} else if (is_array($current)) {
44			if ($current[$field] !== $expected) {
45				printf("[%03d] %s Expecting %s = %s/%s, got %s/%s\n",
46					$test_counter, $desc,
47					$field, $expected, gettype($expected),
48					$current[$field], gettype($current[$field]));
49			}
50		} else {
51			if ($current !== $expected) {
52				printf("[%03d] %s Expecting %s = %s/%s, got %s/%s\n",
53					$test_counter, $desc,
54					$field, $expected, gettype($expected),
55					$current, gettype($current));
56			}
57		}
58
59	}
60
61	function mysqli_get_client_stats_assert_gt($field, $current, $expected, &$test_counter, $desc = "") {
62
63		$test_counter++;
64		if (is_array($current) && is_array($expected)) {
65			if ($current[$field] <= $expected[$field]) {
66				printf("[%03d] %s Expecting %s > %s/%s, got %s/%s\n",
67					$test_counter, $desc,
68					$field, $expected[$field], gettype($expected[$field]),
69					$current[$field], gettype($current[$field]));
70				}
71		} else {
72			if ($current <= $expected) {
73				printf("[%03d] %s Expecting %s > %s/%s, got %s/%s\n",
74					$test_counter, $desc, $field,
75					$expected, gettype($expected),
76					$current, gettype($current));
77			}
78		}
79
80	}
81
82
83	$tmp = $link = null;
84	if (!is_null($tmp = @mysqli_get_client_stats($link)))
85		printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
86
87	require_once("connect.inc");
88
89	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
90		printf("[002] Expecting array/any_non_empty, got %s/%s\n", gettype($info), $info);
91
92	var_dump($info);
93
94	if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
95		printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
96			$host, $user, $db, $port, $socket);
97		exit(1);
98	}
99
100	if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
101		printf("[004] Expecting array/any_non_empty, got %s/%s\n", gettype($new_info), $new_info);
102
103	if (count($info) != count($new_info)) {
104		printf("[005] Expecting the same number of entries in the arrays\n");
105		var_dump($info);
106		var_dump($new_info);
107	}
108
109	$test_counter = 6;
110
111	mysqli_get_client_stats_assert_gt('bytes_sent', $new_info, $info, $test_counter);
112	mysqli_get_client_stats_assert_gt('bytes_received', $new_info, $info, $test_counter);
113	mysqli_get_client_stats_assert_gt('packets_sent', $new_info, $info, $test_counter);
114	mysqli_get_client_stats_assert_gt('packets_received', $new_info, $info, $test_counter);
115	mysqli_get_client_stats_assert_gt('protocol_overhead_in', $new_info, $info, $test_counter);
116	mysqli_get_client_stats_assert_gt('protocol_overhead_out', $new_info, $info, $test_counter);
117
118	// we assume the above as tested and in the following we check only those
119	mysqli_get_client_stats_assert_eq('result_set_queries', $new_info, $info, $test_counter);
120
121	/* we need to skip this test in unicode - we send set names utf8 during mysql_connect */
122	if (!(version_compare(PHP_VERSION, '6.0', '==') == 1))
123		mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, $info, $test_counter);
124	mysqli_get_client_stats_assert_eq('buffered_sets', $new_info, $info, $test_counter);
125	mysqli_get_client_stats_assert_eq('unbuffered_sets', $new_info, $info, $test_counter);
126	mysqli_get_client_stats_assert_eq('ps_buffered_sets', $new_info, $info, $test_counter);
127	mysqli_get_client_stats_assert_eq('ps_unbuffered_sets', $new_info, $info, $test_counter);
128
129	mysqli_get_client_stats_assert_eq('rows_skipped_ps', $new_info, $info, $test_counter);
130	mysqli_get_client_stats_assert_eq('copy_on_write_saved', $new_info, $info, $test_counter);
131	mysqli_get_client_stats_assert_eq('copy_on_write_performed', $new_info, $info, $test_counter);
132	mysqli_get_client_stats_assert_eq('command_buffer_too_small', $new_info, $info, $test_counter);
133	// This is not a mistake that I use %unicode|string%(1) "1" here! Andrey did not go for int to avoid any
134	// issues for very large numbers and 32 vs. 64bit systems
135	mysqli_get_client_stats_assert_eq('connect_success', $new_info, "1", $test_counter);
136	mysqli_get_client_stats_assert_eq('connect_failure', $new_info, $info, $test_counter);
137	mysqli_get_client_stats_assert_eq('connection_reused', $new_info, $info, $test_counter);
138
139	// No data fetched so far
140	mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $new_info, "0", $test_counter);
141	mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $new_info, "0", $test_counter);
142
143	require('table.inc');
144	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
145		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
146			++$test_counter, gettype($info), $info);
147
148	// fetch stats
149	$expected = $info;
150
151	// buffered normal
152	print "Testing buffered normal...\n";
153	if (!$res = mysqli_query($link, 'SELECT COUNT(*) AS _num FROM test', MYSQLI_STORE_RESULT))
154		printf("[%03d] SELECT COUNT() FROM test failed, [%d] %s\n",
155			++$test_counter, mysqli_errno($link), mysqli_error($link));
156
157	$expected['rows_fetched_from_server_normal'] = (string)($expected['rows_fetched_from_server_normal'] + 1);
158	$expected['buffered_sets'] = (string)($expected['buffered_sets'] + 1);
159	$expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
160	$expected['rows_buffered_from_client_normal'] = (string)($expected['rows_buffered_from_client_normal'] + 1);
161
162	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
163		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
164			++$test_counter, gettype($info), $info);
165
166	mysqli_get_client_stats_assert_gt('bytes_sent', $info, $expected, $test_counter);
167	mysqli_get_client_stats_assert_gt('bytes_received', $info, $expected, $test_counter);
168
169	// real_data_* get incremented after mysqli_*fetch*()
170    mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $info, "0", $test_counter);
171	mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $info, "0", $test_counter);
172
173	mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
174	mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_buffered', $info, $expected, $test_counter);
175	mysqli_get_client_stats_assert_eq('buffered_sets', $info, $expected, $test_counter);
176	mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
177	mysqli_get_client_stats_assert_eq('rows_buffered_from_client_normal', $info, $expected, $test_counter);
178
179	/* no change to rows_fetched_from_client_normal_buffered! */
180	if (!$row = mysqli_fetch_assoc($res))
181		printf("[%03d] fetch_assoc - SELECT COUNT() FROM test failed, [%d] %s\n",
182			++$test_counter, mysqli_errno($link), mysqli_error($link));
183
184	$expected['rows_fetched_from_client_normal_buffered'] = (string)($expected['rows_fetched_from_client_normal_buffered'] + 1);
185
186	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
187		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
188			++$test_counter, gettype($info), $info);
189
190	// fetch will increment
191	mysqli_get_client_stats_assert_gt('bytes_received_real_data_normal', $info, $expected, $test_counter);
192	$expected['bytes_received_real_data_normal'] = $info['bytes_received_real_data_normal'];
193	mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $info, "0", $test_counter);
194
195	mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
196	mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_buffered', $info, $expected, $test_counter);
197	mysqli_get_client_stats_assert_eq('rows_buffered_from_client_normal', $info, $expected, $test_counter);
198
199	$num_rows = $row['_num'];
200	mysqli_free_result($res);
201
202	print "Testing buffered normal... - SELECT id, label FROM test\n";
203	if (!$res = mysqli_query($link, 'SELECT id, label FROM test', MYSQLI_STORE_RESULT))
204		printf("[%03d] SELECT id, label FROM test failed, [%d] %s\n",
205			++$test_counter, mysqli_errno($link), mysqli_error($link));
206
207
208	assert(mysqli_num_rows($res) == $num_rows);
209
210	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
211		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
212			++$test_counter, gettype($info), $info);
213
214
215	$expected['rows_fetched_from_server_normal'] = (string)($expected['rows_fetched_from_server_normal'] + $num_rows);
216	$expected['rows_buffered_from_client_normal'] = (string)($expected['rows_buffered_from_client_normal'] + $num_rows);
217	$expected['buffered_sets'] = (string)($expected['buffered_sets'] + 1);
218	$expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
219
220	mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $info, $expected, $test_counter);
221
222	mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
223	mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_buffered', $info, $expected, $test_counter);
224	mysqli_get_client_stats_assert_eq('buffered_sets', $info, $expected, $test_counter);
225	mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
226	mysqli_get_client_stats_assert_eq('rows_buffered_from_client_normal', $info, $expected, $test_counter);
227	mysqli_get_client_stats_assert_eq('rows_buffered_from_client_normal', $info, $expected, $test_counter);
228
229	/* fetching none, but stats should not be affected - current implementation */
230	mysqli_free_result($res);
231
232	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
233		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
234			++$test_counter, gettype($info), $info);
235
236
237	mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $info, $expected, $test_counter);
238	mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
239	mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_buffered', $info, $expected, $test_counter);
240
241	print "Testing unbuffered normal...\n";
242	if (!$res = mysqli_query($link, 'SELECT id, label FROM test', MYSQLI_USE_RESULT))
243		printf("[%03d] SELECT id, label FROM test failed, [%d] %s\n",
244			++$test_counter, mysqli_errno($link), mysqli_error($link));
245
246	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
247		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
248			++$test_counter, gettype($info), $info);
249
250	mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
251	mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_unbuffered', $info, $expected, $test_counter);
252	mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $info, $expected, $test_counter);
253
254	while ($row = mysqli_fetch_assoc($res))
255		;
256	mysqli_free_result($res);
257
258	$expected['rows_fetched_from_server_normal'] = (string)($expected['rows_fetched_from_server_normal'] + $num_rows);
259	$expected['rows_fetched_from_client_normal_unbuffered'] = (string)($expected['rows_fetched_from_client_normal_unbuffered'] + $num_rows);
260	$expected['unbuffered_sets'] = (string)($expected['unbuffered_sets'] + 1);
261	$expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
262
263	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
264		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
265			++$test_counter, gettype($info), $info);
266
267	mysqli_get_client_stats_assert_gt('bytes_received_real_data_normal', $info, $expected, $test_counter);
268	$expected['bytes_received_real_data_normal'] = $info['bytes_received_real_data_normal'];
269
270	mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
271	mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_unbuffered', $info, $expected, $test_counter);
272	mysqli_get_client_stats_assert_eq('unbuffered_sets', $info, $expected, $test_counter);
273	mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
274
275	print "Testing unbuffered normal... - SELECT id, label FROM test, not all fetched\n";
276	if (!$res = mysqli_query($link, 'SELECT id, label FROM test', MYSQLI_USE_RESULT))
277		printf("[%03d] SELECT id, label FROM test failed, [%d] %s\n",
278			++$test_counter, mysqli_errno($link), mysqli_error($link));
279
280	for ($i = 0; $i < $num_rows - 1; $i++)
281		$row = mysqli_fetch_assoc($res);
282
283	$expected['rows_fetched_from_server_normal'] = (string)($expected['rows_fetched_from_server_normal'] + $num_rows - 1);
284	$expected['rows_fetched_from_client_normal_unbuffered'] = (string)($expected['rows_fetched_from_client_normal_unbuffered'] + $num_rows - 1);
285	$expected['unbuffered_sets'] = (string)($expected['unbuffered_sets'] + 1);
286	$expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
287
288	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
289		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
290			++$test_counter, gettype($info), $info);
291
292	mysqli_get_client_stats_assert_gt('bytes_received_real_data_normal', $info, $expected, $test_counter);
293	$expected['bytes_received_real_data_normal'] = $info['bytes_received_real_data_normal'];
294
295	mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
296	mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_unbuffered', $info, $expected, $test_counter);
297	mysqli_get_client_stats_assert_eq('unbuffered_sets', $info, $expected, $test_counter);
298	mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
299
300	print "Testing if implicit fetching and cleaning happens...\n";
301	mysqli_free_result($res);
302
303	/* last row has been implicitly cleaned from the wire by freeing the result set */
304	$expected['rows_fetched_from_server_normal'] = (string)($expected['rows_fetched_from_server_normal'] + 1);
305	$expected['rows_fetched_from_client_normal_unbuffered'] = (string)($expected['rows_fetched_from_client_normal_unbuffered'] + 1);
306	$expected['rows_skipped_normal'] = (string)($info['rows_skipped_normal'] + 1);
307	$expected['flushed_normal_sets'] = (string)($expected['flushed_normal_sets'] + 1);
308
309	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
310		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
311			++$test_counter, gettype($info), $info);
312
313	mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $info, $expected, $test_counter);
314
315	mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
316	mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_unbuffered', $info, $expected, $test_counter);
317	mysqli_get_client_stats_assert_eq('rows_skipped_normal', $info, $expected, $test_counter);
318	mysqli_get_client_stats_assert_eq('flushed_normal_sets', $info, $expected, $test_counter);
319
320	print "Testing buffered Prepared Statements...\n";
321	if (!$stmt = mysqli_stmt_init($link))
322		printf("[%03d] stmt_init() failed, [%d] %s\n",
323			++$test_counter, mysqli_errno($link), mysqli_error($link));
324
325	if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test') ||
326			!mysqli_stmt_execute($stmt))
327		printf("[%03d] prepare/execute failed, [%d] %s\n",
328			++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
329
330	/* by default PS is unbuffered - no change */
331	mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
332	mysqli_get_client_stats_assert_eq('rows_fetched_from_client_ps_buffered', $info, $expected, $test_counter);
333
334	if (!mysqli_stmt_store_result($stmt))
335		printf("[%03d] store_result failed, [%d] %s\n",
336			++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
337	mysqli_stmt_free_result($stmt);
338
339	mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $info, "0", $test_counter);
340	mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $info, $expected, $test_counter);
341
342	$expected['rows_fetched_from_server_ps'] = (string)($expected['rows_fetched_from_server_ps'] + $num_rows);
343	$expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
344	$expected['ps_buffered_sets'] = (string)($expected['ps_buffered_sets'] + 1);
345	$expected['rows_buffered_from_client_ps'] = (string)($expected['rows_buffered_from_client_ps'] + $num_rows);
346
347
348	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
349		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
350			++$test_counter, gettype($info), $info);
351
352	mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
353	mysqli_get_client_stats_assert_eq('rows_fetched_from_client_ps_buffered', $info, $expected, $test_counter);
354	mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
355	mysqli_get_client_stats_assert_eq('ps_buffered_sets', $info, $expected, $test_counter);
356	mysqli_get_client_stats_assert_eq('rows_buffered_from_client_ps', $info, $expected, $test_counter);
357
358	mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $info, "0", $test_counter);
359
360	print "Testing buffered Prepared Statements... - fetching all\n";
361
362	if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test') ||
363			!mysqli_stmt_execute($stmt))
364		printf("[%03d] prepare/execute failed, [%d] %s\n",
365			++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
366
367	$id = $label = null;
368	if (!mysqli_stmt_bind_result($stmt, $id, $label))
369		printf("[%03d] bind_result failed, [%d] %s\n",
370			++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
371
372	if (!mysqli_stmt_store_result($stmt))
373		printf("[%03d] store_result failed, [%d] %s\n",
374			++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
375
376	while (mysqli_stmt_fetch($stmt))
377		;
378
379	$expected['rows_fetched_from_server_ps'] = (string)($expected['rows_fetched_from_server_ps'] + $num_rows);
380	$expected['rows_fetched_from_client_ps_buffered'] = (string)($expected['rows_fetched_from_client_ps_buffered'] + $num_rows);
381	$expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
382	$expected['ps_buffered_sets'] = (string)($expected['ps_buffered_sets'] + 1);
383	$expected['rows_buffered_from_client_ps'] = (string)($expected['rows_buffered_from_client_ps'] + $num_rows);
384
385	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
386		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
387			++$test_counter, gettype($info), $info);
388
389
390	mysqli_get_client_stats_assert_gt('bytes_received_real_data_ps', $info, $expected, $test_counter);
391	$expected['bytes_received_real_data_ps'] = $info['bytes_received_real_data_ps'];
392
393	mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
394	mysqli_get_client_stats_assert_eq('rows_fetched_from_client_ps_buffered', $info, $expected, $test_counter);
395	mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
396	mysqli_get_client_stats_assert_eq('ps_buffered_sets', $info, $expected, $test_counter);
397	mysqli_get_client_stats_assert_eq('rows_buffered_from_client_ps', $info, $expected, $test_counter);
398
399	mysqli_stmt_free_result($stmt);
400
401	print "Testing buffered Prepared Statements... - fetching all but one\n";
402
403	if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test') ||
404			!mysqli_stmt_execute($stmt))
405		printf("[%03d] prepare/execute failed, [%d] %s\n",
406			++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
407
408	$id = $label = null;
409	if (!mysqli_stmt_bind_result($stmt, $id, $label))
410		printf("[%03d] bind_result failed, [%d] %s\n",
411			++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
412
413	if (!mysqli_stmt_store_result($stmt))
414		printf("[%03d] store_result failed, [%d] %s\n",
415			++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
416
417	for ($i = 0; $i < $num_rows - 1; $i++)
418		mysqli_stmt_fetch($stmt);
419
420	$expected['rows_fetched_from_server_ps'] = (string)($expected['rows_fetched_from_server_ps'] + $num_rows);
421	$expected['rows_fetched_from_client_ps_buffered'] = (string)($expected['rows_fetched_from_client_ps_buffered'] + $num_rows - 1);
422	$expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
423	$expected['ps_buffered_sets'] = (string)($expected['ps_buffered_sets'] + 1);
424	$expected['rows_buffered_from_client_ps'] = (string)($expected['rows_buffered_from_client_ps'] + $num_rows);
425
426	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
427		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
428			++$test_counter, gettype($info), $info);
429
430	mysqli_get_client_stats_assert_gt('bytes_received_real_data_ps', $info, $expected, $test_counter);
431	$expected['bytes_received_real_data_ps'] = $info['bytes_received_real_data_ps'];
432
433	mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
434	mysqli_get_client_stats_assert_eq('rows_fetched_from_client_ps_buffered', $info, $expected, $test_counter);
435	mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
436	mysqli_get_client_stats_assert_eq('ps_buffered_sets', $info, $expected, $test_counter);
437	mysqli_get_client_stats_assert_eq('rows_buffered_from_client_ps', $info, $expected, $test_counter);
438
439	$expected['rows_skipped_ps'] = $info['rows_skipped_ps'];
440	mysqli_stmt_free_result($stmt);
441
442	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
443		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
444			++$test_counter, gettype($info), $info);
445
446	/* buffered result set - no skipping possible! */
447	mysqli_get_client_stats_assert_eq('rows_skipped_ps', $info, $expected, $test_counter);
448
449	print "Testing unbuffered Prepared Statements... - fetching all\n";
450
451	if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test') ||
452			!mysqli_stmt_execute($stmt))
453		printf("[%03d] prepare/execute failed, [%d] %s\n",
454			++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
455
456	$id = $label = null;
457	if (!mysqli_stmt_bind_result($stmt, $id, $label))
458		printf("[%03d] bind_result failed, [%d] %s\n",
459			++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
460
461	$i = 0;
462	while (mysqli_stmt_fetch($stmt))
463		$i++;
464	assert($num_rows = $i);
465
466	$expected['rows_fetched_from_server_ps'] = (string)($expected['rows_fetched_from_server_ps'] + $num_rows);
467	$expected['rows_fetched_from_client_ps_unbuffered'] = (string)($expected['rows_fetched_from_client_ps_unbuffered'] + $num_rows);
468	$expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
469	$expected['ps_unbuffered_sets'] = (string)($expected['ps_unbuffered_sets'] + 1);
470
471	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
472		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
473			++$test_counter, gettype($info), $info);
474
475	mysqli_get_client_stats_assert_gt('bytes_received_real_data_ps', $info, $expected, $test_counter);
476	$expected['bytes_received_real_data_ps'] = $info['bytes_received_real_data_ps'];
477
478	mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
479	mysqli_get_client_stats_assert_eq('rows_fetched_from_client_ps_unbuffered', $info, $expected, $test_counter);
480	mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
481	mysqli_get_client_stats_assert_eq('ps_unbuffered_sets', $info, $expected, $test_counter);
482	mysqli_get_client_stats_assert_eq('rows_buffered_from_client_ps', $info, $expected, $test_counter);
483
484	mysqli_stmt_free_result($stmt);
485
486	print "Testing unbuffered Prepared Statements... - fetching all but one\n";
487
488	if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test') ||
489			!mysqli_stmt_execute($stmt))
490		printf("[%03d] prepare/execute failed, [%d] %s\n",
491			++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
492
493	$id = $label = null;
494	if (!mysqli_stmt_bind_result($stmt, $id, $label))
495		printf("[%03d] bind_result failed, [%d] %s\n",
496			++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
497
498	for ($i = 0; $i < $num_rows - 1; $i++)
499		mysqli_stmt_fetch($stmt);
500
501	$expected['rows_fetched_from_server_ps'] = (string)($expected['rows_fetched_from_server_ps'] + $num_rows - 1);
502	$expected['rows_fetched_from_client_ps_unbuffered'] = (string)($expected['rows_fetched_from_client_ps_unbuffered'] + $num_rows - 1);
503	$expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
504	$expected['ps_unbuffered_sets'] = (string)($expected['ps_unbuffered_sets'] + 1);
505
506	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
507		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
508			++$test_counter, gettype($info), $info);
509
510	mysqli_get_client_stats_assert_gt('bytes_received_real_data_ps', $info, $expected, $test_counter);
511	$expected['bytes_received_real_data_ps'] = $info['bytes_received_real_data_ps'];
512
513	mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
514	mysqli_get_client_stats_assert_eq('rows_fetched_from_client_ps_unbuffered', $info, $expected, $test_counter);
515	mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
516	mysqli_get_client_stats_assert_eq('ps_unbuffered_sets', $info, $expected, $test_counter);
517	mysqli_get_client_stats_assert_eq('rows_buffered_from_client_ps', $info, $expected, $test_counter);
518
519	mysqli_stmt_free_result($stmt);
520	$expected['rows_skipped_ps'] = (string)($expected['rows_skipped_ps'] + 1);
521	$expected['flushed_ps_sets'] = (string)($expected['flushed_ps_sets'] + 1);
522	$expected['rows_fetched_from_server_ps'] = (string)($expected['rows_fetched_from_server_ps'] + 1);
523
524	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
525		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
526			++$test_counter, gettype($info), $info);
527
528	mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $info, $expected, $test_counter);
529
530	mysqli_get_client_stats_assert_eq('rows_skipped_ps', $info, $expected, $test_counter);
531	mysqli_get_client_stats_assert_eq('flushed_ps_sets', $info, $expected, $test_counter);
532	mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
533
534	/*
535	print "Checking for normal buffered side effects...\n";
536	foreach ($info as $k => $v)
537		if ($info[$k] != $expected[$k])
538			printf("$k - $v != %s\n", $expected[$k]);
539	*/
540	print "... done with fetch statistics\n";
541
542	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
543		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
544			++$test_counter, gettype($info), $info);
545
546	mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $info, $expected, $test_counter);
547	mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $info, $expected, $test_counter);
548
549	//
550	// result_set_queries statistics
551	//
552
553	if (!is_array($info = mysqli_get_client_stats()) || empty($info))
554		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
555			++$test_counter, gettype($info), $info);
556
557	if (!$res = mysqli_query($link, "SELECT id, label FROM test"))
558		printf("[%03d] SELECT failed, [%d] %s\n", ++$test_counter,
559			mysqli_errno($link), mysqli_error($link));
560
561	$rows = 0;
562	while ($row = mysqli_fetch_assoc($res))
563		$rows++;
564
565	if (0 == $rows)
566		printf("[%03d] Expecting at least one result, [%d] %s\n", ++$test_counter,
567			mysqli_errno($link), mysqli_error($link));
568
569	mysqli_free_result($res);
570
571	if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
572		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
573			++$test_counter, gettype($new_info), $new_info);
574
575	mysqli_get_client_stats_assert_eq('result_set_queries', $new_info, (string)($info['result_set_queries'] + 1), $test_counter);
576	$info = $new_info;
577
578	mysqli_get_client_stats_assert_gt('bytes_received_real_data_normal', $info, $expected, $test_counter);
579	$expected['bytes_received_real_data_normal'] = $info['bytes_received_real_data_normal'];
580
581	//
582	// non_result_set_queries - DDL
583	//
584
585	// CREATE TABLE, DROP TABLE
586	if (!mysqli_query($link, "DROP TABLE IF EXISTS non_result_set_queries_test"))
587		printf("[%03d] DROP TABLE failed, [%d] %s\n", ++$test_counter,
588			mysqli_errno($link), mysqli_error($link));
589
590	if (!mysqli_query($link, "CREATE TABLE non_result_set_queries_test(id INT) ENGINE = " . $engine)) {
591		printf("[%03d] CREATE TABLE failed, [%d] %s\n", ++$test_counter,
592			mysqli_errno($link), mysqli_error($link));
593	} else {
594		if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
595			printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
596			++$test_counter, gettype($new_info), $new_info);
597		mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 2), $test_counter, 'CREATE/DROP TABLE');
598	}
599	$info = $new_info;
600
601	// ALERT TABLE
602	if (!mysqli_query($link, "ALTER TABLE non_result_set_queries_test ADD label CHAR(1)")) {
603		printf("[%03d] ALTER TABLE failed, [%d] %s\n", ++$test_counter,
604			mysqli_errno($link), mysqli_error($link));
605	} else {
606		if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
607			printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
608				++$test_counter, gettype($new_info), $new_info);
609		mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'ALTER TABLE');
610	}
611	$info = $new_info;
612
613	// CREATE INDEX, DROP INDEX
614	if (!mysqli_query($link, "CREATE INDEX idx_1 ON non_result_set_queries_test(id)")) {
615		printf("[%03d] CREATE INDEX failed, [%d] %s\n", ++$test_counter,
616			mysqli_errno($link), mysqli_error($link));
617	} else {
618
619		if (!mysqli_query($link, "DROP INDEX idx_1 ON non_result_set_queries_test"))
620			printf("[%03d] DROP INDEX failed, [%d] %s\n", ++$test_counter,
621				mysqli_errno($link), mysqli_error($link));
622
623		if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
624			printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
625				++$test_counter, gettype($new_info), $new_info);
626		mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 2), $test_counter, 'DROP INDEX');
627	}
628	$info = $new_info;
629
630	// RENAME TABLE
631	if (!mysqli_query($link, "DROP TABLE IF EXISTS client_stats_test"))
632		printf("[%03d] Cleanup, DROP TABLE client_stats_test failed, [%d] %s\n", ++$test_counter,
633			mysqli_errno($link), mysqli_error($link));
634
635	if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
636		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
637			++$test_counter, gettype($new_info), $new_info);
638	$info = $new_info;
639
640	if (!mysqli_query($link, "RENAME TABLE non_result_set_queries_test TO client_stats_test")) {
641		printf("[%03d] RENAME TABLE failed, [%d] %s\n", ++$test_counter,
642			mysqli_errno($link), mysqli_error($link));
643
644	} else {
645		if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
646			printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
647				++$test_counter, gettype($new_info), $new_info);
648		mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'RENAME TABLE');
649
650	}
651	$info = $new_info;
652
653	if (!mysqli_query($link, "DROP TABLE IF EXISTS non_result_set_queries_test"))
654		printf("[%03d] Cleanup, DROP TABLE failed, [%d] %s\n", ++$test_counter,
655			mysqli_errno($link), mysqli_error($link));
656
657	if (!mysqli_query($link, "DROP TABLE IF EXISTS client_stats_test"))
658		printf("[%03d] Cleanup, DROP TABLE failed, [%d] %s\n", ++$test_counter,
659			mysqli_errno($link), mysqli_error($link));
660
661	// Let's see if we have privileges for CREATE DATABASE
662	mysqli_query($link, "DROP DATABASE IF EXISTS mysqli_get_client_stats");
663	if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
664		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
665			++$test_counter, gettype($new_info), $new_info);
666	$info = $new_info;
667
668
669	// CREATE, ALTER, RENAME, DROP DATABASE
670	if (mysqli_query($link, "CREATE DATABASE mysqli_get_client_stats")) {
671
672		if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
673			printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
674				++$test_counter, gettype($new_info), $new_info);
675		mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'CREATE DATABASE');
676		$info = $new_info;
677
678		if (!mysqli_query($link, "ALTER DATABASE DEFAULT CHARACTER SET latin1"))
679			printf("[%03d] ALTER DATABASE failed, [%d] %s\n", ++$test_counter,
680				mysqli_errno($link), mysqli_error($link));
681
682		if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
683			printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
684				++$test_counter, gettype($new_info), $new_info);
685		mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'CREATE DATABASE');
686		$info = $new_info;
687
688		if (mysqli_get_server_version($link) > 51700) {
689			if (!mysqli_query($link, "RENAME DATABASE mysqli_get_client_stats TO mysqli_get_client_stats_"))
690				printf("[%03d] RENAME DATABASE failed, [%d] %s\n", ++$test_counter,
691					mysqli_errno($link), mysqli_error($link));
692
693			if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
694				printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
695					++$test_counter, gettype($new_info), $new_info);
696			mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'CREATE DATABASE');
697			$info = $new_info;
698		} else {
699			if (!mysqli_query($link, "CREATE DATABASE mysqli_get_client_stats_"))
700				printf("[%03d] CREATE DATABASE failed, [%d] %s\n", ++$test_counter,
701					mysqli_errno($link), mysqli_error($link));
702			if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
703				printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
704					++$test_counter, gettype($new_info), $new_info);
705			$info = $new_info;
706		}
707
708		if (!mysqli_query($link, "DROP DATABASE mysqli_get_client_stats_"))
709			printf("[%03d] DROP DATABASE failed, [%d] %s\n", ++$test_counter,
710				mysqli_errno($link), mysqli_error($link));
711
712		if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
713			printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
714				++$test_counter, gettype($new_info), $new_info);
715		mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'DROP DATABASE');
716		$info = $new_info;
717	}
718
719	// CREATE SERVER, ALTER SERVER, DROP SERVER
720	// We don't really try to use federated, we just want to see if the syntax works
721	mysqli_query($link, "DROP SERVER IF EXISTS myself");
722
723	if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
724		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
725			++$test_counter, gettype($new_info), $new_info);
726	$info = $new_info;
727
728	$sql = sprintf("CREATE SERVER myself FOREIGN DATA WRAPPER mysql OPTIONS (user '%s', password '%s', database '%s')",
729		$user, $passwd, $db);
730	if (mysqli_query($link, $sql)) {
731		// server knows about it
732
733		if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
734			printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
735				++$test_counter, gettype($new_info), $new_info);
736
737		mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'CREATE SERVER');
738		$info = $new_info;
739
740		if (!mysqli_query($link, sprintf("ALTER SERVER myself OPTIONS(user '%s_')", $user)))
741			printf("[%03d] ALTER SERVER failed, [%d] %s\n", ++$test_counter,
742				mysqli_errno($link), mysqli_error($link));
743
744		if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
745			printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
746				++$test_counter, gettype($new_info), $new_info);
747		mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'ALTER SERVER');
748		$info = $new_info;
749
750		if (!mysqli_query($link, "DROP SERVER myself"))
751			printf("[%03d] DROP SERVER failed, [%d] %s\n", ++$test_counter,
752				mysqli_errno($link), mysqli_error($link));
753
754		if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
755			printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
756				++$test_counter, gettype($new_info), $new_info);
757		mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'DROP SERVER');
758		$info = $new_info;
759	}
760
761	mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $info, $expected, $test_counter);
762	mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $info, $expected, $test_counter);
763
764	/*
765	We don't test the NDB ones.
766	13.1. Data Definition Statements
767	13.1.3. ALTER LOGFILE GROUP Syntax
768	13.1.4. ALTER TABLESPACE Syntax
769	13.1.9. CREATE LOGFILE GROUP Syntax
770	13.1.10. CREATE TABLESPACE Syntax
771	13.1.15. DROP LOGFILE GROUP Syntax
772	13.1.16. DROP TABLESPACE Syntax
773	*/
774
775	//
776	// DML
777	//
778	if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
779		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
780				++$test_counter, gettype($new_info), $new_info);
781	$info = $new_info;
782
783	if (!mysqli_query($link, "INSERT INTO test(id) VALUES (100)"))
784		printf("[%03d] INSERT failed, [%d] %s\n", ++$test_counter,
785			mysqli_errno($link), mysqli_error($link));
786
787	if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
788		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
789			++$test_counter, gettype($new_info), $new_info);
790	mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'INSERT');
791	$info = $new_info;
792
793	if (!mysqli_query($link, "UPDATE test SET label ='z' WHERE id = 100"))
794		printf("[%03d] UPDATE failed, [%d] %s\n", ++$test_counter,
795			mysqli_errno($link), mysqli_error($link));
796
797	if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
798		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
799			++$test_counter, gettype($new_info), $new_info);
800	mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'UPDATE');
801	$info = $new_info;
802
803	if (!mysqli_query($link, "REPLACE INTO test(id, label) VALUES (100, 'b')"))
804		printf("[%03d] INSERT failed, [%d] %s\n", ++$test_counter,
805			mysqli_errno($link), mysqli_error($link));
806
807	if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
808		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
809			++$test_counter, gettype($new_info), $new_info);
810	mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'REPLACE');
811	$info = $new_info;
812
813	// NOTE: this will NOT update dbl_ddls counter
814	if (!$res = mysqli_query($link, "SELECT id, label FROM test WHERE id = 100"))
815		printf("[%03d] SELECT@dml failed, [%d] %s\n", ++$test_counter,
816			mysqli_errno($link), mysqli_error($link));
817	mysqli_free_result($res);
818
819	if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
820		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
821			++$test_counter, gettype($new_info), $new_info);
822	mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, $info, $test_counter, 'SELECT@dml');
823	$info = $new_info;
824
825	if (!mysqli_query($link, "DELETE FROM test WHERE id = 100"))
826		printf("[%03d] DELETE failed, [%d] %s\n", ++$test_counter,
827			mysqli_errno($link), mysqli_error($link));
828
829	if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
830		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
831			++$test_counter, gettype($new_info), $new_info);
832	mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'DELETE');
833	$info = $new_info;
834
835	if (!$res = mysqli_query($link, "TRUNCATE TABLE test"))
836		printf("[%03d] TRUNCATE failed, [%d] %s\n", ++$test_counter,
837			mysqli_errno($link), mysqli_error($link));
838
839	if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
840		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
841			++$test_counter, gettype($new_info), $new_info);
842	mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'TRUNCATE');
843	$info = $new_info;
844
845
846	$file = tempnam(sys_get_temp_dir(), 'mysqli_test');
847	if ($fp = fopen($file, 'w')) {
848		@fwrite($fp, '1;"a"');
849		fclose($fp);
850		chmod($file, 0644);
851		$sql = sprintf('LOAD DATA LOCAL INFILE "%s" INTO TABLE test', mysqli_real_escape_string($link, $file));
852		if (mysqli_query($link, $sql)) {
853			if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
854				printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
855					++$test_counter, gettype($new_info), $new_info);
856			mysqli_get_client_stats_assert_eq('non_result_set_queries', $new_info, (string)($info['non_result_set_queries'] + 1), $test_counter, 'LOAD DATA LOCAL');
857			$info = $new_info;
858		}
859		unlink($file);
860	}
861
862	mysqli_get_client_stats_assert_eq('bytes_received_real_data_normal', $info, $expected, $test_counter);
863	mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $info, $expected, $test_counter);
864
865	/*
866	We skip those:
867	13.2. Data Manipulation Statements
868	13.2.2. DO Syntax
869	13.2.3. HANDLER Syntax
870	13.2.5. LOAD DATA INFILE Syntax
871	*/
872	mysqli_query($link, "DELETE FROM test");
873	if (!mysqli_query($link, "INSERT INTO test(id, label) VALUES (1, 'a'), (2, 'b')"))
874		printf("[%03d] Cannot insert new records, [%d] %s\n", ++$test_counter,
875			mysqli_errno($link), mysqli_error($link));
876
877	if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id"))
878		printf("[%03d] Cannot SELECT with mysqli_real_query(), [%d] %s\n", ++$test_counter,
879			mysqli_errno($link), mysqli_error($link));
880
881	if (!is_object($res = mysqli_use_result($link)))
882		printf("[%03d] mysqli_use_result() failed, [%d] %s\n", ++$test_counter,
883			mysqli_errno($link), mysqli_error($link));
884
885	while ($row = mysqli_fetch_assoc($res))
886		;
887	mysqli_free_result($res);
888	if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
889		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
890			++$test_counter, gettype($new_info), $new_info);
891	mysqli_get_client_stats_assert_eq('unbuffered_sets', $new_info, (string)($info['unbuffered_sets'] + 1), $test_counter, 'mysqli_use_result()');
892	$info = $new_info;
893
894	if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id"))
895		printf("[%03d] Cannot SELECT with mysqli_real_query() II, [%d] %s\n", ++$test_counter,
896			mysqli_errno($link), mysqli_error($link));
897
898	if (!is_object($res = mysqli_store_result($link)))
899		printf("[%03d] mysqli_use_result() failed, [%d] %s\n", ++$test_counter,
900			mysqli_errno($link), mysqli_error($link));
901
902	while ($row = mysqli_fetch_assoc($res))
903		;
904	mysqli_free_result($res);
905	if (!is_array($new_info = mysqli_get_client_stats()) || empty($new_info))
906		printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
907			++$test_counter, gettype($new_info), $new_info);
908	mysqli_get_client_stats_assert_eq('buffered_sets', $new_info, (string)($info['buffered_sets'] + 1), $test_counter, 'mysqli_use_result()');
909	$info = $new_info;
910
911	mysqli_close($link);
912
913	mysqli_get_client_stats_assert_gt('bytes_received_real_data_normal', $info, $expected, $test_counter);
914	$expected['bytes_received_real_data_normal'] = $info['bytes_received_real_data_normal'];
915	mysqli_get_client_stats_assert_eq('bytes_received_real_data_ps', $info, $expected, $test_counter);
916
917	/*
918	no_index_used
919	bad_index_used
920	flushed_normal_sets
921	flushed_ps_sets
922	explicit_close
923	implicit_close
924	disconnect_close
925	in_middle_of_command_close
926	explicit_free_result
927	implicit_free_result
928	explicit_stmt_close
929	implicit_stmt_close
930	*/
931
932	print "done!";
933?>
934--CLEAN--
935<?php
936require_once("connect.inc");
937if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
938   printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
939
940if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
941	printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
942
943if (!mysqli_query($link, "DROP TABLE IF EXISTS non_result_set_queries_test"))
944	printf("[c003] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
945
946if (!mysqli_query($link, "DROP TABLE IF EXISTS client_stats_test"))
947	printf("[c004] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
948
949if (!mysqli_query($link, "DROP DATABASE IF EXISTS mysqli_get_client_stats_"))
950	printf("[c005] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
951
952if (!mysqli_query($link, "DROP DATABASE IF EXISTS mysqli_get_client_stats"))
953	printf("[c006] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
954
955if (!mysqli_query($link, "DROP SERVER IF EXISTS myself"))
956	printf("[c007] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
957
958mysqli_close($link);
959?>
960--EXPECTF--
961array(163) {
962  [%u|b%"bytes_sent"]=>
963  %unicode|string%(1) "0"
964  [%u|b%"bytes_received"]=>
965  %unicode|string%(1) "0"
966  [%u|b%"packets_sent"]=>
967  %unicode|string%(1) "0"
968  [%u|b%"packets_received"]=>
969  %unicode|string%(1) "0"
970  [%u|b%"protocol_overhead_in"]=>
971  %unicode|string%(1) "0"
972  [%u|b%"protocol_overhead_out"]=>
973  %unicode|string%(1) "0"
974  [%u|b%"bytes_received_ok_packet"]=>
975  %unicode|string%(1) "0"
976  [%u|b%"bytes_received_eof_packet"]=>
977  %unicode|string%(1) "0"
978  [%u|b%"bytes_received_rset_header_packet"]=>
979  %unicode|string%(1) "0"
980  [%u|b%"bytes_received_rset_field_meta_packet"]=>
981  %unicode|string%(1) "0"
982  [%u|b%"bytes_received_rset_row_packet"]=>
983  %unicode|string%(1) "0"
984  [%u|b%"bytes_received_prepare_response_packet"]=>
985  %unicode|string%(1) "0"
986  [%u|b%"bytes_received_change_user_packet"]=>
987  %unicode|string%(1) "0"
988  [%u|b%"packets_sent_command"]=>
989  %unicode|string%(1) "0"
990  [%u|b%"packets_received_ok"]=>
991  %unicode|string%(1) "0"
992  [%u|b%"packets_received_eof"]=>
993  %unicode|string%(1) "0"
994  [%u|b%"packets_received_rset_header"]=>
995  %unicode|string%(1) "0"
996  [%u|b%"packets_received_rset_field_meta"]=>
997  %unicode|string%(1) "0"
998  [%u|b%"packets_received_rset_row"]=>
999  %unicode|string%(1) "0"
1000  [%u|b%"packets_received_prepare_response"]=>
1001  %unicode|string%(1) "0"
1002  [%u|b%"packets_received_change_user"]=>
1003  %unicode|string%(1) "0"
1004  [%u|b%"result_set_queries"]=>
1005  %unicode|string%(1) "0"
1006  [%u|b%"non_result_set_queries"]=>
1007  %unicode|string%(1) "0"
1008  [%u|b%"no_index_used"]=>
1009  %unicode|string%(1) "0"
1010  [%u|b%"bad_index_used"]=>
1011  %unicode|string%(1) "0"
1012  [%u|b%"slow_queries"]=>
1013  %unicode|string%(1) "0"
1014  [%u|b%"buffered_sets"]=>
1015  %unicode|string%(1) "0"
1016  [%u|b%"unbuffered_sets"]=>
1017  %unicode|string%(1) "0"
1018  [%u|b%"ps_buffered_sets"]=>
1019  %unicode|string%(1) "0"
1020  [%u|b%"ps_unbuffered_sets"]=>
1021  %unicode|string%(1) "0"
1022  [%u|b%"flushed_normal_sets"]=>
1023  %unicode|string%(1) "0"
1024  [%u|b%"flushed_ps_sets"]=>
1025  %unicode|string%(1) "0"
1026  [%u|b%"ps_prepared_never_executed"]=>
1027  %unicode|string%(1) "0"
1028  [%u|b%"ps_prepared_once_executed"]=>
1029  %unicode|string%(1) "0"
1030  [%u|b%"rows_fetched_from_server_normal"]=>
1031  %unicode|string%(1) "0"
1032  [%u|b%"rows_fetched_from_server_ps"]=>
1033  %unicode|string%(1) "0"
1034  [%u|b%"rows_buffered_from_client_normal"]=>
1035  %unicode|string%(1) "0"
1036  [%u|b%"rows_buffered_from_client_ps"]=>
1037  %unicode|string%(1) "0"
1038  [%u|b%"rows_fetched_from_client_normal_buffered"]=>
1039  %unicode|string%(1) "0"
1040  [%u|b%"rows_fetched_from_client_normal_unbuffered"]=>
1041  %unicode|string%(1) "0"
1042  [%u|b%"rows_fetched_from_client_ps_buffered"]=>
1043  %unicode|string%(1) "0"
1044  [%u|b%"rows_fetched_from_client_ps_unbuffered"]=>
1045  %unicode|string%(1) "0"
1046  [%u|b%"rows_fetched_from_client_ps_cursor"]=>
1047  %unicode|string%(1) "0"
1048  [%u|b%"rows_affected_normal"]=>
1049  %unicode|string%(1) "0"
1050  [%u|b%"rows_affected_ps"]=>
1051  %unicode|string%(1) "0"
1052  [%u|b%"rows_skipped_normal"]=>
1053  %unicode|string%(1) "0"
1054  [%u|b%"rows_skipped_ps"]=>
1055  %unicode|string%(1) "0"
1056  [%u|b%"copy_on_write_saved"]=>
1057  %unicode|string%(1) "0"
1058  [%u|b%"copy_on_write_performed"]=>
1059  %unicode|string%(1) "0"
1060  [%u|b%"command_buffer_too_small"]=>
1061  %unicode|string%(1) "0"
1062  [%u|b%"connect_success"]=>
1063  %unicode|string%(1) "0"
1064  [%u|b%"connect_failure"]=>
1065  %unicode|string%(1) "0"
1066  [%u|b%"connection_reused"]=>
1067  %unicode|string%(1) "0"
1068  [%u|b%"reconnect"]=>
1069  %unicode|string%(1) "0"
1070  [%u|b%"pconnect_success"]=>
1071  %unicode|string%(1) "0"
1072  [%u|b%"active_connections"]=>
1073  %unicode|string%(1) "0"
1074  [%u|b%"active_persistent_connections"]=>
1075  %unicode|string%(1) "0"
1076  [%u|b%"explicit_close"]=>
1077  %unicode|string%(1) "0"
1078  [%u|b%"implicit_close"]=>
1079  %unicode|string%(1) "0"
1080  [%u|b%"disconnect_close"]=>
1081  %unicode|string%(1) "0"
1082  [%u|b%"in_middle_of_command_close"]=>
1083  %unicode|string%(1) "0"
1084  [%u|b%"explicit_free_result"]=>
1085  %unicode|string%(1) "0"
1086  [%u|b%"implicit_free_result"]=>
1087  %unicode|string%(1) "0"
1088  [%u|b%"explicit_stmt_close"]=>
1089  %unicode|string%(1) "0"
1090  [%u|b%"implicit_stmt_close"]=>
1091  %unicode|string%(1) "0"
1092  [%u|b%"mem_emalloc_count"]=>
1093  %unicode|string%(1) "0"
1094  [%u|b%"mem_emalloc_amount"]=>
1095  %unicode|string%(1) "0"
1096  [%u|b%"mem_ecalloc_count"]=>
1097  %unicode|string%(1) "0"
1098  [%u|b%"mem_ecalloc_amount"]=>
1099  %unicode|string%(1) "0"
1100  [%u|b%"mem_erealloc_count"]=>
1101  %unicode|string%(1) "0"
1102  [%u|b%"mem_erealloc_amount"]=>
1103  %unicode|string%(1) "0"
1104  [%u|b%"mem_efree_count"]=>
1105  %unicode|string%(1) "0"
1106  [%u|b%"mem_efree_amount"]=>
1107  %unicode|string%(1) "0"
1108  [%u|b%"mem_malloc_count"]=>
1109  %unicode|string%(1) "0"
1110  [%u|b%"mem_malloc_amount"]=>
1111  %unicode|string%(1) "0"
1112  [%u|b%"mem_calloc_count"]=>
1113  %unicode|string%(%d) "%d"
1114  [%u|b%"mem_calloc_amount"]=>
1115  %unicode|string%(%d) "%d"
1116  [%u|b%"mem_realloc_count"]=>
1117  %unicode|string%(1) "0"
1118  [%u|b%"mem_realloc_amount"]=>
1119  %unicode|string%(1) "0"
1120  [%u|b%"mem_free_count"]=>
1121  %unicode|string%(1) "0"
1122  [%u|b%"mem_free_amount"]=>
1123  %unicode|string%(1) "0"
1124  [%u|b%"mem_estrndup_count"]=>
1125  %unicode|string%(1) "0"
1126  [%u|b%"mem_strndup_count"]=>
1127  %unicode|string%(1) "0"
1128  [%u|b%"mem_estrdup_count"]=>
1129  %unicode|string%(1) "0"
1130  [%u|b%"mem_strdup_count"]=>
1131  %unicode|string%(1) "0"
1132  [%u|b%"mem_edupl_count"]=>
1133  %unicode|string%(1) "0"
1134  [%u|b%"mem_dupl_count"]=>
1135  %unicode|string%(1) "0"
1136  [%u|b%"proto_text_fetched_null"]=>
1137  %unicode|string%(1) "0"
1138  [%u|b%"proto_text_fetched_bit"]=>
1139  %unicode|string%(1) "0"
1140  [%u|b%"proto_text_fetched_tinyint"]=>
1141  %unicode|string%(1) "0"
1142  [%u|b%"proto_text_fetched_short"]=>
1143  %unicode|string%(1) "0"
1144  [%u|b%"proto_text_fetched_int24"]=>
1145  %unicode|string%(1) "0"
1146  [%u|b%"proto_text_fetched_int"]=>
1147  %unicode|string%(1) "0"
1148  [%u|b%"proto_text_fetched_bigint"]=>
1149  %unicode|string%(1) "0"
1150  [%u|b%"proto_text_fetched_decimal"]=>
1151  %unicode|string%(1) "0"
1152  [%u|b%"proto_text_fetched_float"]=>
1153  %unicode|string%(1) "0"
1154  [%u|b%"proto_text_fetched_double"]=>
1155  %unicode|string%(1) "0"
1156  [%u|b%"proto_text_fetched_date"]=>
1157  %unicode|string%(1) "0"
1158  [%u|b%"proto_text_fetched_year"]=>
1159  %unicode|string%(1) "0"
1160  [%u|b%"proto_text_fetched_time"]=>
1161  %unicode|string%(1) "0"
1162  [%u|b%"proto_text_fetched_datetime"]=>
1163  %unicode|string%(1) "0"
1164  [%u|b%"proto_text_fetched_timestamp"]=>
1165  %unicode|string%(1) "0"
1166  [%u|b%"proto_text_fetched_string"]=>
1167  %unicode|string%(1) "0"
1168  [%u|b%"proto_text_fetched_blob"]=>
1169  %unicode|string%(1) "0"
1170  [%u|b%"proto_text_fetched_enum"]=>
1171  %unicode|string%(1) "0"
1172  [%u|b%"proto_text_fetched_set"]=>
1173  %unicode|string%(1) "0"
1174  [%u|b%"proto_text_fetched_geometry"]=>
1175  %unicode|string%(1) "0"
1176  [%u|b%"proto_text_fetched_other"]=>
1177  %unicode|string%(1) "0"
1178  [%u|b%"proto_binary_fetched_null"]=>
1179  %unicode|string%(1) "0"
1180  [%u|b%"proto_binary_fetched_bit"]=>
1181  %unicode|string%(1) "0"
1182  [%u|b%"proto_binary_fetched_tinyint"]=>
1183  %unicode|string%(1) "0"
1184  [%u|b%"proto_binary_fetched_short"]=>
1185  %unicode|string%(1) "0"
1186  [%u|b%"proto_binary_fetched_int24"]=>
1187  %unicode|string%(1) "0"
1188  [%u|b%"proto_binary_fetched_int"]=>
1189  %unicode|string%(1) "0"
1190  [%u|b%"proto_binary_fetched_bigint"]=>
1191  %unicode|string%(1) "0"
1192  [%u|b%"proto_binary_fetched_decimal"]=>
1193  %unicode|string%(1) "0"
1194  [%u|b%"proto_binary_fetched_float"]=>
1195  %unicode|string%(1) "0"
1196  [%u|b%"proto_binary_fetched_double"]=>
1197  %unicode|string%(1) "0"
1198  [%u|b%"proto_binary_fetched_date"]=>
1199  %unicode|string%(1) "0"
1200  [%u|b%"proto_binary_fetched_year"]=>
1201  %unicode|string%(1) "0"
1202  [%u|b%"proto_binary_fetched_time"]=>
1203  %unicode|string%(1) "0"
1204  [%u|b%"proto_binary_fetched_datetime"]=>
1205  %unicode|string%(1) "0"
1206  [%u|b%"proto_binary_fetched_timestamp"]=>
1207  %unicode|string%(1) "0"
1208  [%u|b%"proto_binary_fetched_string"]=>
1209  %unicode|string%(1) "0"
1210  [%u|b%"proto_binary_fetched_json"]=>
1211  %unicode|string%(1) "0"
1212  [%u|b%"proto_binary_fetched_blob"]=>
1213  %unicode|string%(1) "0"
1214  [%u|b%"proto_binary_fetched_enum"]=>
1215  %unicode|string%(1) "0"
1216  [%u|b%"proto_binary_fetched_set"]=>
1217  %unicode|string%(1) "0"
1218  [%u|b%"proto_binary_fetched_geometry"]=>
1219  %unicode|string%(1) "0"
1220  [%u|b%"proto_binary_fetched_other"]=>
1221  %unicode|string%(1) "0"
1222  [%u|b%"init_command_executed_count"]=>
1223  %unicode|string%(1) "0"
1224  [%u|b%"init_command_failed_count"]=>
1225  %unicode|string%(1) "0"
1226  [%u|b%"com_quit"]=>
1227  %unicode|string%(1) "0"
1228  [%u|b%"com_init_db"]=>
1229  %unicode|string%(1) "0"
1230  [%u|b%"com_query"]=>
1231  %unicode|string%(1) "0"
1232  [%u|b%"com_field_list"]=>
1233  %unicode|string%(1) "0"
1234  [%u|b%"com_create_db"]=>
1235  %unicode|string%(1) "0"
1236  [%u|b%"com_drop_db"]=>
1237  %unicode|string%(1) "0"
1238  [%u|b%"com_refresh"]=>
1239  %unicode|string%(1) "0"
1240  [%u|b%"com_shutdown"]=>
1241  %unicode|string%(1) "0"
1242  [%u|b%"com_statistics"]=>
1243  %unicode|string%(1) "0"
1244  [%u|b%"com_process_info"]=>
1245  %unicode|string%(1) "0"
1246  [%u|b%"com_connect"]=>
1247  %unicode|string%(1) "0"
1248  [%u|b%"com_process_kill"]=>
1249  %unicode|string%(1) "0"
1250  [%u|b%"com_debug"]=>
1251  %unicode|string%(1) "0"
1252  [%u|b%"com_ping"]=>
1253  %unicode|string%(1) "0"
1254  [%u|b%"com_time"]=>
1255  %unicode|string%(1) "0"
1256  [%u|b%"com_delayed_insert"]=>
1257  %unicode|string%(1) "0"
1258  [%u|b%"com_change_user"]=>
1259  %unicode|string%(1) "0"
1260  [%u|b%"com_binlog_dump"]=>
1261  %unicode|string%(1) "0"
1262  [%u|b%"com_table_dump"]=>
1263  %unicode|string%(1) "0"
1264  [%u|b%"com_connect_out"]=>
1265  %unicode|string%(1) "0"
1266  [%u|b%"com_register_slave"]=>
1267  %unicode|string%(1) "0"
1268  [%u|b%"com_stmt_prepare"]=>
1269  %unicode|string%(1) "0"
1270  [%u|b%"com_stmt_execute"]=>
1271  %unicode|string%(1) "0"
1272  [%u|b%"com_stmt_send_long_data"]=>
1273  %unicode|string%(1) "0"
1274  [%u|b%"com_stmt_close"]=>
1275  %unicode|string%(1) "0"
1276  [%u|b%"com_stmt_reset"]=>
1277  %unicode|string%(1) "0"
1278  [%u|b%"com_stmt_set_option"]=>
1279  %unicode|string%(1) "0"
1280  [%u|b%"com_stmt_fetch"]=>
1281  %unicode|string%(1) "0"
1282  [%u|b%"com_deamon"]=>
1283  %unicode|string%(1) "0"
1284  [%u|b%"bytes_received_real_data_normal"]=>
1285  %unicode|string%(1) "0"
1286  [%u|b%"bytes_received_real_data_ps"]=>
1287  %unicode|string%(1) "0"
1288}
1289Testing buffered normal...
1290Testing buffered normal... - SELECT id, label FROM test
1291Testing unbuffered normal...
1292Testing unbuffered normal... - SELECT id, label FROM test, not all fetched
1293Testing if implicit fetching and cleaning happens...
1294Testing buffered Prepared Statements...
1295Testing buffered Prepared Statements... - fetching all
1296Testing buffered Prepared Statements... - fetching all but one
1297Testing unbuffered Prepared Statements... - fetching all
1298Testing unbuffered Prepared Statements... - fetching all but one
1299... done with fetch statistics
1300done!
1301