1--TEST--
2Persistent connections and mysqli.max_links
3--SKIPIF--
4<?php
5    require_once('skipif.inc');
6    require_once('skipifconnectfailure.inc');
7    require_once('table.inc');
8
9    mysqli_query($link, 'DROP USER pcontest');
10    mysqli_query($link, 'DROP USER pcontest@localhost');
11
12    if (!mysqli_query($link, 'CREATE USER pcontest@"%" IDENTIFIED BY "pcontest"') ||
13        !mysqli_query($link, 'CREATE USER pcontest@localhost IDENTIFIED BY "pcontest"')) {
14        printf("skip Cannot create second DB user [%d] %s", mysqli_errno($link), mysqli_error($link));
15        mysqli_close($link);
16        die("skip CREATE USER failed");
17    }
18
19    // we might be able to specify the host using CURRENT_USER(), but...
20    if (!mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pcontest@'%%'", $db)) ||
21        !mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pcontest@'localhost'", $db))) {
22        printf("skip Cannot GRANT SELECT to second DB user [%d] %s", mysqli_errno($link), mysqli_error($link));
23        mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest');
24        mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest@localhost');
25        mysqli_query($link, 'DROP USER pcontest@localhost');
26        mysqli_query($link, 'DROP USER pcontest');
27        mysqli_close($link);
28        die("skip GRANT failed");
29    }
30
31    if (!($link_pcontest = @my_mysqli_connect($host, 'pcontest', 'pcontest', $db, $port, $socket))) {
32        mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest');
33        mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest@localhost');
34        mysqli_query($link, 'DROP USER pcontest@localhost');
35        mysqli_query($link, 'DROP USER pcontest');
36        mysqli_close($link);
37        die("skip CONNECT using new user failed");
38    }
39    mysqli_close($link);
40?>
41--INI--
42mysqli.allow_persistent=1
43mysqli.max_persistent=2
44mysqli.rollback_on_cached_plink=1
45--FILE--
46<?php
47    require_once("connect.inc");
48    require_once('table.inc');
49
50
51    if (!mysqli_query($link, 'DROP USER pcontest') ||
52        !mysqli_query($link, 'DROP USER pcontest@localhost') ||
53        !mysqli_query($link, 'CREATE USER pcontest@"%" IDENTIFIED BY "pcontest"') ||
54        !mysqli_query($link, 'CREATE USER pcontest@localhost IDENTIFIED BY "pcontest"') ||
55        !mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pcontest@'%%'", $db)) ||
56        !mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pcontest@'localhost'", $db))) {
57        printf("[000] Init failed, [%d] %s\n",
58            mysqli_errno($plink), mysqli_error($plink));
59    }
60
61    try {
62        mysqli_get_links_stats(1);
63    } catch (ArgumentCountError $exception) {
64        echo $exception->getMessage() . "\n";
65    }
66
67    echo "Before pconnect:";
68    var_dump(mysqli_get_links_stats());
69
70    if (!$plink = my_mysqli_connect('p:' . $host, 'pcontest', 'pcontest', $db, $port, $socket))
71        printf("[001] Cannot connect using the second DB user created during SKIPIF, [%d] %s\n",
72            mysqli_connect_errno(), mysqli_connect_error());
73
74    echo "After pconnect:";
75    var_dump(mysqli_get_links_stats());
76
77    ob_start();
78    phpinfo();
79    $phpinfo = strip_tags(ob_get_contents());
80    ob_end_clean();
81
82    $phpinfo = substr($phpinfo, strpos($phpinfo, 'MysqlI Support => enabled'), 500);
83    if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches))
84        printf("[002] Cannot get # active persistent links from phpinfo()\n");
85    $num_plinks = $matches[1];
86
87    if (!$res = mysqli_query($plink, 'SELECT id, label FROM test WHERE id = 1'))
88        printf("[003] Cannot run query on persistent connection of second DB user, [%d] %s\n",
89            mysqli_errno($plink), mysqli_error($plink));
90
91    if (!$row = mysqli_fetch_assoc($res))
92        printf("[004] Cannot run fetch result, [%d] %s\n",
93            mysqli_errno($plink), mysqli_error($plink));
94    mysqli_free_result($res);
95    var_dump($row);
96
97    // change the password for the second DB user and kill the persistent connection
98    if ((!mysqli_query($link, 'SET PASSWORD FOR pcontest = "newpass"') &&
99            !mysqli_query($link, 'SET PASSWORD FOR pcontest = PASSWORD("newpass")'))||
100            !mysqli_query($link, 'FLUSH PRIVILEGES'))
101        printf("[005] Cannot change PW of second DB user, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
102
103        // change the password for the second DB user and kill the persistent connection
104    if ((!mysqli_query($link, 'SET PASSWORD FOR pcontest@localhost = "newpass"') &&
105        !mysqli_query($link, 'SET PASSWORD FOR pcontest@localhost = PASSWORD("newpass")')) ||
106            !mysqli_query($link, 'FLUSH PRIVILEGES'))
107        printf("[006] Cannot change PW of second DB user, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
108
109    // persistent connections cannot be closed but only be killed
110    $pthread_id = mysqli_thread_id($plink);
111    if (!mysqli_query($link, sprintf('KILL %d', $pthread_id)))
112        printf("[007] Cannot KILL persistent connection of second DB user, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
113    // give the server a second to really kill the thread
114    sleep(1);
115
116    if (!$res = mysqli_query($link, "SHOW FULL PROCESSLIST"))
117        printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
118
119    $running_threads = array();
120    while ($row = mysqli_fetch_assoc($res))
121        $running_threads[$row['Id']] = $row;
122    mysqli_free_result($res);
123
124    if (isset($running_threads[$pthread_id]))
125        printf("[009] Persistent connection has not been killed\n");
126
127    echo "Before second pconnect:";
128    var_dump(mysqli_get_links_stats());
129
130    // this fails and we have 0 (<= $num_plinks) connections
131    if ($plink = @my_mysqli_connect('p:' . $host, 'pcontest', 'pcontest', $db, $port, $socket))
132        printf("[010] Can connect using the old password, [%d] %s\n",
133            mysqli_connect_errno($link), mysqli_connect_error($link));
134
135    echo "After second pconnect:";
136    var_dump(mysqli_get_links_stats());
137
138    ob_start();
139    phpinfo();
140    $phpinfo = strip_tags(ob_get_contents());
141    ob_end_clean();
142    $phpinfo = substr($phpinfo, stripos($phpinfo, 'MysqlI Support => enabled'), 500);
143    if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches))
144        printf("[010] Cannot get # of active persistent links from phpinfo()\n");
145
146    var_dump(mysqli_get_links_stats());
147
148    $num_plinks_kill = $matches[1];
149    $sstats = mysqli_get_links_stats();
150    if ($sstats['active_plinks'] != $num_plinks_kill) {
151        printf("[010.2] Num of active plinks differ %s %s\n", $sstats['active_plinks'], $num_plinks_kill);
152    }
153    if ($num_plinks_kill > $num_plinks)
154        printf("[011] Expecting Active Persistent Links < %d, got %d\n", $num_plinks, $num_plinks_kill);
155
156    if (!$plink = my_mysqli_connect('p:' . $host, 'pcontest', 'newpass', $db, $port, $socket))
157        printf("[012] Cannot connect using the new password, [%d] %s\n",
158            mysqli_connect_errno(), mysqli_connect_error());
159
160    if (!$res = mysqli_query($plink, 'SELECT id, label FROM test WHERE id = 1'))
161        printf("[013] Cannot run query on persistent connection of second DB user, [%d] %s\n",
162            mysqli_errno($plink), mysqli_error($plink));
163
164    if (!$row = mysqli_fetch_assoc($res))
165        printf("[014] Cannot run fetch result, [%d] %s\n",
166            mysqli_errno($plink), mysqli_error($plink));
167    mysqli_free_result($res);
168    var_dump($row);
169
170    if ($plink2 = my_mysqli_connect('p:' . $host, 'pcontest', 'newpass', $db, $port, $socket)) {
171        printf("[015] Can open more persistent connections than allowed, [%d] %s\n",
172            mysqli_connect_errno(), mysqli_connect_error());
173        var_dump(mysqli_get_links_stats());
174    }
175
176    ob_start();
177    phpinfo();
178    $phpinfo = strip_tags(ob_get_contents());
179    ob_end_clean();
180    $phpinfo = substr($phpinfo, stripos($phpinfo, 'MysqlI Support => enabled'), 500);
181    if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches))
182        printf("[016] Cannot get # of active persistent links from phpinfo()\n");
183
184    $num_plinks = $matches[1];
185    if ($num_plinks > (int)ini_get('mysqli.max_persistent'))
186        printf("[017] mysqli.max_persistent=%d allows %d open connections!\n", ini_get('mysqli.max_persistent'),$num_plinks);
187
188    mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest');
189    mysqli_query($link, 'DROP USER pcontest');
190    mysqli_close($link);
191    print "done!";
192?>
193--CLEAN--
194<?php
195require_once("connect.inc");
196if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
197   printf("[c001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
198
199if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
200	printf("[c002] Cannot drop table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
201
202mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest');
203mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest@localhost');
204mysqli_query($link, 'DROP USER pcontest@localhost');
205mysqli_query($link, 'DROP USER pcontest');
206
207mysqli_close($link);
208?>
209--EXPECT--
210mysqli_get_links_stats() expects exactly 0 arguments, 1 given
211Before pconnect:array(3) {
212  ["total"]=>
213  int(1)
214  ["active_plinks"]=>
215  int(0)
216  ["cached_plinks"]=>
217  int(0)
218}
219After pconnect:array(3) {
220  ["total"]=>
221  int(2)
222  ["active_plinks"]=>
223  int(1)
224  ["cached_plinks"]=>
225  int(0)
226}
227array(2) {
228  ["id"]=>
229  string(1) "1"
230  ["label"]=>
231  string(1) "a"
232}
233Before second pconnect:array(3) {
234  ["total"]=>
235  int(2)
236  ["active_plinks"]=>
237  int(1)
238  ["cached_plinks"]=>
239  int(0)
240}
241After second pconnect:array(3) {
242  ["total"]=>
243  int(1)
244  ["active_plinks"]=>
245  int(0)
246  ["cached_plinks"]=>
247  int(0)
248}
249array(3) {
250  ["total"]=>
251  int(1)
252  ["active_plinks"]=>
253  int(0)
254  ["cached_plinks"]=>
255  int(0)
256}
257array(2) {
258  ["id"]=>
259  string(1) "1"
260  ["label"]=>
261  string(1) "a"
262}
263[015] Can open more persistent connections than allowed, [0]
264array(3) {
265  ["total"]=>
266  int(3)
267  ["active_plinks"]=>
268  int(2)
269  ["cached_plinks"]=>
270  int(0)
271}
272done!
273