From: Andrey Hristov Date: Thu, 12 Nov 2015 12:04:58 +0000 (+0100) Subject: MNDR: X-Git-Tag: php-7.1.0alpha1~755 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=abc8c000727845adf7ad0505044d85bbb49294df;p=php MNDR: - rename mysqlnd.c to mysqlnd_connection.c --- diff --git a/ext/mysqlnd/config.w32 b/ext/mysqlnd/config.w32 index 00a7cd4453..012c52401a 100644 --- a/ext/mysqlnd/config.w32 +++ b/ext/mysqlnd/config.w32 @@ -6,10 +6,10 @@ if (PHP_MYSQLND != "no") { if (CHECK_LIB("ws2_32.lib", "mysqlnd")) { mysqlnd_source = - "mysqlnd.c " + "mysqlnd_alloc.c " + "mysqlnd_auth.c " + "mysqlnd_block_alloc.c " + + "mysqlnd_connection.c " + "mysqlnd_charset.c " + "mysqlnd_commands.c " + "mysqlnd_debug.c " + diff --git a/ext/mysqlnd/config9.m4 b/ext/mysqlnd/config9.m4 index ef85f9bcca..e8f078aff6 100644 --- a/ext/mysqlnd/config9.m4 +++ b/ext/mysqlnd/config9.m4 @@ -18,7 +18,7 @@ fi dnl If some extension uses mysqlnd it will get compiled in PHP core if test "$PHP_MYSQLND" != "no" || test "$PHP_MYSQLND_ENABLED" = "yes"; then mysqlnd_ps_sources="mysqlnd_ps.c mysqlnd_ps_codec.c" - mysqlnd_base_sources="mysqlnd.c mysqlnd_alloc.c mysqlnd_charset.c mysqlnd_wireprotocol.c \ + mysqlnd_base_sources="mysqlnd_connection.c mysqlnd_alloc.c mysqlnd_charset.c mysqlnd_wireprotocol.c \ mysqlnd_loaddata.c mysqlnd_reverse_api.c mysqlnd_vio.c mysqlnd_protocol_frame_codec.c \ mysqlnd_statistics.c mysqlnd_driver.c mysqlnd_ext_plugin.c mysqlnd_auth.c \ mysqlnd_result.c mysqlnd_result_meta.c mysqlnd_debug.c mysqlnd_commands.c \ diff --git a/ext/mysqlnd/mysqlnd.h b/ext/mysqlnd/mysqlnd.h index a622c27b57..849ac990a6 100644 --- a/ext/mysqlnd/mysqlnd.h +++ b/ext/mysqlnd/mysqlnd.h @@ -224,14 +224,14 @@ PHPAPI zend_ulong mysqlnd_old_escape_string(char * newstr, const char * escapest /* PS */ -#define mysqlnd_stmt_init(conn) ((conn)->data)->m->stmt_init(((conn)->data)) -#define mysqlnd_stmt_store_result(stmt) (!mysqlnd_stmt_field_count((stmt)) ? PASS:((stmt)->m->store_result((stmt))? PASS:FAIL)) -#define mysqlnd_stmt_get_result(stmt) (stmt)->m->get_result((stmt)) -#define mysqlnd_stmt_more_results(stmt) (stmt)->m->more_results((stmt)) -#define mysqlnd_stmt_next_result(stmt) (stmt)->m->next_result((stmt)) -#define mysqlnd_stmt_data_seek(stmt, row) (stmt)->m->seek_data((stmt), (row)) -#define mysqlnd_stmt_prepare(stmt, q, qlen) (stmt)->m->prepare((stmt), (q), (qlen)) -#define mysqlnd_stmt_execute(stmt) (stmt)->m->execute((stmt)) +#define mysqlnd_stmt_init(conn) ((conn)->data)->m->stmt_init(((conn)->data)) +#define mysqlnd_stmt_store_result(stmt) (!mysqlnd_stmt_field_count((stmt)) ? PASS:((stmt)->m->store_result((stmt))? PASS:FAIL)) +#define mysqlnd_stmt_get_result(stmt) (stmt)->m->get_result((stmt)) +#define mysqlnd_stmt_more_results(stmt) (stmt)->m->more_results((stmt)) +#define mysqlnd_stmt_next_result(stmt) (stmt)->m->next_result((stmt)) +#define mysqlnd_stmt_data_seek(stmt, row) (stmt)->m->seek_data((stmt), (row)) +#define mysqlnd_stmt_prepare(stmt, q, qlen) (stmt)->m->prepare((stmt), (q), (qlen)) +#define mysqlnd_stmt_execute(stmt) (stmt)->m->execute((stmt)) #define mysqlnd_stmt_send_long_data(stmt,p,d,l) (stmt)->m->send_long_data((stmt), (p), (d), (l)) #define mysqlnd_stmt_alloc_param_bind(stmt) (stmt)->m->alloc_parameter_bind((stmt)) #define mysqlnd_stmt_free_param_bind(stmt,bind) (stmt)->m->free_parameter_bind((stmt), (bind)) @@ -245,10 +245,10 @@ PHPAPI zend_ulong mysqlnd_old_escape_string(char * newstr, const char * escapest #define mysqlnd_stmt_param_metadata(stmt) (stmt)->m->get_parameter_metadata((stmt)) #define mysqlnd_stmt_result_metadata(stmt) (stmt)->m->get_result_metadata((stmt)) -#define mysqlnd_stmt_free_result(stmt) (stmt)->m->free_result((stmt)) -#define mysqlnd_stmt_close(stmt, implicit) (stmt)->m->dtor((stmt), (implicit)) -#define mysqlnd_stmt_reset(stmt) (stmt)->m->reset((stmt)) -#define mysqlnd_stmt_flush(stmt) (stmt)->m->flush((stmt)) +#define mysqlnd_stmt_free_result(stmt) (stmt)->m->free_result((stmt)) +#define mysqlnd_stmt_close(stmt, implicit) (stmt)->m->dtor((stmt), (implicit)) +#define mysqlnd_stmt_reset(stmt) (stmt)->m->reset((stmt)) +#define mysqlnd_stmt_flush(stmt) (stmt)->m->flush((stmt)) #define mysqlnd_stmt_attr_get(stmt, attr, value) (stmt)->m->get_attribute((stmt), (attr), (value)) @@ -261,8 +261,8 @@ PHPAPI zend_ulong mysqlnd_old_escape_string(char * newstr, const char * escapest PHPAPI void _mysqlnd_get_client_stats(zval *return_value ZEND_FILE_LINE_DC); /* double check the class name to avoid naming conflicts when using these: */ -#define MYSQLND_METHOD(class, method) php_##class##_##method##_pub -#define MYSQLND_METHOD_PRIVATE(class, method) php_##class##_##method##_priv +#define MYSQLND_METHOD(class, method) mysqlnd_##class##_##method##_pub +#define MYSQLND_METHOD_PRIVATE(class, method) mysqlnd_##class##_##method##_priv ZEND_BEGIN_MODULE_GLOBALS(mysqlnd) char * debug; /* The actual string */ diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd_connection.c similarity index 99% rename from ext/mysqlnd/mysqlnd.c rename to ext/mysqlnd/mysqlnd_connection.c index 2c9a554a9e..d484e1f04e 100644 --- a/ext/mysqlnd/mysqlnd.c +++ b/ext/mysqlnd/mysqlnd_connection.c @@ -830,54 +830,6 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn_handle, /* }}} */ -/* {{{ mysqlnd_connect */ -PHPAPI MYSQLND * mysqlnd_connection_connect(MYSQLND * conn_handle, - const char * const host, - const char * const user, - const char * const passwd, unsigned int passwd_len, - const char * const db, unsigned int db_len, - unsigned int port, - const char * const sock_or_pipe, - unsigned int mysql_flags, - unsigned int client_api_flags - ) -{ - enum_func_status ret = FAIL; - zend_bool self_alloced = FALSE; - MYSQLND_CSTRING hostname = { host, host? strlen(host) : 0 }; - MYSQLND_CSTRING username = { user, user? strlen(user) : 0 }; - MYSQLND_CSTRING password = { passwd, passwd_len }; - MYSQLND_CSTRING database = { db, db_len }; - MYSQLND_CSTRING socket_or_pipe = { sock_or_pipe, sock_or_pipe? strlen(sock_or_pipe) : 0 }; - - DBG_ENTER("mysqlnd_connect"); - DBG_INF_FMT("host=%s user=%s db=%s port=%u flags=%u", host? host:"", user? user:"", db? db:"", port, mysql_flags); - - if (!conn_handle) { - self_alloced = TRUE; - if (!(conn_handle = mysqlnd_connection_init(client_api_flags, FALSE, NULL))) { - /* OOM */ - DBG_RETURN(NULL); - } - } - - ret = conn_handle->m->connect(conn_handle, hostname, username, password, database, port, socket_or_pipe, mysql_flags); - - if (ret == FAIL) { - if (self_alloced) { - /* - We have alloced, thus there are no references to this - object - we are free to kill it! - */ - conn_handle->m->dtor(conn_handle); - } - DBG_RETURN(NULL); - } - DBG_RETURN(conn_handle); -} -/* }}} */ - - /* {{{ mysqlnd_conn_data::query */ /* If conn->error_info->error_no is not zero, then we had an error. @@ -965,198 +917,6 @@ MYSQLND_METHOD(mysqlnd_conn_data, reap_query)(MYSQLND_CONN_DATA * conn, enum_mys /* }}} */ -#include "php_network.h" - -/* {{{ mysqlnd_stream_array_to_fd_set */ -MYSQLND ** mysqlnd_stream_array_check_for_readiness(MYSQLND ** conn_array) -{ - int cnt = 0; - MYSQLND **p = conn_array, **p_p; - MYSQLND **ret = NULL; - - while (*p) { - const enum mysqlnd_connection_state conn_state = GET_CONNECTION_STATE(&((*p)->data->state)); - if (conn_state <= CONN_READY || conn_state == CONN_QUIT_SENT) { - cnt++; - } - p++; - } - if (cnt) { - MYSQLND **ret_p = ret = ecalloc(cnt + 1, sizeof(MYSQLND *)); - p_p = p = conn_array; - while (*p) { - const enum mysqlnd_connection_state conn_state = GET_CONNECTION_STATE(&((*p)->data->state)); - if (conn_state <= CONN_READY || conn_state == CONN_QUIT_SENT) { - *ret_p = *p; - *p = NULL; - ret_p++; - } else { - *p_p = *p; - p_p++; - } - p++; - } - *ret_p = NULL; - } - return ret; -} -/* }}} */ - - -/* {{{ mysqlnd_stream_array_to_fd_set */ -static int mysqlnd_stream_array_to_fd_set(MYSQLND ** conn_array, fd_set * fds, php_socket_t * max_fd) -{ - php_socket_t this_fd; - php_stream *stream = NULL; - unsigned int cnt = 0; - MYSQLND **p = conn_array; - DBG_ENTER("mysqlnd_stream_array_to_fd_set"); - - while (*p) { - /* get the fd. - * NB: Most other code will NOT use the PHP_STREAM_CAST_INTERNAL flag - * when casting. It is only used here so that the buffered data warning - * is not displayed. - * */ - stream = (*p)->data->vio->data->m.get_stream((*p)->data->vio); - DBG_INF_FMT("conn=%llu stream=%p", (*p)->data->thread_id, stream); - if (stream != NULL && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, - (void*)&this_fd, 1) && ZEND_VALID_SOCKET(this_fd)) { - - PHP_SAFE_FD_SET(this_fd, fds); - - if (this_fd > *max_fd) { - *max_fd = this_fd; - } - cnt++; - } - p++; - } - DBG_RETURN(cnt ? 1 : 0); -} -/* }}} */ - - -/* {{{ mysqlnd_stream_array_from_fd_set */ -static int mysqlnd_stream_array_from_fd_set(MYSQLND ** conn_array, fd_set * fds) -{ - php_socket_t this_fd; - php_stream *stream = NULL; - int ret = 0; - zend_bool disproportion = FALSE; - MYSQLND **fwd = conn_array, **bckwd = conn_array; - DBG_ENTER("mysqlnd_stream_array_from_fd_set"); - - while (*fwd) { - stream = (*fwd)->data->vio->data->m.get_stream((*fwd)->data->vio); - DBG_INF_FMT("conn=%llu stream=%p", (*fwd)->data->thread_id, stream); - if (stream != NULL && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, - (void*)&this_fd, 1) && ZEND_VALID_SOCKET(this_fd)) { - if (PHP_SAFE_FD_ISSET(this_fd, fds)) { - if (disproportion) { - *bckwd = *fwd; - } - bckwd++; - fwd++; - ret++; - continue; - } - } - disproportion = TRUE; - fwd++; - } - *bckwd = NULL;/* NULL-terminate the list */ - - DBG_RETURN(ret); -} -/* }}} */ - - -#ifndef PHP_WIN32 -#define php_select(m, r, w, e, t) select(m, r, w, e, t) -#else -#include "win32/select.h" -#endif - - -/* {{{ mysqlnd_poll */ -PHPAPI enum_func_status -mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQLND ***dont_poll, long sec, long usec, int * desc_num) -{ - struct timeval tv; - struct timeval *tv_p = NULL; - fd_set rfds, wfds, efds; - php_socket_t max_fd = 0; - int retval, sets = 0; - int set_count, max_set_count = 0; - - DBG_ENTER("_mysqlnd_poll"); - if (sec < 0 || usec < 0) { - php_error_docref(NULL, E_WARNING, "Negative values passed for sec and/or usec"); - DBG_RETURN(FAIL); - } - - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_ZERO(&efds); - - if (r_array != NULL) { - *dont_poll = mysqlnd_stream_array_check_for_readiness(r_array); - set_count = mysqlnd_stream_array_to_fd_set(r_array, &rfds, &max_fd); - if (set_count > max_set_count) { - max_set_count = set_count; - } - sets += set_count; - } - - if (e_array != NULL) { - set_count = mysqlnd_stream_array_to_fd_set(e_array, &efds, &max_fd); - if (set_count > max_set_count) { - max_set_count = set_count; - } - sets += set_count; - } - - if (!sets) { - php_error_docref(NULL, E_WARNING, *dont_poll ? "All arrays passed are clear":"No stream arrays were passed"); - DBG_ERR_FMT(*dont_poll ? "All arrays passed are clear":"No stream arrays were passed"); - DBG_RETURN(FAIL); - } - - PHP_SAFE_MAX_FD(max_fd, max_set_count); - - /* Solaris + BSD do not like microsecond values which are >= 1 sec */ - if (usec > 999999) { - tv.tv_sec = sec + (usec / 1000000); - tv.tv_usec = usec % 1000000; - } else { - tv.tv_sec = sec; - tv.tv_usec = usec; - } - - tv_p = &tv; - - retval = php_select(max_fd + 1, &rfds, &wfds, &efds, tv_p); - - if (retval == -1) { - php_error_docref(NULL, E_WARNING, "unable to select [%d]: %s (max_fd=%d)", - errno, strerror(errno), max_fd); - DBG_RETURN(FAIL); - } - - if (r_array != NULL) { - mysqlnd_stream_array_from_fd_set(r_array, &rfds); - } - if (e_array != NULL) { - mysqlnd_stream_array_from_fd_set(e_array, &efds); - } - - *desc_num = retval; - DBG_RETURN(PASS); -} -/* }}} */ - - /* {{{ mysqlnd_conn_data::list_method */ MYSQLND_RES * MYSQLND_METHOD(mysqlnd_conn_data, list_method)(MYSQLND_CONN_DATA * conn, const char * const query, const char * const achtung_wild, const char * const par1) @@ -2209,7 +1969,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, store_result)(MYSQLND_CONN_DATA * const conn, /* {{{ mysqlnd_conn_data::get_connection_stats */ static void MYSQLND_METHOD(mysqlnd_conn_data, get_connection_stats)(const MYSQLND_CONN_DATA * const conn, - zval * return_value ZEND_FILE_LINE_DC) + zval * return_value ZEND_FILE_LINE_DC) { DBG_ENTER("mysqlnd_conn_data::get_connection_stats"); mysqlnd_fill_stats_hash(conn->stats, mysqlnd_stats_values_names, return_value ZEND_FILE_LINE_CC); @@ -2702,7 +2462,7 @@ MYSQLND_METHOD(mysqlnd_conn, close)(MYSQLND * conn_handle, const enum_connection */ ret = conn->m->send_close(conn); - /* do it after free_reference/dtor and we might crash */ + /* If we do it after free_reference/dtor then we might crash */ conn->m->local_tx_end(conn, this_func, ret); conn_handle->m->dtor(conn_handle); @@ -2720,6 +2480,246 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn) MYSQLND_CLASS_METHODS_END; +#include "php_network.h" + +/* {{{ mysqlnd_stream_array_to_fd_set */ +MYSQLND ** mysqlnd_stream_array_check_for_readiness(MYSQLND ** conn_array) +{ + int cnt = 0; + MYSQLND **p = conn_array, **p_p; + MYSQLND **ret = NULL; + + while (*p) { + const enum mysqlnd_connection_state conn_state = GET_CONNECTION_STATE(&((*p)->data->state)); + if (conn_state <= CONN_READY || conn_state == CONN_QUIT_SENT) { + cnt++; + } + p++; + } + if (cnt) { + MYSQLND **ret_p = ret = ecalloc(cnt + 1, sizeof(MYSQLND *)); + p_p = p = conn_array; + while (*p) { + const enum mysqlnd_connection_state conn_state = GET_CONNECTION_STATE(&((*p)->data->state)); + if (conn_state <= CONN_READY || conn_state == CONN_QUIT_SENT) { + *ret_p = *p; + *p = NULL; + ret_p++; + } else { + *p_p = *p; + p_p++; + } + p++; + } + *ret_p = NULL; + } + return ret; +} +/* }}} */ + + +/* {{{ mysqlnd_stream_array_to_fd_set */ +static int mysqlnd_stream_array_to_fd_set(MYSQLND ** conn_array, fd_set * fds, php_socket_t * max_fd) +{ + php_socket_t this_fd; + php_stream *stream = NULL; + unsigned int cnt = 0; + MYSQLND **p = conn_array; + DBG_ENTER("mysqlnd_stream_array_to_fd_set"); + + while (*p) { + /* get the fd. + * NB: Most other code will NOT use the PHP_STREAM_CAST_INTERNAL flag + * when casting. It is only used here so that the buffered data warning + * is not displayed. + * */ + stream = (*p)->data->vio->data->m.get_stream((*p)->data->vio); + DBG_INF_FMT("conn=%llu stream=%p", (*p)->data->thread_id, stream); + if (stream != NULL && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, + (void*)&this_fd, 1) && ZEND_VALID_SOCKET(this_fd)) { + + PHP_SAFE_FD_SET(this_fd, fds); + + if (this_fd > *max_fd) { + *max_fd = this_fd; + } + cnt++; + } + p++; + } + DBG_RETURN(cnt ? 1 : 0); +} +/* }}} */ + + +/* {{{ mysqlnd_stream_array_from_fd_set */ +static int mysqlnd_stream_array_from_fd_set(MYSQLND ** conn_array, fd_set * fds) +{ + php_socket_t this_fd; + php_stream *stream = NULL; + int ret = 0; + zend_bool disproportion = FALSE; + MYSQLND **fwd = conn_array, **bckwd = conn_array; + DBG_ENTER("mysqlnd_stream_array_from_fd_set"); + + while (*fwd) { + stream = (*fwd)->data->vio->data->m.get_stream((*fwd)->data->vio); + DBG_INF_FMT("conn=%llu stream=%p", (*fwd)->data->thread_id, stream); + if (stream != NULL && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, + (void*)&this_fd, 1) && ZEND_VALID_SOCKET(this_fd)) { + if (PHP_SAFE_FD_ISSET(this_fd, fds)) { + if (disproportion) { + *bckwd = *fwd; + } + bckwd++; + fwd++; + ret++; + continue; + } + } + disproportion = TRUE; + fwd++; + } + *bckwd = NULL;/* NULL-terminate the list */ + + DBG_RETURN(ret); +} +/* }}} */ + + +#ifndef PHP_WIN32 +#define php_select(m, r, w, e, t) select(m, r, w, e, t) +#else +#include "win32/select.h" +#endif + + +/* {{{ mysqlnd_poll */ +PHPAPI enum_func_status +mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQLND ***dont_poll, long sec, long usec, int * desc_num) +{ + struct timeval tv; + struct timeval *tv_p = NULL; + fd_set rfds, wfds, efds; + php_socket_t max_fd = 0; + int retval, sets = 0; + int set_count, max_set_count = 0; + + DBG_ENTER("_mysqlnd_poll"); + if (sec < 0 || usec < 0) { + php_error_docref(NULL, E_WARNING, "Negative values passed for sec and/or usec"); + DBG_RETURN(FAIL); + } + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&efds); + + if (r_array != NULL) { + *dont_poll = mysqlnd_stream_array_check_for_readiness(r_array); + set_count = mysqlnd_stream_array_to_fd_set(r_array, &rfds, &max_fd); + if (set_count > max_set_count) { + max_set_count = set_count; + } + sets += set_count; + } + + if (e_array != NULL) { + set_count = mysqlnd_stream_array_to_fd_set(e_array, &efds, &max_fd); + if (set_count > max_set_count) { + max_set_count = set_count; + } + sets += set_count; + } + + if (!sets) { + php_error_docref(NULL, E_WARNING, *dont_poll ? "All arrays passed are clear":"No stream arrays were passed"); + DBG_ERR_FMT(*dont_poll ? "All arrays passed are clear":"No stream arrays were passed"); + DBG_RETURN(FAIL); + } + + PHP_SAFE_MAX_FD(max_fd, max_set_count); + + /* Solaris + BSD do not like microsecond values which are >= 1 sec */ + if (usec > 999999) { + tv.tv_sec = sec + (usec / 1000000); + tv.tv_usec = usec % 1000000; + } else { + tv.tv_sec = sec; + tv.tv_usec = usec; + } + + tv_p = &tv; + + retval = php_select(max_fd + 1, &rfds, &wfds, &efds, tv_p); + + if (retval == -1) { + php_error_docref(NULL, E_WARNING, "unable to select [%d]: %s (max_fd=%d)", + errno, strerror(errno), max_fd); + DBG_RETURN(FAIL); + } + + if (r_array != NULL) { + mysqlnd_stream_array_from_fd_set(r_array, &rfds); + } + if (e_array != NULL) { + mysqlnd_stream_array_from_fd_set(e_array, &efds); + } + + *desc_num = retval; + DBG_RETURN(PASS); +} +/* }}} */ + + +/* {{{ mysqlnd_connect */ +PHPAPI MYSQLND * mysqlnd_connection_connect(MYSQLND * conn_handle, + const char * const host, + const char * const user, + const char * const passwd, unsigned int passwd_len, + const char * const db, unsigned int db_len, + unsigned int port, + const char * const sock_or_pipe, + unsigned int mysql_flags, + unsigned int client_api_flags + ) +{ + enum_func_status ret = FAIL; + zend_bool self_alloced = FALSE; + MYSQLND_CSTRING hostname = { host, host? strlen(host) : 0 }; + MYSQLND_CSTRING username = { user, user? strlen(user) : 0 }; + MYSQLND_CSTRING password = { passwd, passwd_len }; + MYSQLND_CSTRING database = { db, db_len }; + MYSQLND_CSTRING socket_or_pipe = { sock_or_pipe, sock_or_pipe? strlen(sock_or_pipe) : 0 }; + + DBG_ENTER("mysqlnd_connect"); + DBG_INF_FMT("host=%s user=%s db=%s port=%u flags=%u", host? host:"", user? user:"", db? db:"", port, mysql_flags); + + if (!conn_handle) { + self_alloced = TRUE; + if (!(conn_handle = mysqlnd_connection_init(client_api_flags, FALSE, NULL))) { + /* OOM */ + DBG_RETURN(NULL); + } + } + + ret = conn_handle->m->connect(conn_handle, hostname, username, password, database, port, socket_or_pipe, mysql_flags); + + if (ret == FAIL) { + if (self_alloced) { + /* + We have alloced, thus there are no references to this + object - we are free to kill it! + */ + conn_handle->m->dtor(conn_handle); + } + DBG_RETURN(NULL); + } + DBG_RETURN(conn_handle); +} +/* }}} */ + + /* {{{ mysqlnd_connection_init */ PHPAPI MYSQLND * mysqlnd_connection_init(const size_t client_flags, const zend_bool persistent, struct st_mysqlnd_object_factory_methods * object_factory)