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