1--TEST--
2mysqli_fetch_array() - large packages (to test compression)
3--SKIPIF--
4<?php
5require_once('skipif.inc');
6require_once('skipifconnectfailure.inc');
7?>
8--INI--
9memory_limit=-1
10--FILE--
11<?php
12	require_once("connect.inc");
13
14	function mysqli_fetch_array_large($offset, $link, $package_size) {
15
16		/* we are aiming for maximum compression to test MYSQLI_CLIENT_COMPRESS */
17		$random_char = str_repeat('a', 255);
18		$sql = "INSERT INTO test(label) VALUES ";
19
20		while (strlen($sql) < ($package_size - 259))
21			$sql .= sprintf("('%s'), ", $random_char);
22
23		$sql = substr($sql, 0, -2);
24		$len = strlen($sql);
25		assert($len < $package_size);
26
27		if (!@mysqli_query($link, $sql)) {
28			if (1153 == mysqli_errno($link) || 2006 == mysqli_errno($link) || stristr(mysqli_error($link), 'max_allowed_packet'))
29				/*
30					myslqnd - [1153] Got a packet bigger than 'max_allowed_packet' bytes
31					libmysql -[2006] MySQL server has gone away
32				*/
33				return false;
34
35			printf("[%03d + 1] len = %d, [%d] %s\n", $offset, $len, mysqli_errno($link), mysqli_error($link));
36			return false;
37		}
38
39		/* buffered result set - let's hope we do not run into PHP memory limit... */
40		if (!$res = mysqli_query($link, "SELECT id, label FROM test")) {
41			printf("[%03d + 2] len = %d, [%d] %s\n", $offset, $len, mysqli_errno($link), mysqli_error($link));
42			return false;
43		}
44
45		while ($row = mysqli_fetch_assoc($res)) {
46			if ($row['label'] != $random_char) {
47				printf("[%03d + 3] Wrong results - expecting '%s' got '%s', len = %d, [%d] %s\n",
48					$offset, $random_char, $row['label'], $len, mysqli_errno($link), mysqli_error($link));
49				return false;
50			}
51		}
52		mysqli_free_result($res);
53
54		if (!$stmt = mysqli_prepare($link, "SELECT id, label FROM test")) {
55			printf("[%03d + 4] len = %d, [%d] %s\n", $offset, $len, mysqli_errno($link), mysqli_error($link));
56			return false;
57		}
58
59		/* unbuffered result set */
60		if (!mysqli_stmt_execute($stmt)) {
61			printf("[%03d + 5] len = %d, [%d] %s, [%d] %s\n", $offset, $len, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt), mysqli_errno($link), mysqli_error($link));
62			return false;
63		}
64
65		$id = $label = NULL;
66		if (!mysqli_stmt_bind_result($stmt, $id, $label)) {
67			printf("[%03d + 6] len = %d, [%d] %s, [%d] %s\n", $offset, $len, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt), mysqli_errno($link), mysqli_error($link));
68			return false;
69		}
70
71		while (mysqli_stmt_fetch($stmt)) {
72			if ($label != $random_char) {
73				printf("[%03d + 7] Wrong results - expecting '%s' got '%s', len = %d, [%d] %s\n",
74					$offset, $random_char, $label, $len, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
75				return false;
76			}
77		}
78
79		mysqli_stmt_free_result($stmt);
80		mysqli_stmt_close($stmt);
81
82		return true;
83	}
84
85	function parse_memory_limit($limit) {
86
87		$val = trim($limit);
88		$last = strtolower($val[strlen($val)-1]);
89
90		switch($last) {
91				// The 'G' modifier is available since PHP 5.1.0
92				case 'g':
93					$val *= 1024;
94				case 'm':
95					$val *= 1024;
96				case 'k':
97					$val *= 1024;
98				default:
99					break;
100    	}
101			return $val;
102	}
103
104
105	function test_fetch($host, $user, $passwd, $db, $port, $socket, $engine, $flags = null) {
106
107		$link = mysqli_init();
108		if (!my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket, $flags)) {
109			printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
110			$host, $user, $db, $port, $socket);
111			return false;
112		}
113
114		if (!mysqli_query($link, "DROP TABLE IF EXISTS test") ||
115			!mysqli_query($link, sprintf("CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, label VARCHAR(255)) ENGINE = %s", $engine))) {
116			printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
117			return false;
118		}
119
120		$package_size = 524288;
121		$offset = 3;
122		$limit = (ini_get('memory_limit') > 0) ? parse_memory_limit(ini_get('memory_limit')) : pow(2, 32);
123
124		/* try to respect php.ini but make run time a soft limit */
125		$max_runtime = (ini_get('max_execution_time') > 0) ? ini_get('max_execution_time') : 30;
126		set_time_limit(0);
127
128		do {
129			if ($package_size > $limit) {
130				printf("stop: memory limit - %s vs. %s\n", $package_size, $limit);
131				break;
132			}
133
134			$start = microtime(true);
135			if (!mysqli_fetch_array_large($offset++, $link, $package_size)) {
136				printf("stop: packet size - %d\n", $package_size);
137				break;
138			}
139
140			$duration = microtime(true) - $start;
141			$max_runtime -= $duration;
142			if ($max_runtime < ($duration * 3)) {
143				/* likely the next iteration will not be within max_execution_time */
144				printf("stop: time limit - %2.2fs\n", $max_runtime);
145				break;
146			}
147
148			$package_size += $package_size;
149
150		} while (true);
151
152
153		mysqli_close($link);
154		return true;
155	}
156
157
158	test_fetch($host, $user, $passwd, $db, $port, $socket, $engine, null);
159	test_fetch($host, $user, $passwd, $db, $port, $socket, $engine, MYSQLI_CLIENT_COMPRESS);
160	print "done!";
161?>
162--CLEAN--
163<?php
164	require_once("clean_table.inc");
165?>
166--EXPECTF--
167stop: %s
168stop: %s
169done!
170