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);
}
/* }}} */
-/* {{{ 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) {
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);
*/
/* 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
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) {
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);
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)--;
if (mysql->hash_key) {
efree(mysql->hash_key);
mysql->hash_key = NULL;
+ mysql->persistent = FALSE;
}
if (!is_real_connect) {
efree(mysql);
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
--- /dev/null
+--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
--- /dev/null
+--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
conn->thread_id = greet_packet.thread_id;
conn->protocol_version = greet_packet.protocol_version;
- conn->server_version = greet_packet.server_version;
- greet_packet.server_version = NULL; /* The string will be freed otherwise */
+ conn->server_version = pestrdup(greet_packet.server_version, conn->persistent);
conn->greet_charset = mysqlnd_find_charset_nr(greet_packet.charset_no);
/* we allow load data local infile by default */
break;
#endif
case MYSQLND_OPT_NET_CMD_BUFFER_SIZE:
+ DBG_INF("MYSQLND_OPT_NET_CMD_BUFFER_SIZE");
if (*(unsigned int*) value < MYSQLND_NET_CMD_BUFFER_MIN_SIZE) {
DBG_RETURN(FAIL);
}
conn->net.cmd_buffer.length = *(unsigned int*) value;
+ DBG_INF_FMT("new_length=%u", conn->net.cmd_buffer.length);
if (!conn->net.cmd_buffer.buffer) {
conn->net.cmd_buffer.buffer = mnd_pemalloc(conn->net.cmd_buffer.length, conn->persistent);
} else {
}
break;
case MYSQLND_OPT_NET_READ_BUFFER_SIZE:
+ DBG_INF("MYSQLND_OPT_NET_READ_BUFFER_SIZE");
conn->options.net_read_buffer_size = *(unsigned int*) value;
+ DBG_INF_FMT("new_length=%u", conn->options.net_read_buffer_size);
break;
#ifdef MYSQLND_STRING_TO_INT_CONVERSION
case MYSQLND_OPT_INT_AND_FLOAT_NATIVE:
+ DBG_INF("MYSQLND_OPT_INT_AND_FLOAT_NATIVE");
conn->options.int_and_float_native = *(unsigned int*) value;
break;
#endif
case MYSQL_OPT_CONNECT_TIMEOUT:
+ DBG_INF("MYSQL_OPT_CONNECT_TIMEOUT");
conn->options.timeout_connect = *(unsigned int*) value;
break;
#ifdef WHEN_SUPPORTED_BY_MYSQLI
case MYSQL_OPT_READ_TIMEOUT:
+ DBG_INF("MYSQL_OPT_READ_TIMEOUT");
conn->options.timeout_read = *(unsigned int*) value;
break;
case MYSQL_OPT_WRITE_TIMEOUT:
+ DBG_INF("MYSQL_OPT_WRITE_TIMEOUT");
conn->options.timeout_write = *(unsigned int*) value;
break;
#endif
case MYSQL_OPT_LOCAL_INFILE:
+ DBG_INF("MYSQL_OPT_LOCAL_INFILE");
if (!value || (*(unsigned int*) value) ? 1 : 0) {
conn->options.flags |= CLIENT_LOCAL_FILES;
} else {
}
break;
case MYSQL_INIT_COMMAND:
+ DBG_INF("MYSQL_INIT_COMMAND");
+ DBG_INF_FMT("command=%s", value);
/* when num_commands is 0, then realloc will be effectively a malloc call, internally */
conn->options.init_commands = mnd_perealloc(conn->options.init_commands, sizeof(char *) * (conn->options.num_commands + 1),
conn->persistent);
/* currently not supported. Todo!! */
break;
case MYSQL_SET_CHARSET_NAME:
+ DBG_INF("MYSQL_SET_CHARSET_NAME");
conn->options.charset_name = pestrdup(value, conn->persistent);
+ DBG_INF_FMT("charset=%s", conn->options.charset_name);
break;
#ifdef WHEN_SUPPORTED_BY_MYSQLI
case MYSQL_SET_CHARSET_DIR:
DBG_RETURN(PASS);
}
- packet->server_version = pestrdup((char *)p, conn->persistent);
+ packet->server_version = estrdup((char *)p);
p+= strlen(packet->server_version) + 1; /* eat the '\0' */
packet->thread_id = uint4korr(p);