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