summaryrefslogtreecommitdiff
path: root/ext/mysqli
diff options
context:
space:
mode:
Diffstat (limited to 'ext/mysqli')
-rw-r--r--ext/mysqli/mysqli.c17
-rw-r--r--ext/mysqli/mysqli_api.c38
-rw-r--r--ext/mysqli/mysqli_libmysql.h6
-rw-r--r--ext/mysqli/mysqli_nonapi.c24
-rw-r--r--ext/mysqli/php_mysqli_structs.h3
-rw-r--r--ext/mysqli/tests/mysqli_pconn_conn_multiple.phpt164
-rw-r--r--ext/mysqli/tests/mysqli_pconn_twice.phpt79
7 files changed, 280 insertions, 51 deletions
diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c
index b5867a0efb..f4a98b6745 100644
--- a/ext/mysqli/mysqli.c
+++ b/ext/mysqli/mysqli.c
@@ -228,22 +228,7 @@ static void mysqli_link_free_storage(void *object TSRMLS_DC)
if (my_res && my_res->ptr) {
MY_MYSQL *mysql = (MY_MYSQL *)my_res->ptr;
if (mysql->mysql) {
- if (!mysql->persistent) {
- mysqli_close(mysql->mysql, MYSQLI_CLOSE_IMPLICIT);
- } else {
- zend_rsrc_list_entry *le;
- if (zend_hash_find(&EG(persistent_list), mysql->hash_key, strlen(mysql->hash_key) + 1, (void **)&le) == SUCCESS) {
- if (Z_TYPE_P(le) == php_le_pmysqli()) {
- mysqli_plist_entry *plist = (mysqli_plist_entry *) le->ptr;
-
- zend_ptr_stack_push(&plist->free_links, mysql->mysql);
-
- MyG(num_links)--;
- MyG(num_active_persistent)--;
- MyG(num_inactive_persistent)++;
- }
- }
- }
+ php_mysqli_close(mysql, MYSQLI_CLOSE_EXPLICIT TSRMLS_CC);
}
php_clear_mysql(mysql);
efree(mysql);
diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c
index 07bc303d72..4061d09757 100644
--- a/ext/mysqli/mysqli_api.c
+++ b/ext/mysqli/mysqli_api.c
@@ -552,22 +552,12 @@ PHP_FUNCTION(mysqli_character_set_name)
}
/* }}} */
-/* {{{ proto bool mysqli_close(object link)
- Close connection */
-PHP_FUNCTION(mysqli_close)
-{
- zval *mysql_link;
- MY_MYSQL *mysql;
-
- if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
- return;
- }
-
- MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_INITIALIZED);
+/* {{{ php_mysqli_close */
+void php_mysqli_close(MY_MYSQL * mysql, int close_type TSRMLS_DC)
+{
if (!mysql->persistent) {
- mysqli_close(mysql->mysql, MYSQLI_CLOSE_EXPLICIT);
- mysql->mysql = NULL;
+ mysqli_close(mysql->mysql, close_type);
} else {
zend_rsrc_list_entry *le;
if (zend_hash_find(&EG(persistent_list), mysql->hash_key, strlen(mysql->hash_key) + 1, (void **)&le) == SUCCESS) {
@@ -580,9 +570,29 @@ PHP_FUNCTION(mysqli_close)
MyG(num_inactive_persistent)++;
}
}
+ mysql->persistent = FALSE;
}
+ mysql->mysql = NULL;
php_clear_mysql(mysql);
+}
+/* }}} */
+
+
+/* {{{ proto bool mysqli_close(object link)
+ Close connection */
+PHP_FUNCTION(mysqli_close)
+{
+ zval *mysql_link;
+ MY_MYSQL *mysql;
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
+ return;
+ }
+
+ MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_INITIALIZED);
+
+ php_mysqli_close(mysql, MYSQLI_CLOSE_EXPLICIT TSRMLS_CC);
MYSQLI_CLEAR_RESOURCE(&mysql_link);
efree(mysql);
diff --git a/ext/mysqli/mysqli_libmysql.h b/ext/mysqli/mysqli_libmysql.h
index 1ea1fc3bf4..be82c4b982 100644
--- a/ext/mysqli/mysqli_libmysql.h
+++ b/ext/mysqli/mysqli_libmysql.h
@@ -20,9 +20,9 @@
*/
/* These are unused */
-#define MYSQLI_CLOSE_EXPLICIT
-#define MYSQLI_CLOSE_IMPLICIT
-#define MYSQLI_CLOSE_DISCONNECTED
+#define MYSQLI_CLOSE_EXPLICIT 0
+#define MYSQLI_CLOSE_IMPLICIT 1
+#define MYSQLI_CLOSE_DISCONNECTED 2
#define MYSQLND_OPT_NUMERIC_AND_DATETIME_AS_UNICODE 200
#define MYSQLND_OPT_INT_AND_YEAR_AS_INT 201
diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c
index 187b9bec30..3e0a43e446 100644
--- a/ext/mysqli/mysqli_nonapi.c
+++ b/ext/mysqli/mysqli_nonapi.c
@@ -89,14 +89,7 @@ void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_real_conne
if (object && instanceof_function(Z_OBJCE_P(object), mysqli_link_class_entry TSRMLS_CC)) {
mysqli_resource = ((mysqli_object *) zend_object_store_get_object(object TSRMLS_CC))->ptr;
if (mysqli_resource && mysqli_resource->ptr) {
- mysql = (MY_MYSQL*) mysqli_resource->ptr;
- if (mysqli_resource->status > MYSQLI_STATUS_INITIALIZED) {
- php_clear_mysql(mysql);
- if (mysql->mysql) {
- mysqli_close(mysql->mysql, MYSQLI_CLOSE_EXPLICIT);
- mysql->mysql = NULL;
- }
- }
+ mysql = (MY_MYSQL*) mysqli_resource->ptr;
}
}
if (!mysql) {
@@ -122,7 +115,10 @@ void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_real_conne
flags &= ~CLIENT_LOCAL_FILES;
}
}
-
+ if (mysql->mysql && mysqli_resource && mysqli_resource->status > MYSQLI_STATUS_INITIALIZED) {
+ /* already connected, we should close the connection */
+ php_mysqli_close(mysql, MYSQLI_CLOSE_IMPLICIT TSRMLS_CC);
+ }
if (!socket_len || !socket) {
socket = MyG(default_socket);
@@ -161,15 +157,6 @@ void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_real_conne
do {
if (zend_ptr_stack_num_elements(&plist->free_links)) {
- if (is_real_connect) {
- /*
- Gotcha! If there are some options set on the handle with mysqli_options()
- they will be lost. We will fetch other handle with other options. This could
- be a source of bug reports of people complaining but...nothing else could be
- done, if they want PCONN!
- */
- mysqli_close(mysql->mysql, MYSQLI_CLOSE_IMPLICIT);
- }
mysql->mysql = zend_ptr_stack_pop(&plist->free_links);
MyG(num_inactive_persistent)--;
@@ -298,6 +285,7 @@ err:
if (mysql->hash_key) {
efree(mysql->hash_key);
mysql->hash_key = NULL;
+ mysql->persistent = FALSE;
}
if (!is_real_connect) {
efree(mysql);
diff --git a/ext/mysqli/php_mysqli_structs.h b/ext/mysqli/php_mysqli_structs.h
index 81d1044ce1..821b27b3ee 100644
--- a/ext/mysqli/php_mysqli_structs.h
+++ b/ext/mysqli/php_mysqli_structs.h
@@ -220,6 +220,9 @@ extern zend_class_entry *mysqli_exception_class_entry;
extern int php_le_pmysqli(void);
extern void php_mysqli_dtor_p_elements(void *data);
+extern void php_mysqli_close(MY_MYSQL * mysql, int close_type TSRMLS_DC);
+
+
#ifdef HAVE_SPL
extern PHPAPI zend_class_entry *spl_ce_RuntimeException;
#endif
diff --git a/ext/mysqli/tests/mysqli_pconn_conn_multiple.phpt b/ext/mysqli/tests/mysqli_pconn_conn_multiple.phpt
new file mode 100644
index 0000000000..2c6aae0d3b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_pconn_conn_multiple.phpt
@@ -0,0 +1,164 @@
+--TEST--
+Calling connect() on an open persistent connection to create a new persistent connection
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!$IS_MYSQLND)
+ die("skip mysqlnd test only");
+
+?>
+--INI--
+mysqli.allow_persistent=1
+mysqli.max_persistent=-1
+mysqli.max_links=-1
+--FILE--
+<?php
+ include "connect.inc";
+
+ $phost = 'p:' . $host;
+
+ if (!$link = my_mysqli_connect($phost, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $phost, $user, $db, $port, $socket);
+
+ if (!$thread_id = $link->thread_id)
+ printf("[002] Cannot determine thread id, test will fail, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($tmp = my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)))
+ printf("[003] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_int($new_thread_id = mysqli_thread_id($link)) || ($new_thread_id < 0))
+ printf("[004] Expecting int/any got %s/%s\n", gettype($tmp), $tmp);
+
+ if ($thread_id == $new_thread_id)
+ printf("[005] Expecting new connection and new thread id. Old thread id %d, new thread id %d\n", $thread_id, $new_thread_id);
+
+ if (!($res = mysqli_query($link, "SELECT 'ok' AS it_works")) ||
+ !($row = mysqli_fetch_assoc($res)))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($row);
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ if (!$link = new my_mysqli($phost, $user, $passwd, $db, $port, $socket))
+ printf("[007] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $phost, $user, $db, $port, $socket);
+
+ if (!$thread_id = $link->thread_id)
+ printf("[008] Cannot determine thread id, test will fail, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($tmp = $link->real_connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[009] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_int($new_thread_id = $link->thread_id) || ($new_thread_id < 0))
+ printf("[010] Expecting int/any got %s/%s\n", gettype($tmp), $tmp);
+
+ if ($thread_id == $new_thread_id)
+ printf("[011] Expecting new connection and new thread id. Old thread id %d, new thread id %d\n", $thread_id, $new_thread_id);
+
+ if (!($res = $link->query("SELECT 'works also with oo' AS syntax")) ||
+ !($row = $res->fetch_assoc()))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($row);
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = $link->connect($phost, $user, $passwd, $db, $port, $socket)))
+ printf("[013] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = mysqli_connect($phost, $user, $passwd, $db, $port, $socket))
+ printf("[014] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $phost, $user, $db, $port, $socket);
+
+ if (NULL !== ($tmp = $link->connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[015] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ printf("Flipping phost/host order\n");
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[016] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$thread_id = mysqli_thread_id($link))
+ printf("[017] Cannot determine thread id, test will fail, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($tmp = my_mysqli_real_connect($link, $phost, $user, $passwd, $db, $port, $socket)))
+ printf("[018] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_int($new_thread_id = mysqli_thread_id($link)) || ($new_thread_id < 0))
+ printf("[019] Expecting int/any got %s/%s\n", gettype($tmp), $tmp);
+
+ if ($thread_id == $new_thread_id)
+ printf("[020] Expecting new connection and new thread id. Old thread id %d, new thread id %d\n", $thread_id, $new_thread_id);
+
+ if (!($res = mysqli_query($link, "SELECT 'ok' AS it_works")) ||
+ !($row = mysqli_fetch_assoc($res)))
+ printf("[021] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($row);
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ if (!$link = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[022] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$thread_id = $link->thread_id)
+ printf("[023] Cannot determine thread id, test will fail, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($tmp = $link->real_connect($phost, $user, $passwd, $db, $port, $socket)))
+ printf("[024] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_int($new_thread_id = $link->thread_id) || ($new_thread_id < 0))
+ printf("[025] Expecting int/any got %s/%s\n", gettype($tmp), $tmp);
+
+ if ($thread_id == $new_thread_id)
+ printf("[026] Expecting new connection and new thread id. Old thread id %d, new thread id %d\n", $thread_id, $new_thread_id);
+
+ if (!($res = $link->query("SELECT 'works also with oo' AS syntax")) ||
+ !($row = $res->fetch_assoc()))
+ printf("[027] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($row);
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = $link->connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[028] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[029] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (NULL !== ($tmp = $link->connect($phost, $user, $passwd, $db, $port, $socket)))
+ printf("[030] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+array(1) {
+ [%u|b%"it_works"]=>
+ %unicode|string%(2) "ok"
+}
+array(1) {
+ [%u|b%"syntax"]=>
+ %unicode|string%(18) "works also with oo"
+}
+Flipping phost/host order
+array(1) {
+ [%u|b%"it_works"]=>
+ %unicode|string%(2) "ok"
+}
+array(1) {
+ [%u|b%"syntax"]=>
+ %unicode|string%(18) "works also with oo"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_pconn_twice.phpt b/ext/mysqli/tests/mysqli_pconn_twice.phpt
new file mode 100644
index 0000000000..ddb95e732d
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_pconn_twice.phpt
@@ -0,0 +1,79 @@
+--TEST--
+Calling connect() on an open persistent connection to create a new persistent connection
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!$IS_MYSQLND)
+ die("skip mysqlnd test only");
+
+?>
+--INI--
+mysqli.allow_persistent=1
+mysqli.max_persistent=-1
+mysqli.max_links=-1
+--FILE--
+<?php
+ include "connect.inc";
+
+ $host = 'p:' . $host;
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (true !== ($tmp = my_mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)))
+ printf("[003] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+
+ /* it is undefined which pooled connection we get - thread ids may differ */
+
+ if (!($res = mysqli_query($link, "SELECT 'ok' AS it_works")) ||
+ !($row = mysqli_fetch_assoc($res)))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($row);
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ if (!$link = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ printf("[007] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+
+ if (true !== ($tmp = $link->real_connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[009] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+
+ /* it is undefined which pooled connection we get - thread ids may differ */
+
+ if (!($res = $link->query("SELECT 'works also with oo' AS syntax")) ||
+ !($row = $res->fetch_assoc()))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($row);
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = $link->connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[013] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[014] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (NULL !== ($tmp = $link->connect($host, $user, $passwd, $db, $port, $socket)))
+ printf("[015] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+array(1) {
+ [%u|b%"it_works"]=>
+ %unicode|string%(2) "ok"
+}
+array(1) {
+ [%u|b%"syntax"]=>
+ %unicode|string%(18) "works also with oo"
+}
+done! \ No newline at end of file