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