summaryrefslogtreecommitdiff
path: root/ext/mysqlnd
diff options
context:
space:
mode:
Diffstat (limited to 'ext/mysqlnd')
-rw-r--r--ext/mysqlnd/CREDITS2
-rw-r--r--ext/mysqlnd/config.w329
-rw-r--r--ext/mysqlnd/config9.m47
-rw-r--r--ext/mysqlnd/mysqlnd.c2145
-rw-r--r--ext/mysqlnd/mysqlnd.h150
-rw-r--r--ext/mysqlnd/mysqlnd_alloc.c796
-rw-r--r--ext/mysqlnd/mysqlnd_alloc.h100
-rw-r--r--ext/mysqlnd/mysqlnd_auth.c477
-rw-r--r--ext/mysqlnd/mysqlnd_bt.c484
-rw-r--r--ext/mysqlnd/mysqlnd_charset.c45
-rw-r--r--ext/mysqlnd/mysqlnd_charset.h14
-rw-r--r--ext/mysqlnd/mysqlnd_debug.c1121
-rw-r--r--ext/mysqlnd/mysqlnd_debug.h75
-rw-r--r--ext/mysqlnd/mysqlnd_driver.c306
-rw-r--r--ext/mysqlnd/mysqlnd_enum_n_def.h15
-rw-r--r--ext/mysqlnd/mysqlnd_ext_plugin.c226
-rw-r--r--ext/mysqlnd/mysqlnd_ext_plugin.h72
-rw-r--r--ext/mysqlnd/mysqlnd_loaddata.c81
-rw-r--r--ext/mysqlnd/mysqlnd_net.c419
-rw-r--r--ext/mysqlnd/mysqlnd_net.h10
-rw-r--r--ext/mysqlnd/mysqlnd_plugin.c209
-rw-r--r--ext/mysqlnd/mysqlnd_priv.h99
-rw-r--r--ext/mysqlnd/mysqlnd_ps.c442
-rw-r--r--ext/mysqlnd/mysqlnd_ps_codec.c43
-rw-r--r--ext/mysqlnd/mysqlnd_result.c221
-rw-r--r--ext/mysqlnd/mysqlnd_result.h7
-rw-r--r--ext/mysqlnd/mysqlnd_result_meta.c10
-rw-r--r--ext/mysqlnd/mysqlnd_result_meta.h4
-rw-r--r--ext/mysqlnd/mysqlnd_reverse_api.c100
-rw-r--r--ext/mysqlnd/mysqlnd_reverse_api.h50
-rw-r--r--ext/mysqlnd/mysqlnd_statistics.c323
-rw-r--r--ext/mysqlnd/mysqlnd_statistics.h6
-rw-r--r--ext/mysqlnd/mysqlnd_structs.h491
-rw-r--r--ext/mysqlnd/mysqlnd_wireprotocol.c612
-rw-r--r--ext/mysqlnd/mysqlnd_wireprotocol.h82
-rw-r--r--ext/mysqlnd/php_mysqlnd.c118
-rw-r--r--ext/mysqlnd/php_mysqlnd.h6
37 files changed, 5976 insertions, 3401 deletions
diff --git a/ext/mysqlnd/CREDITS b/ext/mysqlnd/CREDITS
index bac8d1a4a2..5aed316e89 100644
--- a/ext/mysqlnd/CREDITS
+++ b/ext/mysqlnd/CREDITS
@@ -1,2 +1,2 @@
MySQLnd
-Georg Richter, Andrey Hristov, Ulf Wendel
+Andrey Hristov, Ulf Wendel, Georg Richter
diff --git a/ext/mysqlnd/config.w32 b/ext/mysqlnd/config.w32
index 9f6ccc5e38..a910a0e509 100644
--- a/ext/mysqlnd/config.w32
+++ b/ext/mysqlnd/config.w32
@@ -7,18 +7,25 @@ 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_bt.c " +
"mysqlnd_charset.c " +
"mysqlnd_debug.c " +
+ "mysqlnd_driver.c " +
+ "mysqlnd_ext_plugin.c " +
"mysqlnd_loaddata.c " +
+ "mysqlnd_reverse_api.c " +
"mysqlnd_net.c " +
+ "mysqlnd_plugin.c " +
"mysqlnd_ps.c " +
"mysqlnd_ps_codec.c " +
"mysqlnd_result.c " +
"mysqlnd_result_meta.c " +
"mysqlnd_statistics.c " +
"mysqlnd_wireprotocol.c " +
- "php_mysqlnd.c";
+ "php_mysqlnd.c ";
EXTENSION("mysqlnd", mysqlnd_source, false);
if (((PHP_ZLIB=="no") && (CHECK_LIB("zlib_a.lib;zlib.lib", "mysqlnd", PHP_MYSQLND))) ||
(PHP_ZLIB_SHARED && CHECK_LIB("zlib.lib", "mysqlnd", PHP_MYSQLND)) || (PHP_ZLIB == "yes" && (!PHP_ZLIB_SHARED)))
diff --git a/ext/mysqlnd/config9.m4 b/ext/mysqlnd/config9.m4
index 73101eb50e..2c15c34e8d 100644
--- a/ext/mysqlnd/config9.m4
+++ b/ext/mysqlnd/config9.m4
@@ -18,10 +18,11 @@ 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_charset.c mysqlnd_wireprotocol.c \
- mysqlnd_loaddata.c mysqlnd_net.c mysqlnd_statistics.c \
+ mysqlnd_base_sources="mysqlnd.c mysqlnd_alloc.c mysqlnd_bt.c mysqlnd_charset.c mysqlnd_wireprotocol.c \
+ mysqlnd_loaddata.c mysqlnd_reverse_api.c mysqlnd_net.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_block_alloc.c php_mysqlnd.c"
+ mysqlnd_block_alloc.c mysqlnd_plugin.c php_mysqlnd.c"
if test "$PHP_MYSQLND_COMPRESSION_SUPPORT" != "no"; then
diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c
index 20bab915e2..3483d8692a 100644
--- a/ext/mysqlnd/mysqlnd.c
+++ b/ext/mysqlnd/mysqlnd.c
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -27,8 +27,6 @@
#include "mysqlnd_statistics.h"
#include "mysqlnd_charset.h"
#include "mysqlnd_debug.h"
-/* for php_get_current_user() */
-#include "ext/standard/basic_functions.h"
/*
TODO :
@@ -64,60 +62,50 @@ PHPAPI const char * const mysqlnd_out_of_sync = "Commands out of sync; you can't
PHPAPI const char * const mysqlnd_out_of_memory = "Out of memory";
PHPAPI MYSQLND_STATS *mysqlnd_global_stats = NULL;
-static zend_bool mysqlnd_library_initted = FALSE;
-static struct st_mysqlnd_conn_methods *mysqlnd_conn_methods;
-/* {{{ mysqlnd_library_end */
-PHPAPI void mysqlnd_library_end(TSRMLS_D)
-{
- if (mysqlnd_library_initted == TRUE) {
- mysqlnd_stats_end(mysqlnd_global_stats);
- mysqlnd_global_stats = NULL;
- mysqlnd_library_initted = FALSE;
- }
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_conn::free_options */
+/* {{{ mysqlnd_conn_data::free_options */
static void
-MYSQLND_METHOD(mysqlnd_conn, free_options)(MYSQLND * conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, free_options)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
zend_bool pers = conn->persistent;
- if (conn->options.charset_name) {
- mnd_pefree(conn->options.charset_name, pers);
- conn->options.charset_name = NULL;
+ if (conn->options->charset_name) {
+ mnd_pefree(conn->options->charset_name, pers);
+ conn->options->charset_name = NULL;
+ }
+ if (conn->options->auth_protocol) {
+ mnd_pefree(conn->options->auth_protocol, pers);
+ conn->options->auth_protocol = NULL;
}
- if (conn->options.num_commands) {
+ if (conn->options->num_commands) {
unsigned int i;
- for (i = 0; i < conn->options.num_commands; i++) {
+ for (i = 0; i < conn->options->num_commands; i++) {
/* allocated with pestrdup */
- mnd_pefree(conn->options.init_commands[i], pers);
+ mnd_pefree(conn->options->init_commands[i], pers);
}
- mnd_pefree(conn->options.init_commands, pers);
- conn->options.init_commands = NULL;
+ mnd_pefree(conn->options->init_commands, pers);
+ conn->options->init_commands = NULL;
}
- if (conn->options.cfg_file) {
- mnd_pefree(conn->options.cfg_file, pers);
- conn->options.cfg_file = NULL;
+ if (conn->options->cfg_file) {
+ mnd_pefree(conn->options->cfg_file, pers);
+ conn->options->cfg_file = NULL;
}
- if (conn->options.cfg_section) {
- mnd_pefree(conn->options.cfg_section, pers);
- conn->options.cfg_section = NULL;
+ if (conn->options->cfg_section) {
+ mnd_pefree(conn->options->cfg_section, pers);
+ conn->options->cfg_section = NULL;
}
}
/* }}} */
-/* {{{ mysqlnd_conn::free_contents */
+/* {{{ mysqlnd_conn_data::free_contents */
static void
-MYSQLND_METHOD(mysqlnd_conn, free_contents)(MYSQLND * conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, free_contents)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
zend_bool pers = conn->persistent;
- DBG_ENTER("mysqlnd_conn::free_contents");
+ DBG_ENTER("mysqlnd_conn_data::free_contents");
mysqlnd_local_infile_default(conn);
if (conn->current_result) {
@@ -132,55 +120,51 @@ MYSQLND_METHOD(mysqlnd_conn, free_contents)(MYSQLND * conn TSRMLS_DC)
DBG_INF("Freeing memory of members");
if (conn->host) {
- DBG_INF("Freeing host");
mnd_pefree(conn->host, pers);
conn->host = NULL;
}
if (conn->user) {
- DBG_INF("Freeing user");
mnd_pefree(conn->user, pers);
conn->user = NULL;
}
if (conn->passwd) {
- DBG_INF("Freeing passwd");
mnd_pefree(conn->passwd, pers);
conn->passwd = NULL;
}
if (conn->connect_or_select_db) {
- DBG_INF("Freeing connect_or_select_db");
mnd_pefree(conn->connect_or_select_db, pers);
conn->connect_or_select_db = NULL;
}
if (conn->unix_socket) {
- DBG_INF("Freeing unix_socket");
mnd_pefree(conn->unix_socket, pers);
conn->unix_socket = NULL;
}
DBG_INF_FMT("scheme=%s", conn->scheme);
if (conn->scheme) {
- DBG_INF("Freeing scheme");
mnd_pefree(conn->scheme, pers);
conn->scheme = NULL;
}
if (conn->server_version) {
- DBG_INF("Freeing server_version");
mnd_pefree(conn->server_version, pers);
conn->server_version = NULL;
}
if (conn->host_info) {
- DBG_INF("Freeing host_info");
mnd_pefree(conn->host_info, pers);
conn->host_info = NULL;
}
- if (conn->scramble) {
- DBG_INF("Freeing scramble");
- mnd_pefree(conn->scramble, pers);
- conn->scramble = NULL;
+ if (conn->auth_plugin_data) {
+ mnd_pefree(conn->auth_plugin_data, pers);
+ conn->auth_plugin_data = NULL;
}
if (conn->last_message) {
mnd_pefree(conn->last_message, pers);
conn->last_message = NULL;
}
+ if (conn->error_info->error_list) {
+ zend_llist_clean(conn->error_info->error_list);
+ mnd_pefree(conn->error_info->error_list, pers);
+ conn->error_info->error_list = NULL;
+ }
conn->charset = NULL;
conn->greet_charset = NULL;
@@ -189,24 +173,22 @@ MYSQLND_METHOD(mysqlnd_conn, free_contents)(MYSQLND * conn TSRMLS_DC)
/* }}} */
-/* {{{ mysqlnd_conn::dtor */
+/* {{{ mysqlnd_conn_data::dtor */
static void
-MYSQLND_METHOD_PRIVATE(mysqlnd_conn, dtor)(MYSQLND * conn TSRMLS_DC)
+MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, dtor)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_conn::dtor");
+ DBG_ENTER("mysqlnd_conn_data::dtor");
DBG_INF_FMT("conn=%llu", conn->thread_id);
conn->m->free_contents(conn TSRMLS_CC);
conn->m->free_options(conn TSRMLS_CC);
if (conn->net) {
- DBG_INF("Freeing net");
- mysqlnd_net_free(conn->net TSRMLS_CC);
+ mysqlnd_net_free(conn->net, conn->stats, conn->error_info TSRMLS_CC);
conn->net = NULL;
}
if (conn->protocol) {
- DBG_INF("Freeing protocol");
mysqlnd_protocol_free(conn->protocol TSRMLS_CC);
conn->protocol = NULL;
}
@@ -222,22 +204,22 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, dtor)(MYSQLND * conn TSRMLS_DC)
/* }}} */
-/* {{{ mysqlnd_conn::simple_command_handle_response */
+/* {{{ mysqlnd_conn_data::simple_command_handle_response */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND * conn, enum mysqlnd_packet_type ok_packet,
+MYSQLND_METHOD(mysqlnd_conn_data, simple_command_handle_response)(MYSQLND_CONN_DATA * conn, enum mysqlnd_packet_type ok_packet,
zend_bool silent, enum php_mysqlnd_server_command command,
zend_bool ignore_upsert_status TSRMLS_DC)
{
enum_func_status ret = FAIL;
- DBG_ENTER("mysqlnd_conn::simple_command_handle_response");
+ DBG_ENTER("mysqlnd_conn_data::simple_command_handle_response");
DBG_INF_FMT("silent=%u packet=%u command=%s", silent, ok_packet, mysqlnd_command_to_text[command]);
switch (ok_packet) {
case PROT_OK_PACKET:{
MYSQLND_PACKET_OK * ok_response = conn->protocol->m.get_ok_packet(conn->protocol, FALSE TSRMLS_CC);
if (!ok_response) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
break;
}
if (FAIL == (ret = PACKET_READ(ok_response, conn))) {
@@ -250,7 +232,7 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND * conn, enu
DBG_INF_FMT("OK from server");
if (0xFF == ok_response->field_count) {
/* The server signalled error. Set the error */
- SET_CLIENT_ERROR(conn->error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
+ SET_CLIENT_ERROR(*conn->error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
ret = FAIL;
/*
Cover a protocol design error: error packet does not
@@ -261,7 +243,7 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND * conn, enu
a multi-statement or a stored procedure, so it should be
safe to unconditionally turn off the flag here.
*/
- conn->upsert_status.server_status &= ~SERVER_MORE_RESULTS_EXISTS;
+ conn->upsert_status->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
SET_ERROR_AFF_ROWS(conn);
} else {
SET_NEW_MESSAGE(conn->last_message, conn->last_message_len,
@@ -269,10 +251,10 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND * conn, enu
conn->persistent);
if (!ignore_upsert_status) {
- conn->upsert_status.warning_count = ok_response->warning_count;
- conn->upsert_status.server_status = ok_response->server_status;
- conn->upsert_status.affected_rows = ok_response->affected_rows;
- conn->upsert_status.last_insert_id = ok_response->last_insert_id;
+ conn->upsert_status->warning_count = ok_response->warning_count;
+ conn->upsert_status->server_status = ok_response->server_status;
+ conn->upsert_status->affected_rows = ok_response->affected_rows;
+ conn->upsert_status->last_insert_id = ok_response->last_insert_id;
}
}
}
@@ -282,11 +264,11 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND * conn, enu
case PROT_EOF_PACKET:{
MYSQLND_PACKET_EOF * ok_response = conn->protocol->m.get_eof_packet(conn->protocol, FALSE TSRMLS_CC);
if (!ok_response) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
break;
}
if (FAIL == (ret = PACKET_READ(ok_response, conn))) {
- SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE,
+ SET_CLIENT_ERROR(*conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE,
"Malformed packet");
if (!silent) {
DBG_ERR_FMT("Error while reading %s's EOF packet", mysqlnd_command_to_text[command]);
@@ -295,10 +277,10 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND * conn, enu
}
} else if (0xFF == ok_response->field_count) {
/* The server signalled error. Set the error */
- SET_CLIENT_ERROR(conn->error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
+ SET_CLIENT_ERROR(*conn->error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
SET_ERROR_AFF_ROWS(conn);
} else if (0xFE != ok_response->field_count) {
- SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
+ SET_CLIENT_ERROR(*conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
if (!silent) {
DBG_ERR_FMT("EOF packet expected, field count wasn't 0xFE but 0x%2X", ok_response->field_count);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "EOF packet expected, field count wasn't 0xFE but 0x%2X",
@@ -311,7 +293,7 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND * conn, enu
break;
}
default:
- SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
+ SET_CLIENT_ERROR(*conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Wrong response packet %u passed to the function", ok_packet);
break;
}
@@ -321,41 +303,41 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response)(MYSQLND * conn, enu
/* }}} */
-/* {{{ mysqlnd_conn::simple_command */
+/* {{{ mysqlnd_conn_data::simple_command */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, simple_command)(MYSQLND * conn, enum php_mysqlnd_server_command command,
- const char * const arg, size_t arg_len, enum mysqlnd_packet_type ok_packet, zend_bool silent,
+MYSQLND_METHOD(mysqlnd_conn_data, simple_command)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command,
+ const zend_uchar * const arg, size_t arg_len, enum mysqlnd_packet_type ok_packet, zend_bool silent,
zend_bool ignore_upsert_status TSRMLS_DC)
{
enum_func_status ret = PASS;
MYSQLND_PACKET_COMMAND * cmd_packet;
- DBG_ENTER("mysqlnd_conn::simple_command");
+ DBG_ENTER("mysqlnd_conn_data::simple_command");
DBG_INF_FMT("command=%s ok_packet=%u silent=%u", mysqlnd_command_to_text[command], ok_packet, silent);
switch (CONN_GET_STATE(conn)) {
case CONN_READY:
break;
case CONN_QUIT_SENT:
- SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
DBG_ERR("Server is gone");
DBG_RETURN(FAIL);
default:
- SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_ERR_FMT("Command out of sync. State=%u", CONN_GET_STATE(conn));
DBG_RETURN(FAIL);
}
/* clean UPSERT info */
if (!ignore_upsert_status) {
- memset(&conn->upsert_status, 0, sizeof(conn->upsert_status));
+ memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
}
SET_ERROR_AFF_ROWS(conn);
- SET_EMPTY_ERROR(conn->error_info);
+ SET_EMPTY_ERROR(*conn->error_info);
cmd_packet = conn->protocol->m.get_command_packet(conn->protocol, FALSE TSRMLS_CC);
if (!cmd_packet) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(FAIL);
}
@@ -372,6 +354,7 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command)(MYSQLND * conn, enum php_mysqlnd_se
DBG_ERR_FMT("Error while sending %s packet", mysqlnd_command_to_text[command]);
php_error(E_WARNING, "Error while sending %s packet. PID=%d", mysqlnd_command_to_text[command], getpid());
}
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
DBG_ERR("Server is gone");
ret = FAIL;
} else if (ok_packet != PROT_LAST) {
@@ -385,26 +368,31 @@ MYSQLND_METHOD(mysqlnd_conn, simple_command)(MYSQLND * conn, enum php_mysqlnd_se
/* }}} */
-/* {{{ mysqlnd_conn::set_server_option */
+/* {{{ mysqlnd_conn_data::set_server_option */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, set_server_option)(MYSQLND * const conn, enum_mysqlnd_server_option option TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, set_server_option)(MYSQLND_CONN_DATA * const conn, enum_mysqlnd_server_option option TSRMLS_DC)
{
- enum_func_status ret;
- char buffer[2];
- DBG_ENTER("mysqlnd_conn::set_server_option");
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, set_server_option);
+ zend_uchar buffer[2];
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_conn_data::set_server_option");
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
- int2store(buffer, (unsigned int) option);
- ret = conn->m->simple_command(conn, COM_SET_OPTION, buffer, sizeof(buffer), PROT_EOF_PACKET, FALSE, TRUE TSRMLS_CC);
+ int2store(buffer, (unsigned int) option);
+ ret = conn->m->simple_command(conn, COM_SET_OPTION, buffer, sizeof(buffer), PROT_EOF_PACKET, FALSE, TRUE TSRMLS_CC);
+
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::restart_psession */
+/* {{{ mysqlnd_conn_data::restart_psession */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, restart_psession)(MYSQLND * conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, restart_psession)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_conn::restart_psession");
+ DBG_ENTER("mysqlnd_conn_data::restart_psession");
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_CONNECT_REUSED);
/* Free here what should not be seen by the next script */
if (conn->last_message) {
@@ -416,49 +404,38 @@ MYSQLND_METHOD(mysqlnd_conn, restart_psession)(MYSQLND * conn TSRMLS_DC)
/* }}} */
-/* {{{ mysqlnd_conn::end_psession */
+/* {{{ mysqlnd_conn_data::end_psession */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, end_psession)(MYSQLND * conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, end_psession)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_conn::end_psession");
+ DBG_ENTER("mysqlnd_conn_data::end_psession");
DBG_RETURN(PASS);
}
/* }}} */
-#define MYSQLND_ASSEBLED_PACKET_MAX_SIZE 3UL*1024UL*1024UL*1024UL
-/* {{{ mysqlnd_connect_run_authentication */
+/* {{{ mysqlnd_switch_to_ssl_if_needed */
static enum_func_status
-mysqlnd_connect_run_authentication(
- MYSQLND * conn,
- const char * const user,
- const char * const passwd,
- const char * const db,
- size_t db_len,
+mysqlnd_switch_to_ssl_if_needed(
+ MYSQLND_CONN_DATA * conn,
const MYSQLND_PACKET_GREET * const greet_packet,
const MYSQLND_OPTIONS * const options,
unsigned long mysql_flags
- TSRMLS_DC)
+ TSRMLS_DC
+ )
{
- const MYSQLND_CHARSET * charset = NULL;
enum_func_status ret = FAIL;
- MYSQLND_PACKET_AUTH * auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE TSRMLS_CC);
- MYSQLND_PACKET_OK * ok_packet = conn->protocol->m.get_ok_packet(conn->protocol, FALSE TSRMLS_CC);
-
- DBG_ENTER("mysqlnd_connect_run_authentication");
-
- if (!auth_packet || !ok_packet) {
- SET_OOM_ERROR(conn->error_info);
- goto err;
- }
+ const MYSQLND_CHARSET * charset;
+ MYSQLND_PACKET_AUTH * auth_packet;
+ DBG_ENTER("mysqlnd_switch_to_ssl_if_needed");
-#ifdef MYSQLND_SSL_SUPPORTED
- if ((greet_packet->server_capabilities & CLIENT_SSL) && (mysql_flags & CLIENT_SSL)) {
- auth_packet->send_half_packet = TRUE;
+ auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE TSRMLS_CC);
+ if (!auth_packet) {
+ SET_OOM_ERROR(*conn->error_info);
+ goto end;
}
-#endif
- auth_packet->user = user;
- auth_packet->password = passwd;
+ auth_packet->client_flags = mysql_flags;
+ auth_packet->max_packet_size = MYSQLND_ASSEMBLED_PACKET_MAX_SIZE;
if (options->charset_name && (charset = mysqlnd_find_charset_name(options->charset_name))) {
auth_packet->charset_no = charset->nr;
@@ -469,106 +446,201 @@ mysqlnd_connect_run_authentication(
auth_packet->charset_no = greet_packet->charset_no;
#endif
}
- auth_packet->db = db;
- auth_packet->db_len = db_len;
- auth_packet->max_packet_size= MYSQLND_ASSEBLED_PACKET_MAX_SIZE;
- auth_packet->client_flags= mysql_flags;
-
- conn->scramble = auth_packet->server_scramble_buf = mnd_pemalloc(SCRAMBLE_LENGTH, conn->persistent);
- if (!conn->scramble) {
- SET_OOM_ERROR(conn->error_info);
- goto err;
- }
- memcpy(auth_packet->server_scramble_buf, greet_packet->scramble_buf, SCRAMBLE_LENGTH);
-
- if (!PACKET_WRITE(auth_packet, conn)) {
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
- SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
- goto err;
- }
#ifdef MYSQLND_SSL_SUPPORTED
- if (auth_packet->send_half_packet) {
+ if ((greet_packet->server_capabilities & CLIENT_SSL) && (mysql_flags & CLIENT_SSL)) {
zend_bool verify = mysql_flags & CLIENT_SSL_VERIFY_SERVER_CERT? TRUE:FALSE;
DBG_INF("Switching to SSL");
-
- conn->net->m.set_client_option(conn->net, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char *) &verify TSRMLS_CC);
-
- if (FAIL == conn->net->m.enable_ssl(conn->net TSRMLS_CC)) {
- goto err;
- }
-
- auth_packet->send_half_packet = FALSE;
if (!PACKET_WRITE(auth_packet, conn)) {
CONN_SET_STATE(conn, CONN_QUIT_SENT);
- SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
- goto err;
+ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ goto end;
}
- }
-#endif
+ conn->net->m.set_client_option(conn->net, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char *) &verify TSRMLS_CC);
- if (FAIL == PACKET_READ(ok_packet, conn) || ok_packet->field_count >= 0xFE) {
- if (ok_packet->field_count == 0xFE) {
- /* old authentication with new server !*/
- DBG_ERR(mysqlnd_old_passwd);
- SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
- } else if (ok_packet->field_count == 0xFF) {
- if (ok_packet->sqlstate[0]) {
- strlcpy(conn->error_info.sqlstate, ok_packet->sqlstate, sizeof(conn->error_info.sqlstate));
- DBG_ERR_FMT("ERROR:%u [SQLSTATE:%s] %s", ok_packet->error_no, ok_packet->sqlstate, ok_packet->error);
- }
- conn->error_info.error_no = ok_packet->error_no;
- strlcpy(conn->error_info.error, ok_packet->error, sizeof(conn->error_info.error));
+ if (FAIL == conn->net->m.enable_ssl(conn->net TSRMLS_CC)) {
+ goto end;
}
- goto err;
}
-
- SET_NEW_MESSAGE(conn->last_message, conn->last_message_len,
- ok_packet->message, ok_packet->message_len,
- conn->persistent);
- conn->charset = mysqlnd_find_charset_nr(auth_packet->charset_no);
+#endif
ret = PASS;
-err:
+end:
PACKET_FREE(auth_packet);
- PACKET_FREE(ok_packet);
DBG_RETURN(ret);
}
/* }}} */
-#define MYSQLND_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS | \
- CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | \
- CLIENT_MULTI_RESULTS)
+/* {{{ mysqlnd_connect_run_authentication */
+static enum_func_status
+mysqlnd_connect_run_authentication(
+ MYSQLND_CONN_DATA * conn,
+ const char * const user,
+ const char * const passwd,
+ const char * const db,
+ size_t db_len,
+ size_t passwd_len,
+ const MYSQLND_PACKET_GREET * const greet_packet,
+ const MYSQLND_OPTIONS * const options,
+ unsigned long mysql_flags
+ TSRMLS_DC)
+{
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_connect_run_authentication");
+ ret = mysqlnd_switch_to_ssl_if_needed(conn, greet_packet, options, mysql_flags TSRMLS_CC);
+ if (PASS == ret) {
+ zend_bool first_call = TRUE;
+ char * switch_to_auth_protocol = NULL;
+ size_t switch_to_auth_protocol_len = 0;
+ char * requested_protocol = NULL;
+ zend_uchar * plugin_data;
+ size_t plugin_data_len;
-/* {{{ mysqlnd_conn::connect */
+ plugin_data_len = greet_packet->auth_plugin_data_len;
+ plugin_data = mnd_emalloc(plugin_data_len + 1);
+ if (!plugin_data) {
+ ret = FAIL;
+ goto end;
+ }
+ memcpy(plugin_data, greet_packet->auth_plugin_data, plugin_data_len);
+ plugin_data[plugin_data_len] = '\0';
+
+ requested_protocol = mnd_pestrdup(greet_packet->auth_protocol? greet_packet->auth_protocol: "mysql_native_password", FALSE);
+ if (!requested_protocol) {
+ ret = FAIL;
+ goto end;
+ }
+
+ do {
+ struct st_mysqlnd_authentication_plugin * auth_plugin;
+ {
+ char * plugin_name = NULL;
+
+ mnd_sprintf(&plugin_name, 0, "auth_plugin_%s", requested_protocol);
+
+ DBG_INF_FMT("looking for %s auth plugin", plugin_name);
+ auth_plugin = mysqlnd_plugin_find(plugin_name);
+ mnd_sprintf_free(plugin_name);
+
+ if (!auth_plugin) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The server requested authentication method unknown to the client [%s]", requested_protocol);
+ SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "The server requested authentication method umknown to the client");
+ break;
+ }
+ }
+ DBG_INF("plugin found");
+
+ {
+ zend_uchar * switch_to_auth_protocol_data = NULL;
+ size_t switch_to_auth_protocol_data_len = 0;
+ zend_uchar * scrambled_data = NULL;
+ size_t scrambled_data_len = 0;
+
+ switch_to_auth_protocol = NULL;
+ switch_to_auth_protocol_len = 0;
+
+ if (conn->auth_plugin_data) {
+ mnd_pefree(conn->auth_plugin_data, conn->persistent);
+ conn->auth_plugin_data = NULL;
+ }
+ conn->auth_plugin_data_len = plugin_data_len;
+ conn->auth_plugin_data = mnd_pemalloc(conn->auth_plugin_data_len, conn->persistent);
+ if (!conn->auth_plugin_data) {
+ SET_OOM_ERROR(*conn->error_info);
+ goto end;
+ }
+ memcpy(conn->auth_plugin_data, plugin_data, plugin_data_len);
+
+ DBG_INF_FMT("salt=[%*s]", plugin_data_len - 1, plugin_data);
+ /* The data should be allocated with malloc() */
+ scrambled_data =
+ auth_plugin->methods.get_auth_data(NULL, &scrambled_data_len, conn, user, passwd, passwd_len,
+ plugin_data, plugin_data_len, options, mysql_flags TSRMLS_CC);
+
+
+ ret = mysqlnd_auth_handshake(conn, user, passwd, passwd_len, db, db_len, options, mysql_flags,
+ greet_packet->charset_no,
+ first_call,
+ requested_protocol,
+ scrambled_data, scrambled_data_len,
+ &switch_to_auth_protocol, &switch_to_auth_protocol_len,
+ &switch_to_auth_protocol_data, &switch_to_auth_protocol_data_len
+ TSRMLS_CC);
+ first_call = FALSE;
+ free(scrambled_data);
+
+ DBG_INF_FMT("switch_to_auth_protocol=%s", switch_to_auth_protocol? switch_to_auth_protocol:"n/a");
+ if (requested_protocol && switch_to_auth_protocol) {
+ mnd_efree(requested_protocol);
+ requested_protocol = switch_to_auth_protocol;
+ }
+
+ if (plugin_data) {
+ mnd_efree(plugin_data);
+ }
+ plugin_data_len = switch_to_auth_protocol_data_len;
+ plugin_data = switch_to_auth_protocol_data;
+ }
+ DBG_INF_FMT("conn->error_info->error_no = %d", conn->error_info->error_no);
+ } while (ret == FAIL && conn->error_info->error_no == 0 && switch_to_auth_protocol != NULL);
+ if (plugin_data) {
+ mnd_efree(plugin_data);
+ }
+
+ if (ret == PASS) {
+ DBG_INF_FMT("saving requested_protocol=%s", requested_protocol);
+ conn->m->set_client_option(conn, MYSQLND_OPT_AUTH_PROTOCOL, requested_protocol TSRMLS_CC);
+ }
+
+ if (requested_protocol) {
+ mnd_efree(requested_protocol);
+ }
+ }
+end:
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_conn_data::connect */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
+MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,
const char *host, const char *user,
const char *passwd, unsigned int passwd_len,
const char *db, unsigned int db_len,
unsigned int port,
- const char * socket_or_pipe,
+ const char *socket_or_pipe,
unsigned int mysql_flags
TSRMLS_DC)
{
- char *errstr = NULL;
- int errcode = 0, host_len;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, connect);
+ size_t host_len;
zend_bool unix_socket = FALSE;
+ zend_bool named_pipe = FALSE;
zend_bool reconnect = FALSE;
zend_bool saved_compression = FALSE;
+ zend_bool local_tx_started = FALSE;
MYSQLND_PACKET_GREET * greet_packet = NULL;
- DBG_ENTER("mysqlnd_conn::connect");
+ DBG_ENTER("mysqlnd_conn_data::connect");
+
+ if (PASS != conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ goto err;
+ }
+ local_tx_started = TRUE;
+
+ SET_EMPTY_ERROR(*conn->error_info);
+ SET_ERROR_AFF_ROWS(conn);
DBG_INF_FMT("host=%s user=%s db=%s port=%u flags=%u persistent=%u state=%u",
host?host:"", user?user:"", db?db:"", port, mysql_flags,
conn? conn->persistent:0, conn? CONN_GET_STATE(conn):-1);
- if (conn && CONN_GET_STATE(conn) > CONN_ALLOCED && CONN_GET_STATE(conn) ) {
+ if (CONN_GET_STATE(conn) > CONN_ALLOCED && CONN_GET_STATE(conn) ) {
DBG_INF("Connecting on a connected handle.");
if (CONN_GET_STATE(conn) < CONN_QUIT_SENT) {
@@ -592,6 +664,9 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
saved_compression = TRUE;
conn->net->compressed = FALSE;
}
+ } else {
+ unsigned int max_allowed_size = MYSQLND_ASSEMBLED_PACKET_MAX_SIZE;
+ conn->m->set_client_option(conn, MYSQLND_OPT_MAX_ALLOWED_PACKET, (char *)&max_allowed_size TSRMLS_CC);
}
if (!host || !host[0]) {
@@ -622,24 +697,31 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
if (!socket_or_pipe) {
socket_or_pipe = "/tmp/mysql.sock";
}
- transport_len = spprintf(&transport, 0, "unix://%s", socket_or_pipe);
+ transport_len = mnd_sprintf(&transport, 0, "unix://%s", socket_or_pipe);
unix_socket = TRUE;
- } else
+#else
+ if (host_len == sizeof(".") - 1 && host[0] == '.') {
+ /* named pipe in socket */
+ if (!socket_or_pipe) {
+ socket_or_pipe = "\\\\.\\pipe\\MySQL";
+ }
+ transport_len = mnd_sprintf(&transport, 0, "pipe://%s", socket_or_pipe);
+ named_pipe = TRUE;
#endif
- {
+ } else {
if (!port) {
port = 3306;
}
- transport_len = spprintf(&transport, 0, "tcp://%s:%u", host, port);
+ transport_len = mnd_sprintf(&transport, 0, "tcp://%s:%u", host, port);
}
if (!transport) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
goto err; /* OOM */
}
DBG_INF_FMT("transport=%s conn->scheme=%s", transport, conn->scheme);
conn->scheme = mnd_pestrndup(transport, transport_len, conn->persistent);
conn->scheme_len = transport_len;
- efree(transport); /* allocated by spprintf */
+ mnd_sprintf_free(transport);
transport = NULL;
if (!conn->scheme) {
goto err; /* OOM */
@@ -648,11 +730,13 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
greet_packet = conn->protocol->m.get_greet_packet(conn->protocol, FALSE TSRMLS_CC);
if (!greet_packet) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
goto err; /* OOM */
}
- if (FAIL == conn->net->m.connect(conn->net, conn->scheme, conn->scheme_len, conn->persistent, &errstr, &errcode TSRMLS_CC)) {
+ if (FAIL == conn->net->m.connect_ex(conn->net, conn->scheme, conn->scheme_len, conn->persistent,
+ conn->stats, conn->error_info TSRMLS_CC))
+ {
goto err;
}
@@ -664,13 +748,13 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
goto err;
} else if (greet_packet->error_no) {
DBG_ERR_FMT("errorno=%u error=%s", greet_packet->error_no, greet_packet->error);
- SET_CLIENT_ERROR(conn->error_info, greet_packet->error_no, greet_packet->sqlstate, greet_packet->error);
+ SET_CLIENT_ERROR(*conn->error_info, greet_packet->error_no, greet_packet->sqlstate, greet_packet->error);
goto err;
} else if (greet_packet->pre41) {
DBG_ERR_FMT("Connecting to 3.22, 3.23 & 4.0 is not supported. Server is %-.32s", greet_packet->server_version);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connecting to 3.22, 3.23 & 4.0 "
" is not supported. Server is %-.32s", greet_packet->server_version);
- SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
+ SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
"Connecting to 3.22, 3.23 & 4.0 servers is not supported");
goto err;
}
@@ -683,12 +767,11 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
if (!conn->greet_charset) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"Server sent charset (%d) unknown to the client. Please, report to the developers", greet_packet->charset_no);
- SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
+ SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
"Server sent charset unknown to the client. Please, report to the developers");
goto err;
}
/* we allow load data local infile by default */
- mysql_flags |= CLIENT_LOCAL_FILES | CLIENT_PS_MULTI_RESULTS;
mysql_flags |= MYSQLND_CAPABILITIES;
mysql_flags |= conn->options.flags; /* use the flags from set_client_option() */
@@ -722,7 +805,9 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
}
#endif
- if (FAIL == mysqlnd_connect_run_authentication(conn, user, passwd, db, db_len, greet_packet, &conn->options, mysql_flags TSRMLS_CC)) {
+ if (FAIL == mysqlnd_connect_run_authentication(conn, user, passwd, db, db_len, (size_t) passwd_len,
+ greet_packet, conn->options, mysql_flags TSRMLS_CC))
+ {
goto err;
}
@@ -748,49 +833,66 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
conn->connect_or_select_db_len = db_len;
if (!conn->user || !conn->passwd || !conn->connect_or_select_db) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
goto err; /* OOM */
}
- if (!unix_socket) {
+ if (!unix_socket && !named_pipe) {
conn->host = mnd_pestrdup(host, conn->persistent);
if (!conn->host) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
goto err; /* OOM */
}
conn->host_len = strlen(conn->host);
{
char *p;
- spprintf(&p, 0, "%s via TCP/IP", conn->host);
+ mnd_sprintf(&p, 0, "%s via TCP/IP", conn->host);
if (!p) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
goto err; /* OOM */
}
conn->host_info = mnd_pestrdup(p, conn->persistent);
- efree(p); /* allocated by spprintf */
+ mnd_sprintf_free(p);
if (!conn->host_info) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
goto err; /* OOM */
}
}
} else {
- conn->unix_socket = mnd_pestrdup(socket_or_pipe, conn->persistent);
- conn->host_info = mnd_pestrdup("Localhost via UNIX socket", conn->persistent);
+ conn->unix_socket = mnd_pestrdup(socket_or_pipe, conn->persistent);
+ if (unix_socket) {
+ conn->host_info = mnd_pestrdup("Localhost via UNIX socket", conn->persistent);
+ } else if (named_pipe) {
+ char *p;
+ mnd_sprintf(&p, 0, "%s via named pipe", conn->unix_socket);
+ if (!p) {
+ SET_OOM_ERROR(*conn->error_info);
+ goto err; /* OOM */
+ }
+ conn->host_info = mnd_pestrdup(p, conn->persistent);
+ mnd_sprintf_free(p);
+ if (!conn->host_info) {
+ SET_OOM_ERROR(*conn->error_info);
+ goto err; /* OOM */
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Impossible. Should be either socket or a pipe. Report a bug!");
+ }
if (!conn->unix_socket || !conn->host_info) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
goto err; /* OOM */
}
conn->unix_socket_len = strlen(conn->unix_socket);
}
conn->client_flag = mysql_flags;
- conn->max_packet_size = MYSQLND_ASSEBLED_PACKET_MAX_SIZE;
+ conn->max_packet_size = MYSQLND_ASSEMBLED_PACKET_MAX_SIZE;
/* todo: check if charset is available */
conn->server_capabilities = greet_packet->server_capabilities;
- conn->upsert_status.warning_count = 0;
- conn->upsert_status.server_status = greet_packet->server_status;
- conn->upsert_status.affected_rows = 0;
+ conn->upsert_status->warning_count = 0;
+ conn->upsert_status->server_status = greet_packet->server_status;
+ conn->upsert_status->affected_rows = 0;
- SET_EMPTY_ERROR(conn->error_info);
+ SET_EMPTY_ERROR(*conn->error_info);
mysqlnd_local_infile_default(conn);
@@ -801,10 +903,10 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
DBG_INF("unicode set");
}
#endif
- if (conn->options.init_commands) {
+ if (conn->options->init_commands) {
unsigned int current_command = 0;
- for (; current_command < conn->options.num_commands; ++current_command) {
- const char * const command = conn->options.init_commands[current_command];
+ for (; current_command < conn->options->num_commands; ++current_command) {
+ const char * const command = conn->options->init_commands[current_command];
if (command) {
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_INIT_COMMAND_EXECUTED_COUNT);
if (PASS != conn->m->query(conn, command, strlen(command) TSRMLS_CC)) {
@@ -834,33 +936,63 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
PACKET_FREE(greet_packet);
+ conn->m->local_tx_end(conn, this_func, PASS TSRMLS_CC);
DBG_RETURN(PASS);
}
err:
PACKET_FREE(greet_packet);
- if (errstr) {
- DBG_ERR_FMT("[%u] %.128s (trying to connect via %s)", errcode, errstr, conn->scheme);
- SET_CLIENT_ERROR(conn->error_info, errcode? errcode:CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, errstr);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "[%u] %.128s (trying to connect via %s)", errcode, errstr, conn->scheme);
- /* no mnd_ since we don't allocate it */
- efree(errstr);
+ DBG_ERR_FMT("[%u] %.128s (trying to connect via %s)", conn->error_info->error_no, conn->error_info->error, conn->scheme);
+ if (!conn->error_info->error_no) {
+ SET_CLIENT_ERROR(*conn->error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, conn->error_info->error? conn->error_info->error:"Unknown error");
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "[%u] %.128s (trying to connect via %s)",
+ conn->error_info->error_no, conn->error_info->error, conn->scheme);
}
+
conn->m->free_contents(conn TSRMLS_CC);
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_CONNECT_FAILURE);
+ if (TRUE == local_tx_started) {
+ conn->m->local_tx_end(conn, this_func, FAIL TSRMLS_CC);
+ }
DBG_RETURN(FAIL);
}
/* }}} */
+/* {{{ mysqlnd_conn::connect */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn_handle,
+ const char * host, const char * user,
+ const char * passwd, unsigned int passwd_len,
+ const char * db, unsigned int db_len,
+ unsigned int port,
+ const char * socket_or_pipe,
+ unsigned int mysql_flags
+ TSRMLS_DC)
+{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, connect);
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = conn_handle->data;
+
+ DBG_ENTER("mysqlnd_conn::connect");
+
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ ret = conn->m->connect(conn, host, user, passwd, passwd_len, db, db_len, port, socket_or_pipe, mysql_flags TSRMLS_CC);
+
+ conn->m->local_tx_end(conn, this_func, FAIL TSRMLS_CC);
+ }
+ DBG_RETURN(ret);
+}
+/* }}} */
+
/* {{{ mysqlnd_connect */
-PHPAPI MYSQLND * mysqlnd_connect(MYSQLND * conn,
- const char *host, const char *user,
- const char *passwd, unsigned int passwd_len,
- const char *db, unsigned int db_len,
+PHPAPI MYSQLND * mysqlnd_connect(MYSQLND * conn_handle,
+ const char * host, const char * user,
+ const char * passwd, unsigned int passwd_len,
+ const char * db, unsigned int db_len,
unsigned int port,
- const char *socket_or_pipe,
+ const char * socket_or_pipe,
unsigned int mysql_flags
TSRMLS_DC)
{
@@ -870,15 +1002,15 @@ PHPAPI MYSQLND * mysqlnd_connect(MYSQLND * conn,
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) {
+ if (!conn_handle) {
self_alloced = TRUE;
- if (!(conn = mysqlnd_init(FALSE))) {
+ if (!(conn_handle = mysqlnd_init(FALSE))) {
/* OOM */
DBG_RETURN(NULL);
}
}
- ret = conn->m->connect(conn, host, user, passwd, passwd_len, db, db_len, port, socket_or_pipe, mysql_flags TSRMLS_CC);
+ ret = conn_handle->m->connect(conn_handle, host, user, passwd, passwd_len, db, db_len, port, socket_or_pipe, mysql_flags TSRMLS_CC);
if (ret == FAIL) {
if (self_alloced) {
@@ -886,215 +1018,88 @@ PHPAPI MYSQLND * mysqlnd_connect(MYSQLND * conn,
We have alloced, thus there are no references to this
object - we are free to kill it!
*/
- conn->m->dtor(conn TSRMLS_CC);
+ conn_handle->m->dtor(conn_handle TSRMLS_CC);
}
DBG_RETURN(NULL);
}
- DBG_RETURN(conn);
+ DBG_RETURN(conn_handle);
}
/* }}} */
-/* {{{ mysqlnd_conn::change_user */
-static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, change_user)(MYSQLND * const conn,
- const char *user,
- const char *passwd,
- const char *db,
- zend_bool silent TSRMLS_DC)
-{
- size_t user_len;
- enum_func_status ret = FAIL;
- MYSQLND_PACKET_CHG_USER_RESPONSE * chg_user_resp;
- char buffer[MYSQLND_MAX_ALLOWED_USER_LEN + 1 + 1 + SCRAMBLE_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1 + 2 /* charset*/ + 2];
- char *p = buffer;
- const MYSQLND_CHARSET * old_cs = conn->charset;
-
- DBG_ENTER("mysqlnd_conn::change_user");
- DBG_INF_FMT("conn=%llu user=%s passwd=%s db=%s silent=%u",
- conn->thread_id, user?user:"", passwd?"***":"null", db?db:"", (silent == TRUE)?1:0 );
-
- SET_ERROR_AFF_ROWS(conn);
-
- if (!user) {
- user = "";
- }
- if (!passwd) {
- passwd = "";
- }
- if (!db) {
- db = "";
- }
-
- /* 1. user ASCIIZ */
- user_len = MIN(strlen(user), MYSQLND_MAX_ALLOWED_USER_LEN);
- memcpy(p, user, user_len);
- p += user_len;
- *p++ = '\0';
-
- /* 2. password SCRAMBLE_LENGTH followed by the scramble or \0 */
- if (passwd[0]) {
- *p++ = SCRAMBLE_LENGTH;
- php_mysqlnd_scramble((unsigned char *)p, conn->scramble, (unsigned char *)passwd);
- p += SCRAMBLE_LENGTH;
- } else {
- *p++ = '\0';
- }
-
- /* 3. db ASCIIZ */
- if (db[0]) {
- size_t db_len = MIN(strlen(db), MYSQLND_MAX_ALLOWED_DB_LEN);
- memcpy(p, db, db_len);
- p += db_len;
- }
- *p++ = '\0';
-
- /*
- 4. request the current charset, or it will be reset to the system one.
- 5.0 doesn't support it. Support added in 5.1.23 by fixing the following bug :
- Bug #30472 libmysql doesn't reset charset, insert_id after succ. mysql_change_user() call
- */
- if (mysqlnd_get_server_version(conn) >= 50123) {
- int2store(p, conn->charset->nr);
- p+=2;
- }
-
- if (PASS != conn->m->simple_command(conn, COM_CHANGE_USER, buffer, p - buffer,
- PROT_LAST /* we will handle the OK packet*/,
- silent, TRUE TSRMLS_CC)) {
- DBG_RETURN(FAIL);
- }
-
- chg_user_resp = conn->protocol->m.get_change_user_response_packet(conn->protocol, FALSE TSRMLS_CC);
- if (!chg_user_resp) {
- SET_OOM_ERROR(conn->error_info);
- goto end;
- }
- ret = PACKET_READ(chg_user_resp, conn);
- conn->error_info = chg_user_resp->error_info;
-
- if (conn->error_info.error_no) {
- ret = FAIL;
- /*
- COM_CHANGE_USER is broken in 5.1. At least in 5.1.15 and 5.1.14, 5.1.11 is immune.
- bug#25371 mysql_change_user() triggers "packets out of sync"
- When it gets fixed, there should be one more check here
- */
- if (mysqlnd_get_server_version(conn) > 50113L && mysqlnd_get_server_version(conn) < 50118L) {
- MYSQLND_PACKET_OK * redundant_error_packet = conn->protocol->m.get_ok_packet(conn->protocol, FALSE TSRMLS_CC);
- if (redundant_error_packet) {
- PACKET_READ(redundant_error_packet, conn);
- PACKET_FREE(redundant_error_packet);
- DBG_INF_FMT("Server is %u, buggy, sends two ERR messages", mysqlnd_get_server_version(conn));
- } else {
- SET_OOM_ERROR(conn->error_info);
- }
- }
- }
- if (ret == PASS) {
- char * tmp = NULL;
- /* if we get conn->user as parameter and then we first free it, then estrndup it, we will crash */
- tmp = mnd_pestrndup(user, user_len, conn->persistent);
- if (conn->user) {
- mnd_pefree(conn->user, conn->persistent);
- }
- conn->user = tmp;
-
- tmp = mnd_pestrdup(passwd, conn->persistent);
- if (conn->passwd) {
- mnd_pefree(conn->passwd, conn->persistent);
- }
- conn->passwd = tmp;
-
- if (conn->last_message) {
- mnd_pefree(conn->last_message, conn->persistent);
- conn->last_message = NULL;
- }
- memset(&conn->upsert_status, 0, sizeof(conn->upsert_status));
- /* set charset for old servers */
- if (mysqlnd_get_server_version(conn) < 50123) {
- ret = conn->m->set_charset(conn, old_cs->name TSRMLS_CC);
- }
- } else if (ret == FAIL && chg_user_resp->server_asked_323_auth == TRUE) {
- /* old authentication with new server !*/
- DBG_ERR(mysqlnd_old_passwd);
- SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
- }
-end:
- PACKET_FREE(chg_user_resp);
-
- /*
- Here we should close all statements. Unbuffered queries should not be a
- problem as we won't allow sending COM_CHANGE_USER.
- */
- DBG_INF(ret == PASS? "PASS":"FAIL");
- DBG_RETURN(ret);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_conn::query */
+/* {{{ mysqlnd_conn_data::query */
/*
- If conn->error_info.error_no is not zero, then we had an error.
+ If conn->error_info->error_no is not zero, then we had an error.
Still the result from the query is PASS
*/
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, query)(MYSQLND * conn, const char * query, unsigned int query_len TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, query)(MYSQLND_CONN_DATA * conn, const char * query, unsigned int query_len TSRMLS_DC)
{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, query);
enum_func_status ret = FAIL;
- DBG_ENTER("mysqlnd_conn::query");
+ DBG_ENTER("mysqlnd_conn_data::query");
DBG_INF_FMT("conn=%llu query=%s", conn->thread_id, query);
- if (PASS == conn->m->send_query(conn, query, query_len TSRMLS_CC) &&
- PASS == conn->m->reap_query(conn TSRMLS_CC))
- {
- ret = PASS;
- if (conn->last_query_type == QUERY_UPSERT && conn->upsert_status.affected_rows) {
- MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_NORMAL, conn->upsert_status.affected_rows);
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ if (PASS == conn->m->send_query(conn, query, query_len TSRMLS_CC) &&
+ PASS == conn->m->reap_query(conn TSRMLS_CC))
+ {
+ ret = PASS;
+ if (conn->last_query_type == QUERY_UPSERT && conn->upsert_status->affected_rows) {
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_NORMAL, conn->upsert_status->affected_rows);
+ }
}
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
}
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::send_query */
+/* {{{ mysqlnd_conn_data::send_query */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, send_query)(MYSQLND * conn, const char * query, unsigned int query_len TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, send_query)(MYSQLND_CONN_DATA * conn, const char * query, unsigned int query_len TSRMLS_DC)
{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, send_query);
enum_func_status ret;
- DBG_ENTER("mysqlnd_conn::send_query");
+ DBG_ENTER("mysqlnd_conn_data::send_query");
DBG_INF_FMT("conn=%llu query=%s", conn->thread_id, query);
- ret = conn->m->simple_command(conn, COM_QUERY, query, query_len,
- PROT_LAST /* we will handle the OK packet*/,
- FALSE, FALSE TSRMLS_CC);
- if (PASS == ret) {
- CONN_SET_STATE(conn, CONN_QUERY_SENT);
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ ret = conn->m->simple_command(conn, COM_QUERY, (zend_uchar *) query, query_len,
+ PROT_LAST /* we will handle the OK packet*/,
+ FALSE, FALSE TSRMLS_CC);
+ if (PASS == ret) {
+ CONN_SET_STATE(conn, CONN_QUERY_SENT);
+ }
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
}
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::reap_query */
+/* {{{ mysqlnd_conn_data::reap_query */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, reap_query)(MYSQLND * conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, reap_query)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, reap_query);
enum_mysqlnd_connection_state state = CONN_GET_STATE(conn);
- DBG_ENTER("mysqlnd_conn::reap_query");
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_conn_data::reap_query");
DBG_INF_FMT("conn=%llu", conn->thread_id);
- if (state <= CONN_READY || state == CONN_QUIT_SENT) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not opened, clear or has been closed");
- DBG_ERR_FMT("Connection not opened, clear or has been closed. State=%u", state);
- DBG_RETURN(FAIL);
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ if (state <= CONN_READY || state == CONN_QUIT_SENT) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not opened, clear or has been closed");
+ DBG_ERR_FMT("Connection not opened, clear or has been closed. State=%u", state);
+ DBG_RETURN(ret);
+ }
+ ret = conn->m->query_read_result_set_header(conn, NULL TSRMLS_CC);
+
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
}
- /*
- Here read the result set. We don't do it in simple_command because it need
- information from the ok packet. We will fetch it ourselves.
- */
- DBG_RETURN(conn->m->query_read_result_set_header(conn, NULL TSRMLS_CC));
+ DBG_RETURN(ret);
}
/* }}} */
@@ -1108,7 +1113,7 @@ MYSQLND ** mysqlnd_stream_array_check_for_readiness(MYSQLND ** conn_array TSRMLS
MYSQLND **ret = NULL;
while (*p) {
- if (CONN_GET_STATE(*p) <= CONN_READY || CONN_GET_STATE(*p) == CONN_QUIT_SENT) {
+ if (CONN_GET_STATE((*p)->data) <= CONN_READY || CONN_GET_STATE((*p)->data) == CONN_QUIT_SENT) {
cnt++;
}
p++;
@@ -1117,7 +1122,7 @@ MYSQLND ** mysqlnd_stream_array_check_for_readiness(MYSQLND ** conn_array TSRMLS
MYSQLND **ret_p = ret = ecalloc(cnt + 1, sizeof(MYSQLND *));
p_p = p = conn_array;
while (*p) {
- if (CONN_GET_STATE(*p) <= CONN_READY || CONN_GET_STATE(*p) == CONN_QUIT_SENT) {
+ if (CONN_GET_STATE((*p)->data) <= CONN_READY || CONN_GET_STATE((*p)->data) == CONN_QUIT_SENT) {
*ret_p = *p;
*p = NULL;
ret_p++;
@@ -1134,7 +1139,7 @@ MYSQLND ** mysqlnd_stream_array_check_for_readiness(MYSQLND ** conn_array TSRMLS
/* {{{ stream_select mysqlnd_stream_array_to_fd_set functions */
-static int mysqlnd_stream_array_to_fd_set(MYSQLND **conn_array, fd_set *fds, php_socket_t *max_fd TSRMLS_DC)
+static int mysqlnd_stream_array_to_fd_set(MYSQLND ** conn_array, fd_set * fds, php_socket_t * max_fd TSRMLS_DC)
{
php_socket_t this_fd;
int cnt = 0;
@@ -1146,7 +1151,7 @@ static int mysqlnd_stream_array_to_fd_set(MYSQLND **conn_array, fd_set *fds, php
* when casting. It is only used here so that the buffered data warning
* is not displayed.
* */
- if (SUCCESS == php_stream_cast((*p)->net->stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL,
+ if (SUCCESS == php_stream_cast((*p)->data->net->stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL,
(void*)&this_fd, 1) && this_fd >= 0) {
PHP_SAFE_FD_SET(this_fd, fds);
@@ -1161,7 +1166,7 @@ static int mysqlnd_stream_array_to_fd_set(MYSQLND **conn_array, fd_set *fds, php
return cnt ? 1 : 0;
}
-static int mysqlnd_stream_array_from_fd_set(MYSQLND **conn_array, fd_set *fds TSRMLS_DC)
+static int mysqlnd_stream_array_from_fd_set(MYSQLND ** conn_array, fd_set * fds TSRMLS_DC)
{
php_socket_t this_fd;
int ret = 0;
@@ -1171,7 +1176,7 @@ static int mysqlnd_stream_array_from_fd_set(MYSQLND **conn_array, fd_set *fds TS
MYSQLND **fwd = conn_array, **bckwd = conn_array;
while (*fwd) {
- if (SUCCESS == php_stream_cast((*fwd)->net->stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL,
+ if (SUCCESS == php_stream_cast((*fwd)->data->net->stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL,
(void*)&this_fd, 1) && this_fd >= 0) {
if (PHP_SAFE_FD_ISSET(this_fd, fds)) {
if (disproportion) {
@@ -1192,25 +1197,26 @@ static int mysqlnd_stream_array_from_fd_set(MYSQLND **conn_array, fd_set *fds TS
}
/* }}} */
+
#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, uint * desc_num TSRMLS_DC)
{
-
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");
+ DBG_ENTER("_mysqlnd_poll");
if (sec < 0 || usec < 0) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Negative values passed for sec and/or usec");
DBG_RETURN(FAIL);
@@ -1273,7 +1279,6 @@ _mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQLND ***dont_poll, long s
}
*desc_num = retval;
-
DBG_RETURN(PASS);
}
/* }}} */
@@ -1286,322 +1291,385 @@ _mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQLND ***dont_poll, long s
- The EOF packet is consumed by the metadata packet reader.
*/
-/* {{{ mysqlnd_conn::list_fields */
+/* {{{ mysqlnd_conn_data::list_fields */
MYSQLND_RES *
-MYSQLND_METHOD(mysqlnd_conn, list_fields)(MYSQLND * conn, const char *table, const char *achtung_wild TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, list_fields)(MYSQLND_CONN_DATA * conn, const char *table, const char *achtung_wild TSRMLS_DC)
{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, list_fields);
/* db + \0 + wild + \0 (for wild) */
- char buff[MYSQLND_MAX_ALLOWED_DB_LEN * 2 + 1 + 1], *p;
+ zend_uchar buff[MYSQLND_MAX_ALLOWED_DB_LEN * 2 + 1 + 1], *p;
size_t table_len, wild_len;
- MYSQLND_RES *result = NULL;
- DBG_ENTER("mysqlnd_conn::list_fields");
+ MYSQLND_RES * result = NULL;
+ DBG_ENTER("mysqlnd_conn_data::list_fields");
DBG_INF_FMT("conn=%llu table=%s wild=%s", conn->thread_id, table? table:"",achtung_wild? achtung_wild:"");
- p = buff;
- if (table && (table_len = strlen(table))) {
- size_t to_copy = MIN(table_len, MYSQLND_MAX_ALLOWED_DB_LEN);
- memcpy(p, table, to_copy);
- p += to_copy;
- *p++ = '\0';
- }
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ do {
+ p = buff;
+ if (table && (table_len = strlen(table))) {
+ size_t to_copy = MIN(table_len, MYSQLND_MAX_ALLOWED_DB_LEN);
+ memcpy(p, table, to_copy);
+ p += to_copy;
+ *p++ = '\0';
+ }
- if (achtung_wild && (wild_len = strlen(achtung_wild))) {
- size_t to_copy = MIN(wild_len, MYSQLND_MAX_ALLOWED_DB_LEN);
- memcpy(p, achtung_wild, to_copy);
- p += to_copy;
- *p++ = '\0';
- }
+ if (achtung_wild && (wild_len = strlen(achtung_wild))) {
+ size_t to_copy = MIN(wild_len, MYSQLND_MAX_ALLOWED_DB_LEN);
+ memcpy(p, achtung_wild, to_copy);
+ p += to_copy;
+ *p++ = '\0';
+ }
- if (PASS != conn->m->simple_command(conn, COM_FIELD_LIST, buff, p - buff,
- PROT_LAST /* we will handle the OK packet*/,
- FALSE, TRUE TSRMLS_CC)) {
- DBG_RETURN(NULL);
- }
+ if (PASS != conn->m->simple_command(conn, COM_FIELD_LIST, buff, p - buff,
+ PROT_LAST /* we will handle the OK packet*/,
+ FALSE, TRUE TSRMLS_CC)) {
+ conn->m->local_tx_end(conn, 0, FAIL TSRMLS_CC);
+ break;
+ }
- /*
- Prepare for the worst case.
- MyISAM goes to 2500 BIT columns, double it for safety.
- */
- result = conn->m->result_init(5000, conn->persistent TSRMLS_CC);
- if (!result) {
- DBG_RETURN(NULL);
- }
+ /*
+ Prepare for the worst case.
+ MyISAM goes to 2500 BIT columns, double it for safety.
+ */
+ result = conn->m->result_init(5000, conn->persistent TSRMLS_CC);
+ if (!result) {
+ break;
+ }
- if (FAIL == result->m.read_result_metadata(result, conn TSRMLS_CC)) {
- DBG_ERR("Error ocurred while reading metadata");
- result->m.free_result(result, TRUE TSRMLS_CC);
- DBG_RETURN(NULL);
- }
+ if (FAIL == result->m.read_result_metadata(result, conn TSRMLS_CC)) {
+ DBG_ERR("Error ocurred while reading metadata");
+ result->m.free_result(result, TRUE TSRMLS_CC);
+ result = NULL;
+ break;
+ }
- result->type = MYSQLND_RES_NORMAL;
- result->m.fetch_row = result->m.fetch_row_normal_unbuffered;
- result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
- if (!result->unbuf) {
- /* OOM */
- SET_OOM_ERROR(conn->error_info);
- result->m.free_result(result, TRUE TSRMLS_CC);
- DBG_RETURN(NULL);
+ result->type = MYSQLND_RES_NORMAL;
+ result->m.fetch_row = result->m.fetch_row_normal_unbuffered;
+ result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
+ if (!result->unbuf) {
+ /* OOM */
+ SET_OOM_ERROR(*conn->error_info);
+ result->m.free_result(result, TRUE TSRMLS_CC);
+ result = NULL;
+ break;
+ }
+ result->unbuf->eof_reached = TRUE;
+ } while (0);
+ conn->m->local_tx_end(conn, this_func, result == NULL? FAIL:PASS TSRMLS_CC);
}
- result->unbuf->eof_reached = TRUE;
DBG_RETURN(result);
}
/* }}} */
-/* {{{ mysqlnd_conn::list_method */
+/* {{{ mysqlnd_conn_data::list_method */
MYSQLND_RES *
-MYSQLND_METHOD(mysqlnd_conn, list_method)(MYSQLND * conn, const char * query, const char *achtung_wild, char *par1 TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, list_method)(MYSQLND_CONN_DATA * conn, const char * query, const char *achtung_wild, char *par1 TSRMLS_DC)
{
- char *show_query = NULL;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, list_method);
+ char * show_query = NULL;
size_t show_query_len;
- MYSQLND_RES *result = NULL;
+ MYSQLND_RES * result = NULL;
- DBG_ENTER("mysqlnd_conn::list_method");
+ DBG_ENTER("mysqlnd_conn_data::list_method");
DBG_INF_FMT("conn=%llu query=%s wild=%u", conn->thread_id, query, achtung_wild);
- if (par1) {
- if (achtung_wild) {
- show_query_len = spprintf(&show_query, 0, query, par1, achtung_wild);
- } else {
- show_query_len = spprintf(&show_query, 0, query, par1);
- }
- } else {
- if (achtung_wild) {
- show_query_len = spprintf(&show_query, 0, query, achtung_wild);
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ if (par1) {
+ if (achtung_wild) {
+ show_query_len = mnd_sprintf(&show_query, 0, query, par1, achtung_wild);
+ } else {
+ show_query_len = mnd_sprintf(&show_query, 0, query, par1);
+ }
} else {
- show_query_len = strlen(show_query = (char *)query);
+ if (achtung_wild) {
+ show_query_len = mnd_sprintf(&show_query, 0, query, achtung_wild);
+ } else {
+ show_query_len = strlen(show_query = (char *)query);
+ }
}
- }
- if (PASS == conn->m->query(conn, show_query, show_query_len TSRMLS_CC)) {
- result = conn->m->store_result(conn TSRMLS_CC);
- }
- if (show_query != query) {
- efree(show_query); /* allocated by spprintf */
+ if (PASS == conn->m->query(conn, show_query, show_query_len TSRMLS_CC)) {
+ result = conn->m->store_result(conn TSRMLS_CC);
+ }
+ if (show_query != query) {
+ mnd_sprintf_free(show_query);
+ }
+ conn->m->local_tx_end(conn, this_func, result == NULL? FAIL:PASS TSRMLS_CC);
}
DBG_RETURN(result);
}
/* }}} */
-/* {{{ mysqlnd_conn::errno */
+/* {{{ mysqlnd_conn_data::errno */
static unsigned int
-MYSQLND_METHOD(mysqlnd_conn, errno)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, errno)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- return conn->error_info.error_no;
+ return conn->error_info->error_no;
}
/* }}} */
-/* {{{ mysqlnd_conn::error */
+/* {{{ mysqlnd_conn_data::error */
static const char *
-MYSQLND_METHOD(mysqlnd_conn, error)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, error)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- return conn->error_info.error;
+ return conn->error_info->error;
}
/* }}} */
-/* {{{ mysqlnd_conn::sqlstate */
+/* {{{ mysqlnd_conn_data::sqlstate */
static const char *
-MYSQLND_METHOD(mysqlnd_conn, sqlstate)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, sqlstate)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- return conn->error_info.sqlstate[0] ? conn->error_info.sqlstate:MYSQLND_SQLSTATE_NULL;
+ return conn->error_info->sqlstate[0] ? conn->error_info->sqlstate:MYSQLND_SQLSTATE_NULL;
}
/* }}} */
/* {{{ mysqlnd_old_escape_string */
-PHPAPI ulong mysqlnd_old_escape_string(char *newstr, const char *escapestr, size_t escapestr_len TSRMLS_DC)
+PHPAPI ulong
+mysqlnd_old_escape_string(char * newstr, const char * escapestr, size_t escapestr_len TSRMLS_DC)
{
DBG_ENTER("mysqlnd_old_escape_string");
DBG_RETURN(mysqlnd_cset_escape_slashes(mysqlnd_find_charset_name("latin1"), newstr, escapestr, escapestr_len TSRMLS_CC));
}
/* }}} */
-/* {{{ mysqlnd_conn::ssl_set */
+
+/* {{{ mysqlnd_conn_data::ssl_set */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, ssl_set)(MYSQLND * const conn, const char * key, const char * const cert, const char * const ca, const char * const capath, const char * const cipher TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, ssl_set)(MYSQLND_CONN_DATA * const conn, const char * key, const char * const cert,
+ const char * const ca, const char * const capath, const char * const cipher TSRMLS_DC)
{
- return (PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_KEY, key TSRMLS_CC) &&
- PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CERT, cert TSRMLS_CC) &&
- PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CA, ca TSRMLS_CC) &&
- PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CAPATH, capath TSRMLS_CC) &&
- PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CIPHER, cipher TSRMLS_CC)) ? PASS : FAIL;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, ssl_set);
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_conn_data::ssl_set");
+
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ ret = (PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_KEY, key TSRMLS_CC) &&
+ PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CERT, cert TSRMLS_CC) &&
+ PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CA, ca TSRMLS_CC) &&
+ PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CAPATH, capath TSRMLS_CC) &&
+ PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CIPHER, cipher TSRMLS_CC)) ? PASS : FAIL;
+
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+ DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::escape_string */
+/* {{{ mysqlnd_conn_data::escape_string */
static ulong
-MYSQLND_METHOD(mysqlnd_conn, escape_string)(MYSQLND * const conn, char *newstr, const char *escapestr, size_t escapestr_len TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, escape_string)(MYSQLND_CONN_DATA * const conn, char * newstr, const char * escapestr, size_t escapestr_len TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_conn::escape_string");
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, escape_string);
+ ulong ret;
+ DBG_ENTER("mysqlnd_conn_data::escape_string");
DBG_INF_FMT("conn=%llu", conn->thread_id);
- if (conn->upsert_status.server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) {
- DBG_RETURN(mysqlnd_cset_escape_quotes(conn->charset, newstr, escapestr, escapestr_len TSRMLS_CC));
+
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ if (conn->upsert_status->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) {
+ ret = mysqlnd_cset_escape_quotes(conn->charset, newstr, escapestr, escapestr_len TSRMLS_CC);
+ } else {
+ ret = mysqlnd_cset_escape_slashes(conn->charset, newstr, escapestr, escapestr_len TSRMLS_CC);
+ }
+ conn->m->local_tx_end(conn, this_func, PASS TSRMLS_CC);
}
- DBG_RETURN(mysqlnd_cset_escape_slashes(conn->charset, newstr, escapestr, escapestr_len TSRMLS_CC));
+ DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::dump_debug_info */
+/* {{{ mysqlnd_conn_data::dump_debug_info */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, dump_debug_info)(MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, dump_debug_info)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_conn::dump_debug_info");
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, server_dump_debug_information);
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_conn_data::dump_debug_info");
DBG_INF_FMT("conn=%llu", conn->thread_id);
- DBG_RETURN(conn->m->simple_command(conn, COM_DEBUG, NULL, 0, PROT_EOF_PACKET, FALSE, TRUE TSRMLS_CC));
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ ret = conn->m->simple_command(conn, COM_DEBUG, NULL, 0, PROT_EOF_PACKET, FALSE, TRUE TSRMLS_CC);
+
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+
+ DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::select_db */
+/* {{{ mysqlnd_conn_data::select_db */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, select_db)(MYSQLND * const conn, const char * const db, unsigned int db_len TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, select_db)(MYSQLND_CONN_DATA * const conn, const char * const db, unsigned int db_len TSRMLS_DC)
{
- enum_func_status ret;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, select_db);
+ enum_func_status ret = FAIL;
- DBG_ENTER("mysqlnd_conn::select_db");
+ DBG_ENTER("mysqlnd_conn_data::select_db");
DBG_INF_FMT("conn=%llu db=%s", conn->thread_id, db);
- ret = conn->m->simple_command(conn, COM_INIT_DB, db, db_len, PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC);
- /*
- The server sends 0 but libmysql doesn't read it and has established
- a protocol of giving back -1. Thus we have to follow it :(
- */
- SET_ERROR_AFF_ROWS(conn);
- if (ret == PASS) {
- if (conn->connect_or_select_db) {
- mnd_pefree(conn->connect_or_select_db, conn->persistent);
- }
- conn->connect_or_select_db = mnd_pestrndup(db, db_len, conn->persistent);
- conn->connect_or_select_db_len = db_len;
- if (!conn->connect_or_select_db) {
- /* OOM */
- SET_OOM_ERROR(conn->error_info);
- ret = FAIL;
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ ret = conn->m->simple_command(conn, COM_INIT_DB, (zend_uchar*) db, db_len, PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC);
+ /*
+ The server sends 0 but libmysql doesn't read it and has established
+ a protocol of giving back -1. Thus we have to follow it :(
+ */
+ SET_ERROR_AFF_ROWS(conn);
+ if (ret == PASS) {
+ if (conn->connect_or_select_db) {
+ mnd_pefree(conn->connect_or_select_db, conn->persistent);
+ }
+ conn->connect_or_select_db = mnd_pestrndup(db, db_len, conn->persistent);
+ conn->connect_or_select_db_len = db_len;
+ if (!conn->connect_or_select_db) {
+ /* OOM */
+ SET_OOM_ERROR(*conn->error_info);
+ ret = FAIL;
+ }
}
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
}
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::ping */
+/* {{{ mysqlnd_conn_data::ping */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, ping)(MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, ping)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- enum_func_status ret;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, ping);
+ enum_func_status ret = FAIL;
- DBG_ENTER("mysqlnd_conn::ping");
+ DBG_ENTER("mysqlnd_conn_data::ping");
DBG_INF_FMT("conn=%llu", conn->thread_id);
- ret = conn->m->simple_command(conn, COM_PING, NULL, 0, PROT_OK_PACKET, TRUE, TRUE TSRMLS_CC);
- /*
- The server sends 0 but libmysql doesn't read it and has established
- a protocol of giving back -1. Thus we have to follow it :(
- */
- SET_ERROR_AFF_ROWS(conn);
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ ret = conn->m->simple_command(conn, COM_PING, NULL, 0, PROT_OK_PACKET, TRUE, TRUE TSRMLS_CC);
+ /*
+ The server sends 0 but libmysql doesn't read it and has established
+ a protocol of giving back -1. Thus we have to follow it :(
+ */
+ SET_ERROR_AFF_ROWS(conn);
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
DBG_INF_FMT("ret=%u", ret);
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::statistic */
+/* {{{ mysqlnd_conn_data::statistic */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, statistic)(MYSQLND * conn, char **message, unsigned int * message_len TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, statistic)(MYSQLND_CONN_DATA * conn, char **message, unsigned int * message_len TSRMLS_DC)
{
- enum_func_status ret;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, get_server_statistics);
+ enum_func_status ret = FAIL;
MYSQLND_PACKET_STATS * stats_header;
- DBG_ENTER("mysqlnd_conn::statistic");
+ DBG_ENTER("mysqlnd_conn_data::statistic");
DBG_INF_FMT("conn=%llu", conn->thread_id);
- ret = conn->m->simple_command(conn, COM_STATISTICS, NULL, 0, PROT_LAST, FALSE, TRUE TSRMLS_CC);
- if (FAIL == ret) {
- DBG_RETURN(FAIL);
- }
- stats_header = conn->protocol->m.get_stats_packet(conn->protocol, FALSE TSRMLS_CC);
- if (!stats_header) {
- SET_OOM_ERROR(conn->error_info);
- DBG_RETURN(FAIL);
- }
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ do {
+ ret = conn->m->simple_command(conn, COM_STATISTICS, NULL, 0, PROT_LAST, FALSE, TRUE TSRMLS_CC);
+ if (FAIL == ret) {
+ break;
+ }
+ stats_header = conn->protocol->m.get_stats_packet(conn->protocol, FALSE TSRMLS_CC);
+ if (!stats_header) {
+ SET_OOM_ERROR(*conn->error_info);
+ break;
+ }
- if (FAIL == (ret = PACKET_READ(stats_header, conn))) {
- DBG_RETURN(FAIL);
- }
- /* will be freed by Zend, thus don't use the mnd_ allocator */
- *message = estrndup(stats_header->message, stats_header->message_len);
- *message_len = stats_header->message_len;
- PACKET_FREE(stats_header);
+ if (PASS == (ret = PACKET_READ(stats_header, conn))) {
+ /* will be freed by Zend, thus don't use the mnd_ allocator */
+ *message = estrndup(stats_header->message, stats_header->message_len);
+ *message_len = stats_header->message_len;
+ DBG_INF(*message);
+ }
+ PACKET_FREE(stats_header);
+ } while (0);
- DBG_INF(*message);
- DBG_RETURN(PASS);
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+ DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::kill */
+/* {{{ mysqlnd_conn_data::kill */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, kill)(MYSQLND * conn, unsigned int pid TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, kill)(MYSQLND_CONN_DATA * conn, unsigned int pid TSRMLS_DC)
{
- enum_func_status ret;
- char buff[4];
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, kill_connection);
+ enum_func_status ret = FAIL;
+ zend_uchar buff[4];
- DBG_ENTER("mysqlnd_conn::kill");
+ DBG_ENTER("mysqlnd_conn_data::kill");
DBG_INF_FMT("conn=%llu pid=%u", conn->thread_id, pid);
- int4store(buff, pid);
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ int4store(buff, pid);
- /* If we kill ourselves don't expect OK packet, PROT_LAST will skip it */
- if (pid != conn->thread_id) {
- ret = conn->m->simple_command(conn, COM_PROCESS_KILL, buff, 4, PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC);
- /*
- The server sends 0 but libmysql doesn't read it and has established
- a protocol of giving back -1. Thus we have to follow it :(
- */
- SET_ERROR_AFF_ROWS(conn);
- } else if (PASS == (ret = conn->m->simple_command(conn, COM_PROCESS_KILL, buff, 4, PROT_LAST, FALSE, TRUE TSRMLS_CC))) {
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ /* If we kill ourselves don't expect OK packet, PROT_LAST will skip it */
+ if (pid != conn->thread_id) {
+ ret = conn->m->simple_command(conn, COM_PROCESS_KILL, buff, 4, PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC);
+ /*
+ The server sends 0 but libmysql doesn't read it and has established
+ a protocol of giving back -1. Thus we have to follow it :(
+ */
+ SET_ERROR_AFF_ROWS(conn);
+ } else if (PASS == (ret = conn->m->simple_command(conn, COM_PROCESS_KILL, buff, 4, PROT_LAST, FALSE, TRUE TSRMLS_CC))) {
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ }
+
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
}
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::set_charset */
+/* {{{ mysqlnd_conn_data::set_charset */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, set_charset)(MYSQLND * const conn, const char * const csname TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, set_charset)(MYSQLND_CONN_DATA * const conn, const char * const csname TSRMLS_DC)
{
- enum_func_status ret = PASS;
- char * query;
- size_t query_len;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, set_charset);
+ enum_func_status ret = FAIL;
const MYSQLND_CHARSET * const charset = mysqlnd_find_charset_name(csname);
- DBG_ENTER("mysqlnd_conn::set_charset");
+ DBG_ENTER("mysqlnd_conn_data::set_charset");
DBG_INF_FMT("conn=%llu cs=%s", conn->thread_id, csname);
if (!charset) {
- SET_CLIENT_ERROR(conn->error_info, CR_CANT_FIND_CHARSET, UNKNOWN_SQLSTATE,
+ SET_CLIENT_ERROR(*conn->error_info, CR_CANT_FIND_CHARSET, UNKNOWN_SQLSTATE,
"Invalid characterset or character set not supported");
- DBG_RETURN(FAIL);
+ DBG_RETURN(ret);
}
- query_len = spprintf(&query, 0, "SET NAMES %s", csname);
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ char * query;
+ size_t query_len = mnd_sprintf(&query, 0, "SET NAMES %s", csname);
- if (FAIL == conn->m->query(conn, query, query_len TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error executing query");
- } else if (conn->error_info.error_no) {
- ret = FAIL;
- } else {
- conn->charset = charset;
+ if (FAIL == (ret = conn->m->query(conn, query, query_len TSRMLS_CC))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error executing query");
+ } else if (conn->error_info->error_no) {
+ ret = FAIL;
+ } else {
+ conn->charset = charset;
+ }
+ mnd_sprintf_free(query);
+
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
}
- efree(query); /* allocated by spprintf */
DBG_INF(ret == PASS? "PASS":"FAIL");
DBG_RETURN(ret);
@@ -1609,39 +1677,53 @@ MYSQLND_METHOD(mysqlnd_conn, set_charset)(MYSQLND * const conn, const char * con
/* }}} */
-/* {{{ mysqlnd_conn::refresh */
+/* {{{ mysqlnd_conn_data::refresh */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, refresh)(MYSQLND * const conn, uint8_t options TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, refresh)(MYSQLND_CONN_DATA * const conn, uint8_t options TSRMLS_DC)
{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, refresh_server);
+ enum_func_status ret = FAIL;
zend_uchar bits[1];
- DBG_ENTER("mysqlnd_conn::refresh");
+ DBG_ENTER("mysqlnd_conn_data::refresh");
DBG_INF_FMT("conn=%llu options=%lu", conn->thread_id, options);
- int1store(bits, options);
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ int1store(bits, options);
+
+ ret = conn->m->simple_command(conn, COM_REFRESH, bits, 1, PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC);
- DBG_RETURN(conn->m->simple_command(conn, COM_REFRESH, (char *)bits, 1, PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC));
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+ DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::shutdown */
+/* {{{ mysqlnd_conn_data::shutdown */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, shutdown)(MYSQLND * const conn, uint8_t level TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, shutdown)(MYSQLND_CONN_DATA * const conn, uint8_t level TSRMLS_DC)
{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, shutdown_server);
+ enum_func_status ret = FAIL;
zend_uchar bits[1];
- DBG_ENTER("mysqlnd_conn::shutdown");
+ DBG_ENTER("mysqlnd_conn_data::shutdown");
DBG_INF_FMT("conn=%llu level=%lu", conn->thread_id, level);
- int1store(bits, level);
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ int1store(bits, level);
- DBG_RETURN(conn->m->simple_command(conn, COM_SHUTDOWN, (char *)bits, 1, PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC));
+ ret = conn->m->simple_command(conn, COM_SHUTDOWN, bits, 1, PROT_OK_PACKET, FALSE, TRUE TSRMLS_CC);
+
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+ DBG_RETURN(ret);
}
/* }}} */
/* {{{ mysqlnd_send_close */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, send_close)(MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, send_close)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
enum_func_status ret = PASS;
@@ -1649,11 +1731,17 @@ MYSQLND_METHOD(mysqlnd_conn, send_close)(MYSQLND * const conn TSRMLS_DC)
DBG_INF_FMT("conn=%llu conn->net->stream->abstract=%p",
conn->thread_id, conn->net->stream? conn->net->stream->abstract:NULL);
+ if (CONN_GET_STATE(conn) >= CONN_READY) {
+ MYSQLND_DEC_CONN_STATISTIC(conn->stats, STAT_OPENED_CONNECTIONS);
+ if (conn->persistent) {
+ MYSQLND_DEC_CONN_STATISTIC(conn->stats, STAT_OPENED_PERSISTENT_CONNECTIONS);
+ }
+ }
switch (CONN_GET_STATE(conn)) {
case CONN_READY:
DBG_INF("Connection clean, sending COM_QUIT");
if (conn->net->stream) {
- ret = conn->m->simple_command(conn, COM_QUIT, NULL, 0, PROT_LAST, TRUE, TRUE TSRMLS_CC);
+ ret = conn->m->simple_command(conn, COM_QUIT, NULL, 0, PROT_LAST, TRUE, TRUE TSRMLS_CC);
}
/* Do nothing */
break;
@@ -1693,48 +1781,11 @@ MYSQLND_METHOD(mysqlnd_conn, send_close)(MYSQLND * const conn TSRMLS_DC)
/* }}} */
-/* {{{ mysqlnd_conn::close */
-static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, close)(MYSQLND * conn, enum_connection_close_type close_type TSRMLS_DC)
+/* {{{ mysqlnd_conn_data::get_reference */
+static MYSQLND_CONN_DATA *
+MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, get_reference)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- enum_func_status ret = PASS;
- static enum_mysqlnd_collected_stats
- close_type_to_stat_map[MYSQLND_CLOSE_LAST] = {
- STAT_CLOSE_EXPLICIT,
- STAT_CLOSE_IMPLICIT,
- STAT_CLOSE_DISCONNECT
- };
- enum_mysqlnd_collected_stats statistic = close_type_to_stat_map[close_type];
-
- DBG_ENTER("mysqlnd_conn::close");
- DBG_INF_FMT("conn=%llu", conn->thread_id);
-
- if (conn->state >= CONN_READY) {
- MYSQLND_INC_CONN_STATISTIC(conn->stats, statistic);
- MYSQLND_DEC_CONN_STATISTIC(conn->stats, STAT_OPENED_CONNECTIONS);
- if (conn->persistent) {
- MYSQLND_DEC_CONN_STATISTIC(conn->stats, STAT_OPENED_PERSISTENT_CONNECTIONS);
- }
- }
-
- /*
- Close now, free_reference will try,
- if we are last, but that's not a problem.
- */
- ret = conn->m->send_close(conn TSRMLS_CC);
-
- ret = conn->m->free_reference(conn TSRMLS_CC);
-
- DBG_RETURN(ret);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_conn::get_reference */
-static MYSQLND *
-MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_reference)(MYSQLND * const conn TSRMLS_DC)
-{
- DBG_ENTER("mysqlnd_conn::get_reference");
+ DBG_ENTER("mysqlnd_conn_data::get_reference");
++conn->refcount;
DBG_INF_FMT("conn=%llu new_refcount=%u", conn->thread_id, conn->refcount);
DBG_RETURN(conn);
@@ -1742,12 +1793,12 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_reference)(MYSQLND * const conn TSRMLS_
/* }}} */
-/* {{{ mysqlnd_conn::free_reference */
+/* {{{ mysqlnd_conn_data::free_reference */
static enum_func_status
-MYSQLND_METHOD_PRIVATE(mysqlnd_conn, free_reference)(MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, free_reference)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
enum_func_status ret = PASS;
- DBG_ENTER("mysqlnd_conn::free_reference");
+ DBG_ENTER("mysqlnd_conn_data::free_reference");
DBG_INF_FMT("conn=%llu old_refcount=%u", conn->thread_id, conn->refcount);
if (!(--conn->refcount)) {
/*
@@ -1763,21 +1814,21 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, free_reference)(MYSQLND * const conn TSRMLS
/* }}} */
-/* {{{ mysqlnd_conn::get_state */
+/* {{{ mysqlnd_conn_data::get_state */
static enum mysqlnd_connection_state
-MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_state)(MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, get_state)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_conn::get_state");
+ DBG_ENTER("mysqlnd_conn_data::get_state");
DBG_RETURN(conn->state);
}
/* }}} */
-/* {{{ mysqlnd_conn::set_state */
+/* {{{ mysqlnd_conn_data::set_state */
static void
-MYSQLND_METHOD_PRIVATE(mysqlnd_conn, set_state)(MYSQLND * const conn, enum mysqlnd_connection_state new_state TSRMLS_DC)
+MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, set_state)(MYSQLND_CONN_DATA * const conn, enum mysqlnd_connection_state new_state TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_conn::set_state");
+ DBG_ENTER("mysqlnd_conn_data::set_state");
DBG_INF_FMT("New state=%u", new_state);
conn->state = new_state;
DBG_VOID_RETURN;
@@ -1785,51 +1836,59 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, set_state)(MYSQLND * const conn, enum mysql
/* }}} */
-/* {{{ mysqlnd_conn::field_count */
+/* {{{ mysqlnd_conn_data::field_count */
static unsigned int
-MYSQLND_METHOD(mysqlnd_conn, field_count)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, field_count)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
return conn->field_count;
}
/* }}} */
-/* {{{ mysqlnd_conn::insert_id */
+/* {{{ mysqlnd_conn_data::server_status */
+static unsigned int
+MYSQLND_METHOD(mysqlnd_conn_data, server_status)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
+{
+ return conn->upsert_status->server_status;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_conn_data::insert_id */
static uint64_t
-MYSQLND_METHOD(mysqlnd_conn, insert_id)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, insert_id)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- return conn->upsert_status.last_insert_id;
+ return conn->upsert_status->last_insert_id;
}
/* }}} */
-/* {{{ mysqlnd_conn::affected_rows */
+/* {{{ mysqlnd_conn_data::affected_rows */
static uint64_t
-MYSQLND_METHOD(mysqlnd_conn, affected_rows)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, affected_rows)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- return conn->upsert_status.affected_rows;
+ return conn->upsert_status->affected_rows;
}
/* }}} */
-/* {{{ mysqlnd_conn::warning_count */
+/* {{{ mysqlnd_conn_data::warning_count */
static unsigned int
-MYSQLND_METHOD(mysqlnd_conn, warning_count)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, warning_count)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- return conn->upsert_status.warning_count;
+ return conn->upsert_status->warning_count;
}
/* }}} */
-/* {{{ mysqlnd_conn::info */
+/* {{{ mysqlnd_conn_data::info */
static const char *
-MYSQLND_METHOD(mysqlnd_conn, info)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, info)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
return conn->last_message;
}
/* }}} */
-#if !defined(MYSQLND_USE_OPTIMISATIONS) || MYSQLND_USE_OPTIMISATIONS == 0
/* {{{ mysqlnd_get_client_info */
PHPAPI const char * mysqlnd_get_client_info()
{
@@ -1844,56 +1903,56 @@ PHPAPI unsigned int mysqlnd_get_client_version()
return MYSQLND_VERSION_ID;
}
/* }}} */
-#endif
-/* {{{ mysqlnd_conn::get_server_info */
+
+/* {{{ mysqlnd_conn_data::get_server_info */
static const char *
-MYSQLND_METHOD(mysqlnd_conn, get_server_info)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, get_server_info)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
return conn->server_version;
}
/* }}} */
-/* {{{ mysqlnd_conn::get_host_info */
+/* {{{ mysqlnd_conn_data::get_host_info */
static const char *
-MYSQLND_METHOD(mysqlnd_conn, get_host_info)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, get_host_info)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
return conn->host_info;
}
/* }}} */
-/* {{{ mysqlnd_conn::get_proto_info */
+/* {{{ mysqlnd_conn_data::get_proto_info */
static unsigned int
-MYSQLND_METHOD(mysqlnd_conn, get_proto_info)(const MYSQLND *const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, get_proto_info)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
return conn->protocol_version;
}
/* }}} */
-/* {{{ mysqlnd_conn::charset_name */
+/* {{{ mysqlnd_conn_data::charset_name */
static const char *
-MYSQLND_METHOD(mysqlnd_conn, charset_name)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, charset_name)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
return conn->charset->name;
}
/* }}} */
-/* {{{ mysqlnd_conn::thread_id */
+/* {{{ mysqlnd_conn_data::thread_id */
static uint64_t
-MYSQLND_METHOD(mysqlnd_conn, thread_id)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, thread_id)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
return conn->thread_id;
}
/* }}} */
-/* {{{ mysqlnd_conn::get_server_version */
+/* {{{ mysqlnd_conn_data::get_server_version */
static unsigned long
-MYSQLND_METHOD(mysqlnd_conn, get_server_version)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, get_server_version)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
long major, minor, patch;
char *p;
@@ -1913,51 +1972,58 @@ MYSQLND_METHOD(mysqlnd_conn, get_server_version)(const MYSQLND * const conn TSRM
/* }}} */
-/* {{{ mysqlnd_conn::more_results */
+/* {{{ mysqlnd_conn_data::more_results */
static zend_bool
-MYSQLND_METHOD(mysqlnd_conn, more_results)(const MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, more_results)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_conn::more_results");
+ DBG_ENTER("mysqlnd_conn_data::more_results");
/* (conn->state == CONN_NEXT_RESULT_PENDING) too */
- DBG_RETURN(conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS? TRUE:FALSE);
+ DBG_RETURN(conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS? TRUE:FALSE);
}
/* }}} */
-/* {{{ mysqlnd_conn::next_result */
+/* {{{ mysqlnd_conn_data::next_result */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, next_result)(MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, next_result)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- enum_func_status ret;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, next_result);
+ enum_func_status ret = FAIL;
- DBG_ENTER("mysqlnd_conn::next_result");
+ DBG_ENTER("mysqlnd_conn_data::next_result");
DBG_INF_FMT("conn=%llu", conn->thread_id);
- if (CONN_GET_STATE(conn) != CONN_NEXT_RESULT_PENDING) {
- DBG_RETURN(FAIL);
- }
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ do {
+ if (CONN_GET_STATE(conn) != CONN_NEXT_RESULT_PENDING) {
+ break;
+ }
- SET_EMPTY_ERROR(conn->error_info);
- SET_ERROR_AFF_ROWS(conn);
- /*
- We are sure that there is a result set, since conn->state is set accordingly
- in mysqlnd_store_result() or mysqlnd_fetch_row_unbuffered()
- */
- if (FAIL == (ret = conn->m->query_read_result_set_header(conn, NULL TSRMLS_CC))) {
- /*
- There can be an error in the middle of a multi-statement, which will cancel the multi-statement.
- So there are no more results and we should just return FALSE, error_no has been set
- */
- if (!conn->error_info.error_no) {
- DBG_ERR_FMT("Serious error. %s::%u", __FILE__, __LINE__);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Serious error. PID=%d", getpid());
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
- } else {
- DBG_INF_FMT("Error from the server : (%u) %s", conn->error_info.error_no, conn->error_info.error);
- }
- }
- if (ret == PASS && conn->last_query_type == QUERY_UPSERT && conn->upsert_status.affected_rows) {
- MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_NORMAL, conn->upsert_status.affected_rows);
+ SET_EMPTY_ERROR(*conn->error_info);
+ SET_ERROR_AFF_ROWS(conn);
+ /*
+ We are sure that there is a result set, since conn->state is set accordingly
+ in mysqlnd_store_result() or mysqlnd_fetch_row_unbuffered()
+ */
+ if (FAIL == (ret = conn->m->query_read_result_set_header(conn, NULL TSRMLS_CC))) {
+ /*
+ There can be an error in the middle of a multi-statement, which will cancel the multi-statement.
+ So there are no more results and we should just return FALSE, error_no has been set
+ */
+ if (!conn->error_info->error_no) {
+ DBG_ERR_FMT("Serious error. %s::%u", __FILE__, __LINE__);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Serious error. PID=%d", getpid());
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ } else {
+ DBG_INF_FMT("Error from the server : (%u) %s", conn->error_info->error_no, conn->error_info->error);
+ }
+ break;
+ }
+ if (conn->last_query_type == QUERY_UPSERT && conn->upsert_status->affected_rows) {
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_NORMAL, conn->upsert_status->affected_rows);
+ }
+ } while (0);
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
}
DBG_RETURN(ret);
@@ -2016,16 +2082,182 @@ PHPAPI const char *mysqlnd_field_type_name(enum mysqlnd_field_types field_type)
/* }}} */
-/* {{{ mysqlnd_conn::set_client_option */
+/* {{{ mysqlnd_conn_data::change_user */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, set_client_option)(MYSQLND * const conn,
+MYSQLND_METHOD(mysqlnd_conn_data, change_user)(MYSQLND_CONN_DATA * const conn,
+ const char * user,
+ const char * passwd,
+ const char * db,
+ zend_bool silent,
+ size_t passwd_len
+ TSRMLS_DC)
+{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, change_user);
+ /*
+ User could be max 16 * 3 (utf8), pass is 20 usually, db is up to 64*3
+ Stack space is not that expensive, so use a bit more to be protected against
+ buffer overflows.
+ */
+ enum_func_status ret = FAIL;
+ zend_bool local_tx_started = FALSE;
+
+ DBG_ENTER("mysqlnd_conn_data::change_user");
+ DBG_INF_FMT("conn=%llu user=%s passwd=%s db=%s silent=%u",
+ conn->thread_id, user?user:"", passwd?"***":"null", db?db:"", (silent == TRUE)?1:0 );
+
+ if (PASS != conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ goto end;
+ }
+ local_tx_started = TRUE;
+
+ SET_EMPTY_ERROR(*conn->error_info);
+ SET_ERROR_AFF_ROWS(conn);
+
+ if (!user) {
+ user = "";
+ }
+ if (!passwd) {
+ passwd = "";
+ }
+ if (!db) {
+ db = "";
+ }
+
+ {
+ zend_bool first_call = TRUE;
+ char * switch_to_auth_protocol = NULL;
+ size_t switch_to_auth_protocol_len = 0;
+ char * requested_protocol = NULL;
+ zend_uchar * plugin_data;
+ size_t plugin_data_len;
+
+ plugin_data_len = conn->auth_plugin_data_len;
+ plugin_data = mnd_emalloc(plugin_data_len);
+ if (!plugin_data) {
+ ret = FAIL;
+ goto end;
+ }
+ memcpy(plugin_data, conn->auth_plugin_data, plugin_data_len);
+
+ requested_protocol = mnd_pestrdup(conn->options->auth_protocol? conn->options->auth_protocol:"mysql_native_password", FALSE);
+ if (!requested_protocol) {
+ ret = FAIL;
+ goto end;
+ }
+
+ do {
+ struct st_mysqlnd_authentication_plugin * auth_plugin;
+ {
+ char * plugin_name = NULL;
+
+ mnd_sprintf(&plugin_name, 0, "auth_plugin_%s", requested_protocol);
+
+ DBG_INF_FMT("looking for %s auth plugin", plugin_name);
+ auth_plugin = mysqlnd_plugin_find(plugin_name);
+ mnd_sprintf_free(plugin_name);
+
+ if (!auth_plugin) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The server requested authentication method unknown to the client [%s]", requested_protocol);
+ SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "The server requested authentication method umknown to the client");
+ break;
+ }
+ }
+ DBG_INF("plugin found");
+
+ {
+ zend_uchar * switch_to_auth_protocol_data = NULL;
+ size_t switch_to_auth_protocol_data_len = 0;
+ zend_uchar * scrambled_data = NULL;
+ size_t scrambled_data_len = 0;
+
+ switch_to_auth_protocol = NULL;
+ switch_to_auth_protocol_len = 0;
+
+ if (conn->auth_plugin_data) {
+ mnd_pefree(conn->auth_plugin_data, conn->persistent);
+ conn->auth_plugin_data = NULL;
+ }
+ conn->auth_plugin_data_len = plugin_data_len;
+ conn->auth_plugin_data = mnd_pemalloc(conn->auth_plugin_data_len, conn->persistent);
+ if (!conn->auth_plugin_data) {
+ SET_OOM_ERROR(*conn->error_info);
+ ret = FAIL;
+ goto end;
+ }
+ memcpy(conn->auth_plugin_data, plugin_data, plugin_data_len);
+
+ DBG_INF_FMT("salt=[%*.s]", plugin_data_len - 1, plugin_data);
+
+ /* The data should be allocated with malloc() */
+ scrambled_data =
+ auth_plugin->methods.get_auth_data(NULL, &scrambled_data_len, conn, user, passwd, passwd_len,
+ plugin_data, plugin_data_len, 0, conn->server_capabilities TSRMLS_CC);
+
+
+ ret = mysqlnd_auth_change_user(conn, user, strlen(user), passwd, passwd_len, db, strlen(db), silent,
+ first_call,
+ requested_protocol,
+ scrambled_data, scrambled_data_len,
+ &switch_to_auth_protocol, &switch_to_auth_protocol_len,
+ &switch_to_auth_protocol_data, &switch_to_auth_protocol_data_len
+ TSRMLS_CC);
+
+ first_call = FALSE;
+ free(scrambled_data);
+
+ DBG_INF_FMT("switch_to_auth_protocol=%s", switch_to_auth_protocol? switch_to_auth_protocol:"n/a");
+ if (requested_protocol) {
+ mnd_efree(requested_protocol);
+ }
+ requested_protocol = switch_to_auth_protocol;
+
+ if (plugin_data) {
+ mnd_efree(plugin_data);
+ }
+ plugin_data_len = switch_to_auth_protocol_data_len;
+ plugin_data = switch_to_auth_protocol_data;
+ }
+ DBG_INF_FMT("conn->error_info->error_no = %d", conn->error_info->error_no);
+ } while (ret == FAIL && conn->error_info->error_no == 0 && switch_to_auth_protocol != NULL);
+ if (plugin_data) {
+ mnd_efree(plugin_data);
+ }
+ if (ret == PASS) {
+ conn->m->set_client_option(conn, MYSQLND_OPT_AUTH_PROTOCOL, requested_protocol TSRMLS_CC);
+ }
+ if (requested_protocol) {
+ mnd_efree(requested_protocol);
+ }
+ }
+ /*
+ Here we should close all statements. Unbuffered queries should not be a
+ problem as we won't allow sending COM_CHANGE_USER.
+ */
+end:
+ if (TRUE == local_tx_started) {
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+ DBG_INF(ret == PASS? "PASS":"FAIL");
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_conn_data::set_client_option */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_conn_data, set_client_option)(MYSQLND_CONN_DATA * const conn,
enum mysqlnd_option option,
const char * const value
TSRMLS_DC)
{
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, set_client_option);
enum_func_status ret = PASS;
- DBG_ENTER("mysqlnd_conn::set_client_option");
+ DBG_ENTER("mysqlnd_conn_data::set_client_option");
DBG_INF_FMT("conn=%llu option=%u", conn->thread_id, option);
+
+ if (PASS != conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ goto end;
+ }
switch (option) {
case MYSQL_OPT_COMPRESS:
#ifdef WHEN_SUPPORTED_BY_MYSQLI
@@ -2045,42 +2277,38 @@ MYSQLND_METHOD(mysqlnd_conn, set_client_option)(MYSQLND * const conn,
break;
#if MYSQLND_UNICODE
case MYSQLND_OPT_NUMERIC_AND_DATETIME_AS_UNICODE:
- conn->options.numeric_and_datetime_as_unicode = *(unsigned int*) value;
+ conn->options->numeric_and_datetime_as_unicode = *(unsigned int*) value;
break;
#endif
#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;
+ conn->options->int_and_float_native = *(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;
+ conn->options->flags |= CLIENT_LOCAL_FILES;
} else {
- conn->options.flags &= ~CLIENT_LOCAL_FILES;
+ conn->options->flags &= ~CLIENT_LOCAL_FILES;
}
break;
case MYSQL_INIT_COMMAND:
{
char ** new_init_commands;
char * new_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 */
- /* Don't assign to conn->options.init_commands because in case of OOM we will lose the pointer and leak */
- new_init_commands = mnd_perealloc(conn->options.init_commands, sizeof(char *) * (conn->options.num_commands + 1), conn->persistent);
+ /* Don't assign to conn->options->init_commands because in case of OOM we will lose the pointer and leak */
+ new_init_commands = mnd_perealloc(conn->options->init_commands, sizeof(char *) * (conn->options->num_commands + 1), conn->persistent);
if (!new_init_commands) {
goto oom;
}
- conn->options.init_commands = new_init_commands;
+ conn->options->init_commands = new_init_commands;
new_command = mnd_pestrdup(value, conn->persistent);
if (!new_command) {
goto oom;
}
- conn->options.init_commands[conn->options.num_commands] = new_command;
- ++conn->options.num_commands;
+ conn->options->init_commands[conn->options->num_commands] = new_command;
+ ++conn->options->num_commands;
break;
}
case MYSQL_READ_DEFAULT_FILE:
@@ -2094,23 +2322,22 @@ MYSQLND_METHOD(mysqlnd_conn, set_client_option)(MYSQLND * const conn,
case MYSQL_SET_CHARSET_NAME:
{
char * new_charset_name = mnd_pestrdup(value, conn->persistent);
- DBG_INF("MYSQL_SET_CHARSET_NAME");
if (!new_charset_name) {
goto oom;
}
- if (conn->options.charset_name) {
- mnd_pefree(conn->options.charset_name, conn->persistent);
+ if (conn->options->charset_name) {
+ mnd_pefree(conn->options->charset_name, conn->persistent);
}
- conn->options.charset_name = new_charset_name;
- DBG_INF_FMT("charset=%s", conn->options.charset_name);
+ conn->options->charset_name = new_charset_name;
+ DBG_INF_FMT("charset=%s", conn->options->charset_name);
break;
}
case MYSQL_OPT_NAMED_PIPE:
- conn->options.protocol = MYSQL_PROTOCOL_PIPE;
+ conn->options->protocol = MYSQL_PROTOCOL_PIPE;
break;
case MYSQL_OPT_PROTOCOL:
if (*(unsigned int*) value < MYSQL_PROTOCOL_LAST) {
- conn->options.protocol = *(unsigned int*) value;
+ conn->options->protocol = *(unsigned int*) value;
}
break;
#ifdef WHEN_SUPPORTED_BY_MYSQLI
@@ -2125,7 +2352,24 @@ MYSQLND_METHOD(mysqlnd_conn, set_client_option)(MYSQLND * const conn,
/* todo: throw an error, we don't support embedded */
break;
#endif
-
+ case MYSQLND_OPT_MAX_ALLOWED_PACKET:
+ if (*(unsigned int*) value > (1<<16)) {
+ conn->options->max_allowed_packet = *(unsigned int*) value;
+ }
+ break;
+ case MYSQLND_OPT_AUTH_PROTOCOL:
+ {
+ char * new_auth_protocol = value? mnd_pestrdup(value, conn->persistent) : NULL;
+ if (value && !new_auth_protocol) {
+ goto oom;
+ }
+ if (conn->options->auth_protocol) {
+ mnd_pefree(conn->options->auth_protocol, conn->persistent);
+ }
+ conn->options->auth_protocol = new_auth_protocol;
+ DBG_INF_FMT("auth_protocol=%s", conn->options->auth_protocol);
+ break;
+ }
#ifdef WHEN_SUPPORTED_BY_MYSQLI
case MYSQL_SHARED_MEMORY_BASE_NAME:
case MYSQL_OPT_USE_RESULT:
@@ -2135,315 +2379,364 @@ MYSQLND_METHOD(mysqlnd_conn, set_client_option)(MYSQLND * const conn,
default:
ret = FAIL;
}
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
DBG_RETURN(ret);
oom:
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
+ conn->m->local_tx_end(conn, this_func, FAIL TSRMLS_CC);
+end:
DBG_RETURN(FAIL);
}
/* }}} */
-/* {{{ mysqlnd_conn::use_result */
+/* {{{ mysqlnd_conn_data::use_result */
static MYSQLND_RES *
-MYSQLND_METHOD(mysqlnd_conn, use_result)(MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, use_result)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- MYSQLND_RES * result;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, use_result);
+ MYSQLND_RES * result = NULL;
- DBG_ENTER("mysqlnd_conn::use_result");
+ DBG_ENTER("mysqlnd_conn_data::use_result");
DBG_INF_FMT("conn=%llu", conn->thread_id);
- if (!conn->current_result) {
- DBG_RETURN(NULL);
- }
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ do {
+ if (!conn->current_result) {
+ break;
+ }
- /* Nothing to store for UPSERT/LOAD DATA */
- if (conn->last_query_type != QUERY_SELECT || CONN_GET_STATE(conn) != CONN_FETCHING_DATA) {
- SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
- mysqlnd_out_of_sync);
- DBG_ERR("Command out of sync");
- DBG_RETURN(NULL);
- }
+ /* Nothing to store for UPSERT/LOAD DATA */
+ if (conn->last_query_type != QUERY_SELECT || CONN_GET_STATE(conn) != CONN_FETCHING_DATA) {
+ SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ DBG_ERR("Command out of sync");
+ break;
+ }
- MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_UNBUFFERED_SETS);
+ MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_UNBUFFERED_SETS);
- conn->current_result->conn = conn->m->get_reference(conn TSRMLS_CC);
- result = conn->current_result->m.use_result(conn->current_result, FALSE TSRMLS_CC);
+ conn->current_result->conn = conn->m->get_reference(conn TSRMLS_CC);
+ result = conn->current_result->m.use_result(conn->current_result, FALSE TSRMLS_CC);
- if (!result) {
- conn->current_result->m.free_result(conn->current_result, TRUE TSRMLS_CC);
+ if (!result) {
+ conn->current_result->m.free_result(conn->current_result, TRUE TSRMLS_CC);
+ }
+ conn->current_result = NULL;
+ } while (0);
+
+ conn->m->local_tx_end(conn, this_func, result == NULL? FAIL:PASS TSRMLS_CC);
}
- conn->current_result = NULL;
DBG_RETURN(result);
}
/* }}} */
-/* {{{ mysqlnd_conn::store_result */
+/* {{{ mysqlnd_conn_data::store_result */
static MYSQLND_RES *
-MYSQLND_METHOD(mysqlnd_conn, store_result)(MYSQLND * const conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, store_result)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- MYSQLND_RES *result;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, store_result);
+ MYSQLND_RES * result = NULL;
- DBG_ENTER("mysqlnd_conn::store_result");
+ DBG_ENTER("mysqlnd_conn_data::store_result");
DBG_INF_FMT("conn=%llu", conn->thread_id);
- if (!conn->current_result) {
- DBG_RETURN(NULL);
- }
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ do {
+ if (!conn->current_result) {
+ break;
+ }
- /* Nothing to store for UPSERT/LOAD DATA*/
- if (conn->last_query_type != QUERY_SELECT || CONN_GET_STATE(conn) != CONN_FETCHING_DATA) {
- SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
- mysqlnd_out_of_sync);
- DBG_ERR("Command out of sync");
- DBG_RETURN(NULL);
- }
+ /* Nothing to store for UPSERT/LOAD DATA*/
+ if (conn->last_query_type != QUERY_SELECT || CONN_GET_STATE(conn) != CONN_FETCHING_DATA) {
+ SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ DBG_ERR("Command out of sync");
+ break;
+ }
- MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_BUFFERED_SETS);
+ MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_BUFFERED_SETS);
- result = conn->current_result->m.store_result(conn->current_result, conn, FALSE TSRMLS_CC);
- if (!result) {
- conn->current_result->m.free_result(conn->current_result, TRUE TSRMLS_CC);
+ result = conn->current_result->m.store_result(conn->current_result, conn, FALSE TSRMLS_CC);
+ if (!result) {
+ conn->current_result->m.free_result(conn->current_result, TRUE TSRMLS_CC);
+ }
+ conn->current_result = NULL;
+ } while (0);
+
+ conn->m->local_tx_end(conn, this_func, result == NULL? FAIL:PASS TSRMLS_CC);
}
- conn->current_result = NULL;
DBG_RETURN(result);
}
/* }}} */
-/* {{{ mysqlnd_conn::get_connection_stats */
+/* {{{ mysqlnd_conn_data::get_connection_stats */
static void
-MYSQLND_METHOD(mysqlnd_conn, get_connection_stats)(const MYSQLND * const conn,
- zval *return_value
- TSRMLS_DC ZEND_FILE_LINE_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, get_connection_stats)(const MYSQLND_CONN_DATA * const conn,
+ zval * return_value TSRMLS_DC ZEND_FILE_LINE_DC)
{
- DBG_ENTER("mysqlnd_conn::get_connection_stats");
- DBG_INF_FMT("conn=%llu", conn->thread_id);
+ DBG_ENTER("mysqlnd_conn_data::get_connection_stats");
mysqlnd_fill_stats_hash(conn->stats, mysqlnd_stats_values_names, return_value TSRMLS_CC ZEND_FILE_LINE_CC);
DBG_VOID_RETURN;
}
/* }}} */
-/* {{{ mysqlnd_conn::set_autocommit */
+/* {{{ mysqlnd_conn_data::set_autocommit */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, set_autocommit)(MYSQLND * conn, unsigned int mode TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, set_autocommit)(MYSQLND_CONN_DATA * conn, unsigned int mode TSRMLS_DC)
{
- enum_func_status ret;
- DBG_ENTER("mysqlnd_conn::set_autocommit");
- ret = conn->m->query(conn, (mode) ? "SET AUTOCOMMIT=1":"SET AUTOCOMMIT=0", sizeof("SET AUTOCOMMIT=1") - 1 TSRMLS_CC);
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, set_autocommit);
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_conn_data::set_autocommit");
+
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ ret = conn->m->query(conn, (mode) ? "SET AUTOCOMMIT=1":"SET AUTOCOMMIT=0", sizeof("SET AUTOCOMMIT=1") - 1 TSRMLS_CC);
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::tx_commit */
+/* {{{ mysqlnd_conn_data::tx_commit */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, tx_commit)(MYSQLND * conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, tx_commit)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
- enum_func_status ret;
- DBG_ENTER("mysqlnd_conn::tx_commit");
- ret = conn->m->query(conn, "COMMIT", sizeof("COMMIT") - 1 TSRMLS_CC);
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, tx_commit);
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_conn_data::tx_commit");
+
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ ret = conn->m->query(conn, "COMMIT", sizeof("COMMIT") - 1 TSRMLS_CC);
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn::tx_rollback */
+/* {{{ mysqlnd_conn_data::tx_rollback */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, tx_rollback)(MYSQLND * conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, tx_rollback)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
- enum_func_status ret;
- DBG_ENTER("mysqlnd_conn::tx_rollback");
- ret = conn->m->query(conn, "ROLLBACK", sizeof("ROLLBACK") - 1 TSRMLS_CC);
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, tx_rollback);
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_conn_data::tx_rollback");
+
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ ret = conn->m->query(conn, "ROLLBACK", sizeof("ROLLBACK") - 1 TSRMLS_CC);
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+ }
+
DBG_RETURN(ret);
}
/* }}} */
+/* {{{ mysqlnd_conn_data::local_tx_start */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_conn_data, local_tx_start)(MYSQLND_CONN_DATA * conn, size_t this_func TSRMLS_DC)
+{
+ enum_func_status ret = PASS;
+ DBG_ENTER("mysqlnd_conn_data::local_tx_start");
+ DBG_RETURN(ret);
+}
+/* }}} */
-MYSQLND_STMT * _mysqlnd_stmt_init(MYSQLND * const conn TSRMLS_DC);
-static enum_func_status MYSQLND_METHOD(mysqlnd_conn, init)(MYSQLND * conn TSRMLS_DC);
-
-static
-MYSQLND_CLASS_METHODS_START(mysqlnd_conn)
- MYSQLND_METHOD(mysqlnd_conn, init),
- MYSQLND_METHOD(mysqlnd_conn, connect),
-
- MYSQLND_METHOD(mysqlnd_conn, escape_string),
- MYSQLND_METHOD(mysqlnd_conn, set_charset),
- MYSQLND_METHOD(mysqlnd_conn, query),
- MYSQLND_METHOD(mysqlnd_conn, send_query),
- MYSQLND_METHOD(mysqlnd_conn, reap_query),
- MYSQLND_METHOD(mysqlnd_conn, use_result),
- MYSQLND_METHOD(mysqlnd_conn, store_result),
- MYSQLND_METHOD(mysqlnd_conn, next_result),
- MYSQLND_METHOD(mysqlnd_conn, more_results),
-
- _mysqlnd_stmt_init,
-
- MYSQLND_METHOD(mysqlnd_conn, shutdown),
- MYSQLND_METHOD(mysqlnd_conn, refresh),
-
- MYSQLND_METHOD(mysqlnd_conn, ping),
- MYSQLND_METHOD(mysqlnd_conn, kill),
- MYSQLND_METHOD(mysqlnd_conn, select_db),
- MYSQLND_METHOD(mysqlnd_conn, dump_debug_info),
- MYSQLND_METHOD(mysqlnd_conn, change_user),
-
- MYSQLND_METHOD(mysqlnd_conn, errno),
- MYSQLND_METHOD(mysqlnd_conn, error),
- MYSQLND_METHOD(mysqlnd_conn, sqlstate),
- MYSQLND_METHOD(mysqlnd_conn, thread_id),
-
- MYSQLND_METHOD(mysqlnd_conn, get_connection_stats),
-
- MYSQLND_METHOD(mysqlnd_conn, get_server_version),
- MYSQLND_METHOD(mysqlnd_conn, get_server_info),
- MYSQLND_METHOD(mysqlnd_conn, statistic),
- MYSQLND_METHOD(mysqlnd_conn, get_host_info),
- MYSQLND_METHOD(mysqlnd_conn, get_proto_info),
- MYSQLND_METHOD(mysqlnd_conn, info),
- MYSQLND_METHOD(mysqlnd_conn, charset_name),
- MYSQLND_METHOD(mysqlnd_conn, list_fields),
- MYSQLND_METHOD(mysqlnd_conn, list_method),
-
- MYSQLND_METHOD(mysqlnd_conn, insert_id),
- MYSQLND_METHOD(mysqlnd_conn, affected_rows),
- MYSQLND_METHOD(mysqlnd_conn, warning_count),
- MYSQLND_METHOD(mysqlnd_conn, field_count),
-
- MYSQLND_METHOD(mysqlnd_conn, set_server_option),
- MYSQLND_METHOD(mysqlnd_conn, set_client_option),
- MYSQLND_METHOD(mysqlnd_conn, free_contents),
- MYSQLND_METHOD(mysqlnd_conn, free_options),
- MYSQLND_METHOD(mysqlnd_conn, close),
-
- MYSQLND_METHOD_PRIVATE(mysqlnd_conn, dtor),
-
- mysqlnd_query_read_result_set_header,
- MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_reference),
- MYSQLND_METHOD_PRIVATE(mysqlnd_conn, free_reference),
- MYSQLND_METHOD_PRIVATE(mysqlnd_conn, get_state),
- MYSQLND_METHOD_PRIVATE(mysqlnd_conn, set_state),
-
- MYSQLND_METHOD(mysqlnd_conn, simple_command),
- MYSQLND_METHOD(mysqlnd_conn, simple_command_handle_response),
- MYSQLND_METHOD(mysqlnd_conn, restart_psession),
- MYSQLND_METHOD(mysqlnd_conn, end_psession),
- MYSQLND_METHOD(mysqlnd_conn, send_close),
-
- MYSQLND_METHOD(mysqlnd_conn, ssl_set),
- mysqlnd_result_init
-#ifdef AUTOCOMMIT_TX_COMMIT_ROLLBACK
- ,MYSQLND_METHOD(mysqlnd_conn, set_autocommit),
- MYSQLND_METHOD(mysqlnd_conn, tx_commit),
- MYSQLND_METHOD(mysqlnd_conn, tx_rollback)
-#endif
-MYSQLND_CLASS_METHODS_END;
+/* {{{ mysqlnd_conn_data::local_tx_end */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_conn_data, local_tx_end)(MYSQLND_CONN_DATA * conn, size_t this_func, enum_func_status status TSRMLS_DC)
+{
+ DBG_ENTER("mysqlnd_conn_data::local_tx_end");
+ DBG_RETURN(status);
+}
+/* }}} */
-/* {{{ mysqlnd_conn::init */
+/* {{{ mysqlnd_conn_data::init */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, init)(MYSQLND * conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, init)(MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_conn::init");
+ DBG_ENTER("mysqlnd_conn_data::init");
mysqlnd_stats_init(&conn->stats, STAT_LAST);
SET_ERROR_AFF_ROWS(conn);
- conn->net = mysqlnd_net_init(conn->persistent TSRMLS_CC);
+ conn->net = mysqlnd_net_init(conn->persistent, conn->stats, conn->error_info TSRMLS_CC);
conn->protocol = mysqlnd_protocol_init(conn->persistent TSRMLS_CC);
- DBG_RETURN(conn->net && conn->protocol? PASS:FAIL);
+ DBG_RETURN(conn->stats && conn->net && conn->protocol? PASS:FAIL);
}
/* }}} */
-/* {{{ mysqlnd_init */
-PHPAPI MYSQLND * _mysqlnd_init(zend_bool persistent TSRMLS_DC)
-{
- size_t alloc_size = sizeof(MYSQLND) + mysqlnd_plugin_count() * sizeof(void *);
- MYSQLND *ret;
+MYSQLND_STMT * _mysqlnd_stmt_init(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
- DBG_ENTER("mysqlnd_init");
- DBG_INF_FMT("persistent=%u", persistent);
- ret = mnd_pecalloc(1, alloc_size, persistent);
- if (!ret) {
- DBG_RETURN(NULL);
- }
- ret->persistent = persistent;
- ret->m = mysqlnd_conn_methods;
- CONN_SET_STATE(ret, CONN_ALLOCED);
- ret->m->get_reference(ret TSRMLS_CC);
+MYSQLND_CLASS_METHODS_START(mysqlnd_conn_data)
+ MYSQLND_METHOD(mysqlnd_conn_data, init),
+ MYSQLND_METHOD(mysqlnd_conn_data, connect),
- if (PASS != ret->m->init(ret TSRMLS_CC)) {
- ret->m->dtor(ret TSRMLS_CC);
- ret = NULL;
- }
+ MYSQLND_METHOD(mysqlnd_conn_data, escape_string),
+ MYSQLND_METHOD(mysqlnd_conn_data, set_charset),
+ MYSQLND_METHOD(mysqlnd_conn_data, query),
+ MYSQLND_METHOD(mysqlnd_conn_data, send_query),
+ MYSQLND_METHOD(mysqlnd_conn_data, reap_query),
+ MYSQLND_METHOD(mysqlnd_conn_data, use_result),
+ MYSQLND_METHOD(mysqlnd_conn_data, store_result),
+ MYSQLND_METHOD(mysqlnd_conn_data, next_result),
+ MYSQLND_METHOD(mysqlnd_conn_data, more_results),
- DBG_RETURN(ret);
-}
-/* }}} */
+ _mysqlnd_stmt_init,
+ MYSQLND_METHOD(mysqlnd_conn_data, shutdown),
+ MYSQLND_METHOD(mysqlnd_conn_data, refresh),
-/* {{{ mysqlnd_library_init */
-PHPAPI void mysqlnd_library_init(TSRMLS_D)
-{
- if (mysqlnd_library_initted == FALSE) {
- mysqlnd_library_initted = TRUE;
- mysqlnd_conn_methods = &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_conn);
- _mysqlnd_init_ps_subsystem();
- /* Should be calloc, as mnd_calloc will reference LOCK_access*/
- mysqlnd_stats_init(&mysqlnd_global_stats, STAT_LAST);
- }
-}
-/* }}} */
+ MYSQLND_METHOD(mysqlnd_conn_data, ping),
+ MYSQLND_METHOD(mysqlnd_conn_data, kill),
+ MYSQLND_METHOD(mysqlnd_conn_data, select_db),
+ MYSQLND_METHOD(mysqlnd_conn_data, dump_debug_info),
+ MYSQLND_METHOD(mysqlnd_conn_data, change_user),
+
+ MYSQLND_METHOD(mysqlnd_conn_data, errno),
+ MYSQLND_METHOD(mysqlnd_conn_data, error),
+ MYSQLND_METHOD(mysqlnd_conn_data, sqlstate),
+ MYSQLND_METHOD(mysqlnd_conn_data, thread_id),
+
+ MYSQLND_METHOD(mysqlnd_conn_data, get_connection_stats),
+
+ MYSQLND_METHOD(mysqlnd_conn_data, get_server_version),
+ MYSQLND_METHOD(mysqlnd_conn_data, get_server_info),
+ MYSQLND_METHOD(mysqlnd_conn_data, statistic),
+ MYSQLND_METHOD(mysqlnd_conn_data, get_host_info),
+ MYSQLND_METHOD(mysqlnd_conn_data, get_proto_info),
+ MYSQLND_METHOD(mysqlnd_conn_data, info),
+ MYSQLND_METHOD(mysqlnd_conn_data, charset_name),
+ MYSQLND_METHOD(mysqlnd_conn_data, list_fields),
+ MYSQLND_METHOD(mysqlnd_conn_data, list_method),
+
+ MYSQLND_METHOD(mysqlnd_conn_data, insert_id),
+ MYSQLND_METHOD(mysqlnd_conn_data, affected_rows),
+ MYSQLND_METHOD(mysqlnd_conn_data, warning_count),
+ MYSQLND_METHOD(mysqlnd_conn_data, field_count),
+
+ MYSQLND_METHOD(mysqlnd_conn_data, server_status),
+
+ MYSQLND_METHOD(mysqlnd_conn_data, set_server_option),
+ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option),
+ MYSQLND_METHOD(mysqlnd_conn_data, free_contents),
+ MYSQLND_METHOD(mysqlnd_conn_data, free_options),
+
+ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, dtor),
+
+ mysqlnd_query_read_result_set_header,
+
+ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, get_reference),
+ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, free_reference),
+ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, get_state),
+ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, set_state),
+
+ MYSQLND_METHOD(mysqlnd_conn_data, simple_command),
+ MYSQLND_METHOD(mysqlnd_conn_data, simple_command_handle_response),
+ MYSQLND_METHOD(mysqlnd_conn_data, restart_psession),
+ MYSQLND_METHOD(mysqlnd_conn_data, end_psession),
+ MYSQLND_METHOD(mysqlnd_conn_data, send_close),
+
+ MYSQLND_METHOD(mysqlnd_conn_data, ssl_set),
+ mysqlnd_result_init,
+ MYSQLND_METHOD(mysqlnd_conn_data, set_autocommit),
+ MYSQLND_METHOD(mysqlnd_conn_data, tx_commit),
+ MYSQLND_METHOD(mysqlnd_conn_data, tx_rollback),
+ MYSQLND_METHOD(mysqlnd_conn_data, local_tx_start),
+ MYSQLND_METHOD(mysqlnd_conn_data, local_tx_end)
+MYSQLND_CLASS_METHODS_END;
-/* {{{ mysqlnd_conn_get_methods */
-PHPAPI struct st_mysqlnd_conn_methods * mysqlnd_conn_get_methods()
+
+/* {{{ mysqlnd_conn::get_reference */
+static MYSQLND *
+MYSQLND_METHOD(mysqlnd_conn, clone_object)(MYSQLND * const conn TSRMLS_DC)
{
- return mysqlnd_conn_methods;
+ MYSQLND * ret;
+ DBG_ENTER("mysqlnd_conn::get_reference");
+ ret = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).clone_connection_object(conn TSRMLS_CC);
+ DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_conn_set_methods */
-PHPAPI void mysqlnd_conn_set_methods(struct st_mysqlnd_conn_methods *methods)
+
+/* {{{ mysqlnd_conn_data::dtor */
+static void
+MYSQLND_METHOD_PRIVATE(mysqlnd_conn, dtor)(MYSQLND * conn TSRMLS_DC)
{
- mysqlnd_conn_methods = methods;
-}
-/* }}} */
+ DBG_ENTER("mysqlnd_conn::dtor");
+ DBG_INF_FMT("conn=%llu", conn->data->thread_id);
+ conn->data->m->free_reference(conn->data TSRMLS_CC);
-static unsigned int mysqlnd_plugins_counter = 0;
+ mnd_pefree(conn, conn->persistent);
-/* {{{ mysqlnd_plugin_register */
-PHPAPI unsigned int mysqlnd_plugin_register()
-{
- return mysqlnd_plugins_counter++;
+ DBG_VOID_RETURN;
}
/* }}} */
-/* {{{ mysqlnd_plugin_count */
-PHPAPI unsigned int mysqlnd_plugin_count()
+/* {{{ mysqlnd_conn_data::close */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_conn, close)(MYSQLND * conn_handle, enum_connection_close_type close_type TSRMLS_DC)
{
- return mysqlnd_plugins_counter;
+ size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_methods, close);
+ MYSQLND_CONN_DATA * conn = conn_handle->data;
+ enum_func_status ret = FAIL;
+
+ DBG_ENTER("mysqlnd_conn::close");
+ DBG_INF_FMT("conn=%llu", conn->thread_id);
+
+ if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
+ if (CONN_GET_STATE(conn) >= CONN_READY) {
+ static enum_mysqlnd_collected_stats close_type_to_stat_map[MYSQLND_CLOSE_LAST] = {
+ STAT_CLOSE_EXPLICIT,
+ STAT_CLOSE_IMPLICIT,
+ STAT_CLOSE_DISCONNECT
+ };
+ MYSQLND_INC_CONN_STATISTIC(conn->stats, close_type_to_stat_map[close_type]);
+ }
+
+ /*
+ Close now, free_reference will try,
+ if we are last, but that's not a problem.
+ */
+ ret = conn->m->send_close(conn TSRMLS_CC);
+
+ /* do it after free_reference/dtor and we might crash */
+ conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC);
+
+ conn_handle->m->dtor(conn_handle TSRMLS_CC);
+ }
+ DBG_RETURN(ret);
}
/* }}} */
-/* {{{ _mysqlnd_plugin_get_plugin_connection_data */
-PHPAPI void ** _mysqlnd_plugin_get_plugin_connection_data(const MYSQLND * conn, unsigned int plugin_id TSRMLS_DC)
+MYSQLND_CLASS_METHODS_START(mysqlnd_conn)
+ MYSQLND_METHOD(mysqlnd_conn, connect),
+ MYSQLND_METHOD(mysqlnd_conn, clone_object),
+ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, dtor),
+ MYSQLND_METHOD(mysqlnd_conn, close)
+MYSQLND_CLASS_METHODS_END;
+
+
+/* {{{ _mysqlnd_init */
+PHPAPI MYSQLND *
+_mysqlnd_init(zend_bool persistent TSRMLS_DC)
{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_connection_data");
- DBG_INF_FMT("plugin_id=%u", plugin_id);
- if (!conn || plugin_id >= mysqlnd_plugin_count()) {
- return NULL;
- }
- DBG_RETURN((void *)((char *)conn + sizeof(MYSQLND) + plugin_id * sizeof(void *)));
+ MYSQLND * ret;
+ DBG_ENTER("mysqlnd_init");
+ ret = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_connection(persistent TSRMLS_CC);
+ DBG_RETURN(ret);
}
/* }}} */
diff --git a/ext/mysqlnd/mysqlnd.h b/ext/mysqlnd/mysqlnd.h
index 731e5b87ba..e707c415db 100644
--- a/ext/mysqlnd/mysqlnd.h
+++ b/ext/mysqlnd/mysqlnd.h
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
@@ -22,12 +22,10 @@
#ifndef MYSQLND_H
#define MYSQLND_H
-#define MYSQLND_VERSION "mysqlnd 5.0.8-dev - 20102224 - $Id$"
-#define MYSQLND_VERSION_ID 50008
+#define MYSQLND_VERSION "mysqlnd 5.0.10 - 20111026 - $Id$"
+#define MYSQLND_VERSION_ID 50010
-/* This forces inlining of some accessor functions */
-#define MYSQLND_USE_OPTIMISATIONS 0
-#define AUTOCOMMIT_TX_COMMIT_ROLLBACK
+#define MYSQLND_PLUGIN_API_VERSION 1
#define MYSQLND_STRING_TO_INT_CONVERSION
/*
@@ -69,29 +67,16 @@ PHPAPI void mysqlnd_library_init(TSRMLS_D);
PHPAPI void mysqlnd_library_end(TSRMLS_D);
PHPAPI unsigned int mysqlnd_plugin_register();
+PHPAPI unsigned int mysqlnd_plugin_register_ex(struct st_mysqlnd_plugin_header * plugin TSRMLS_DC);
PHPAPI unsigned int mysqlnd_plugin_count();
-PHPAPI void ** _mysqlnd_plugin_get_plugin_connection_data(const MYSQLND * conn, unsigned int plugin_id TSRMLS_DC);
-#define mysqlnd_plugin_get_plugin_connection_data(c, p_id) _mysqlnd_plugin_get_plugin_connection_data((c), (p_id) TSRMLS_CC)
+PHPAPI void * _mysqlnd_plugin_find(const char * const name TSRMLS_DC);
+#define mysqlnd_plugin_find(name) _mysqlnd_plugin_find((name) TSRMLS_CC);
-PHPAPI void ** _mysqlnd_plugin_get_plugin_result_data(const MYSQLND_RES * result, unsigned int plugin_id TSRMLS_DC);
-#define mysqlnd_plugin_get_plugin_result_data(r, p_id) _mysqlnd_plugin_get_plugin_result_data((r), (p_id) TSRMLS_CC)
+PHPAPI void _mysqlnd_plugin_apply_with_argument(apply_func_arg_t apply_func, void * argument TSRMLS_DC);
+#define mysqlnd_plugin_apply_with_argument(func, argument) _mysqlnd_plugin_apply_with_argument((func), (argument) TSRMLS_CC);
-PHPAPI void ** _mysqlnd_plugin_get_plugin_stmt_data(const MYSQLND_STMT * stmt, unsigned int plugin_id TSRMLS_DC);
-#define mysqlnd_plugin_get_plugin_stmt_data(s, p_id) _mysqlnd_plugin_get_plugin_stmt_data((s), (p_id) TSRMLS_CC)
-
-PHPAPI void ** _mysqlnd_plugin_get_plugin_protocol_data(const MYSQLND_PROTOCOL * protocol, unsigned int plugin_id TSRMLS_DC);
-#define mysqlnd_plugin_get_plugin_protocol_data(p, p_id) _mysqlnd_plugin_get_plugin_protocol_data((p), (p_id) TSRMLS_CC)
-
-
-PHPAPI struct st_mysqlnd_conn_methods * mysqlnd_conn_get_methods();
-PHPAPI void mysqlnd_conn_set_methods(struct st_mysqlnd_conn_methods *methods);
-
-PHPAPI struct st_mysqlnd_stmt_methods * mysqlnd_stmt_get_methods();
-PHPAPI void mysqlnd_stmt_set_methods(struct st_mysqlnd_stmt_methods *methods);
-
-
-#define mysqlnd_restart_psession(conn) (conn)->m->restart_psession((conn) TSRMLS_CC)
-#define mysqlnd_end_psession(conn) (conn)->m->end_psession((conn) TSRMLS_CC)
+#define mysqlnd_restart_psession(conn) ((conn)->data)->m->restart_psession((conn)->data TSRMLS_CC)
+#define mysqlnd_end_psession(conn) ((conn)->data)->m->end_psession((conn)->data TSRMLS_CC)
PHPAPI void mysqlnd_minfo_print_hash(zval *values);
#define mysqlnd_thread_safe() TRUE
@@ -102,16 +87,17 @@ PHPAPI const MYSQLND_CHARSET * mysqlnd_find_charset_name(const char * const char
/* Connect */
#define mysqlnd_init(persistent) _mysqlnd_init((persistent) TSRMLS_CC)
PHPAPI MYSQLND * _mysqlnd_init(zend_bool persistent TSRMLS_DC);
-PHPAPI MYSQLND * mysqlnd_connect(MYSQLND *conn,
- const char *host, const char *user,
- const char *passwd, unsigned int passwd_len,
- const char *db, unsigned int db_len,
+PHPAPI MYSQLND * mysqlnd_connect(MYSQLND * conn,
+ const char * host, const char * user,
+ const char * passwd, unsigned int passwd_len,
+ const char * db, unsigned int db_len,
unsigned int port,
- const char *socket_or_pipe,
+ const char * socket_or_pipe,
unsigned int mysql_flags
TSRMLS_DC);
-#define mysqlnd_change_user(conn, user, passwd, db, silent) (conn)->m->change_user((conn), (user), (passwd), (db), (silent) TSRMLS_CC)
+#define mysqlnd_change_user(conn, user, passwd, db, silent) ((conn)->data)->m->change_user((conn)->data, (user), (passwd), (db), (silent), strlen((passwd)) TSRMLS_CC)
+#define mysqlnd_change_user_ex(conn, user, passwd, db, silent, passwd_len) ((conn)->data)->m->change_user((conn)->data, (user), (passwd), (db), (silent), (passwd_len) TSRMLS_CC)
#define mysqlnd_debug(x) _mysqlnd_debug((x) TSRMLS_CC)
PHPAPI void _mysqlnd_debug(const char *mode TSRMLS_DC);
@@ -121,43 +107,45 @@ PHPAPI void _mysqlnd_debug(const char *mode TSRMLS_DC);
#define mysqlnd_fetch_row_c(result) (result)->m.fetch_row_c((result) TSRMLS_CC)
#define mysqlnd_fetch_all(result, flags, return_value) (result)->m.fetch_all((result), (flags), (return_value) TSRMLS_CC ZEND_FILE_LINE_CC)
#define mysqlnd_result_fetch_field_data(res,offset,ret) (res)->m.fetch_field_data((res), (offset), (ret) TSRMLS_CC)
-#define mysqlnd_get_connection_stats(conn, values) (conn)->m->get_statistics((conn), (values) TSRMLS_CC ZEND_FILE_LINE_CC)
+#define mysqlnd_get_connection_stats(conn, values) ((conn)->data)->m->get_statistics((conn)->data, (values) TSRMLS_CC ZEND_FILE_LINE_CC)
#define mysqlnd_get_client_stats(values) _mysqlnd_get_client_stats((values) TSRMLS_CC ZEND_FILE_LINE_CC)
#define mysqlnd_close(conn,is_forced) (conn)->m->close((conn), (is_forced) TSRMLS_CC)
-#define mysqlnd_query(conn, query_str, query_len) (conn)->m->query((conn), (query_str), (query_len) TSRMLS_CC)
-#define mysqlnd_async_query(conn, query_str, query_len) (conn)->m->send_query((conn), (query_str), (query_len) TSRMLS_CC)
+#define mysqlnd_query(conn, query_str, query_len) ((conn)->data)->m->query((conn)->data, (query_str), (query_len) TSRMLS_CC)
+#define mysqlnd_async_query(conn, query_str, query_len) ((conn)->data)->m->send_query((conn)->data, (query_str), (query_len) TSRMLS_CC)
#define mysqlnd_poll(r, err, d_pull,sec,usec,desc_num) _mysqlnd_poll((r), (err), (d_pull), (sec), (usec), (desc_num) TSRMLS_CC)
-#define mysqlnd_reap_async_query(conn) (conn)->m->reap_query((conn) TSRMLS_CC)
+#define mysqlnd_reap_async_query(conn) ((conn)->data)->m->reap_query((conn)->data TSRMLS_CC)
#define mysqlnd_unbuffered_skip_result(result) (result)->m.skip_result((result) TSRMLS_CC)
PHPAPI enum_func_status _mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQLND ***dont_poll, long sec, long usec, uint * desc_num TSRMLS_DC);
-#define mysqlnd_use_result(conn) (conn)->m->use_result((conn) TSRMLS_CC)
-#define mysqlnd_store_result(conn) (conn)->m->store_result((conn) TSRMLS_CC)
-#define mysqlnd_next_result(conn) (conn)->m->next_result((conn) TSRMLS_CC)
-#define mysqlnd_more_results(conn) (conn)->m->more_results((conn) TSRMLS_CC)
+#define mysqlnd_use_result(conn) ((conn)->data)->m->use_result((conn)->data TSRMLS_CC)
+#define mysqlnd_store_result(conn) ((conn)->data)->m->store_result((conn)->data TSRMLS_CC)
+#define mysqlnd_next_result(conn) ((conn)->data)->m->next_result((conn)->data TSRMLS_CC)
+#define mysqlnd_more_results(conn) ((conn)->data)->m->more_results((conn)->data TSRMLS_CC)
#define mysqlnd_free_result(r,e_or_i) ((MYSQLND_RES*)r)->m.free_result(((MYSQLND_RES*)(r)), (e_or_i) TSRMLS_CC)
#define mysqlnd_data_seek(result, row) (result)->m.seek_data((result), (row) TSRMLS_CC)
/* Errors */
-#define mysqlnd_errno(conn) (conn)->m->get_error_no((conn) TSRMLS_CC)
-#define mysqlnd_error(conn) (conn)->m->get_error_str((conn) TSRMLS_CC)
-#define mysqlnd_sqlstate(conn) (conn)->m->get_sqlstate((conn) TSRMLS_CC)
+#define mysqlnd_errno(conn) ((conn)->data)->m->get_error_no((conn)->data TSRMLS_CC)
+#define mysqlnd_error(conn) ((conn)->data)->m->get_error_str((conn)->data TSRMLS_CC)
+#define mysqlnd_sqlstate(conn) ((conn)->data)->m->get_sqlstate((conn)->data TSRMLS_CC)
/* Charset */
-#define mysqlnd_character_set_name(conn) (conn)->m->charset_name((conn) TSRMLS_CC)
+#define mysqlnd_character_set_name(conn) ((conn)->data)->m->charset_name((conn)->data TSRMLS_CC)
/* Simple metadata */
-#define mysqlnd_field_count(conn) (conn)->m->get_field_count((conn) TSRMLS_CC)
-#define mysqlnd_insert_id(conn) (conn)->m->get_last_insert_id((conn) TSRMLS_CC)
-#define mysqlnd_affected_rows(conn) (conn)->m->get_affected_rows((conn) TSRMLS_CC)
-#define mysqlnd_warning_count(conn) (conn)->m->get_warning_count((conn) TSRMLS_CC)
-#define mysqlnd_info(conn) (conn)->m->get_last_message((conn) TSRMLS_CC)
-#define mysqlnd_get_server_info(conn) (conn)->m->get_server_information((conn) TSRMLS_CC)
-#define mysqlnd_get_host_info(conn) (conn)->m->get_host_information((conn) TSRMLS_CC)
-#define mysqlnd_get_proto_info(conn) (conn)->m->get_protocol_information((conn) TSRMLS_CC)
-#define mysqlnd_thread_id(conn) (conn)->m->get_thread_id((conn) TSRMLS_CC)
+#define mysqlnd_field_count(conn) ((conn)->data)->m->get_field_count((conn)->data TSRMLS_CC)
+#define mysqlnd_insert_id(conn) ((conn)->data)->m->get_last_insert_id((conn)->data TSRMLS_CC)
+#define mysqlnd_affected_rows(conn) ((conn)->data)->m->get_affected_rows((conn)->data TSRMLS_CC)
+#define mysqlnd_warning_count(conn) ((conn)->data)->m->get_warning_count((conn)->data TSRMLS_CC)
+#define mysqlnd_info(conn) ((conn)->data)->m->get_last_message((conn)->data TSRMLS_CC)
+#define mysqlnd_get_server_info(conn) ((conn)->data)->m->get_server_information((conn)->data TSRMLS_CC)
+#define mysqlnd_get_server_version(conn) ((conn)->data)->m->get_server_version((conn)->data TSRMLS_CC)
+#define mysqlnd_get_host_info(conn) ((conn)->data)->m->get_host_information((conn)->data TSRMLS_CC)
+#define mysqlnd_get_proto_info(conn) ((conn)->data)->m->get_protocol_information((conn)->data TSRMLS_CC)
+#define mysqlnd_thread_id(conn) ((conn)->data)->m->get_thread_id((conn)->data TSRMLS_CC)
+#define mysqlnd_get_server_status(conn) ((conn)->data)->m->get_server_status((conn)->data TSRMLS_CC)
#define mysqlnd_num_rows(result) (result)->m.num_rows((result) TSRMLS_CC)
#define mysqlnd_num_fields(result) (result)->m.num_fields((result) TSRMLS_CC)
@@ -175,7 +163,7 @@ PHPAPI unsigned long * _mysqlnd_fetch_lengths(MYSQLND_RES * const result TSRMLS
PHPAPI const char * mysqlnd_get_client_info();
PHPAPI unsigned int mysqlnd_get_client_version();
-#define mysqlnd_ssl_set(conn, key, cert, ca, capath, cipher) (conn)->m->ssl_set((conn), (key), (cert), (ca), (capath), (cipher) TSRMLS_CC)
+#define mysqlnd_ssl_set(conn, key, cert, ca, capath, cipher) ((conn)->data)->m->ssl_set((conn)->data, (key), (cert), (ca), (capath), (cipher) TSRMLS_CC)
/* PS */
#define mysqlnd_stmt_insert_id(stmt) (stmt)->m->get_last_insert_id((stmt) TSRMLS_CC)
@@ -199,46 +187,39 @@ PHPAPI void mysqlnd_free_result_bind_dtor(MYSQLND_RESULT_BIND * result_bind TSRM
PHPAPI const char * mysqlnd_field_type_name(enum mysqlnd_field_types field_type);
/* LOAD DATA LOCAL */
-PHPAPI void mysqlnd_local_infile_default(MYSQLND *conn);
-PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND * const conn, const char * const funcname);
+PHPAPI void mysqlnd_local_infile_default(MYSQLND_CONN_DATA * conn);
+PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND_CONN_DATA * const conn, const char * const funcname);
/* Simple commands */
-#ifdef AUTOCOMMIT_TX_COMMIT_ROLLBACK
-#define mysqlnd_autocommit(conn, mode) (conn)->m->set_autocommit((conn), (mode) TSRMLS_CC)
-#define mysqlnd_commit(conn) (conn)->m->tx_commit((conn) TSRMLS_CC)
-#define mysqlnd_rollback(conn) (conn)->m->tx_rollback((conn) TSRMLS_CC)
-#else
-#define mysqlnd_autocommit(conn, mode) (conn)->m->query((conn),(mode) ? "SET AUTOCOMMIT=1":"SET AUTOCOMMIT=0", 16 TSRMLS_CC)
-#define mysqlnd_commit(conn) (conn)->m->query((conn), "COMMIT", sizeof("COMMIT")-1 TSRMLS_CC)
-#define mysqlnd_rollback(conn) (conn)->m->query((conn), "ROLLBACK", sizeof("ROLLBACK")-1 TSRMLS_CC)
-#endif
-#define mysqlnd_list_dbs(conn, wild) (conn)->m->list_method((conn), wild? "SHOW DATABASES LIKE %s":"SHOW DATABASES", (wild), NULL TSRMLS_CC)
-#define mysqlnd_list_fields(conn, tab,wild) (conn)->m->list_fields((conn), (tab), (wild) TSRMLS_CC)
-#define mysqlnd_list_processes(conn) (conn)->m->list_method((conn), "SHOW PROCESSLIST", NULL, NULL TSRMLS_CC)
-#define mysqlnd_list_tables(conn, wild) (conn)->m->list_method((conn), wild? "SHOW TABLES LIKE %s":"SHOW TABLES", (wild), NULL TSRMLS_CC)
-#define mysqlnd_dump_debug_info(conn) (conn)->m->server_dump_debug_information((conn) TSRMLS_CC)
-#define mysqlnd_select_db(conn, db, db_len) (conn)->m->select_db((conn), (db), (db_len) TSRMLS_CC)
-#define mysqlnd_ping(conn) (conn)->m->ping((conn) TSRMLS_CC)
-#define mysqlnd_kill(conn, pid) (conn)->m->kill_connection((conn), (pid) TSRMLS_CC)
-#define mysqlnd_refresh(conn, options) (conn)->m->refresh_server((conn), (options) TSRMLS_CC)
-#define mysqlnd_shutdown(conn, level) (conn)->m->shutdown_server((conn), (level) TSRMLS_CC)
-#define mysqlnd_get_server_version(conn) (conn)->m->get_server_version((conn) TSRMLS_CC)
-#define mysqlnd_set_character_set(conn, cs) (conn)->m->set_charset((conn), (cs) TSRMLS_CC)
-#define mysqlnd_stat(conn, msg, msg_len) (conn)->m->get_server_statistics((conn), (msg), (msg_len) TSRMLS_CC)
-#define mysqlnd_options(conn, opt, value) (conn)->m->set_client_option((conn), (opt), (value) TSRMLS_CC)
-#define mysqlnd_set_server_option(conn, op) (conn)->m->set_server_option((conn), (op) TSRMLS_CC)
+#define mysqlnd_autocommit(conn, mode) ((conn)->data)->m->set_autocommit((conn)->data, (mode) TSRMLS_CC)
+#define mysqlnd_commit(conn) ((conn)->data)->m->tx_commit((conn)->data TSRMLS_CC)
+#define mysqlnd_rollback(conn) ((conn)->data)->m->tx_rollback((conn)->data TSRMLS_CC)
+#define mysqlnd_list_dbs(conn, wild) ((conn)->data)->m->list_method((conn)->data, wild? "SHOW DATABASES LIKE %s":"SHOW DATABASES", (wild), NULL TSRMLS_CC)
+#define mysqlnd_list_fields(conn, tab,wild) ((conn)->data)->m->list_fields((conn)->data, (tab), (wild) TSRMLS_CC)
+#define mysqlnd_list_processes(conn) ((conn)->data)->m->list_method((conn)->data, "SHOW PROCESSLIST", NULL, NULL TSRMLS_CC)
+#define mysqlnd_list_tables(conn, wild) ((conn)->data)->m->list_method((conn)->data, wild? "SHOW TABLES LIKE %s":"SHOW TABLES", (wild), NULL TSRMLS_CC)
+#define mysqlnd_dump_debug_info(conn) ((conn)->data)->m->server_dump_debug_information((conn)->data TSRMLS_CC)
+#define mysqlnd_select_db(conn, db, db_len) ((conn)->data)->m->select_db((conn)->data, (db), (db_len) TSRMLS_CC)
+#define mysqlnd_ping(conn) ((conn)->data)->m->ping((conn)->data TSRMLS_CC)
+#define mysqlnd_kill(conn, pid) ((conn)->data)->m->kill_connection((conn)->data, (pid) TSRMLS_CC)
+#define mysqlnd_refresh(conn, options) ((conn)->data)->m->refresh_server((conn)->data, (options) TSRMLS_CC)
+#define mysqlnd_shutdown(conn, level) ((conn)->data)->m->shutdown_server((conn)->data, (level) TSRMLS_CC)
+#define mysqlnd_set_character_set(conn, cs) ((conn)->data)->m->set_charset((conn)->data, (cs) TSRMLS_CC)
+#define mysqlnd_stat(conn, msg, msg_len) ((conn)->data)->m->get_server_statistics(((conn)->data), (msg), (msg_len) TSRMLS_CC)
+#define mysqlnd_options(conn, opt, value) ((conn)->data)->m->set_client_option((conn)->data, (opt), (value) TSRMLS_CC)
+#define mysqlnd_set_server_option(conn, op) ((conn)->data)->m->set_server_option((conn)->data, (op) TSRMLS_CC)
/* Escaping */
#define mysqlnd_real_escape_string(conn, newstr, escapestr, escapestr_len) \
- (conn)->m->escape_string((conn), (newstr), (escapestr), (escapestr_len) TSRMLS_CC)
+ ((conn)->data)->m->escape_string((conn)->data, (newstr), (escapestr), (escapestr_len) TSRMLS_CC)
#define mysqlnd_escape_string(newstr, escapestr, escapestr_len) \
mysqlnd_old_escape_string((newstr), (escapestr), (escapestr_len) TSRMLS_CC)
-PHPAPI ulong mysqlnd_old_escape_string(char *newstr, const char *escapestr, size_t escapestr_len TSRMLS_DC);
+PHPAPI ulong mysqlnd_old_escape_string(char * newstr, const char * escapestr, size_t escapestr_len TSRMLS_DC);
/* PS */
-#define mysqlnd_stmt_init(conn) (conn)->m->stmt_init((conn) TSRMLS_CC)
+#define mysqlnd_stmt_init(conn) ((conn)->data)->m->stmt_init(((conn)->data) TSRMLS_CC)
#define mysqlnd_stmt_store_result(stmt) (!mysqlnd_stmt_field_count((stmt)) ? PASS:((stmt)->m->store_result((stmt) TSRMLS_CC)? PASS:FAIL))
#define mysqlnd_stmt_get_result(stmt) (stmt)->m->get_result((stmt) TSRMLS_CC)
#define mysqlnd_stmt_more_results(stmt) (stmt)->m->more_results((stmt) TSRMLS_CC)
@@ -262,6 +243,7 @@ PHPAPI ulong mysqlnd_old_escape_string(char *newstr, const char *escapestr, size
#define mysqlnd_stmt_free_result(stmt) (stmt)->m->free_result((stmt) TSRMLS_CC)
#define mysqlnd_stmt_close(stmt, implicit) (stmt)->m->dtor((stmt), (implicit) TSRMLS_CC)
#define mysqlnd_stmt_reset(stmt) (stmt)->m->reset((stmt) TSRMLS_CC)
+#define mysqlnd_stmt_flush(stmt) (stmt)->m->flush((stmt) TSRMLS_CC)
#define mysqlnd_stmt_attr_get(stmt, attr, value) (stmt)->m->get_attribute((stmt), (attr), (value) TSRMLS_CC)
diff --git a/ext/mysqlnd/mysqlnd_alloc.c b/ext/mysqlnd/mysqlnd_alloc.c
new file mode 100644
index 0000000000..380a0fbaa0
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_alloc.c
@@ -0,0 +1,796 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Georg Richter <georg@mysql.com> |
+ | Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd_debug.c 309303 2011-03-16 12:42:59Z andrey $ */
+#include "php.h"
+#include "mysqlnd.h"
+#include "mysqlnd_priv.h"
+#include "mysqlnd_debug.h"
+#include "mysqlnd_wireprotocol.h"
+#include "mysqlnd_statistics.h"
+
+
+static const char mysqlnd_emalloc_name[] = "_mysqlnd_emalloc";
+static const char mysqlnd_pemalloc_name[] = "_mysqlnd_pemalloc";
+static const char mysqlnd_ecalloc_name[] = "_mysqlnd_ecalloc";
+static const char mysqlnd_pecalloc_name[] = "_mysqlnd_pecalloc";
+static const char mysqlnd_erealloc_name[] = "_mysqlnd_erealloc";
+static const char mysqlnd_perealloc_name[] = "_mysqlnd_perealloc";
+static const char mysqlnd_efree_name[] = "_mysqlnd_efree";
+static const char mysqlnd_pefree_name[] = "_mysqlnd_pefree";
+static const char mysqlnd_malloc_name[] = "_mysqlnd_malloc";
+static const char mysqlnd_calloc_name[] = "_mysqlnd_calloc";
+static const char mysqlnd_realloc_name[] = "_mysqlnd_realloc";
+static const char mysqlnd_free_name[] = "_mysqlnd_free";
+static const char mysqlnd_pestrndup_name[] = "_mysqlnd_pestrndup";
+static const char mysqlnd_pestrdup_name[] = "_mysqlnd_pestrdup";
+
+const char * mysqlnd_debug_std_no_trace_funcs[] =
+{
+ mysqlnd_emalloc_name,
+ mysqlnd_ecalloc_name,
+ mysqlnd_efree_name,
+ mysqlnd_erealloc_name,
+ mysqlnd_pemalloc_name,
+ mysqlnd_pecalloc_name,
+ mysqlnd_pefree_name,
+ mysqlnd_perealloc_name,
+ mysqlnd_malloc_name,
+ mysqlnd_calloc_name,
+ mysqlnd_realloc_name,
+ mysqlnd_free_name,
+ mysqlnd_pestrndup_name,
+ mysqlnd_read_header_name,
+ mysqlnd_read_body_name,
+ NULL /* must be always last */
+};
+
+
+#if ZEND_DEBUG
+#else
+#define __zend_filename "/unknown/unknown"
+#define __zend_lineno 0
+#endif
+
+#define REAL_SIZE(s) (collect_memory_statistics? (s) + sizeof(size_t) : (s))
+#define REAL_PTR(p) (collect_memory_statistics && (p)? (((char *)(p)) - sizeof(size_t)) : (p))
+#define FAKE_PTR(p) (collect_memory_statistics && (p)? (((char *)(p)) + sizeof(size_t)) : (p))
+
+/* {{{ _mysqlnd_emalloc */
+void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D)
+{
+ void *ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+#if PHP_DEBUG
+ long * threshold = &MYSQLND_G(debug_emalloc_fail_threshold);
+#endif
+ DBG_ENTER(mysqlnd_emalloc_name);
+
+#if PHP_DEBUG
+ {
+ char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
+ DBG_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
+ }
+#endif
+
+#if PHP_DEBUG
+ /* -1 is also "true" */
+ if (*threshold) {
+#endif
+ ret = emalloc(REAL_SIZE(size));
+#if PHP_DEBUG
+ --*threshold;
+ } else if (*threshold == 0) {
+ ret = NULL;
+ }
+#endif
+
+ DBG_INF_FMT("size=%lu ptr=%p", size, ret);
+
+ if (ret && collect_memory_statistics) {
+ *(size_t *) ret = size;
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EMALLOC_COUNT, 1, STAT_MEM_EMALLOC_AMOUNT, size);
+ }
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_pemalloc */
+void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)
+{
+ void *ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+#if PHP_DEBUG
+ long * threshold = persistent? &MYSQLND_G(debug_malloc_fail_threshold):&MYSQLND_G(debug_emalloc_fail_threshold);
+#endif
+ DBG_ENTER(mysqlnd_pemalloc_name);
+#if PHP_DEBUG
+ {
+ char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
+ DBG_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
+ }
+#endif
+
+#if PHP_DEBUG
+ /* -1 is also "true" */
+ if (*threshold) {
+#endif
+ ret = pemalloc(REAL_SIZE(size), persistent);
+#if PHP_DEBUG
+ --*threshold;
+ } else if (*threshold == 0) {
+ ret = NULL;
+ }
+#endif
+
+ DBG_INF_FMT("size=%lu ptr=%p persistent=%u", size, ret, persistent);
+
+ if (ret && collect_memory_statistics) {
+ enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_MALLOC_COUNT:STAT_MEM_EMALLOC_COUNT;
+ enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_MALLOC_AMOUNT:STAT_MEM_EMALLOC_AMOUNT;
+ *(size_t *) ret = size;
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);
+ }
+
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_ecalloc */
+void * _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
+{
+ void *ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+#if PHP_DEBUG
+ long * threshold = &MYSQLND_G(debug_ecalloc_fail_threshold);
+#endif
+ DBG_ENTER(mysqlnd_ecalloc_name);
+#if PHP_DEBUG
+ {
+ char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
+ DBG_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
+ }
+#endif
+ DBG_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC));
+
+#if PHP_DEBUG
+ /* -1 is also "true" */
+ if (*threshold) {
+#endif
+ ret = ecalloc(nmemb, REAL_SIZE(size));
+#if PHP_DEBUG
+ --*threshold;
+ } else if (*threshold == 0) {
+ ret = NULL;
+ }
+#endif
+
+ DBG_INF_FMT("after : %lu", zend_memory_usage(FALSE TSRMLS_CC));
+ DBG_INF_FMT("size=%lu ptr=%p", size, ret);
+ if (ret && collect_memory_statistics) {
+ *(size_t *) ret = size;
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_ECALLOC_COUNT, 1, STAT_MEM_ECALLOC_AMOUNT, size);
+ }
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_pecalloc */
+void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D)
+{
+ void *ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+#if PHP_DEBUG
+ long * threshold = persistent? &MYSQLND_G(debug_calloc_fail_threshold):&MYSQLND_G(debug_ecalloc_fail_threshold);
+#endif
+ DBG_ENTER(mysqlnd_pecalloc_name);
+#if PHP_DEBUG
+ {
+ char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
+ DBG_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
+ }
+#endif
+
+#if PHP_DEBUG
+ /* -1 is also "true" */
+ if (*threshold) {
+#endif
+ ret = pecalloc(nmemb, REAL_SIZE(size), persistent);
+#if PHP_DEBUG
+ --*threshold;
+ } else if (*threshold == 0) {
+ ret = NULL;
+ }
+#endif
+
+ DBG_INF_FMT("size=%lu ptr=%p", size, ret);
+
+ if (ret && collect_memory_statistics) {
+ enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_CALLOC_COUNT:STAT_MEM_ECALLOC_COUNT;
+ enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_CALLOC_AMOUNT:STAT_MEM_ECALLOC_AMOUNT;
+ *(size_t *) ret = size;
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);
+ }
+
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_erealloc */
+void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
+{
+ void *ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+ size_t old_size = collect_memory_statistics && ptr? *(size_t *) (((char*)ptr) - sizeof(size_t)) : 0;
+#if PHP_DEBUG
+ long * threshold = &MYSQLND_G(debug_erealloc_fail_threshold);
+#endif
+ DBG_ENTER(mysqlnd_erealloc_name);
+#if PHP_DEBUG
+ {
+ char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
+ DBG_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
+ }
+#endif
+ DBG_INF_FMT("ptr=%p old_size=%lu, new_size=%lu", ptr, old_size, new_size);
+
+#if PHP_DEBUG
+ /* -1 is also "true" */
+ if (*threshold) {
+#endif
+ ret = erealloc(REAL_PTR(ptr), REAL_SIZE(new_size));
+#if PHP_DEBUG
+ --*threshold;
+ } else if (*threshold == 0) {
+ ret = NULL;
+ }
+#endif
+
+ DBG_INF_FMT("new_ptr=%p", (char*)ret);
+ if (ret && collect_memory_statistics) {
+ *(size_t *) ret = new_size;
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EREALLOC_COUNT, 1, STAT_MEM_EREALLOC_AMOUNT, new_size);
+ }
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_perealloc */
+void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D)
+{
+ void *ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+ size_t old_size = collect_memory_statistics && ptr? *(size_t *) (((char*)ptr) - sizeof(size_t)) : 0;
+#if PHP_DEBUG
+ long * threshold = persistent? &MYSQLND_G(debug_realloc_fail_threshold):&MYSQLND_G(debug_erealloc_fail_threshold);
+#endif
+ DBG_ENTER(mysqlnd_perealloc_name);
+#if PHP_DEBUG
+ {
+ char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
+ DBG_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
+ }
+#endif
+ DBG_INF_FMT("ptr=%p old_size=%lu new_size=%lu persistent=%u", ptr, old_size, new_size, persistent);
+
+#if PHP_DEBUG
+ /* -1 is also "true" */
+ if (*threshold) {
+#endif
+ ret = perealloc(REAL_PTR(ptr), REAL_SIZE(new_size), persistent);
+#if PHP_DEBUG
+ --*threshold;
+ } else if (*threshold == 0) {
+ ret = NULL;
+ }
+#endif
+
+ DBG_INF_FMT("new_ptr=%p", (char*)ret);
+
+ if (ret && collect_memory_statistics) {
+ enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_REALLOC_COUNT:STAT_MEM_EREALLOC_COUNT;
+ enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_REALLOC_AMOUNT:STAT_MEM_EREALLOC_AMOUNT;
+ *(size_t *) ret = new_size;
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, new_size);
+ }
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_efree */
+void _mysqlnd_efree(void *ptr MYSQLND_MEM_D)
+{
+ size_t free_amount = 0;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+ DBG_ENTER(mysqlnd_efree_name);
+#if PHP_DEBUG
+ {
+ char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
+ DBG_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
+ }
+#endif
+ DBG_INF_FMT("ptr=%p", ptr);
+
+ if (ptr) {
+ if (collect_memory_statistics) {
+ free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
+ DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
+ }
+ efree(REAL_PTR(ptr));
+ }
+
+ if (collect_memory_statistics) {
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EFREE_COUNT, 1, STAT_MEM_EFREE_AMOUNT, free_amount);
+ }
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_pefree */
+void _mysqlnd_pefree(void *ptr, zend_bool persistent MYSQLND_MEM_D)
+{
+ size_t free_amount = 0;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+ DBG_ENTER(mysqlnd_pefree_name);
+#if PHP_DEBUG
+ {
+ char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
+ DBG_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
+ }
+#endif
+ DBG_INF_FMT("ptr=%p persistent=%u", ptr, persistent);
+
+ if (ptr) {
+ if (collect_memory_statistics) {
+ free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
+ DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
+ }
+ pefree(REAL_PTR(ptr), persistent);
+ }
+
+ if (collect_memory_statistics) {
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(persistent? STAT_MEM_FREE_COUNT:STAT_MEM_EFREE_COUNT, 1,
+ persistent? STAT_MEM_FREE_AMOUNT:STAT_MEM_EFREE_AMOUNT, free_amount);
+ }
+ DBG_VOID_RETURN;
+}
+
+
+/* {{{ _mysqlnd_malloc */
+void * _mysqlnd_malloc(size_t size MYSQLND_MEM_D)
+{
+ void *ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+#if PHP_DEBUG
+ long * threshold = &MYSQLND_G(debug_malloc_fail_threshold);
+#endif
+ DBG_ENTER(mysqlnd_malloc_name);
+#if PHP_DEBUG
+ {
+ char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
+ DBG_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
+ }
+#endif
+
+#if PHP_DEBUG
+ /* -1 is also "true" */
+ if (*threshold) {
+#endif
+ ret = malloc(REAL_SIZE(size));
+#if PHP_DEBUG
+ --*threshold;
+ } else if (*threshold == 0) {
+ ret = NULL;
+ }
+#endif
+
+ DBG_INF_FMT("size=%lu ptr=%p", size, ret);
+ if (ret && collect_memory_statistics) {
+ *(size_t *) ret = size;
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_MALLOC_COUNT, 1, STAT_MEM_MALLOC_AMOUNT, size);
+ }
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_calloc */
+void * _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
+{
+ void *ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+#if PHP_DEBUG
+ long * threshold = &MYSQLND_G(debug_calloc_fail_threshold);
+#endif
+ DBG_ENTER(mysqlnd_calloc_name);
+#if PHP_DEBUG
+ {
+ char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
+ DBG_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
+ }
+#endif
+
+#if PHP_DEBUG
+ /* -1 is also "true" */
+ if (*threshold) {
+#endif
+ ret = calloc(nmemb, REAL_SIZE(size));
+#if PHP_DEBUG
+ --*threshold;
+ } else if (*threshold == 0) {
+ ret = NULL;
+ }
+#endif
+
+ DBG_INF_FMT("size=%lu ptr=%p", size, ret);
+ if (ret && collect_memory_statistics) {
+ *(size_t *) ret = size;
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_CALLOC_COUNT, 1, STAT_MEM_CALLOC_AMOUNT, size);
+ }
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_realloc */
+void * _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D)
+{
+ void *ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+#if PHP_DEBUG
+ long * threshold = &MYSQLND_G(debug_realloc_fail_threshold);
+#endif
+ DBG_ENTER(mysqlnd_realloc_name);
+#if PHP_DEBUG
+ {
+ char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
+ DBG_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
+ }
+#endif
+ DBG_INF_FMT("ptr=%p new_size=%lu ", new_size, ptr);
+ DBG_INF_FMT("before: %lu", zend_memory_usage(TRUE TSRMLS_CC));
+
+#if PHP_DEBUG
+ /* -1 is also "true" */
+ if (*threshold) {
+#endif
+ ret = realloc(REAL_PTR(ptr), REAL_SIZE(new_size));
+#if PHP_DEBUG
+ --*threshold;
+ } else if (*threshold == 0) {
+ ret = NULL;
+ }
+#endif
+
+ DBG_INF_FMT("new_ptr=%p", (char*)ret);
+
+ if (ret && collect_memory_statistics) {
+ *(size_t *) ret = new_size;
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_REALLOC_COUNT, 1, STAT_MEM_REALLOC_AMOUNT, new_size);
+ }
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_free */
+void _mysqlnd_free(void *ptr MYSQLND_MEM_D)
+{
+ size_t free_amount = 0;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+ DBG_ENTER(mysqlnd_free_name);
+#if PHP_DEBUG
+ {
+ char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
+ DBG_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
+ }
+#endif
+ DBG_INF_FMT("ptr=%p", ptr);
+
+ if (ptr) {
+ if (collect_memory_statistics) {
+ free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
+ DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
+ }
+ free(REAL_PTR(ptr));
+ }
+
+ if (collect_memory_statistics) {
+ MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_FREE_COUNT, 1, STAT_MEM_FREE_AMOUNT, free_amount);
+ }
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+#define SMART_STR_START_SIZE 2048
+#define SMART_STR_PREALLOC 512
+#include "ext/standard/php_smart_str.h"
+
+
+/* {{{ _mysqlnd_pestrndup */
+char * _mysqlnd_pestrndup(const char * const ptr, size_t length, zend_bool persistent MYSQLND_MEM_D)
+{
+ char * ret;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+ DBG_ENTER(mysqlnd_pestrndup_name);
+#if PHP_DEBUG
+ {
+ char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
+ DBG_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
+ }
+#endif
+ DBG_INF_FMT("ptr=%p", ptr);
+
+ ret = pemalloc(REAL_SIZE(length) + 1, persistent);
+ {
+ size_t l = length;
+ char * p = (char *) ptr;
+ char * dest = (char *) FAKE_PTR(ret);
+ while (*p && l--) {
+ *dest++ = *p++;
+ }
+ *dest = '\0';
+ }
+
+ if (collect_memory_statistics) {
+ *(size_t *) ret = length;
+ MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRNDUP_COUNT : STAT_MEM_ESTRNDUP_COUNT);
+ }
+
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_pestrdup */
+char * _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D)
+{
+ char * ret;
+ smart_str tmp_str = {0, 0, 0};
+ const char * p = ptr;
+ zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
+ DBG_ENTER(mysqlnd_pestrdup_name);
+#if PHP_DEBUG
+ {
+ char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
+ DBG_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
+ }
+#endif
+ DBG_INF_FMT("ptr=%p", ptr);
+ do {
+ smart_str_appendc(&tmp_str, *p);
+ } while (*p++);
+
+ ret = pemalloc(tmp_str.len + sizeof(size_t), persistent);
+ memcpy(FAKE_PTR(ret), tmp_str.c, tmp_str.len);
+
+ if (ret && collect_memory_statistics) {
+ *(size_t *) ret = tmp_str.len;
+ MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRDUP_COUNT : STAT_MEM_ESTRDUP_COUNT);
+ }
+ smart_str_free(&tmp_str);
+
+ DBG_RETURN(FAKE_PTR(ret));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_sprintf */
+PHPAPI int _mysqlnd_sprintf(char ** pbuf, size_t max_len, const char *format, ...)
+{
+ int len;
+ va_list ap;
+ va_start(ap, format);
+ len = vspprintf(pbuf, max_len, format, ap);
+ va_end(ap);
+ return len;
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_sprintf_free */
+PHPAPI void _mysqlnd_sprintf_free(char * p)
+{
+ efree(p);
+}
+/* }}} */
+
+
+PHPAPI int _mysqlnd_vsprintf(char ** pbuf, size_t max_len, const char * format, va_list ap)
+{
+ return vspprintf(pbuf, max_len, format, ap);
+}
+/* }}} */
+
+
+#define MYSQLND_DEBUG_MEMORY 1
+
+#if MYSQLND_DEBUG_MEMORY == 0
+
+/* {{{ mysqlnd_zend_mm_emalloc */
+static void * mysqlnd_zend_mm_emalloc(size_t size MYSQLND_MEM_D)
+{
+ return emalloc(size);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_pemalloc */
+static void * mysqlnd_zend_mm_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)
+{
+ return pemalloc(size, persistent);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_ecalloc */
+static void * mysqlnd_zend_mm_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
+{
+ return ecalloc(nmemb, size);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_pecalloc */
+static void * mysqlnd_zend_mm_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D)
+{
+ return pecalloc(nmemb, size, persistent);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_erealloc */
+static void * mysqlnd_zend_mm_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
+{
+ return erealloc(ptr, new_size);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_perealloc */
+static void * mysqlnd_zend_mm_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D)
+{
+ return perealloc(ptr, new_size, persistent);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_efree */
+static void mysqlnd_zend_mm_efree(void * ptr MYSQLND_MEM_D)
+{
+ efree(ptr);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_pefree */
+static void mysqlnd_zend_mm_pefree(void * ptr, zend_bool persistent MYSQLND_MEM_D)
+{
+ pefree(ptr, persistent);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_malloc */
+static void * mysqlnd_zend_mm_malloc(size_t size MYSQLND_MEM_D)
+{
+ return malloc(size);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_calloc */
+static void * mysqlnd_zend_mm_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
+{
+ return calloc(nmemb, size);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_realloc */
+static void * mysqlnd_zend_mm_realloc(void * ptr, size_t new_size MYSQLND_MEM_D)
+{
+ return realloc(ptr, new_size);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_free */
+static void mysqlnd_zend_mm_free(void * ptr MYSQLND_MEM_D)
+{
+ free(ptr);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_pestrndup */
+static char * mysqlnd_zend_mm_pestrndup(const char * const ptr, size_t length, zend_bool persistent MYSQLND_MEM_D)
+{
+ return pestrndup(ptr, length, persistent);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_zend_mm_pestrdup */
+static char * mysqlnd_zend_mm_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D)
+{
+ return pestrdup(ptr, persistent);
+}
+/* }}} */
+
+#endif
+
+
+PHPAPI struct st_mysqlnd_allocator_methods mysqlnd_allocator =
+{
+#if MYSQLND_DEBUG_MEMORY
+ _mysqlnd_emalloc,
+ _mysqlnd_pemalloc,
+ _mysqlnd_ecalloc,
+ _mysqlnd_pecalloc,
+ _mysqlnd_erealloc,
+ _mysqlnd_perealloc,
+ _mysqlnd_efree,
+ _mysqlnd_pefree,
+ _mysqlnd_malloc,
+ _mysqlnd_calloc,
+ _mysqlnd_realloc,
+ _mysqlnd_free,
+ _mysqlnd_pestrndup,
+ _mysqlnd_pestrdup,
+ _mysqlnd_sprintf,
+ _mysqlnd_vsprintf,
+ _mysqlnd_sprintf_free
+#else
+ mysqlnd_zend_mm_emalloc,
+ mysqlnd_zend_mm_pemalloc,
+ mysqlnd_zend_mm_ecalloc,
+ mysqlnd_zend_mm_pecalloc,
+ mysqlnd_zend_mm_erealloc,
+ mysqlnd_zend_mm_perealloc,
+ mysqlnd_zend_mm_efree,
+ mysqlnd_zend_mm_pefree,
+ mysqlnd_zend_mm_malloc,
+ mysqlnd_zend_mm_calloc,
+ mysqlnd_zend_mm_realloc,
+ mysqlnd_zend_mm_free,
+ mysqlnd_zend_mm_pestrndup,
+ mysqlnd_zend_mm_pestrdup
+ sprintf,
+ mysqlnd_zend_mm_efree,
+#endif
+};
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_alloc.h b/ext/mysqlnd/mysqlnd_alloc.h
new file mode 100644
index 0000000000..6bd4385e61
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_alloc.h
@@ -0,0 +1,100 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Georg Richter <georg@mysql.com> |
+ | Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd_debug.h 306938 2011-01-01 02:17:06Z felipe $ */
+/* $Id: mysqlnd_debug.h 306938 2011-01-01 02:17:06Z felipe $ */
+
+#ifndef MYSQLND_ALLOC_H
+#define MYSQLND_ALLOC_H
+
+extern const char * mysqlnd_debug_std_no_trace_funcs[];
+
+#define MYSQLND_MEM_D TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC
+#define MYSQLND_MEM_C TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC
+
+struct st_mysqlnd_allocator_methods
+{
+ void * (*m_emalloc)(size_t size MYSQLND_MEM_D);
+ void * (*m_pemalloc)(size_t size, zend_bool persistent MYSQLND_MEM_D);
+ void * (*m_ecalloc)(unsigned int nmemb, size_t size MYSQLND_MEM_D);
+ void * (*m_pecalloc)(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D);
+ void * (*m_erealloc)(void *ptr, size_t new_size MYSQLND_MEM_D);
+ void * (*m_perealloc)(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D);
+ void (*m_efree)(void *ptr MYSQLND_MEM_D);
+ void (*m_pefree)(void *ptr, zend_bool persistent MYSQLND_MEM_D);
+ void * (*m_malloc)(size_t size MYSQLND_MEM_D);
+ void * (*m_calloc)(unsigned int nmemb, size_t size MYSQLND_MEM_D);
+ void * (*m_realloc)(void *ptr, size_t new_size MYSQLND_MEM_D);
+ void (*m_free)(void *ptr MYSQLND_MEM_D);
+ char * (*m_pestrndup)(const char * const ptr, size_t size, zend_bool persistent MYSQLND_MEM_D);
+ char * (*m_pestrdup)(const char * const ptr, zend_bool persistent MYSQLND_MEM_D);
+ int (*m_sprintf)(char **pbuf, size_t max_len, const char *format, ...);
+ int (*m_vsprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
+ void (*m_sprintf_free)(char * p);
+};
+
+PHPAPI extern struct st_mysqlnd_allocator_methods mysqlnd_allocator;
+
+PHPAPI void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D);
+PHPAPI void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D);
+PHPAPI void * _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D);
+PHPAPI void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D);
+PHPAPI void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D);
+PHPAPI void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D);
+PHPAPI void _mysqlnd_efree(void *ptr MYSQLND_MEM_D);
+PHPAPI void _mysqlnd_pefree(void *ptr, zend_bool persistent MYSQLND_MEM_D);
+PHPAPI void * _mysqlnd_malloc(size_t size MYSQLND_MEM_D);
+PHPAPI void * _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D);
+PHPAPI void * _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D);
+PHPAPI void _mysqlnd_free(void *ptr MYSQLND_MEM_D);
+PHPAPI char * _mysqlnd_pestrndup(const char * const ptr, size_t size, zend_bool persistent MYSQLND_MEM_D);
+PHPAPI char * _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D);
+PHPAPI int _mysqlnd_sprintf(char **pbuf, size_t max_len, const char *format, ...);
+PHPAPI void _mysqlnd_sprintf_free(char * p);
+PHPAPI int _mysqlnd_vsprintf(char **pbuf, size_t max_len, const char *format, va_list ap);
+
+#define mnd_emalloc(size) mysqlnd_allocator.m_emalloc((size) MYSQLND_MEM_C)
+#define mnd_pemalloc(size, pers) mysqlnd_allocator.m_pemalloc((size), (pers) MYSQLND_MEM_C)
+#define mnd_ecalloc(nmemb, size) mysqlnd_allocator.m_ecalloc((nmemb), (size) MYSQLND_MEM_C)
+#define mnd_pecalloc(nmemb, size, p) mysqlnd_allocator.m_pecalloc((nmemb), (size), (p) MYSQLND_MEM_C)
+#define mnd_erealloc(ptr, new_size) mysqlnd_allocator.m_erealloc((ptr), (new_size) MYSQLND_MEM_C)
+#define mnd_perealloc(ptr, new_size, p) mysqlnd_allocator.m_perealloc((ptr), (new_size), (p) MYSQLND_MEM_C)
+#define mnd_efree(ptr) mysqlnd_allocator.m_efree((ptr) MYSQLND_MEM_C)
+#define mnd_pefree(ptr, pers) mysqlnd_allocator.m_pefree((ptr), (pers) MYSQLND_MEM_C)
+#define mnd_malloc(size) mysqlnd_allocator.m_malloc((size) MYSQLND_MEM_C)
+#define mnd_calloc(nmemb, size) mysqlnd_allocator.m_calloc((nmemb), (size) MYSQLND_MEM_C)
+#define mnd_realloc(ptr, new_size) mysqlnd_allocator.m_realloc((ptr), (new_size) MYSQLND_MEM_C)
+#define mnd_free(ptr) mysqlnd_allocator.m_free((ptr) MYSQLND_MEM_C)
+#define mnd_pestrndup(ptr, size, pers) mysqlnd_allocator.m_pestrndup((ptr), (size), (pers) MYSQLND_MEM_C)
+#define mnd_pestrdup(ptr, pers) mysqlnd_allocator.m_pestrdup((ptr), (pers) MYSQLND_MEM_C)
+#define mnd_sprintf(p, mx_len, fmt,...) mysqlnd_allocator.m_sprintf((p), (mx_len), (fmt), __VA_ARGS__)
+#define mnd_vsprintf(p, mx_len, fmt,ap) mysqlnd_allocator.m_vsprintf((p), (mx_len), (fmt), (ap))
+#define mnd_sprintf_free(p) mysqlnd_allocator.m_sprintf_free((p))
+
+#endif /* MYSQLND_ALLOC_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_auth.c b/ext/mysqlnd/mysqlnd_auth.c
new file mode 100644
index 0000000000..918697a5f5
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_auth.c
@@ -0,0 +1,477 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Georg Richter <georg@mysql.com> |
+ | Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd.c 307377 2011-01-11 13:02:57Z andrey $ */
+#include "php.h"
+#include "mysqlnd.h"
+#include "mysqlnd_structs.h"
+#include "mysqlnd_wireprotocol.h"
+#include "mysqlnd_priv.h"
+#include "mysqlnd_result.h"
+#include "mysqlnd_charset.h"
+#include "mysqlnd_debug.h"
+
+
+/* {{{ mysqlnd_auth_handshake */
+enum_func_status
+mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
+ const char * const user,
+ const char * const passwd,
+ const size_t passwd_len,
+ const char * const db,
+ const size_t db_len,
+ const MYSQLND_OPTIONS * const options,
+ unsigned long mysql_flags,
+ unsigned int server_charset_no,
+ zend_bool use_full_blown_auth_packet,
+ const char * const auth_protocol,
+ const zend_uchar * const auth_plugin_data,
+ const size_t auth_plugin_data_len,
+ char ** switch_to_auth_protocol,
+ size_t * switch_to_auth_protocol_len,
+ zend_uchar ** switch_to_auth_protocol_data,
+ size_t * switch_to_auth_protocol_data_len
+ TSRMLS_DC)
+{
+ enum_func_status ret = FAIL;
+ const MYSQLND_CHARSET * charset = NULL;
+ MYSQLND_PACKET_CHANGE_AUTH_RESPONSE * change_auth_resp_packet = NULL;
+ MYSQLND_PACKET_AUTH_RESPONSE * auth_resp_packet = NULL;
+ MYSQLND_PACKET_AUTH * auth_packet = NULL;
+
+ DBG_ENTER("mysqlnd_auth_handshake");
+
+ auth_resp_packet = conn->protocol->m.get_auth_response_packet(conn->protocol, FALSE TSRMLS_CC);
+
+ if (!auth_resp_packet) {
+ SET_OOM_ERROR(*conn->error_info);
+ goto end;
+ }
+
+ if (use_full_blown_auth_packet != TRUE) {
+ change_auth_resp_packet = conn->protocol->m.get_change_auth_response_packet(conn->protocol, FALSE TSRMLS_CC);
+ if (!change_auth_resp_packet) {
+ SET_OOM_ERROR(*conn->error_info);
+ goto end;
+ }
+
+ change_auth_resp_packet->auth_data = auth_plugin_data;
+ change_auth_resp_packet->auth_data_len = auth_plugin_data_len;
+
+ if (!PACKET_WRITE(change_auth_resp_packet, conn)) {
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ goto end;
+ }
+ } else {
+ auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE TSRMLS_CC);
+
+ auth_packet->client_flags = mysql_flags;
+ auth_packet->max_packet_size = options->max_allowed_packet;
+ if (options->charset_name && (charset = mysqlnd_find_charset_name(options->charset_name))) {
+ auth_packet->charset_no = charset->nr;
+ } else {
+#if MYSQLND_UNICODE
+ auth_packet->charset_no = 200;/* utf8 - swedish collation, check mysqlnd_charset.c */
+#else
+ auth_packet->charset_no = server_charset_no;
+#endif
+ }
+
+ auth_packet->send_auth_data = TRUE;
+ auth_packet->user = user;
+ auth_packet->db = db;
+ auth_packet->db_len = db_len;
+
+ auth_packet->auth_data = auth_plugin_data;
+ auth_packet->auth_data_len = auth_plugin_data_len;
+ auth_packet->auth_plugin_name = auth_protocol;
+
+ if (!PACKET_WRITE(auth_packet, conn)) {
+ goto end;
+ }
+ }
+ if (use_full_blown_auth_packet == TRUE) {
+ conn->charset = mysqlnd_find_charset_nr(auth_packet->charset_no);
+ }
+
+ if (FAIL == PACKET_READ(auth_resp_packet, conn) || auth_resp_packet->response_code >= 0xFE) {
+ if (auth_resp_packet->response_code == 0xFE) {
+ /* old authentication with new server !*/
+ if (!auth_resp_packet->new_auth_protocol) {
+ DBG_ERR(mysqlnd_old_passwd);
+ SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
+ } else {
+ *switch_to_auth_protocol = mnd_pestrndup(auth_resp_packet->new_auth_protocol, auth_resp_packet->new_auth_protocol_len, FALSE);
+ *switch_to_auth_protocol_len = auth_resp_packet->new_auth_protocol_len;
+ if (auth_resp_packet->new_auth_protocol_data) {
+ *switch_to_auth_protocol_data_len = auth_resp_packet->new_auth_protocol_data_len;
+ *switch_to_auth_protocol_data = mnd_emalloc(*switch_to_auth_protocol_data_len);
+ memcpy(*switch_to_auth_protocol_data, auth_resp_packet->new_auth_protocol_data, *switch_to_auth_protocol_data_len);
+ } else {
+ *switch_to_auth_protocol_data = NULL;
+ *switch_to_auth_protocol_data_len = 0;
+ }
+ }
+ } else if (auth_resp_packet->response_code == 0xFF) {
+ if (auth_resp_packet->sqlstate[0]) {
+ strlcpy(conn->error_info->sqlstate, auth_resp_packet->sqlstate, sizeof(conn->error_info->sqlstate));
+ DBG_ERR_FMT("ERROR:%u [SQLSTATE:%s] %s", auth_resp_packet->error_no, auth_resp_packet->sqlstate, auth_resp_packet->error);
+ }
+ SET_CLIENT_ERROR(*conn->error_info, auth_resp_packet->error_no, UNKNOWN_SQLSTATE, auth_resp_packet->error);
+ }
+ goto end;
+ }
+
+ SET_NEW_MESSAGE(conn->last_message, conn->last_message_len, auth_resp_packet->message, auth_resp_packet->message_len, conn->persistent);
+ ret = PASS;
+end:
+ PACKET_FREE(change_auth_resp_packet);
+ PACKET_FREE(auth_packet);
+ PACKET_FREE(auth_resp_packet);
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_auth_change_user */
+enum_func_status
+mysqlnd_auth_change_user(MYSQLND_CONN_DATA * const conn,
+ const char * const user,
+ const size_t user_len,
+ const char * const passwd,
+ const size_t passwd_len,
+ const char * const db,
+ const size_t db_len,
+ const zend_bool silent,
+ zend_bool use_full_blown_auth_packet,
+ const char * const auth_protocol,
+ zend_uchar * auth_plugin_data,
+ size_t auth_plugin_data_len,
+ char ** switch_to_auth_protocol,
+ size_t * switch_to_auth_protocol_len,
+ zend_uchar ** switch_to_auth_protocol_data,
+ size_t * switch_to_auth_protocol_data_len
+ TSRMLS_DC)
+{
+ enum_func_status ret = FAIL;
+ const MYSQLND_CHARSET * old_cs = conn->charset;
+ MYSQLND_PACKET_CHANGE_AUTH_RESPONSE * change_auth_resp_packet = NULL;
+ MYSQLND_PACKET_CHG_USER_RESPONSE * chg_user_resp = NULL;
+ MYSQLND_PACKET_AUTH * auth_packet = NULL;
+
+ DBG_ENTER("mysqlnd_auth_change_user");
+
+ chg_user_resp = conn->protocol->m.get_change_user_response_packet(conn->protocol, FALSE TSRMLS_CC);
+
+ if (!chg_user_resp) {
+ SET_OOM_ERROR(*conn->error_info);
+ goto end;
+ }
+
+ if (use_full_blown_auth_packet != TRUE) {
+ change_auth_resp_packet = conn->protocol->m.get_change_auth_response_packet(conn->protocol, FALSE TSRMLS_CC);
+ if (!change_auth_resp_packet) {
+ SET_OOM_ERROR(*conn->error_info);
+ goto end;
+ }
+
+ change_auth_resp_packet->auth_data = auth_plugin_data;
+ change_auth_resp_packet->auth_data_len = auth_plugin_data_len;
+
+ if (!PACKET_WRITE(change_auth_resp_packet, conn)) {
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ goto end;
+ }
+ } else {
+ auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE TSRMLS_CC);
+
+ if (!auth_packet) {
+ SET_OOM_ERROR(*conn->error_info);
+ goto end;
+ }
+
+ auth_packet->is_change_user_packet = TRUE;
+ auth_packet->user = user;
+ auth_packet->db = db;
+ auth_packet->db_len = db_len;
+ auth_packet->silent = silent;
+
+ auth_packet->auth_data = auth_plugin_data;
+ auth_packet->auth_data_len = auth_plugin_data_len;
+ auth_packet->auth_plugin_name = auth_protocol;
+
+
+ if (conn->m->get_server_version(conn TSRMLS_CC) >= 50123) {
+ auth_packet->charset_no = conn->charset->nr;
+ }
+
+ if (!PACKET_WRITE(auth_packet, conn)) {
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ goto end;
+ }
+ }
+
+ ret = PACKET_READ(chg_user_resp, conn);
+ COPY_CLIENT_ERROR(*conn->error_info, chg_user_resp->error_info);
+
+ if (0xFE == chg_user_resp->response_code) {
+ ret = FAIL;
+ if (!chg_user_resp->new_auth_protocol) {
+ DBG_ERR(mysqlnd_old_passwd);
+ SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
+ } else {
+ *switch_to_auth_protocol = mnd_pestrndup(chg_user_resp->new_auth_protocol, chg_user_resp->new_auth_protocol_len, FALSE);
+ *switch_to_auth_protocol_len = chg_user_resp->new_auth_protocol_len;
+ if (chg_user_resp->new_auth_protocol_data) {
+ *switch_to_auth_protocol_data_len = chg_user_resp->new_auth_protocol_data_len;
+ *switch_to_auth_protocol_data = mnd_emalloc(*switch_to_auth_protocol_data_len);
+ memcpy(*switch_to_auth_protocol_data, chg_user_resp->new_auth_protocol_data, *switch_to_auth_protocol_data_len);
+ } else {
+ *switch_to_auth_protocol_data = NULL;
+ *switch_to_auth_protocol_data_len = 0;
+ }
+ }
+ }
+
+ if (conn->error_info->error_no) {
+ ret = FAIL;
+ /*
+ COM_CHANGE_USER is broken in 5.1. At least in 5.1.15 and 5.1.14, 5.1.11 is immune.
+ bug#25371 mysql_change_user() triggers "packets out of sync"
+ When it gets fixed, there should be one more check here
+ */
+ if (conn->m->get_server_version(conn TSRMLS_CC) > 50113L &&conn->m->get_server_version(conn TSRMLS_CC) < 50118L) {
+ MYSQLND_PACKET_OK * redundant_error_packet = conn->protocol->m.get_ok_packet(conn->protocol, FALSE TSRMLS_CC);
+ if (redundant_error_packet) {
+ PACKET_READ(redundant_error_packet, conn);
+ PACKET_FREE(redundant_error_packet);
+ DBG_INF_FMT("Server is %u, buggy, sends two ERR messages", conn->m->get_server_version(conn TSRMLS_CC));
+ } else {
+ SET_OOM_ERROR(*conn->error_info);
+ }
+ }
+ }
+ if (ret == PASS) {
+ char * tmp = NULL;
+ /* if we get conn->user as parameter and then we first free it, then estrndup it, we will crash */
+ tmp = mnd_pestrndup(user, user_len, conn->persistent);
+ if (conn->user) {
+ mnd_pefree(conn->user, conn->persistent);
+ }
+ conn->user = tmp;
+
+ tmp = mnd_pestrdup(passwd, conn->persistent);
+ if (conn->passwd) {
+ mnd_pefree(conn->passwd, conn->persistent);
+ }
+ conn->passwd = tmp;
+
+ if (conn->last_message) {
+ mnd_pefree(conn->last_message, conn->persistent);
+ conn->last_message = NULL;
+ }
+ memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
+ /* set charset for old servers */
+ if (conn->m->get_server_version(conn TSRMLS_CC) < 50123) {
+ ret = conn->m->set_charset(conn, old_cs->name TSRMLS_CC);
+ }
+ } else if (ret == FAIL && chg_user_resp->server_asked_323_auth == TRUE) {
+ /* old authentication with new server !*/
+ DBG_ERR(mysqlnd_old_passwd);
+ SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
+ }
+end:
+ PACKET_FREE(change_auth_resp_packet);
+ PACKET_FREE(auth_packet);
+ PACKET_FREE(chg_user_resp);
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/******************************************* MySQL Native Password ***********************************/
+
+#include "ext/standard/sha1.h"
+
+/* {{{ php_mysqlnd_crypt */
+static void
+php_mysqlnd_crypt(zend_uchar *buffer, const zend_uchar *s1, const zend_uchar *s2, size_t len)
+{
+ const zend_uchar *s1_end = s1 + len;
+ while (s1 < s1_end) {
+ *buffer++= *s1++ ^ *s2++;
+ }
+}
+/* }}} */
+
+
+/* {{{ php_mysqlnd_scramble */
+void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const password, size_t password_len)
+{
+ PHP_SHA1_CTX context;
+ zend_uchar sha1[SHA1_MAX_LENGTH];
+ zend_uchar sha2[SHA1_MAX_LENGTH];
+
+ /* Phase 1: hash password */
+ PHP_SHA1Init(&context);
+ PHP_SHA1Update(&context, password, password_len);
+ PHP_SHA1Final(sha1, &context);
+
+ /* Phase 2: hash sha1 */
+ PHP_SHA1Init(&context);
+ PHP_SHA1Update(&context, (zend_uchar*)sha1, SHA1_MAX_LENGTH);
+ PHP_SHA1Final(sha2, &context);
+
+ /* Phase 3: hash scramble + sha2 */
+ PHP_SHA1Init(&context);
+ PHP_SHA1Update(&context, scramble, SCRAMBLE_LENGTH);
+ PHP_SHA1Update(&context, (zend_uchar*)sha2, SHA1_MAX_LENGTH);
+ PHP_SHA1Final(buffer, &context);
+
+ /* let's crypt buffer now */
+ php_mysqlnd_crypt(buffer, (const zend_uchar *)buffer, (const zend_uchar *)sha1, SHA1_MAX_LENGTH);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_native_auth_get_auth_data */
+static zend_uchar *
+mysqlnd_native_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self,
+ size_t * auth_data_len,
+ MYSQLND_CONN_DATA * conn, const char * const user, const char * const passwd,
+ const size_t passwd_len, zend_uchar * auth_plugin_data, size_t auth_plugin_data_len,
+ const MYSQLND_OPTIONS * const options, unsigned long mysql_flags
+ TSRMLS_DC)
+{
+ zend_uchar * ret = NULL;
+ DBG_ENTER("mysqlnd_native_auth_get_auth_data");
+ *auth_data_len = 0;
+
+ /* 5.5.x reports 21 as scramble length because it needs to show the length of the data before the plugin name */
+ if (auth_plugin_data_len < SCRAMBLE_LENGTH) {
+ /* mysql_native_password only works with SCRAMBLE_LENGTH scramble */
+ SET_CLIENT_ERROR(*conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "The server sent wrong length for scramble");
+ DBG_ERR_FMT("The server sent wrong length for scramble %u. Expected %u", auth_plugin_data_len, SCRAMBLE_LENGTH);
+ DBG_RETURN(NULL);
+ }
+
+ /* copy scrambled pass*/
+ if (passwd && passwd_len) {
+ ret = malloc(SCRAMBLE_LENGTH);
+ *auth_data_len = SCRAMBLE_LENGTH;
+ /* In 4.1 we use CLIENT_SECURE_CONNECTION and thus the len of the buf should be passed */
+ php_mysqlnd_scramble((zend_uchar*)ret, auth_plugin_data, (zend_uchar*)passwd, passwd_len);
+ }
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+static struct st_mysqlnd_authentication_plugin mysqlnd_native_auth_plugin =
+{
+ {
+ MYSQLND_PLUGIN_API_VERSION,
+ "auth_plugin_mysql_native_password",
+ MYSQLND_VERSION_ID,
+ MYSQLND_VERSION,
+ "PHP License 3.01",
+ "Andrey Hristov <andrey@mysql.com>, Ulf Wendel <uwendel@mysql.com>, Georg Richter <georg@mysql.com>",
+ {
+ NULL, /* no statistics , will be filled later if there are some */
+ NULL, /* no statistics */
+ },
+ {
+ NULL /* plugin shutdown */
+ }
+ },
+ {/* methods */
+ mysqlnd_native_auth_get_auth_data
+ }
+};
+
+
+/******************************************* PAM Authentication ***********************************/
+
+/* {{{ mysqlnd_pam_auth_get_auth_data */
+static zend_uchar *
+mysqlnd_pam_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self,
+ size_t * auth_data_len,
+ MYSQLND_CONN_DATA * conn, const char * const user, const char * const passwd,
+ const size_t passwd_len, zend_uchar * auth_plugin_data, size_t auth_plugin_data_len,
+ const MYSQLND_OPTIONS * const options, unsigned long mysql_flags
+ TSRMLS_DC)
+{
+ zend_uchar * ret = NULL;
+
+ /* copy pass*/
+ if (passwd && passwd_len) {
+ ret = (zend_uchar*) zend_strndup(passwd, passwd_len);
+ }
+ *auth_data_len = passwd_len;
+
+ return ret;
+}
+/* }}} */
+
+
+static struct st_mysqlnd_authentication_plugin mysqlnd_pam_authentication_plugin =
+{
+ {
+ MYSQLND_PLUGIN_API_VERSION,
+ "auth_plugin_mysql_clear_password",
+ MYSQLND_VERSION_ID,
+ MYSQLND_VERSION,
+ "PHP License 3.01",
+ "Andrey Hristov <andrey@mysql.com>, Ulf Wendel <uwendel@mysql.com>, Georg Richter <georg@mysql.com>",
+ {
+ NULL, /* no statistics , will be filled later if there are some */
+ NULL, /* no statistics */
+ },
+ {
+ NULL /* plugin shutdown */
+ }
+ },
+ {/* methods */
+ mysqlnd_pam_auth_get_auth_data
+ }
+};
+
+
+/* {{{ mysqlnd_register_builtin_authentication_plugins */
+void
+mysqlnd_register_builtin_authentication_plugins(TSRMLS_D)
+{
+ mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_native_auth_plugin TSRMLS_CC);
+ mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_pam_authentication_plugin TSRMLS_CC);
+}
+/* }}} */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_bt.c b/ext/mysqlnd/mysqlnd_bt.c
new file mode 100644
index 0000000000..3aeb8f2bb1
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_bt.c
@@ -0,0 +1,484 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Georg Richter <georg@mysql.com> |
+ | Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd_debug.c 309303 2011-03-16 12:42:59Z andrey $ */
+
+#include "php.h"
+#include "Zend/zend_builtin_functions.h"
+
+/* Follows code borrowed from zend_builtin_functions.c because the functions there are static */
+
+#if MYSQLND_UNICODE
+/* {{{ gettraceasstring() macros */
+#define TRACE_APPEND_CHR(chr) \
+ *str = (char*)erealloc(*str, *len + 1 + 1); \
+ (*str)[(*len)++] = chr
+
+#define TRACE_APPEND_STRL(val, vallen) \
+ { \
+ int l = vallen; \
+ *str = (char*)erealloc(*str, *len + l + 1); \
+ memcpy((*str) + *len, val, l); \
+ *len += l; \
+ }
+
+#define TRACE_APPEND_USTRL(val, vallen) \
+ { \
+ zval tmp, copy; \
+ int use_copy; \
+ ZVAL_UNICODEL(&tmp, val, vallen, 1); \
+ zend_make_printable_zval(&tmp, &copy, &use_copy); \
+ TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
+ zval_dtor(&copy); \
+ zval_dtor(&tmp); \
+ }
+
+#define TRACE_APPEND_ZVAL(zv) \
+ if (Z_TYPE_P((zv)) == IS_UNICODE) { \
+ zval copy; \
+ int use_copy; \
+ zend_make_printable_zval((zv), &copy, &use_copy); \
+ TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
+ zval_dtor(&copy); \
+ } else { \
+ TRACE_APPEND_STRL(Z_STRVAL_P((zv)), Z_STRLEN_P((zv))); \
+ }
+
+#define TRACE_APPEND_STR(val) \
+ TRACE_APPEND_STRL(val, sizeof(val)-1)
+
+#define TRACE_APPEND_KEY(key) \
+ if (zend_ascii_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
+ if (Z_TYPE_PP(tmp) == IS_UNICODE) { \
+ zval copy; \
+ int use_copy; \
+ zend_make_printable_zval(*tmp, &copy, &use_copy); \
+ TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
+ zval_dtor(&copy); \
+ } else { \
+ TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); \
+ } \
+ }
+/* }}} */
+
+
+/* {{{ mysqlnd_build_trace_args */
+static int mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
+{
+ char **str;
+ int *len;
+
+ str = va_arg(args, char**);
+ len = va_arg(args, int*);
+
+ /* the trivial way would be to do:
+ * conver_to_string_ex(arg);
+ * append it and kill the now tmp arg.
+ * but that could cause some E_NOTICE and also damn long lines.
+ */
+
+ switch (Z_TYPE_PP(arg)) {
+ case IS_NULL:
+ TRACE_APPEND_STR("NULL, ");
+ break;
+ case IS_STRING: {
+ int l_added;
+ TRACE_APPEND_CHR('\'');
+ if (Z_STRLEN_PP(arg) > 15) {
+ TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15);
+ TRACE_APPEND_STR("...', ");
+ l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
+ } else {
+ l_added = Z_STRLEN_PP(arg);
+ TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added);
+ TRACE_APPEND_STR("', ");
+ l_added += 3 + 1;
+ }
+ while (--l_added) {
+ if ((unsigned char)(*str)[*len - l_added] < 32) {
+ (*str)[*len - l_added] = '?';
+ }
+ }
+ break;
+ }
+ case IS_UNICODE: {
+ int l_added;
+
+ /*
+ * We do not want to apply current error mode here, since
+ * zend_make_printable_zval() uses output encoding converter.
+ * Temporarily set output encoding converter to escape offending
+ * chars with \uXXXX notation.
+ */
+ zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, ZEND_CONV_ERROR_ESCAPE_JAVA);
+ TRACE_APPEND_CHR('\'');
+ if (Z_USTRLEN_PP(arg) > 15) {
+ TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), 15);
+ TRACE_APPEND_STR("...', ");
+ l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
+ } else {
+ l_added = Z_USTRLEN_PP(arg);
+ TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), l_added);
+ TRACE_APPEND_STR("', ");
+ l_added += 3 + 1;
+ }
+ /*
+ * Reset output encoding converter error mode.
+ */
+ zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, UG(from_error_mode));
+ while (--l_added) {
+ if ((unsigned char)(*str)[*len - l_added] < 32) {
+ (*str)[*len - l_added] = '?';
+ }
+ }
+ break;
+ }
+ case IS_BOOL:
+ if (Z_LVAL_PP(arg)) {
+ TRACE_APPEND_STR("true, ");
+ } else {
+ TRACE_APPEND_STR("false, ");
+ }
+ break;
+ case IS_RESOURCE:
+ TRACE_APPEND_STR("Resource id #");
+ /* break; */
+ case IS_LONG: {
+ long lval = Z_LVAL_PP(arg);
+ char s_tmp[MAX_LENGTH_OF_LONG + 1];
+ int l_tmp = zend_sprintf(s_tmp, "%ld", lval); /* SAFE */
+ TRACE_APPEND_STRL(s_tmp, l_tmp);
+ TRACE_APPEND_STR(", ");
+ break;
+ }
+ case IS_DOUBLE: {
+ double dval = Z_DVAL_PP(arg);
+ char *s_tmp;
+ int l_tmp;
+
+ s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
+ l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval); /* SAFE */
+ TRACE_APPEND_STRL(s_tmp, l_tmp);
+ /* %G already handles removing trailing zeros from the fractional part, yay */
+ efree(s_tmp);
+ TRACE_APPEND_STR(", ");
+ break;
+ }
+ case IS_ARRAY:
+ TRACE_APPEND_STR("Array, ");
+ break;
+ case IS_OBJECT: {
+ zval tmp;
+ zstr class_name;
+ zend_uint class_name_len;
+ int dup;
+
+ TRACE_APPEND_STR("Object(");
+
+ dup = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC);
+
+ ZVAL_UNICODEL(&tmp, class_name.u, class_name_len, 1);
+ convert_to_string_with_converter(&tmp, ZEND_U_CONVERTER(UG(output_encoding_conv)));
+ TRACE_APPEND_STRL(Z_STRVAL(tmp), Z_STRLEN(tmp));
+ zval_dtor(&tmp);
+
+ if(!dup) {
+ efree(class_name.v);
+ }
+
+ TRACE_APPEND_STR("), ");
+ break;
+ }
+ default:
+ break;
+ }
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
+
+static int mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
+{
+ char *s_tmp, **str;
+ int *len, *num;
+ long line;
+ HashTable *ht = Z_ARRVAL_PP(frame);
+ zval **file, **tmp;
+ uint * level;
+
+ level = va_arg(args, uint *);
+ str = va_arg(args, char**);
+ len = va_arg(args, int*);
+ num = va_arg(args, int*);
+
+ if (!*level) {
+ return ZEND_HASH_APPLY_KEEP;
+ }
+ --*level;
+
+ s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);
+ sprintf(s_tmp, "#%d ", (*num)++);
+ TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
+ efree(s_tmp);
+ if (zend_ascii_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
+ if (zend_ascii_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
+ line = Z_LVAL_PP(tmp);
+ } else {
+ line = 0;
+ }
+ TRACE_APPEND_ZVAL(*file);
+ s_tmp = emalloc(MAX_LENGTH_OF_LONG + 2 + 1);
+ sprintf(s_tmp, "(%ld): ", line);
+ TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
+ efree(s_tmp);
+ } else {
+ TRACE_APPEND_STR("[internal function]: ");
+ }
+ TRACE_APPEND_KEY("class");
+ TRACE_APPEND_KEY("type");
+ TRACE_APPEND_KEY("function");
+ TRACE_APPEND_CHR('(');
+ if (zend_ascii_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
+ int last_len = *len;
+ zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_args, 2, str, len);
+ if (last_len != *len) {
+ *len -= 2; /* remove last ', ' */
+ }
+ }
+ TRACE_APPEND_STR(")\n");
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
+
+#else /* PHP 5*/
+
+
+/* {{{ gettraceasstring() macros */
+#define TRACE_APPEND_CHR(chr) \
+ *str = (char*)erealloc(*str, *len + 1 + 1); \
+ (*str)[(*len)++] = chr
+
+#define TRACE_APPEND_STRL(val, vallen) \
+ { \
+ int l = vallen; \
+ *str = (char*)erealloc(*str, *len + l + 1); \
+ memcpy((*str) + *len, val, l); \
+ *len += l; \
+ }
+
+#define TRACE_APPEND_STR(val) \
+ TRACE_APPEND_STRL(val, sizeof(val)-1)
+
+#define TRACE_APPEND_KEY(key) \
+ if (zend_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
+ TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); \
+ }
+
+/* }}} */
+
+
+static int mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
+{
+ char **str;
+ int *len;
+
+ str = va_arg(args, char**);
+ len = va_arg(args, int*);
+
+ /* the trivial way would be to do:
+ * conver_to_string_ex(arg);
+ * append it and kill the now tmp arg.
+ * but that could cause some E_NOTICE and also damn long lines.
+ */
+
+ switch (Z_TYPE_PP(arg)) {
+ case IS_NULL:
+ TRACE_APPEND_STR("NULL, ");
+ break;
+ case IS_STRING: {
+ int l_added;
+ TRACE_APPEND_CHR('\'');
+ if (Z_STRLEN_PP(arg) > 15) {
+ TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15);
+ TRACE_APPEND_STR("...', ");
+ l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
+ } else {
+ l_added = Z_STRLEN_PP(arg);
+ TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added);
+ TRACE_APPEND_STR("', ");
+ l_added += 3 + 1;
+ }
+ while (--l_added) {
+ if ((*str)[*len - l_added] < 32) {
+ (*str)[*len - l_added] = '?';
+ }
+ }
+ break;
+ }
+ case IS_BOOL:
+ if (Z_LVAL_PP(arg)) {
+ TRACE_APPEND_STR("true, ");
+ } else {
+ TRACE_APPEND_STR("false, ");
+ }
+ break;
+ case IS_RESOURCE:
+ TRACE_APPEND_STR("Resource id #");
+ /* break; */
+ case IS_LONG: {
+ long lval = Z_LVAL_PP(arg);
+ char s_tmp[MAX_LENGTH_OF_LONG + 1];
+ int l_tmp = zend_sprintf(s_tmp, "%ld", lval); /* SAFE */
+ TRACE_APPEND_STRL(s_tmp, l_tmp);
+ TRACE_APPEND_STR(", ");
+ break;
+ }
+ case IS_DOUBLE: {
+ double dval = Z_DVAL_PP(arg);
+ char *s_tmp;
+ int l_tmp;
+
+ s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
+ l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval); /* SAFE */
+ TRACE_APPEND_STRL(s_tmp, l_tmp);
+ /* %G already handles removing trailing zeros from the fractional part, yay */
+ efree(s_tmp);
+ TRACE_APPEND_STR(", ");
+ break;
+ }
+ case IS_ARRAY:
+ TRACE_APPEND_STR("Array, ");
+ break;
+ case IS_OBJECT: {
+ char *class_name;
+ zend_uint class_name_len;
+ int dupl;
+
+ TRACE_APPEND_STR("Object(");
+
+ dupl = zend_get_object_classname(*arg, (const char **)&class_name, &class_name_len TSRMLS_CC);
+
+ TRACE_APPEND_STRL(class_name, class_name_len);
+ if (!dupl) {
+ efree(class_name);
+ }
+
+ TRACE_APPEND_STR("), ");
+ break;
+ }
+ default:
+ break;
+ }
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
+static int mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
+{
+ char *s_tmp, **str;
+ int *len, *num;
+ long line;
+ HashTable *ht = Z_ARRVAL_PP(frame);
+ zval **file, **tmp;
+ uint * level;
+
+ level = va_arg(args, uint *);
+ str = va_arg(args, char**);
+ len = va_arg(args, int*);
+ num = va_arg(args, int*);
+
+ if (!*level) {
+ return ZEND_HASH_APPLY_KEEP;
+ }
+ --*level;
+
+ s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);
+ sprintf(s_tmp, "#%d ", (*num)++);
+ TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
+ efree(s_tmp);
+ if (zend_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
+ if (zend_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
+ line = Z_LVAL_PP(tmp);
+ } else {
+ line = 0;
+ }
+ s_tmp = emalloc(Z_STRLEN_PP(file) + MAX_LENGTH_OF_LONG + 4 + 1);
+ sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_PP(file), line);
+ TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
+ efree(s_tmp);
+ } else {
+ TRACE_APPEND_STR("[internal function]: ");
+ }
+ TRACE_APPEND_KEY("class");
+ TRACE_APPEND_KEY("type");
+ TRACE_APPEND_KEY("function");
+ TRACE_APPEND_CHR('(');
+ if (zend_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
+ int last_len = *len;
+ zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_args, 2, str, len);
+ if (last_len != *len) {
+ *len -= 2; /* remove last ', ' */
+ }
+ }
+ TRACE_APPEND_STR(")\n");
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+#endif
+
+
+PHPAPI char * mysqlnd_get_backtrace(uint max_levels, size_t * length TSRMLS_DC)
+{
+ zval *trace;
+ char *res = estrdup(""), **str = &res, *s_tmp;
+ int res_len = 0, *len = &res_len, num = 0;
+ if (max_levels == 0) {
+ max_levels = 99999;
+ }
+
+ MAKE_STD_ZVAL(trace);
+ zend_fetch_debug_backtrace(trace, 0, 0, 0 TSRMLS_CC);
+
+ zend_hash_apply_with_arguments(Z_ARRVAL_P(trace) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_string, 4, &max_levels, str, len, &num);
+ zval_ptr_dtor(&trace);
+
+ if (max_levels) {
+ s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 7 + 1);
+ sprintf(s_tmp, "#%d {main}", num);
+ TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
+ efree(s_tmp);
+ }
+
+ res[res_len] = '\0';
+ *length = res_len;
+
+ return res;
+}
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_charset.c b/ext/mysqlnd/mysqlnd_charset.c
index 2b477db651..a36bb11e92 100644
--- a/ext/mysqlnd/mysqlnd_charset.c
+++ b/ext/mysqlnd/mysqlnd_charset.c
@@ -22,6 +22,7 @@
#include "mysqlnd.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_debug.h"
+#include "mysqlnd_charset.h"
/* {{{ utf8 functions */
static unsigned int check_mb_utf8mb3_sequence(const char *start, const char *end)
@@ -325,7 +326,7 @@ static unsigned int mysqlnd_mbcharlen_gbk(unsigned int gbk)
/* }}} */
-/* {{{ functions */
+/* {{{ sjis functions */
#define valid_sjis_head(c) ((0x81 <= (c) && (c) <= 0x9F) || (0xE0 <= (c) && (c) <= 0xFC))
#define valid_sjis_tail(c) ((0x40 <= (c) && (c) <= 0x7E) || (0x80 <= (c) && (c) <= 0xFC))
@@ -490,8 +491,8 @@ const MYSQLND_CHARSET mysqlnd_charsets[] =
{ 42, "latin7", "latin7_general_cs", 1, 1, "", NULL, NULL},
{ 43, "macce", "macce_bin", 1, 1, "", NULL, NULL},
{ 44, "cp1250", "cp1250_croatian_ci", 1, 1, "", NULL, NULL},
- { 45, UTF8_MB4, UTF8_MB4"_general_ci", 1, 3, "UTF-8 Unicode", mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
- { 46, UTF8_MB4, UTF8_MB4"_bin", 1, 3, "UTF-8 Unicode", mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
+ { 45, UTF8_MB4, UTF8_MB4"_general_ci", 1, 4, "UTF-8 Unicode", mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
+ { 46, UTF8_MB4, UTF8_MB4"_bin", 1, 4, "UTF-8 Unicode", mysqlnd_mbcharlen_utf8, check_mb_utf8_valid},
{ 47, "latin1", "latin1_bin", 1, 1, "", NULL, NULL},
{ 48, "latin1", "latin1_general_ci", 1, 1, "", NULL, NULL},
{ 49, "latin1", "latin1_general_cs", 1, 1, "", NULL, NULL},
@@ -668,7 +669,7 @@ PHPAPI const MYSQLND_CHARSET * mysqlnd_find_charset_nr(unsigned int charsetnr)
/* {{{ mysqlnd_find_charset_name */
PHPAPI const MYSQLND_CHARSET * mysqlnd_find_charset_name(const char * const name)
{
- const MYSQLND_CHARSET *c = mysqlnd_charsets;
+ const MYSQLND_CHARSET * c = mysqlnd_charsets;
do {
if (!strcasecmp(c->name, name)) {
@@ -814,6 +815,42 @@ PHPAPI ulong mysqlnd_cset_escape_slashes(const MYSQLND_CHARSET * const cset, cha
}
/* }}} */
+
+static struct st_mysqlnd_plugin_charsets mysqlnd_plugin_charsets_plugin =
+{
+ {
+ MYSQLND_PLUGIN_API_VERSION,
+ "charsets",
+ MYSQLND_VERSION_ID,
+ MYSQLND_VERSION,
+ "PHP License 3.01",
+ "Andrey Hristov <andrey@mysql.com>, Ulf Wendel <uwendel@mysql.com>, Georg Richter <georg@mysql.com>",
+ {
+ NULL, /* no statistics , will be filled later if there are some */
+ NULL, /* no statistics */
+ },
+ {
+ NULL /* plugin shutdown */
+ }
+ },
+ {/* methods */
+ mysqlnd_find_charset_nr,
+ mysqlnd_find_charset_name,
+ mysqlnd_cset_escape_quotes,
+ mysqlnd_cset_escape_slashes
+ }
+};
+
+
+/* {{{ mysqlnd_charsets_plugin_register */
+void
+mysqlnd_charsets_plugin_register(TSRMLS_D)
+{
+ mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_plugin_charsets_plugin TSRMLS_CC);
+}
+/* }}} */
+
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/mysqlnd/mysqlnd_charset.h b/ext/mysqlnd/mysqlnd_charset.h
index e71157a76b..09d0eb4171 100644
--- a/ext/mysqlnd/mysqlnd_charset.h
+++ b/ext/mysqlnd/mysqlnd_charset.h
@@ -27,6 +27,20 @@ PHPAPI ulong mysqlnd_cset_escape_quotes(const MYSQLND_CHARSET * const charset, c
PHPAPI ulong mysqlnd_cset_escape_slashes(const MYSQLND_CHARSET * const cset, char *newstr,
const char *escapestr, size_t escapestr_len TSRMLS_DC);
+struct st_mysqlnd_plugin_charsets
+{
+ const struct st_mysqlnd_plugin_header plugin_header;
+ struct
+ {
+ const MYSQLND_CHARSET * (*const find_charset_by_nr)(unsigned int charsetnr);
+ const MYSQLND_CHARSET * (*const find_charset_by_name)(const char * const name);
+ unsigned long (*const escape_quotes)(const MYSQLND_CHARSET * const cset, char * newstr, const char * escapestr, size_t escapestr_len TSRMLS_DC);
+ unsigned long (*const escape_slashes)(const MYSQLND_CHARSET * const cset, char * newstr, const char * escapestr, size_t escapestr_len TSRMLS_DC);
+ } methods;
+};
+
+void mysqlnd_charsets_plugin_register(TSRMLS_D);
+
#endif /* MYSQLND_CHARSET_H */
/*
diff --git a/ext/mysqlnd/mysqlnd_debug.c b/ext/mysqlnd/mysqlnd_debug.c
index 0947d00540..fb8a360240 100644
--- a/ext/mysqlnd/mysqlnd_debug.c
+++ b/ext/mysqlnd/mysqlnd_debug.c
@@ -24,9 +24,6 @@
#include "mysqlnd.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_debug.h"
-#include "mysqlnd_wireprotocol.h"
-#include "mysqlnd_statistics.h"
-#include "zend_builtin_functions.h"
static const char * const mysqlnd_debug_default_trace_file = "/tmp/mysqlnd.trace";
@@ -36,41 +33,6 @@ static const char * const mysqlnd_debug_default_trace_file = "/tmp/mysqlnd.trace
#define MYSQLND_ZTS(self)
#endif
-static const char mysqlnd_emalloc_name[] = "_mysqlnd_emalloc";
-static const char mysqlnd_pemalloc_name[] = "_mysqlnd_pemalloc";
-static const char mysqlnd_ecalloc_name[] = "_mysqlnd_ecalloc";
-static const char mysqlnd_pecalloc_name[] = "_mysqlnd_pecalloc";
-static const char mysqlnd_erealloc_name[] = "_mysqlnd_erealloc";
-static const char mysqlnd_perealloc_name[] = "_mysqlnd_perealloc";
-static const char mysqlnd_efree_name[] = "_mysqlnd_efree";
-static const char mysqlnd_pefree_name[] = "_mysqlnd_pefree";
-static const char mysqlnd_malloc_name[] = "_mysqlnd_malloc";
-static const char mysqlnd_calloc_name[] = "_mysqlnd_calloc";
-static const char mysqlnd_realloc_name[] = "_mysqlnd_realloc";
-static const char mysqlnd_free_name[] = "_mysqlnd_free";
-static const char mysqlnd_pestrndup_name[] = "_mysqlnd_pestrndup";
-static const char mysqlnd_pestrdup_name[] = "_mysqlnd_pestrdup";
-
-const char * mysqlnd_debug_std_no_trace_funcs[] =
-{
- mysqlnd_emalloc_name,
- mysqlnd_ecalloc_name,
- mysqlnd_efree_name,
- mysqlnd_erealloc_name,
- mysqlnd_pemalloc_name,
- mysqlnd_pecalloc_name,
- mysqlnd_pefree_name,
- mysqlnd_perealloc_name,
- mysqlnd_malloc_name,
- mysqlnd_calloc_name,
- mysqlnd_realloc_name,
- mysqlnd_free_name,
- mysqlnd_pestrndup_name,
- mysqlnd_read_header_name,
- mysqlnd_read_body_name,
- NULL /* must be always last */
-};
-
/* {{{ mysqlnd_debug::open */
static enum_func_status
@@ -167,7 +129,7 @@ MYSQLND_METHOD(mysqlnd_debug, log)(MYSQLND_DEBUG * self,
level_buffer[sizeof(level_buffer) - 1 ] = '\0';
}
- message_line_len = spprintf(&message_line, 0, "%s%s%s%s%s%s%s%s\n",
+ message_line_len = mnd_sprintf(&message_line, 0, "%s%s%s%s%s%s%s%s\n",
flags & MYSQLND_DEBUG_DUMP_PID? pid_buffer:"",
flags & MYSQLND_DEBUG_DUMP_TIME? time_buffer:"",
flags & MYSQLND_DEBUG_DUMP_FILE? file_buffer:"",
@@ -176,7 +138,7 @@ MYSQLND_METHOD(mysqlnd_debug, log)(MYSQLND_DEBUG * self,
pipe_buffer, type? type:"", message);
ret = php_stream_write(self->stream, message_line, message_line_len)? PASS:FAIL;
- efree(message_line); /* allocated by spprintf */
+ mnd_sprintf_free(message_line);
if (flags & MYSQLND_DEBUG_FLUSH) {
self->m->close(self);
self->m->open(self, TRUE);
@@ -265,21 +227,20 @@ MYSQLND_METHOD(mysqlnd_debug, log_va)(MYSQLND_DEBUG *self,
level_buffer[sizeof(level_buffer) - 1 ] = '\0';
}
-
va_start(args, format);
- vspprintf(&buffer, 0, format, args);
+ mnd_vsprintf(&buffer, 0, format, args);
va_end(args);
- message_line_len = spprintf(&message_line, 0, "%s%s%s%s%s%s%s%s\n",
+ message_line_len = mnd_sprintf(&message_line, 0, "%s%s%s%s%s%s%s%s\n",
flags & MYSQLND_DEBUG_DUMP_PID? pid_buffer:"",
flags & MYSQLND_DEBUG_DUMP_TIME? time_buffer:"",
flags & MYSQLND_DEBUG_DUMP_FILE? file_buffer:"",
flags & MYSQLND_DEBUG_DUMP_LINE? line_buffer:"",
flags & MYSQLND_DEBUG_DUMP_LEVEL? level_buffer:"",
pipe_buffer, type? type:"", buffer);
- efree(buffer);
+ mnd_sprintf_free(buffer);
ret = php_stream_write(self->stream, message_line, message_line_len)? PASS:FAIL;
- efree(message_line); /* allocated by spprintf */
+ mnd_sprintf_free(message_line);
if (flags & MYSQLND_DEBUG_FLUSH) {
self->m->close(self);
@@ -538,7 +499,7 @@ MYSQLND_METHOD(mysqlnd_debug, free)(MYSQLND_DEBUG * self)
zend_stack_destroy(&self->call_time_stack);
zend_hash_destroy(&self->not_filtered_functions);
zend_hash_destroy(&self->function_profiles);
- efree(self);
+ free(self);
return PASS;
}
/* }}} */
@@ -555,9 +516,11 @@ enum mysqlnd_debug_parser_state
static void
MYSQLND_METHOD(mysqlnd_debug, set_mode)(MYSQLND_DEBUG * self, const char * const mode)
{
- unsigned int mode_len = strlen(mode), i;
+ unsigned int mode_len, i;
enum mysqlnd_debug_parser_state state = PARSER_WAIT_MODIFIER;
+ mode_len = mode? strlen(mode) : 0;
+
self->flags = 0;
self->nest_level_limit = 0;
if (self->file_name && self->file_name != mysqlnd_debug_default_trace_file) {
@@ -761,7 +724,7 @@ MYSQLND_CLASS_METHODS_END;
PHPAPI MYSQLND_DEBUG *
mysqlnd_debug_init(const char * skip_functions[] TSRMLS_DC)
{
- MYSQLND_DEBUG *ret = ecalloc(1, sizeof(MYSQLND_DEBUG));
+ MYSQLND_DEBUG *ret = calloc(1, sizeof(MYSQLND_DEBUG));
#ifdef ZTS
ret->TSRMLS_C = TSRMLS_C;
#endif
@@ -783,7 +746,7 @@ mysqlnd_debug_init(const char * skip_functions[] TSRMLS_DC)
/* {{{ _mysqlnd_debug */
PHPAPI void _mysqlnd_debug(const char * mode TSRMLS_DC)
{
-#ifdef PHP_DEBUG
+#if PHP_DEBUG
MYSQLND_DEBUG *dbg = MYSQLND_G(dbg);
if (!dbg) {
MYSQLND_G(dbg) = dbg = mysqlnd_debug_init(mysqlnd_debug_std_no_trace_funcs TSRMLS_CC);
@@ -805,1057 +768,39 @@ PHPAPI void _mysqlnd_debug(const char * mode TSRMLS_DC)
/* }}} */
-#if ZEND_DEBUG
-#else
-#define __zend_filename "/unknown/unknown"
-#define __zend_lineno 0
-#endif
-
-#define REAL_SIZE(s) (collect_memory_statistics? (s) + sizeof(size_t) : (s))
-#define REAL_PTR(p) (collect_memory_statistics && (p)? (((char *)(p)) - sizeof(size_t)) : (p))
-#define FAKE_PTR(p) (collect_memory_statistics && (p)? (((char *)(p)) + sizeof(size_t)) : (p))
-
-/* {{{ _mysqlnd_emalloc */
-void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D)
-{
- void *ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- long * threshold = &MYSQLND_G(debug_emalloc_fail_threshold);
- DBG_ENTER(mysqlnd_emalloc_name);
-
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-
-#ifdef PHP_DEBUG
- /* -1 is also "true" */
- if (*threshold) {
-#endif
- ret = emalloc(REAL_SIZE(size));
-#ifdef PHP_DEBUG
- --*threshold;
- } else if (*threshold == 0) {
- ret = NULL;
- }
-#endif
-
- DBG_INF_FMT("size=%lu ptr=%p", size, ret);
-
- if (ret && collect_memory_statistics) {
- *(size_t *) ret = size;
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EMALLOC_COUNT, 1, STAT_MEM_EMALLOC_AMOUNT, size);
- }
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_pemalloc */
-void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)
-{
- void *ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- long * threshold = persistent? &MYSQLND_G(debug_malloc_fail_threshold):&MYSQLND_G(debug_emalloc_fail_threshold);
- DBG_ENTER(mysqlnd_pemalloc_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-
-#ifdef PHP_DEBUG
- /* -1 is also "true" */
- if (*threshold) {
-#endif
- ret = pemalloc(REAL_SIZE(size), persistent);
-#ifdef PHP_DEBUG
- --*threshold;
- } else if (*threshold == 0) {
- ret = NULL;
- }
-#endif
-
- DBG_INF_FMT("size=%lu ptr=%p persistent=%u", size, ret, persistent);
-
- if (ret && collect_memory_statistics) {
- enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_MALLOC_COUNT:STAT_MEM_EMALLOC_COUNT;
- enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_MALLOC_AMOUNT:STAT_MEM_EMALLOC_AMOUNT;
- *(size_t *) ret = size;
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);
- }
-
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_ecalloc */
-void * _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
-{
- void *ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- long * threshold = &MYSQLND_G(debug_ecalloc_fail_threshold);
- DBG_ENTER(mysqlnd_ecalloc_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
- DBG_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC));
-
-#ifdef PHP_DEBUG
- /* -1 is also "true" */
- if (*threshold) {
-#endif
- ret = ecalloc(nmemb, REAL_SIZE(size));
-#ifdef PHP_DEBUG
- --*threshold;
- } else if (*threshold == 0) {
- ret = NULL;
- }
-#endif
-
- DBG_INF_FMT("after : %lu", zend_memory_usage(FALSE TSRMLS_CC));
- DBG_INF_FMT("size=%lu ptr=%p", size, ret);
- if (ret && collect_memory_statistics) {
- *(size_t *) ret = size;
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_ECALLOC_COUNT, 1, STAT_MEM_ECALLOC_AMOUNT, size);
- }
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_pecalloc */
-void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D)
-{
- void *ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- long * threshold = persistent? &MYSQLND_G(debug_calloc_fail_threshold):&MYSQLND_G(debug_ecalloc_fail_threshold);
- DBG_ENTER(mysqlnd_pecalloc_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-
-#ifdef PHP_DEBUG
- /* -1 is also "true" */
- if (*threshold) {
-#endif
- ret = pecalloc(nmemb, REAL_SIZE(size), persistent);
-#ifdef PHP_DEBUG
- --*threshold;
- } else if (*threshold == 0) {
- ret = NULL;
- }
-#endif
-
- DBG_INF_FMT("size=%lu ptr=%p", size, ret);
-
- if (ret && collect_memory_statistics) {
- enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_CALLOC_COUNT:STAT_MEM_ECALLOC_COUNT;
- enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_CALLOC_AMOUNT:STAT_MEM_ECALLOC_AMOUNT;
- *(size_t *) ret = size;
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);
- }
-
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_erealloc */
-void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
-{
- void *ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- size_t old_size = collect_memory_statistics && ptr? *(size_t *) (((char*)ptr) - sizeof(size_t)) : 0;
- long * threshold = &MYSQLND_G(debug_erealloc_fail_threshold);
- DBG_ENTER(mysqlnd_erealloc_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
- DBG_INF_FMT("ptr=%p old_size=%lu, new_size=%lu", ptr, old_size, new_size);
-
-#ifdef PHP_DEBUG
- /* -1 is also "true" */
- if (*threshold) {
-#endif
- ret = erealloc(REAL_PTR(ptr), REAL_SIZE(new_size));
-#ifdef PHP_DEBUG
- --*threshold;
- } else if (*threshold == 0) {
- ret = NULL;
- }
-#endif
-
- DBG_INF_FMT("new_ptr=%p", (char*)ret);
- if (ret && collect_memory_statistics) {
- *(size_t *) ret = new_size;
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EREALLOC_COUNT, 1, STAT_MEM_EREALLOC_AMOUNT, new_size);
- }
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_perealloc */
-void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D)
-{
- void *ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- size_t old_size = collect_memory_statistics && ptr? *(size_t *) (((char*)ptr) - sizeof(size_t)) : 0;
- long * threshold = persistent? &MYSQLND_G(debug_realloc_fail_threshold):&MYSQLND_G(debug_erealloc_fail_threshold);
- DBG_ENTER(mysqlnd_perealloc_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
- DBG_INF_FMT("ptr=%p old_size=%lu new_size=%lu persistent=%u", ptr, old_size, new_size, persistent);
-
-#ifdef PHP_DEBUG
- /* -1 is also "true" */
- if (*threshold) {
-#endif
- ret = perealloc(REAL_PTR(ptr), REAL_SIZE(new_size), persistent);
-#ifdef PHP_DEBUG
- --*threshold;
- } else if (*threshold == 0) {
- ret = NULL;
- }
-#endif
-
- DBG_INF_FMT("new_ptr=%p", (char*)ret);
-
- if (ret && collect_memory_statistics) {
- enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_REALLOC_COUNT:STAT_MEM_EREALLOC_COUNT;
- enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_REALLOC_AMOUNT:STAT_MEM_EREALLOC_AMOUNT;
- *(size_t *) ret = new_size;
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, new_size);
- }
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_efree */
-void _mysqlnd_efree(void *ptr MYSQLND_MEM_D)
-{
- size_t free_amount = 0;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- DBG_ENTER(mysqlnd_efree_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
- DBG_INF_FMT("ptr=%p", ptr);
-
- if (ptr) {
- if (collect_memory_statistics) {
- free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
- DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
- }
- efree(REAL_PTR(ptr));
- }
-
- if (collect_memory_statistics) {
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EFREE_COUNT, 1, STAT_MEM_EFREE_AMOUNT, free_amount);
- }
- DBG_VOID_RETURN;
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_pefree */
-void _mysqlnd_pefree(void *ptr, zend_bool persistent MYSQLND_MEM_D)
-{
- size_t free_amount = 0;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- DBG_ENTER(mysqlnd_pefree_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
- DBG_INF_FMT("ptr=%p persistent=%u", ptr, persistent);
-
- if (ptr) {
- if (collect_memory_statistics) {
- free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
- DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
- }
- pefree(REAL_PTR(ptr), persistent);
- }
-
- if (collect_memory_statistics) {
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(persistent? STAT_MEM_FREE_COUNT:STAT_MEM_EFREE_COUNT, 1,
- persistent? STAT_MEM_FREE_AMOUNT:STAT_MEM_EFREE_AMOUNT, free_amount);
- }
- DBG_VOID_RETURN;
-}
-
-
-/* {{{ _mysqlnd_malloc */
-void * _mysqlnd_malloc(size_t size MYSQLND_MEM_D)
-{
- void *ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- long * threshold = &MYSQLND_G(debug_malloc_fail_threshold);
- DBG_ENTER(mysqlnd_malloc_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-
-#ifdef PHP_DEBUG
- /* -1 is also "true" */
- if (*threshold) {
-#endif
- ret = malloc(REAL_SIZE(size));
-#ifdef PHP_DEBUG
- --*threshold;
- } else if (*threshold == 0) {
- ret = NULL;
- }
-#endif
-
- DBG_INF_FMT("size=%lu ptr=%p", size, ret);
- if (ret && collect_memory_statistics) {
- *(size_t *) ret = size;
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_MALLOC_COUNT, 1, STAT_MEM_MALLOC_AMOUNT, size);
- }
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_calloc */
-void * _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
-{
- void *ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- long * threshold = &MYSQLND_G(debug_calloc_fail_threshold);
- DBG_ENTER(mysqlnd_calloc_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
-
-#ifdef PHP_DEBUG
- /* -1 is also "true" */
- if (*threshold) {
-#endif
- ret = calloc(nmemb, REAL_SIZE(size));
-#ifdef PHP_DEBUG
- --*threshold;
- } else if (*threshold == 0) {
- ret = NULL;
- }
-#endif
-
- DBG_INF_FMT("size=%lu ptr=%p", size, ret);
- if (ret && collect_memory_statistics) {
- *(size_t *) ret = size;
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_CALLOC_COUNT, 1, STAT_MEM_CALLOC_AMOUNT, size);
- }
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_realloc */
-void * _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D)
-{
- void *ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- long * threshold = &MYSQLND_G(debug_realloc_fail_threshold);
- DBG_ENTER(mysqlnd_realloc_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
- DBG_INF_FMT("ptr=%p new_size=%lu ", new_size, ptr);
- DBG_INF_FMT("before: %lu", zend_memory_usage(TRUE TSRMLS_CC));
-
-#ifdef PHP_DEBUG
- /* -1 is also "true" */
- if (*threshold) {
-#endif
- ret = realloc(REAL_PTR(ptr), REAL_SIZE(new_size));
-#ifdef PHP_DEBUG
- --*threshold;
- } else if (*threshold == 0) {
- ret = NULL;
- }
-#endif
-
- DBG_INF_FMT("new_ptr=%p", (char*)ret);
-
- if (ret && collect_memory_statistics) {
- *(size_t *) ret = new_size;
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_REALLOC_COUNT, 1, STAT_MEM_REALLOC_AMOUNT, new_size);
- }
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_free */
-void _mysqlnd_free(void *ptr MYSQLND_MEM_D)
-{
- size_t free_amount = 0;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- DBG_ENTER(mysqlnd_free_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
- DBG_INF_FMT("ptr=%p", ptr);
-
- if (ptr) {
- if (collect_memory_statistics) {
- free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
- DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
- }
- free(REAL_PTR(ptr));
- }
-
- if (collect_memory_statistics) {
- MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_FREE_COUNT, 1, STAT_MEM_FREE_AMOUNT, free_amount);
- }
- DBG_VOID_RETURN;
-}
-/* }}} */
-
-#define SMART_STR_START_SIZE 2048
-#define SMART_STR_PREALLOC 512
-#include "ext/standard/php_smart_str.h"
-
-
-/* {{{ _mysqlnd_pestrndup */
-char * _mysqlnd_pestrndup(const char * const ptr, size_t length, zend_bool persistent MYSQLND_MEM_D)
+static struct st_mysqlnd_plugin_trace_log mysqlnd_plugin_trace_log_plugin =
{
- char * ret;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- DBG_ENTER(mysqlnd_pestrndup_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
- DBG_INF_FMT("ptr=%p", ptr);
-
- ret = pemalloc(REAL_SIZE(length) + 1, persistent);
{
- size_t l = length;
- char * p = (char *) ptr;
- char * dest = (char *) FAKE_PTR(ret);
- while (*p && l--) {
- *dest++ = *p++;
+ MYSQLND_PLUGIN_API_VERSION,
+ "debug_trace",
+ MYSQLND_VERSION_ID,
+ MYSQLND_VERSION,
+ "PHP License 3.01",
+ "Andrey Hristov <andrey@mysql.com>, Ulf Wendel <uwendel@mysql.com>, Georg Richter <georg@mysql.com>",
+ {
+ NULL, /* no statistics , will be filled later if there are some */
+ NULL, /* no statistics */
+ },
+ {
+ NULL /* plugin shutdown */
}
- *dest = '\0';
- }
-
- if (collect_memory_statistics) {
- *(size_t *) ret = length;
- MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRNDUP_COUNT : STAT_MEM_ESTRNDUP_COUNT);
- }
-
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_pestrdup */
-char * _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D)
-{
- char * ret;
- smart_str tmp_str = {0, 0, 0};
- const char * p = ptr;
- zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
- DBG_ENTER(mysqlnd_pestrdup_name);
- DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno);
- DBG_INF_FMT("ptr=%p", ptr);
- do {
- smart_str_appendc(&tmp_str, *p);
- } while (*p++);
-
- ret = pemalloc(tmp_str.len + sizeof(size_t), persistent);
- memcpy(FAKE_PTR(ret), tmp_str.c, tmp_str.len);
-
- if (ret && collect_memory_statistics) {
- *(size_t *) ret = tmp_str.len;
- MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRDUP_COUNT : STAT_MEM_ESTRDUP_COUNT);
+ },
+ {/* methods */
+ mysqlnd_debug_init,
+ mysqlnd_get_backtrace
}
- smart_str_free(&tmp_str);
-
- DBG_RETURN(FAKE_PTR(ret));
-}
-/* }}} */
-
-#define MYSQLND_DEBUG_MEMORY 1
-
-#if MYSQLND_DEBUG_MEMORY == 0
-
-/* {{{ mysqlnd_zend_mm_emalloc */
-static void * mysqlnd_zend_mm_emalloc(size_t size MYSQLND_MEM_D)
-{
- return emalloc(size);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_pemalloc */
-static void * mysqlnd_zend_mm_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)
-{
- return pemalloc(size, persistent);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_ecalloc */
-static void * mysqlnd_zend_mm_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
-{
- return ecalloc(nmemb, size);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_pecalloc */
-static void * mysqlnd_zend_mm_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D)
-{
- return pecalloc(nmemb, size, persistent);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_erealloc */
-static void * mysqlnd_zend_mm_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
-{
- return erealloc(ptr, new_size);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_perealloc */
-static void * mysqlnd_zend_mm_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D)
-{
- return perealloc(ptr, new_size, persistent);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_efree */
-static void mysqlnd_zend_mm_efree(void * ptr MYSQLND_MEM_D)
-{
- efree(ptr);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_pefree */
-static void mysqlnd_zend_mm_pefree(void * ptr, zend_bool persistent MYSQLND_MEM_D)
-{
- pefree(ptr, persistent);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_malloc */
-static void * mysqlnd_zend_mm_malloc(size_t size MYSQLND_MEM_D)
-{
- return malloc(size);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_calloc */
-static void * mysqlnd_zend_mm_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
-{
- return calloc(nmemb, size);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_realloc */
-static void * mysqlnd_zend_mm_realloc(void * ptr, size_t new_size MYSQLND_MEM_D)
-{
- return realloc(ptr, new_size);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_free */
-static void mysqlnd_zend_mm_free(void * ptr MYSQLND_MEM_D)
-{
- free(ptr);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_pestrndup */
-static char * mysqlnd_zend_mm_pestrndup(const char * const ptr, size_t length, zend_bool persistent MYSQLND_MEM_D)
-{
- return pestrndup(ptr, length, persistent);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_zend_mm_pestrdup */
-static char * mysqlnd_zend_mm_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D)
-{
- return pestrdup(ptr, persistent);
-}
-/* }}} */
-
-#endif
-
-
-PHPAPI struct st_mysqlnd_allocator_methods mysqlnd_allocator =
-{
-#if MYSQLND_DEBUG_MEMORY
- _mysqlnd_emalloc,
- _mysqlnd_pemalloc,
- _mysqlnd_ecalloc,
- _mysqlnd_pecalloc,
- _mysqlnd_erealloc,
- _mysqlnd_perealloc,
- _mysqlnd_efree,
- _mysqlnd_pefree,
- _mysqlnd_malloc,
- _mysqlnd_calloc,
- _mysqlnd_realloc,
- _mysqlnd_free,
- _mysqlnd_pestrndup,
- _mysqlnd_pestrdup
-#else
- mysqlnd_zend_mm_emalloc,
- mysqlnd_zend_mm_pemalloc,
- mysqlnd_zend_mm_ecalloc,
- mysqlnd_zend_mm_pecalloc,
- mysqlnd_zend_mm_erealloc,
- mysqlnd_zend_mm_perealloc,
- mysqlnd_zend_mm_efree,
- mysqlnd_zend_mm_pefree,
- mysqlnd_zend_mm_malloc,
- mysqlnd_zend_mm_calloc,
- mysqlnd_zend_mm_realloc,
- mysqlnd_zend_mm_free,
- mysqlnd_zend_mm_pestrndup,
- mysqlnd_zend_mm_pestrdup
-#endif
};
-
-/* Follows code borrowed from zend_builtin_functions.c because the functions there are static */
-
-#if MYSQLND_UNICODE
-/* {{{ gettraceasstring() macros */
-#define TRACE_APPEND_CHR(chr) \
- *str = (char*)erealloc(*str, *len + 1 + 1); \
- (*str)[(*len)++] = chr
-
-#define TRACE_APPEND_STRL(val, vallen) \
- { \
- int l = vallen; \
- *str = (char*)erealloc(*str, *len + l + 1); \
- memcpy((*str) + *len, val, l); \
- *len += l; \
- }
-
-#define TRACE_APPEND_USTRL(val, vallen) \
- { \
- zval tmp, copy; \
- int use_copy; \
- ZVAL_UNICODEL(&tmp, val, vallen, 1); \
- zend_make_printable_zval(&tmp, &copy, &use_copy); \
- TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
- zval_dtor(&copy); \
- zval_dtor(&tmp); \
- }
-
-#define TRACE_APPEND_ZVAL(zv) \
- if (Z_TYPE_P((zv)) == IS_UNICODE) { \
- zval copy; \
- int use_copy; \
- zend_make_printable_zval((zv), &copy, &use_copy); \
- TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
- zval_dtor(&copy); \
- } else { \
- TRACE_APPEND_STRL(Z_STRVAL_P((zv)), Z_STRLEN_P((zv))); \
- }
-
-#define TRACE_APPEND_STR(val) \
- TRACE_APPEND_STRL(val, sizeof(val)-1)
-
-#define TRACE_APPEND_KEY(key) \
- if (zend_ascii_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
- if (Z_TYPE_PP(tmp) == IS_UNICODE) { \
- zval copy; \
- int use_copy; \
- zend_make_printable_zval(*tmp, &copy, &use_copy); \
- TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
- zval_dtor(&copy); \
- } else { \
- TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); \
- } \
- }
-/* }}} */
-
-/* {{{ mysqlnd_build_trace_args */
-static int mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
-{
- char **str;
- int *len;
-
- str = va_arg(args, char**);
- len = va_arg(args, int*);
-
- /* the trivial way would be to do:
- * conver_to_string_ex(arg);
- * append it and kill the now tmp arg.
- * but that could cause some E_NOTICE and also damn long lines.
- */
-
- switch (Z_TYPE_PP(arg)) {
- case IS_NULL:
- TRACE_APPEND_STR("NULL, ");
- break;
- case IS_STRING: {
- int l_added;
- TRACE_APPEND_CHR('\'');
- if (Z_STRLEN_PP(arg) > 15) {
- TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15);
- TRACE_APPEND_STR("...', ");
- l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
- } else {
- l_added = Z_STRLEN_PP(arg);
- TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added);
- TRACE_APPEND_STR("', ");
- l_added += 3 + 1;
- }
- while (--l_added) {
- if ((unsigned char)(*str)[*len - l_added] < 32) {
- (*str)[*len - l_added] = '?';
- }
- }
- break;
- }
- case IS_UNICODE: {
- int l_added;
-
- /*
- * We do not want to apply current error mode here, since
- * zend_make_printable_zval() uses output encoding converter.
- * Temporarily set output encoding converter to escape offending
- * chars with \uXXXX notation.
- */
- zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, ZEND_CONV_ERROR_ESCAPE_JAVA);
- TRACE_APPEND_CHR('\'');
- if (Z_USTRLEN_PP(arg) > 15) {
- TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), 15);
- TRACE_APPEND_STR("...', ");
- l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
- } else {
- l_added = Z_USTRLEN_PP(arg);
- TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), l_added);
- TRACE_APPEND_STR("', ");
- l_added += 3 + 1;
- }
- /*
- * Reset output encoding converter error mode.
- */
- zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, UG(from_error_mode));
- while (--l_added) {
- if ((unsigned char)(*str)[*len - l_added] < 32) {
- (*str)[*len - l_added] = '?';
- }
- }
- break;
- }
- case IS_BOOL:
- if (Z_LVAL_PP(arg)) {
- TRACE_APPEND_STR("true, ");
- } else {
- TRACE_APPEND_STR("false, ");
- }
- break;
- case IS_RESOURCE:
- TRACE_APPEND_STR("Resource id #");
- /* break; */
- case IS_LONG: {
- long lval = Z_LVAL_PP(arg);
- char s_tmp[MAX_LENGTH_OF_LONG + 1];
- int l_tmp = zend_sprintf(s_tmp, "%ld", lval); /* SAFE */
- TRACE_APPEND_STRL(s_tmp, l_tmp);
- TRACE_APPEND_STR(", ");
- break;
- }
- case IS_DOUBLE: {
- double dval = Z_DVAL_PP(arg);
- char *s_tmp;
- int l_tmp;
-
- s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
- l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval); /* SAFE */
- TRACE_APPEND_STRL(s_tmp, l_tmp);
- /* %G already handles removing trailing zeros from the fractional part, yay */
- efree(s_tmp);
- TRACE_APPEND_STR(", ");
- break;
- }
- case IS_ARRAY:
- TRACE_APPEND_STR("Array, ");
- break;
- case IS_OBJECT: {
- zval tmp;
- zstr class_name;
- zend_uint class_name_len;
- int dup;
-
- TRACE_APPEND_STR("Object(");
-
- dup = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC);
-
- ZVAL_UNICODEL(&tmp, class_name.u, class_name_len, 1);
- convert_to_string_with_converter(&tmp, ZEND_U_CONVERTER(UG(output_encoding_conv)));
- TRACE_APPEND_STRL(Z_STRVAL(tmp), Z_STRLEN(tmp));
- zval_dtor(&tmp);
-
- if(!dup) {
- efree(class_name.v);
- }
-
- TRACE_APPEND_STR("), ");
- break;
- }
- default:
- break;
- }
- return ZEND_HASH_APPLY_KEEP;
-}
-/* }}} */
-
-
-static int mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
-{
- char *s_tmp, **str;
- int *len, *num;
- long line;
- HashTable *ht = Z_ARRVAL_PP(frame);
- zval **file, **tmp;
- uint * level;
-
- level = va_arg(args, uint *);
- str = va_arg(args, char**);
- len = va_arg(args, int*);
- num = va_arg(args, int*);
-
- if (!*level) {
- return ZEND_HASH_APPLY_KEEP;
- }
- --*level;
-
- s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);
- sprintf(s_tmp, "#%d ", (*num)++);
- TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
- efree(s_tmp);
- if (zend_ascii_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
- if (zend_ascii_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
- line = Z_LVAL_PP(tmp);
- } else {
- line = 0;
- }
- TRACE_APPEND_ZVAL(*file);
- s_tmp = emalloc(MAX_LENGTH_OF_LONG + 2 + 1);
- sprintf(s_tmp, "(%ld): ", line);
- TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
- efree(s_tmp);
- } else {
- TRACE_APPEND_STR("[internal function]: ");
- }
- TRACE_APPEND_KEY("class");
- TRACE_APPEND_KEY("type");
- TRACE_APPEND_KEY("function");
- TRACE_APPEND_CHR('(');
- if (zend_ascii_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
- int last_len = *len;
- zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_args, 2, str, len);
- if (last_len != *len) {
- *len -= 2; /* remove last ', ' */
- }
- }
- TRACE_APPEND_STR(")\n");
- return ZEND_HASH_APPLY_KEEP;
-}
-/* }}} */
-
-
-#else /* PHP 5*/
-
-
-/* {{{ gettraceasstring() macros */
-#define TRACE_APPEND_CHR(chr) \
- *str = (char*)erealloc(*str, *len + 1 + 1); \
- (*str)[(*len)++] = chr
-
-#define TRACE_APPEND_STRL(val, vallen) \
- { \
- int l = vallen; \
- *str = (char*)erealloc(*str, *len + l + 1); \
- memcpy((*str) + *len, val, l); \
- *len += l; \
- }
-
-#define TRACE_APPEND_STR(val) \
- TRACE_APPEND_STRL(val, sizeof(val)-1)
-
-#define TRACE_APPEND_KEY(key) \
- if (zend_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
- TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); \
- }
-
-/* }}} */
-
-
-static int mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
-{
- char **str;
- int *len;
-
- str = va_arg(args, char**);
- len = va_arg(args, int*);
-
- /* the trivial way would be to do:
- * conver_to_string_ex(arg);
- * append it and kill the now tmp arg.
- * but that could cause some E_NOTICE and also damn long lines.
- */
-
- switch (Z_TYPE_PP(arg)) {
- case IS_NULL:
- TRACE_APPEND_STR("NULL, ");
- break;
- case IS_STRING: {
- int l_added;
- TRACE_APPEND_CHR('\'');
- if (Z_STRLEN_PP(arg) > 15) {
- TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15);
- TRACE_APPEND_STR("...', ");
- l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */
- } else {
- l_added = Z_STRLEN_PP(arg);
- TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added);
- TRACE_APPEND_STR("', ");
- l_added += 3 + 1;
- }
- while (--l_added) {
- if ((*str)[*len - l_added] < 32) {
- (*str)[*len - l_added] = '?';
- }
- }
- break;
- }
- case IS_BOOL:
- if (Z_LVAL_PP(arg)) {
- TRACE_APPEND_STR("true, ");
- } else {
- TRACE_APPEND_STR("false, ");
- }
- break;
- case IS_RESOURCE:
- TRACE_APPEND_STR("Resource id #");
- /* break; */
- case IS_LONG: {
- long lval = Z_LVAL_PP(arg);
- char s_tmp[MAX_LENGTH_OF_LONG + 1];
- int l_tmp = zend_sprintf(s_tmp, "%ld", lval); /* SAFE */
- TRACE_APPEND_STRL(s_tmp, l_tmp);
- TRACE_APPEND_STR(", ");
- break;
- }
- case IS_DOUBLE: {
- double dval = Z_DVAL_PP(arg);
- char *s_tmp;
- int l_tmp;
-
- s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
- l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval); /* SAFE */
- TRACE_APPEND_STRL(s_tmp, l_tmp);
- /* %G already handles removing trailing zeros from the fractional part, yay */
- efree(s_tmp);
- TRACE_APPEND_STR(", ");
- break;
- }
- case IS_ARRAY:
- TRACE_APPEND_STR("Array, ");
- break;
- case IS_OBJECT: {
- char *class_name;
- zend_uint class_name_len;
- int dupl;
-
- TRACE_APPEND_STR("Object(");
-
- dupl = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC);
-
- TRACE_APPEND_STRL(class_name, class_name_len);
- if (!dupl) {
- efree(class_name);
- }
-
- TRACE_APPEND_STR("), ");
- break;
- }
- default:
- break;
- }
- return ZEND_HASH_APPLY_KEEP;
-}
-/* }}} */
-
-static int mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */
+/* {{{ mysqlnd_debug_trace_plugin_register */
+void
+mysqlnd_debug_trace_plugin_register(TSRMLS_D)
{
- char *s_tmp, **str;
- int *len, *num;
- long line;
- HashTable *ht = Z_ARRVAL_PP(frame);
- zval **file, **tmp;
- uint * level;
-
- level = va_arg(args, uint *);
- str = va_arg(args, char**);
- len = va_arg(args, int*);
- num = va_arg(args, int*);
-
- if (!*level) {
- return ZEND_HASH_APPLY_KEEP;
- }
- --*level;
-
- s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1);
- sprintf(s_tmp, "#%d ", (*num)++);
- TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
- efree(s_tmp);
- if (zend_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) {
- if (zend_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) {
- line = Z_LVAL_PP(tmp);
- } else {
- line = 0;
- }
- s_tmp = emalloc(Z_STRLEN_PP(file) + MAX_LENGTH_OF_LONG + 4 + 1);
- sprintf(s_tmp, "%s(%ld): ", Z_STRVAL_PP(file), line);
- TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
- efree(s_tmp);
- } else {
- TRACE_APPEND_STR("[internal function]: ");
- }
- TRACE_APPEND_KEY("class");
- TRACE_APPEND_KEY("type");
- TRACE_APPEND_KEY("function");
- TRACE_APPEND_CHR('(');
- if (zend_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
- int last_len = *len;
- zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_args, 2, str, len);
- if (last_len != *len) {
- *len -= 2; /* remove last ', ' */
- }
- }
- TRACE_APPEND_STR(")\n");
- return ZEND_HASH_APPLY_KEEP;
+ mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_plugin_trace_log_plugin TSRMLS_CC);
}
/* }}} */
-#endif
-PHPAPI char * mysqlnd_get_backtrace(uint max_levels, size_t * length TSRMLS_DC)
-{
- zval *trace;
- char *res = estrdup(""), **str = &res, *s_tmp;
- int res_len = 0, *len = &res_len, num = 0;
- if (max_levels == 0) {
- max_levels = 99999;
- }
-
- MAKE_STD_ZVAL(trace);
- zend_fetch_debug_backtrace(trace, 0, 0 TSRMLS_CC);
-
- zend_hash_apply_with_arguments(Z_ARRVAL_P(trace) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_string, 4, &max_levels, str, len, &num);
- zval_ptr_dtor(&trace);
-
- if (max_levels) {
- s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 7 + 1);
- sprintf(s_tmp, "#%d {main}", num);
- TRACE_APPEND_STRL(s_tmp, strlen(s_tmp));
- efree(s_tmp);
- }
-
- res[res_len] = '\0';
- *length = res_len;
-
- return res;
-}
-
/*
* Local variables:
* tab-width: 4
diff --git a/ext/mysqlnd/mysqlnd_debug.h b/ext/mysqlnd/mysqlnd_debug.h
index a8bf680bb4..f98c163e74 100644
--- a/ext/mysqlnd/mysqlnd_debug.h
+++ b/ext/mysqlnd/mysqlnd_debug.h
@@ -23,6 +23,7 @@
#ifndef MYSQLND_DEBUG_H
#define MYSQLND_DEBUG_H
+#include "mysqlnd_alloc.h"
#include "zend_stack.h"
struct st_mysqlnd_debug_methods
@@ -59,11 +60,21 @@ struct st_mysqlnd_debug
const char ** skip_functions;
};
-PHPAPI extern const char * mysqlnd_debug_std_no_trace_funcs[];
+struct st_mysqlnd_plugin_trace_log
+{
+ struct st_mysqlnd_plugin_header plugin_header;
+ struct
+ {
+ MYSQLND_DEBUG * (*trace_instance_init)(const char * skip_functions[] TSRMLS_DC);
+ char * (*get_backtrace)(uint max_levels, size_t * length TSRMLS_DC);
+ } methods;
+};
+
+void mysqlnd_debug_trace_plugin_register(TSRMLS_D);
PHPAPI MYSQLND_DEBUG * mysqlnd_debug_init(const char * skip_functions[] TSRMLS_DC);
-PHPAPI char * mysqlnd_get_backtrace(uint max_levels, size_t * length TSRMLS_DC);
+PHPAPI char * mysqlnd_get_backtrace(uint max_levels, size_t * length TSRMLS_DC);
#if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 1400))
#ifdef PHP_WIN32
@@ -141,7 +152,7 @@ static inline void DBG_ENTER_EX(MYSQLND_DEBUG * dbg_obj, const char * const func
#define DBG_VOID_RETURN_EX(dbg_obj) return
#define DBG_BLOCK_LEAVE_EX(dbg_obj) }
-#endif /* defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 1400)) */
+#endif
#if MYSQLND_DBG_ENABLED == 1
@@ -158,8 +169,6 @@ static inline void DBG_ENTER_EX(MYSQLND_DEBUG * dbg_obj, const char * const func
#elif MYSQLND_DBG_ENABLED == 0
-
-
static inline void DBG_INF(const char * const msg) {}
static inline void DBG_ERR(const char * const msg) {}
static inline void DBG_INF_FMT(const char * const format, ...) {}
@@ -172,62 +181,6 @@ static inline void DBG_ENTER(const char * const func_name) {}
#endif
-
-#define MYSQLND_MEM_D TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC
-#define MYSQLND_MEM_C TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC
-
-struct st_mysqlnd_allocator_methods
-{
- void * (*m_emalloc)(size_t size MYSQLND_MEM_D);
- void * (*m_pemalloc)(size_t size, zend_bool persistent MYSQLND_MEM_D);
- void * (*m_ecalloc)(unsigned int nmemb, size_t size MYSQLND_MEM_D);
- void * (*m_pecalloc)(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D);
- void * (*m_erealloc)(void *ptr, size_t new_size MYSQLND_MEM_D);
- void * (*m_perealloc)(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D);
- void (*m_efree)(void *ptr MYSQLND_MEM_D);
- void (*m_pefree)(void *ptr, zend_bool persistent MYSQLND_MEM_D);
- void * (*m_malloc)(size_t size MYSQLND_MEM_D);
- void * (*m_calloc)(unsigned int nmemb, size_t size MYSQLND_MEM_D);
- void * (*m_realloc)(void *ptr, size_t new_size MYSQLND_MEM_D);
- void (*m_free)(void *ptr MYSQLND_MEM_D);
- char * (*m_pestrndup)(const char * const ptr, size_t size, zend_bool persistent MYSQLND_MEM_D);
- char * (*m_pestrdup)(const char * const ptr, zend_bool persistent MYSQLND_MEM_D);
-};
-
-PHPAPI extern struct st_mysqlnd_allocator_methods mysqlnd_allocator;
-
-
-PHPAPI void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D);
-PHPAPI void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D);
-PHPAPI void * _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D);
-PHPAPI void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D);
-PHPAPI void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D);
-PHPAPI void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D);
-PHPAPI void _mysqlnd_efree(void *ptr MYSQLND_MEM_D);
-PHPAPI void _mysqlnd_pefree(void *ptr, zend_bool persistent MYSQLND_MEM_D);
-PHPAPI void * _mysqlnd_malloc(size_t size MYSQLND_MEM_D);
-PHPAPI void * _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D);
-PHPAPI void * _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D);
-PHPAPI void _mysqlnd_free(void *ptr MYSQLND_MEM_D);
-PHPAPI char * _mysqlnd_pestrndup(const char * const ptr, size_t size, zend_bool persistent MYSQLND_MEM_D);
-PHPAPI char * _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D);
-
-
-#define mnd_emalloc(size) mysqlnd_allocator.m_emalloc((size) MYSQLND_MEM_C)
-#define mnd_pemalloc(size, pers) mysqlnd_allocator.m_pemalloc((size), (pers) MYSQLND_MEM_C)
-#define mnd_ecalloc(nmemb, size) mysqlnd_allocator.m_ecalloc((nmemb), (size) MYSQLND_MEM_C)
-#define mnd_pecalloc(nmemb, size, p) mysqlnd_allocator.m_pecalloc((nmemb), (size), (p) MYSQLND_MEM_C)
-#define mnd_erealloc(ptr, new_size) mysqlnd_allocator.m_erealloc((ptr), (new_size) MYSQLND_MEM_C)
-#define mnd_perealloc(ptr, new_size, p) mysqlnd_allocator.m_perealloc((ptr), (new_size), (p) MYSQLND_MEM_C)
-#define mnd_efree(ptr) mysqlnd_allocator.m_efree((ptr) MYSQLND_MEM_C)
-#define mnd_pefree(ptr, pers) mysqlnd_allocator.m_pefree((ptr), (pers) MYSQLND_MEM_C)
-#define mnd_malloc(size) mysqlnd_allocator.m_malloc((size) MYSQLND_MEM_C)
-#define mnd_calloc(nmemb, size) mysqlnd_allocator.m_calloc((nmemb), (size) MYSQLND_MEM_C)
-#define mnd_realloc(ptr, new_size) mysqlnd_allocator.m_realloc((ptr), (new_size) MYSQLND_MEM_C)
-#define mnd_free(ptr) mysqlnd_allocator.m_free((ptr) MYSQLND_MEM_C)
-#define mnd_pestrndup(ptr, size, pers) mysqlnd_allocator.m_pestrndup((ptr), (size), (pers) MYSQLND_MEM_C)
-#define mnd_pestrdup(ptr, pers) mysqlnd_allocator.m_pestrdup((ptr), (pers) MYSQLND_MEM_C)
-
#endif /* MYSQLND_DEBUG_H */
/*
diff --git a/ext/mysqlnd/mysqlnd_driver.c b/ext/mysqlnd/mysqlnd_driver.c
new file mode 100644
index 0000000000..e209a71b49
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_driver.c
@@ -0,0 +1,306 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd.c 317989 2011-10-10 20:49:28Z andrey $ */
+#include "php.h"
+#include "mysqlnd.h"
+#include "mysqlnd_wireprotocol.h"
+#include "mysqlnd_priv.h"
+#include "mysqlnd_result.h"
+#include "mysqlnd_statistics.h"
+#include "mysqlnd_charset.h"
+#include "mysqlnd_debug.h"
+#include "mysqlnd_reverse_api.h"
+#include "mysqlnd_ext_plugin.h"
+
+static zend_bool mysqlnd_library_initted = FALSE;
+
+static struct st_mysqlnd_plugin_core mysqlnd_plugin_core =
+{
+ {
+ MYSQLND_PLUGIN_API_VERSION,
+ "mysqlnd",
+ MYSQLND_VERSION_ID,
+ MYSQLND_VERSION,
+ "PHP License 3.01",
+ "Andrey Hristov <andrey@mysql.com>, Ulf Wendel <uwendel@mysql.com>, Georg Richter <georg@mysql.com>",
+ {
+ NULL, /* will be filled later */
+ mysqlnd_stats_values_names,
+ },
+ {
+ NULL /* plugin shutdown */
+ }
+ }
+};
+
+
+/* {{{ mysqlnd_library_end */
+PHPAPI void mysqlnd_library_end(TSRMLS_D)
+{
+ if (mysqlnd_library_initted == TRUE) {
+ mysqlnd_plugin_subsystem_end(TSRMLS_C);
+ mysqlnd_stats_end(mysqlnd_global_stats);
+ mysqlnd_global_stats = NULL;
+ mysqlnd_library_initted = FALSE;
+ mysqlnd_reverse_api_end(TSRMLS_C);
+ }
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_library_init */
+PHPAPI void mysqlnd_library_init(TSRMLS_D)
+{
+ if (mysqlnd_library_initted == FALSE) {
+ mysqlnd_library_initted = TRUE;
+ mysqlnd_conn_set_methods(&MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_conn));
+ mysqlnd_conn_data_set_methods(&MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_conn_data));
+ _mysqlnd_init_ps_subsystem();
+ /* Should be calloc, as mnd_calloc will reference LOCK_access*/
+ mysqlnd_stats_init(&mysqlnd_global_stats, STAT_LAST);
+ mysqlnd_plugin_subsystem_init(TSRMLS_C);
+ {
+ mysqlnd_plugin_core.plugin_header.plugin_stats.values = mysqlnd_global_stats;
+ mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_plugin_core TSRMLS_CC);
+ }
+ mysqlnd_example_plugin_register(TSRMLS_C);
+ mysqlnd_debug_trace_plugin_register(TSRMLS_C);
+ mysqlnd_register_builtin_authentication_plugins(TSRMLS_C);
+
+ mysqlnd_reverse_api_init(TSRMLS_C);
+ }
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_error_list_pdtor */
+static void
+mysqlnd_error_list_pdtor(void * pDest)
+{
+ MYSQLND_ERROR_LIST_ELEMENT * element = (MYSQLND_ERROR_LIST_ELEMENT *) pDest;
+#ifdef ZTS
+ TSRMLS_FETCH();
+#endif
+ DBG_ENTER("mysqlnd_error_list_pdtor");
+ if (element->error) {
+ mnd_pefree(element->error, TRUE);
+ }
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_object_factory::get_connection */
+static MYSQLND *
+MYSQLND_METHOD(mysqlnd_object_factory, get_connection)(zend_bool persistent TSRMLS_DC)
+{
+ size_t alloc_size_ret = sizeof(MYSQLND) + mysqlnd_plugin_count() * sizeof(void *);
+ size_t alloc_size_ret_data = sizeof(MYSQLND_CONN_DATA) + mysqlnd_plugin_count() * sizeof(void *);
+ MYSQLND * new_object;
+ MYSQLND_CONN_DATA * data;
+
+ DBG_ENTER("mysqlnd_driver::get_connection");
+ DBG_INF_FMT("persistent=%u", persistent);
+ new_object = mnd_pecalloc(1, alloc_size_ret, persistent);
+ if (!new_object) {
+ DBG_RETURN(NULL);
+ }
+ new_object->data = mnd_pecalloc(1, alloc_size_ret_data, persistent);
+ if (!new_object->data) {
+ mnd_pefree(new_object, persistent);
+ DBG_RETURN(NULL);
+ }
+ new_object->persistent = persistent;
+ new_object->m = mysqlnd_conn_get_methods();
+ data = new_object->data;
+
+ data->error_info = &(data->error_info_impl);
+ data->options = &(data->options_impl);
+ data->upsert_status = &(data->upsert_status_impl);
+
+ data->persistent = persistent;
+ data->m = mysqlnd_conn_data_get_methods();
+ CONN_SET_STATE(data, CONN_ALLOCED);
+ data->m->get_reference(data TSRMLS_CC);
+
+ if (PASS != data->m->init(data TSRMLS_CC)) {
+ new_object->m->dtor(new_object TSRMLS_CC);
+ DBG_RETURN(NULL);
+ }
+
+ data->error_info->error_list = mnd_pecalloc(1, sizeof(zend_llist), persistent);
+ if (!data->error_info->error_list) {
+ new_object->m->dtor(new_object TSRMLS_CC);
+ DBG_RETURN(NULL);
+ } else {
+ zend_llist_init(data->error_info->error_list, sizeof(MYSQLND_ERROR_LIST_ELEMENT), (llist_dtor_func_t)mysqlnd_error_list_pdtor, persistent);
+ }
+
+ DBG_RETURN(new_object);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_object_factory::clone_connection_object */
+static MYSQLND *
+MYSQLND_METHOD(mysqlnd_object_factory, clone_connection_object)(MYSQLND * to_be_cloned TSRMLS_DC)
+{
+ size_t alloc_size_ret = sizeof(MYSQLND) + mysqlnd_plugin_count() * sizeof(void *);
+ MYSQLND * new_object;
+
+ DBG_ENTER("mysqlnd_driver::clone_connection_object");
+ DBG_INF_FMT("persistent=%u", to_be_cloned->persistent);
+ if (!to_be_cloned || !to_be_cloned->data) {
+ DBG_RETURN(NULL);
+ }
+ new_object = mnd_pecalloc(1, alloc_size_ret, to_be_cloned->persistent);
+ if (!new_object) {
+ DBG_RETURN(NULL);
+ }
+ new_object->persistent = to_be_cloned->persistent;
+ new_object->m = to_be_cloned->m;
+
+ new_object->data = to_be_cloned->data->m->get_reference(to_be_cloned->data TSRMLS_CC);
+ if (!new_object->data) {
+ new_object->m->dtor(new_object TSRMLS_CC);
+ new_object = NULL;
+ }
+ DBG_RETURN(new_object);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_object_factory::get_prepared_statement */
+static MYSQLND_STMT *
+MYSQLND_METHOD(mysqlnd_object_factory, get_prepared_statement)(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
+{
+ size_t alloc_size = sizeof(MYSQLND_STMT) + mysqlnd_plugin_count() * sizeof(void *);
+ MYSQLND_STMT * ret = mnd_pecalloc(1, alloc_size, conn->persistent);
+ MYSQLND_STMT_DATA * stmt = NULL;
+
+ DBG_ENTER("mysqlnd_object_factory::get_prepared_statement");
+ do {
+ if (!ret) {
+ break;
+ }
+ ret->m = mysqlnd_stmt_get_methods();
+ ret->persistent = conn->persistent;
+
+ stmt = ret->data = mnd_pecalloc(1, sizeof(MYSQLND_STMT_DATA), conn->persistent);
+ DBG_INF_FMT("stmt=%p", stmt);
+ if (!stmt) {
+ break;
+ }
+ stmt->persistent = conn->persistent;
+ stmt->error_info = &(stmt->error_info_impl);
+ stmt->upsert_status = &(stmt->upsert_status_impl);
+ stmt->state = MYSQLND_STMT_INITTED;
+ stmt->execute_cmd_buffer.length = 4096;
+ stmt->execute_cmd_buffer.buffer = mnd_pemalloc(stmt->execute_cmd_buffer.length, stmt->persistent);
+ if (!stmt->execute_cmd_buffer.buffer) {
+ break;
+ }
+
+ stmt->prefetch_rows = MYSQLND_DEFAULT_PREFETCH_ROWS;
+ /*
+ Mark that we reference the connection, thus it won't be
+ be destructed till there is open statements. The last statement
+ or normal query result will close it then.
+ */
+ stmt->conn = conn->m->get_reference(conn TSRMLS_CC);
+ stmt->error_info->error_list = mnd_pecalloc(1, sizeof(zend_llist), ret->persistent);
+ if (!stmt->error_info->error_list) {
+ break;
+ }
+
+ zend_llist_init(stmt->error_info->error_list, sizeof(MYSQLND_ERROR_LIST_ELEMENT), (llist_dtor_func_t) mysqlnd_error_list_pdtor, conn->persistent);
+
+ DBG_RETURN(ret);
+ } while (0);
+
+ SET_OOM_ERROR(*conn->error_info);
+ if (ret) {
+ ret->m->dtor(ret, TRUE TSRMLS_CC);
+ ret = NULL;
+ }
+ DBG_RETURN(NULL);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_object_factory::get_io_channel */
+PHPAPI MYSQLND_NET *
+MYSQLND_METHOD(mysqlnd_object_factory, get_io_channel)(zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC)
+{
+ size_t alloc_size = sizeof(MYSQLND_NET) + mysqlnd_plugin_count() * sizeof(void *);
+ MYSQLND_NET * net = mnd_pecalloc(1, alloc_size, persistent);
+
+ DBG_ENTER("mysqlnd_object_factory::get_io_channel");
+ DBG_INF_FMT("persistent=%u", persistent);
+ if (net) {
+ net->persistent = persistent;
+ net->m = *mysqlnd_net_get_methods();
+
+ if (PASS != net->m.init(net, stats, error_info TSRMLS_CC)) {
+ net->m.dtor(net, stats, error_info TSRMLS_CC);
+ net = NULL;
+ }
+ }
+ DBG_RETURN(net);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_object_factory::get_protocol_decoder */
+PHPAPI MYSQLND_PROTOCOL *
+MYSQLND_METHOD(mysqlnd_object_factory, get_protocol_decoder)(zend_bool persistent TSRMLS_DC)
+{
+ size_t alloc_size = sizeof(MYSQLND_PROTOCOL) + mysqlnd_plugin_count() * sizeof(void *);
+ MYSQLND_PROTOCOL *ret = mnd_pecalloc(1, alloc_size, persistent);
+
+ DBG_ENTER("mysqlnd_object_factory::get_protocol_decoder");
+ DBG_INF_FMT("persistent=%u", persistent);
+ if (ret) {
+ ret->persistent = persistent;
+ ret->m = mysqlnd_mysqlnd_protocol_methods;
+ }
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+MYSQLND_CLASS_METHODS_START(mysqlnd_object_factory)
+ MYSQLND_METHOD(mysqlnd_object_factory, get_connection),
+ MYSQLND_METHOD(mysqlnd_object_factory, clone_connection_object),
+ MYSQLND_METHOD(mysqlnd_object_factory, get_prepared_statement),
+ MYSQLND_METHOD(mysqlnd_object_factory, get_io_channel),
+ MYSQLND_METHOD(mysqlnd_object_factory, get_protocol_decoder)
+MYSQLND_CLASS_METHODS_END;
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_enum_n_def.h b/ext/mysqlnd/mysqlnd_enum_n_def.h
index 10deb03812..56a2bf99b3 100644
--- a/ext/mysqlnd/mysqlnd_enum_n_def.h
+++ b/ext/mysqlnd/mysqlnd_enum_n_def.h
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -35,6 +35,8 @@
#define MYSQLND_MAX_PACKET_SIZE (256L*256L*256L-1)
+#define MYSQLND_ASSEMBLED_PACKET_MAX_SIZE 3UL*1024UL*1024UL*1024UL
+
#define MYSQLND_ERRMSG_SIZE 512
#define MYSQLND_SQLSTATE_LENGTH 5
#define MYSQLND_SQLSTATE_NULL "00000"
@@ -96,6 +98,9 @@
#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30)
+#define MYSQLND_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS | \
+ CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | \
+ CLIENT_MULTI_RESULTS | CLIENT_PS_MULTI_RESULTS | CLIENT_LOCAL_FILES | CLIENT_PLUGIN_AUTH)
#define MYSQLND_NET_FLAG_USE_COMPRESSION 1
@@ -172,7 +177,9 @@ typedef enum mysqlnd_option
MYSQLND_OPT_SSL_CA = 206,
MYSQLND_OPT_SSL_CAPATH = 207,
MYSQLND_OPT_SSL_CIPHER = 208,
- MYSQLND_OPT_SSL_PASSPHRASE = 209
+ MYSQLND_OPT_SSL_PASSPHRASE = 209,
+ MYSQLND_OPT_MAX_ALLOWED_PACKET = 210,
+ MYSQLND_OPT_AUTH_PROTOCOL = 211
} enum_mysqlnd_option;
typedef enum mysqlnd_protocol_type
@@ -517,6 +524,8 @@ enum mysqlnd_packet_type
{
PROT_GREET_PACKET= 0,
PROT_AUTH_PACKET,
+ PROT_AUTH_RESP_PACKET,
+ PROT_CHANGE_AUTH_RESP_PACKET,
PROT_OK_PACKET,
PROT_EOF_PACKET,
PROT_CMD_PACKET,
diff --git a/ext/mysqlnd/mysqlnd_ext_plugin.c b/ext/mysqlnd/mysqlnd_ext_plugin.c
new file mode 100644
index 0000000000..21be3fd37b
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_ext_plugin.c
@@ -0,0 +1,226 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd.c 318221 2011-10-19 15:04:12Z andrey $ */
+#include "php.h"
+#include "mysqlnd.h"
+#include "mysqlnd_priv.h"
+#include "mysqlnd_result.h"
+#include "mysqlnd_debug.h"
+
+static struct st_mysqlnd_conn_methods * mysqlnd_conn_methods;
+static struct st_mysqlnd_conn_data_methods * mysqlnd_conn_data_methods;
+static struct st_mysqlnd_stmt_methods * mysqlnd_stmt_methods;
+
+/* {{{ _mysqlnd_plugin_get_plugin_connection_data */
+PHPAPI void **
+_mysqlnd_plugin_get_plugin_connection_data(const MYSQLND * conn, unsigned int plugin_id TSRMLS_DC)
+{
+ DBG_ENTER("_mysqlnd_plugin_get_plugin_connection_data");
+ DBG_INF_FMT("plugin_id=%u", plugin_id);
+ if (!conn || plugin_id >= mysqlnd_plugin_count()) {
+ return NULL;
+ }
+ DBG_RETURN((void *)((char *)conn + sizeof(MYSQLND) + plugin_id * sizeof(void *)));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_plugin_get_plugin_connection_data_data */
+PHPAPI void **
+_mysqlnd_plugin_get_plugin_connection_data_data(const MYSQLND_CONN_DATA * conn, unsigned int plugin_id TSRMLS_DC)
+{
+ DBG_ENTER("_mysqlnd_plugin_get_plugin_connection_data_data");
+ DBG_INF_FMT("plugin_id=%u", plugin_id);
+ if (!conn || plugin_id >= mysqlnd_plugin_count()) {
+ return NULL;
+ }
+ DBG_RETURN((void *)((char *)conn + sizeof(MYSQLND_CONN_DATA) + plugin_id * sizeof(void *)));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_plugin_get_plugin_result_data */
+PHPAPI void ** _mysqlnd_plugin_get_plugin_result_data(const MYSQLND_RES * result, unsigned int plugin_id TSRMLS_DC)
+{
+ DBG_ENTER("_mysqlnd_plugin_get_plugin_result_data");
+ DBG_INF_FMT("plugin_id=%u", plugin_id);
+ if (!result || plugin_id >= mysqlnd_plugin_count()) {
+ return NULL;
+ }
+ DBG_RETURN((void *)((char *)result + sizeof(MYSQLND_RES) + plugin_id * sizeof(void *)));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_plugin_get_plugin_protocol_data */
+PHPAPI void **
+_mysqlnd_plugin_get_plugin_protocol_data(const MYSQLND_PROTOCOL * protocol, unsigned int plugin_id TSRMLS_DC)
+{
+ DBG_ENTER("_mysqlnd_plugin_get_plugin_protocol_data");
+ DBG_INF_FMT("plugin_id=%u", plugin_id);
+ if (!protocol || plugin_id >= mysqlnd_plugin_count()) {
+ return NULL;
+ }
+ DBG_RETURN((void *)((char *)protocol + sizeof(MYSQLND_PROTOCOL) + plugin_id * sizeof(void *)));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_plugin_get_plugin_stmt_data */
+PHPAPI void ** _mysqlnd_plugin_get_plugin_stmt_data(const MYSQLND_STMT * stmt, unsigned int plugin_id TSRMLS_DC)
+{
+ DBG_ENTER("_mysqlnd_plugin_get_plugin_stmt_data");
+ DBG_INF_FMT("plugin_id=%u", plugin_id);
+ if (!stmt || plugin_id >= mysqlnd_plugin_count()) {
+ return NULL;
+ }
+ DBG_RETURN((void *)((char *)stmt + sizeof(MYSQLND_STMT) + plugin_id * sizeof(void *)));
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_plugin_get_plugin_net_data */
+PHPAPI void ** _mysqlnd_plugin_get_plugin_net_data(const MYSQLND_NET * net, unsigned int plugin_id TSRMLS_DC)
+{
+ DBG_ENTER("_mysqlnd_plugin_get_plugin_net_data");
+ DBG_INF_FMT("plugin_id=%u", plugin_id);
+ if (!net || plugin_id >= mysqlnd_plugin_count()) {
+ return NULL;
+ }
+ DBG_RETURN((void *)((char *)net + sizeof(MYSQLND_NET) + plugin_id * sizeof(void *)));
+}
+/* }}} */
+
+
+
+/* {{{ mysqlnd_conn_get_methods */
+PHPAPI struct st_mysqlnd_conn_methods *
+mysqlnd_conn_get_methods()
+{
+ return mysqlnd_conn_methods;
+}
+/* }}} */
+
+/* {{{ mysqlnd_conn_set_methods */
+PHPAPI void mysqlnd_conn_set_methods(struct st_mysqlnd_conn_methods *methods)
+{
+ mysqlnd_conn_methods = methods;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_conn_get_methods */
+PHPAPI struct st_mysqlnd_conn_data_methods *
+mysqlnd_conn_data_get_methods()
+{
+ return mysqlnd_conn_data_methods;
+}
+/* }}} */
+
+/* {{{ mysqlnd_conn_set_methods */
+PHPAPI void mysqlnd_conn_data_set_methods(struct st_mysqlnd_conn_data_methods * methods)
+{
+ mysqlnd_conn_data_methods = methods;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_result_get_methods */
+PHPAPI struct st_mysqlnd_res_methods *
+mysqlnd_result_get_methods()
+{
+ return &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_res);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_result_set_methods */
+PHPAPI void
+mysqlnd_result_set_methods(struct st_mysqlnd_res_methods * methods)
+{
+ MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_res) = *methods;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_stmt_get_methods */
+PHPAPI struct st_mysqlnd_stmt_methods *
+mysqlnd_stmt_get_methods()
+{
+ return mysqlnd_stmt_methods;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_stmt_set_methods */
+PHPAPI void
+mysqlnd_stmt_set_methods(struct st_mysqlnd_stmt_methods *methods)
+{
+ mysqlnd_stmt_methods = methods;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_protocol_get_methods */
+PHPAPI struct st_mysqlnd_protocol_methods *
+mysqlnd_protocol_get_methods()
+{
+ return &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_protocol);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_protocol_set_methods */
+PHPAPI void
+mysqlnd_protocol_set_methods(struct st_mysqlnd_protocol_methods * methods)
+{
+ MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_protocol) = *methods;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_net_get_methods */
+PHPAPI struct st_mysqlnd_net_methods *
+mysqlnd_net_get_methods()
+{
+ return &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_net);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_net_set_methods */
+PHPAPI void
+mysqlnd_net_set_methods(struct st_mysqlnd_net_methods * methods)
+{
+ MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_net) = *methods;
+}
+/* }}} */
+
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_ext_plugin.h b/ext/mysqlnd/mysqlnd_ext_plugin.h
new file mode 100644
index 0000000000..ef9d085a9b
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_ext_plugin.h
@@ -0,0 +1,72 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+/* $Id: mysqlnd.h 318221 2011-10-19 15:04:12Z andrey $ */
+
+#ifndef MYSQLND_EXT_PLUGIN_H
+#define MYSQLND_EXT_PLUGIN_H
+
+PHPAPI void ** _mysqlnd_plugin_get_plugin_connection_data(const MYSQLND * conn, unsigned int plugin_id TSRMLS_DC);
+#define mysqlnd_plugin_get_plugin_connection_data(c, p_id) _mysqlnd_plugin_get_plugin_connection_data((c), (p_id) TSRMLS_CC)
+
+PHPAPI void ** _mysqlnd_plugin_get_plugin_connection_data_data(const MYSQLND_CONN_DATA * conn, unsigned int plugin_id TSRMLS_DC);
+#define mysqlnd_plugin_get_plugin_connection_data_data(c, p_id) _mysqlnd_plugin_get_plugin_connection_data_data((c), (p_id) TSRMLS_CC)
+
+PHPAPI void ** _mysqlnd_plugin_get_plugin_result_data(const MYSQLND_RES * result, unsigned int plugin_id TSRMLS_DC);
+#define mysqlnd_plugin_get_plugin_result_data(r, p_id) _mysqlnd_plugin_get_plugin_result_data((r), (p_id) TSRMLS_CC)
+
+PHPAPI void ** _mysqlnd_plugin_get_plugin_stmt_data(const MYSQLND_STMT * stmt, unsigned int plugin_id TSRMLS_DC);
+#define mysqlnd_plugin_get_plugin_stmt_data(s, p_id) _mysqlnd_plugin_get_plugin_stmt_data((s), (p_id) TSRMLS_CC)
+
+PHPAPI void ** _mysqlnd_plugin_get_plugin_protocol_data(const MYSQLND_PROTOCOL * protocol, unsigned int plugin_id TSRMLS_DC);
+#define mysqlnd_plugin_get_plugin_protocol_data(p, p_id) _mysqlnd_plugin_get_plugin_protocol_data((p), (p_id) TSRMLS_CC)
+
+PHPAPI void ** _mysqlnd_plugin_get_plugin_net_data(const MYSQLND_NET * net, unsigned int plugin_id TSRMLS_DC);
+#define mysqlnd_plugin_get_plugin_net_data(n, p_id) _mysqlnd_plugin_get_plugin_net_data((n), (p_id) TSRMLS_CC)
+
+
+PHPAPI struct st_mysqlnd_conn_methods * mysqlnd_conn_get_methods();
+PHPAPI void mysqlnd_conn_set_methods(struct st_mysqlnd_conn_methods * methods);
+
+PHPAPI struct st_mysqlnd_conn_data_methods * mysqlnd_conn_data_get_methods();
+PHPAPI void mysqlnd_conn_data_set_methods(struct st_mysqlnd_conn_data_methods * methods);
+
+PHPAPI struct st_mysqlnd_res_methods * mysqlnd_result_get_methods();
+PHPAPI void mysqlnd_result_set_methods(struct st_mysqlnd_res_methods * methods);
+
+PHPAPI struct st_mysqlnd_stmt_methods * mysqlnd_stmt_get_methods();
+PHPAPI void mysqlnd_stmt_set_methods(struct st_mysqlnd_stmt_methods * methods);
+
+PHPAPI struct st_mysqlnd_protocol_methods * mysqlnd_protocol_get_methods();
+PHPAPI void mysqlnd_protocol_set_methods(struct st_mysqlnd_protocol_methods * methods);
+
+PHPAPI struct st_mysqlnd_net_methods * mysqlnd_net_get_methods();
+PHPAPI void mysqlnd_net_set_methods(struct st_mysqlnd_net_methods * methods);
+
+
+#endif /* MYSQLND_EXT_PLUGIN_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_loaddata.c b/ext/mysqlnd/mysqlnd_loaddata.c
index b980c81e1d..40de45b06f 100644
--- a/ext/mysqlnd/mysqlnd_loaddata.c
+++ b/ext/mysqlnd/mysqlnd_loaddata.c
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -25,28 +25,9 @@
#include "mysqlnd_priv.h"
#include "mysqlnd_debug.h"
-
-#define ALLOC_CALLBACK_ARGS(a, b, c)\
-if (c) {\
- a = (zval ***)safe_emalloc(c, sizeof(zval **), 0);\
- for (i = b; i < c; i++) {\
- a[i] = mnd_emalloc(sizeof(zval *));\
- MAKE_STD_ZVAL(*a[i]);\
- }\
-}
-
-#define FREE_CALLBACK_ARGS(a, b, c)\
-if (a) {\
- for (i = b; i < c; i++) {\
- zval_ptr_dtor(a[i]);\
- mnd_efree(a[i]);\
- }\
- mnd_efree(a);\
-}
-
/* {{{ mysqlnd_local_infile_init */
static
-int mysqlnd_local_infile_init(void **ptr, char *filename, void **userdata TSRMLS_DC)
+int mysqlnd_local_infile_init(void ** ptr, char * filename, void ** userdata TSRMLS_DC)
{
MYSQLND_INFILE_INFO *info;
php_stream_context *context = NULL;
@@ -85,14 +66,14 @@ int mysqlnd_local_infile_init(void **ptr, char *filename, void **userdata TSRMLS
/* {{{ mysqlnd_local_infile_read */
static
-int mysqlnd_local_infile_read(void *ptr, char *buf, unsigned int buf_len TSRMLS_DC)
+int mysqlnd_local_infile_read(void * ptr, zend_uchar * buf, unsigned int buf_len TSRMLS_DC)
{
MYSQLND_INFILE_INFO *info = (MYSQLND_INFILE_INFO *)ptr;
int count;
DBG_ENTER("mysqlnd_local_infile_read");
- count = (int)php_stream_read(info->fd, buf, buf_len);
+ count = (int)php_stream_read(info->fd, (char *) buf, buf_len);
if (count < 0) {
strcpy(info->error_msg, "Error reading file");
@@ -106,7 +87,7 @@ int mysqlnd_local_infile_read(void *ptr, char *buf, unsigned int buf_len TSRMLS_
/* {{{ mysqlnd_local_infile_error */
static
-int mysqlnd_local_infile_error(void *ptr, char *error_buf, unsigned int error_buf_len TSRMLS_DC)
+int mysqlnd_local_infile_error(void * ptr, char *error_buf, unsigned int error_buf_len TSRMLS_DC)
{
MYSQLND_INFILE_INFO *info = (MYSQLND_INFILE_INFO *)ptr;
@@ -127,7 +108,7 @@ int mysqlnd_local_infile_error(void *ptr, char *error_buf, unsigned int error_bu
/* {{{ mysqlnd_local_infile_end */
static
-void mysqlnd_local_infile_end(void *ptr TSRMLS_DC)
+void mysqlnd_local_infile_end(void * ptr TSRMLS_DC)
{
MYSQLND_INFILE_INFO *info = (MYSQLND_INFILE_INFO *)ptr;
@@ -144,7 +125,8 @@ void mysqlnd_local_infile_end(void *ptr TSRMLS_DC)
/* {{{ mysqlnd_local_infile_default */
-PHPAPI void mysqlnd_local_infile_default(MYSQLND *conn)
+PHPAPI void
+mysqlnd_local_infile_default(MYSQLND_CONN_DATA * conn)
{
conn->infile.local_infile_init = mysqlnd_local_infile_init;
conn->infile.local_infile_read = mysqlnd_local_infile_read;
@@ -153,8 +135,10 @@ PHPAPI void mysqlnd_local_infile_default(MYSQLND *conn)
}
/* }}} */
+
/* {{{ mysqlnd_set_local_infile_handler */
-PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND * const conn, const char * const funcname)
+PHPAPI void
+mysqlnd_set_local_infile_handler(MYSQLND_CONN_DATA * const conn, const char * const funcname)
{
if (!conn->infile.callback) {
MAKE_STD_ZVAL(conn->infile.callback);
@@ -171,67 +155,70 @@ static const char *lost_conn = "Lost connection to MySQL server during LOAD DATA
/* {{{ mysqlnd_handle_local_infile */
enum_func_status
-mysqlnd_handle_local_infile(MYSQLND *conn, const char *filename, zend_bool *is_warning TSRMLS_DC)
+mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zend_bool * is_warning TSRMLS_DC)
{
- char *buf = NULL;
- char empty_packet[MYSQLND_HEADER_SIZE];
+ zend_uchar *buf = NULL;
+ zend_uchar empty_packet[MYSQLND_HEADER_SIZE];
enum_func_status result = FAIL;
unsigned int buflen = 4096;
void *info = NULL;
int bufsize;
size_t ret;
MYSQLND_INFILE infile;
+ MYSQLND_NET * net = conn->net;
DBG_ENTER("mysqlnd_handle_local_infile");
- if (!(conn->options.flags & CLIENT_LOCAL_FILES)) {
+ if (!(conn->options->flags & CLIENT_LOCAL_FILES)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "LOAD DATA LOCAL INFILE forbidden");
/* write empty packet to server */
- ret = conn->net->m.send(conn, empty_packet, 0 TSRMLS_CC);
+ ret = net->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info TSRMLS_CC);
*is_warning = TRUE;
goto infile_error;
}
infile = conn->infile;
/* allocate buffer for reading data */
- buf = (char *)mnd_ecalloc(1, buflen);
+ buf = (zend_uchar *) mnd_ecalloc(1, buflen);
*is_warning = FALSE;
/* init handler: allocate read buffer and open file */
if (infile.local_infile_init(&info, (char *)filename, conn->infile.userdata TSRMLS_CC)) {
+ char tmp_buf[sizeof(conn->error_info->error)];
+ int tmp_error_no;
*is_warning = TRUE;
- /* error occured */
- strcpy(conn->error_info.sqlstate, UNKNOWN_SQLSTATE);
- conn->error_info.error_no =
- infile.local_infile_error(info, conn->error_info.error, sizeof(conn->error_info.error) TSRMLS_CC);
+ /* error occurred */
+ tmp_error_no = infile.local_infile_error(info, tmp_buf, sizeof(tmp_buf) TSRMLS_CC);
+ SET_CLIENT_ERROR(*conn->error_info, tmp_error_no, UNKNOWN_SQLSTATE, tmp_buf);
/* write empty packet to server */
- ret = conn->net->m.send(conn, empty_packet, 0 TSRMLS_CC);
+ ret = net->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info TSRMLS_CC);
goto infile_error;
}
/* read data */
while ((bufsize = infile.local_infile_read (info, buf + MYSQLND_HEADER_SIZE, buflen - MYSQLND_HEADER_SIZE TSRMLS_CC)) > 0) {
- if ((ret = conn->net->m.send(conn, buf, bufsize TSRMLS_CC)) == 0) {
+ if ((ret = net->m.send_ex(net, buf, bufsize, conn->stats, conn->error_info TSRMLS_CC)) == 0) {
DBG_ERR_FMT("Error during read : %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
- SET_CLIENT_ERROR(conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
+ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
goto infile_error;
}
}
/* send empty packet for eof */
- if ((ret = conn->net->m.send(conn, empty_packet, 0 TSRMLS_CC)) == 0) {
- SET_CLIENT_ERROR(conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
+ if ((ret = net->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info TSRMLS_CC)) == 0) {
+ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
goto infile_error;
}
- /* error during read occured */
+ /* error during read occurred */
if (bufsize < 0) {
+ char tmp_buf[sizeof(conn->error_info->error)];
+ int tmp_error_no;
*is_warning = TRUE;
DBG_ERR_FMT("Bufsize < 0, warning, %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
- strcpy(conn->error_info.sqlstate, UNKNOWN_SQLSTATE);
- conn->error_info.error_no =
- infile.local_infile_error(info, conn->error_info.error, sizeof(conn->error_info.error) TSRMLS_CC);
+ tmp_error_no = infile.local_infile_error(info, tmp_buf, sizeof(tmp_buf) TSRMLS_CC);
+ SET_CLIENT_ERROR(*conn->error_info, tmp_error_no, UNKNOWN_SQLSTATE, tmp_buf);
goto infile_error;
}
diff --git a/ext/mysqlnd/mysqlnd_net.c b/ext/mysqlnd/mysqlnd_net.c
index 512c844517..21241b3ef5 100644
--- a/ext/mysqlnd/mysqlnd_net.c
+++ b/ext/mysqlnd/mysqlnd_net.c
@@ -12,11 +12,13 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
+
+/* $Id: mysqlnd_ps.c 316906 2011-09-17 10:24:18Z pajoye $ */
#include "php.h"
#include "php_globals.h"
#include "mysqlnd.h"
@@ -24,7 +26,7 @@
#include "mysqlnd_wireprotocol.h"
#include "mysqlnd_statistics.h"
#include "mysqlnd_debug.h"
-#include "ext/standard/sha1.h"
+#include "mysqlnd_ext_plugin.h"
#include "php_network.h"
#include "zend_ini.h"
#ifdef MYSQLND_COMPRESSION_ENABLED
@@ -59,48 +61,88 @@ mysqlnd_set_sock_no_delay(php_stream * stream TSRMLS_DC)
/* }}} */
-/* {{{ mysqlnd_net::network_read */
+/* {{{ mysqlnd_net::network_read_ex */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_net, network_read)(MYSQLND * conn, zend_uchar * buffer, size_t count TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_net, network_read_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count,
+ MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
{
enum_func_status return_value = PASS;
size_t to_read = count, ret;
- size_t old_chunk_size = conn->net->stream->chunk_size;
- DBG_ENTER("mysqlnd_net::network_read");
- DBG_INF_FMT("count=%u", count);
- conn->net->stream->chunk_size = MIN(to_read, conn->net->options.net_read_buffer_size);
+ size_t old_chunk_size = net->stream->chunk_size;
+ zend_uchar * p = buffer;
+
+ DBG_ENTER("mysqlnd_net::network_read_ex");
+ DBG_INF_FMT("count="MYSQLND_SZ_T_SPEC, count);
+
+ net->stream->chunk_size = MIN(to_read, net->options.net_read_buffer_size);
while (to_read) {
- if (!(ret = php_stream_read(conn->net->stream, (char *) buffer, to_read))) {
+ if (!(ret = php_stream_read(net->stream, (char *) p, to_read))) {
DBG_ERR_FMT("Error while reading header from socket");
return_value = FAIL;
break;
}
- buffer += ret;
+ p += ret;
to_read -= ret;
}
- MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_BYTES_RECEIVED, count - to_read);
- conn->net->stream->chunk_size = old_chunk_size;
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE(stats, STAT_BYTES_RECEIVED, count - to_read);
+ net->stream->chunk_size = old_chunk_size;
DBG_RETURN(return_value);
}
/* }}} */
-/* {{{ mysqlnd_net::network_write */
+/* {{{ mysqlnd_net::network_write_ex */
static size_t
-MYSQLND_METHOD(mysqlnd_net, network_write)(MYSQLND * const conn, const zend_uchar * const buf, size_t count TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_net, network_write_ex)(MYSQLND_NET * const net, const zend_uchar * const buffer, const size_t count,
+ MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
{
size_t ret;
- DBG_ENTER("mysqlnd_net::network_write");
- ret = php_stream_write(conn->net->stream, (char *)buf, count);
+ DBG_ENTER("mysqlnd_net::network_write_ex");
+ ret = php_stream_write(net->stream, (char *)buffer, count);
DBG_RETURN(ret);
}
/* }}} */
+/* {{{ mysqlnd_net::open_pipe */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_net, open_pipe)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len,
+ const zend_bool persistent,
+ MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
+{
+#if PHP_API_VERSION < 20100412
+ unsigned int streams_options = ENFORCE_SAFE_MODE;
+#else
+ unsigned int streams_options = 0;
+#endif
+ DBG_ENTER("mysqlnd_net::open_pipe");
+ if (persistent) {
+ streams_options |= STREAM_OPEN_PERSISTENT;
+ }
+ streams_options |= IGNORE_URL;
+ net->stream = php_stream_open_wrapper((char*) scheme + sizeof("pipe://") - 1, "r+", streams_options, NULL);
+ if (!net->stream) {
+ SET_CLIENT_ERROR(*error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, "Unknown errror while connecting");
+ DBG_RETURN(FAIL);
+ }
+ /*
+ Streams are not meant for C extensions! Thus we need a hack. Every connected stream will
+ be registered as resource (in EG(regular_list). So far, so good. However, it won't be
+ unregistered yntil the script ends. So, we need to take care of that.
+ */
+ net->stream->in_free = 1;
+ zend_hash_index_del(&EG(regular_list), net->stream->rsrc_id);
+ net->stream->in_free = 0;
+
+ DBG_RETURN(PASS);
+}
+/* }}} */
-/* {{{ mysqlnd_net::connect */
+/* {{{ mysqlnd_net::open_tcp_or_unix */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net, const char * const scheme, size_t scheme_len, zend_bool persistent, char **errstr, int * errcode TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len,
+ const zend_bool persistent,
+ MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
{
#if PHP_API_VERSION < 20100412
unsigned int streams_options = ENFORCE_SAFE_MODE;
@@ -110,27 +152,17 @@ MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net, const char * const schem
unsigned int streams_flags = STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT;
char * hashed_details = NULL;
int hashed_details_len = 0;
+ char * errstr = NULL;
+ int errcode = 0;
struct timeval tv;
- DBG_ENTER("mysqlnd_net::connect");
+
+ DBG_ENTER("mysqlnd_net::open_tcp_or_unix");
if (persistent) {
- hashed_details_len = spprintf(&hashed_details, 0, "%p", net);
+ hashed_details_len = mnd_sprintf(&hashed_details, 0, "%p", net);
DBG_INF_FMT("hashed_details=%s", hashed_details);
}
- net->packet_no = net->compressed_envelope_packet_no = 0;
-
- if (net->stream) {
- /* close before opening a new one */
- DBG_INF_FMT("Freeing stream. abstract=%p", net->stream->abstract);
- if (net->persistent) {
- php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR);
- } else {
- php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE);
- }
- net->stream = NULL;
- }
-
if (net->options.timeout_connect) {
tv.tv_sec = net->options.timeout_connect;
tv.tv_usec = 0;
@@ -139,16 +171,20 @@ MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net, const char * const schem
DBG_INF_FMT("calling php_stream_xport_create");
net->stream = php_stream_xport_create(scheme, scheme_len, streams_options, streams_flags,
hashed_details, (net->options.timeout_connect) ? &tv : NULL,
- NULL /*ctx*/, errstr, errcode);
-
- if (*errstr || !net->stream) {
+ NULL /*ctx*/, &errstr, &errcode);
+ if (errstr || !net->stream) {
+ DBG_ERR("Error");
if (hashed_details) {
- efree(hashed_details); /* allocated by spprintf */
+ mnd_sprintf_free(hashed_details);
+ }
+ errcode = CR_CONNECTION_ERROR;
+ SET_CLIENT_ERROR(*error_info, errcode? errcode:CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, errstr);
+ if (errstr) {
+ /* no mnd_ since we don't allocate it */
+ efree(errstr);
}
- *errcode = CR_CONNECTION_ERROR;
DBG_RETURN(FAIL);
}
-
if (hashed_details) {
/*
If persistent, the streams register it in EG(persistent_list).
@@ -171,22 +207,32 @@ MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net, const char * const schem
/* Shut-up the streams, they don't know what they are doing */
net->stream->__exposed = 1;
#endif
- efree(hashed_details);
+ mnd_sprintf_free(hashed_details);
}
+
/*
Streams are not meant for C extensions! Thus we need a hack. Every connected stream will
be registered as resource (in EG(regular_list). So far, so good. However, it won't be
- unregistered till the script ends. So, we need to take care of that.
+ unregistered yntil the script ends. So, we need to take care of that.
*/
net->stream->in_free = 1;
zend_hash_index_del(&EG(regular_list), net->stream->rsrc_id);
net->stream->in_free = 0;
- if (!net->options.timeout_read) {
- /* should always happen because read_timeout cannot be set via API */
- net->options.timeout_read = (unsigned int) MYSQLND_G(net_read_timeout);
- }
+ DBG_RETURN(PASS);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_net::connect_ex */
+static void
+MYSQLND_METHOD(mysqlnd_net, post_connect_set_opt)(MYSQLND_NET * const net,
+ const char * const scheme, const size_t scheme_len,
+ MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
+{
+ DBG_ENTER("mysqlnd_net::post_connect_set_opt");
if (net->options.timeout_read) {
+ struct timeval tv;
DBG_INF_FMT("setting %u as PHP_STREAM_OPTION_READ_TIMEOUT", net->options.timeout_read);
tv.tv_sec = net->options.timeout_read;
tv.tv_usec = 0;
@@ -198,13 +244,33 @@ MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net, const char * const schem
mysqlnd_set_sock_no_delay(net->stream TSRMLS_CC);
}
- {
- unsigned int buf_size = MYSQLND_G(net_read_buffer_size); /* this is long, cast to unsigned int*/
- net->m.set_client_option(net, MYSQLND_OPT_NET_READ_BUFFER_SIZE, (char *)&buf_size TSRMLS_CC);
- }
+ DBG_VOID_RETURN;
+}
+/* }}} */
- DBG_RETURN(PASS);
+/* {{{ mysqlnd_net::connect_ex */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_net, connect_ex)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len,
+ const zend_bool persistent,
+ MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
+{
+ enum_func_status ret = FAIL;
+ func_mysqlnd_net__open_stream open_stream = NULL;
+ DBG_ENTER("mysqlnd_net::connect_ex");
+
+ net->packet_no = net->compressed_envelope_packet_no = 0;
+
+ net->m.close_stream(net, conn_stats, error_info TSRMLS_CC);
+
+ open_stream = (scheme_len > (sizeof("pipe://") - 1) && !memcmp(scheme, "pipe://", sizeof("pipe://") - 1))? net->m.open_pipe:
+ net->m.open_tcp_or_unix;
+
+ if (PASS == (ret = open_stream(net, scheme, scheme_len, persistent, conn_stats, error_info TSRMLS_CC))) {
+ net->m.post_connect_set_opt(net, scheme, scheme_len, conn_stats, error_info TSRMLS_CC);
+ }
+
+ DBG_RETURN(ret);
}
/* }}} */
@@ -218,34 +284,32 @@ MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net, const char * const schem
#define STORE_HEADER_SIZE(safe_storage, buffer) COPY_HEADER((safe_storage), (buffer))
#define RESTORE_HEADER_SIZE(buffer, safe_storage) STORE_HEADER_SIZE((safe_storage), (buffer))
-/* {{{ mysqlnd_net::send */
+
+/* {{{ mysqlnd_net::send_ex */
/*
- IMPORTANT : It's expected that buf has place in the beginning for MYSQLND_HEADER_SIZE !!!!
+ IMPORTANT : It's expected that buffer has place in the beginning for MYSQLND_HEADER_SIZE !!!!
This is done for performance reasons in the caller of this function.
Otherwise we will have to do send two TCP packets, or do new alloc and memcpy.
Neither are quick, thus the clients of this function are obligated to do
what they are asked for.
`count` is actually the length of the payload data. Thus :
- count + MYSQLND_HEADER_SIZE = sizeof(buf) (not the pointer but the actual buffer)
+ count + MYSQLND_HEADER_SIZE = sizeof(buffer) (not the pointer but the actual buffer)
*/
-size_t
-MYSQLND_METHOD(mysqlnd_net, send)(MYSQLND * const conn, char * const buf, size_t count TSRMLS_DC)
+static size_t
+MYSQLND_METHOD(mysqlnd_net, send_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count,
+ MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
{
zend_uchar safe_buf[((MYSQLND_HEADER_SIZE) + (sizeof(zend_uchar)) - 1) / (sizeof(zend_uchar))];
- zend_uchar *safe_storage = safe_buf;
- MYSQLND_NET *net = conn->net;
- size_t old_chunk_size = net->stream->chunk_size;
- size_t ret, packets_sent = 1;
+ zend_uchar * safe_storage = safe_buf;
+ size_t bytes_sent, packets_sent = 1;
size_t left = count;
- zend_uchar *p = (zend_uchar *) buf;
+ zend_uchar * p = (zend_uchar *) buffer;
zend_uchar * compress_buf = NULL;
size_t to_be_sent;
- DBG_ENTER("mysqlnd_net::send");
- DBG_INF_FMT("conn=%llu count=%lu compression=%u", conn->thread_id, count, net->compressed);
-
- net->stream->chunk_size = MYSQLND_MAX_PACKET_SIZE;
+ DBG_ENTER("mysqlnd_net::send_ex");
+ DBG_INF_FMT("count=" MYSQLND_SZ_T_SPEC " compression=%u", count, net->compressed);
if (net->compressed == TRUE) {
size_t comp_buf_size = MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE + MYSQLND_HEADER_SIZE + MIN(left, MYSQLND_MAX_PACKET_SIZE);
@@ -280,7 +344,8 @@ MYSQLND_METHOD(mysqlnd_net, send)(MYSQLND * const conn, char * const buf, size_t
int3store(compress_buf, payload_size);
int1store(compress_buf + 3, net->packet_no);
DBG_INF_FMT("writing "MYSQLND_SZ_T_SPEC" bytes to the network", payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE);
- ret = conn->net->m.network_write(conn, compress_buf, payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE TSRMLS_CC);
+ bytes_sent = net->m.network_write_ex(net, compress_buf, payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE,
+ conn_stats, error_info TSRMLS_CC);
net->compressed_envelope_packet_no++;
#if WHEN_WE_NEED_TO_CHECK_WHETHER_COMPRESSION_WORKS_CORRECTLY
if (res == Z_OK) {
@@ -311,7 +376,7 @@ MYSQLND_METHOD(mysqlnd_net, send)(MYSQLND * const conn, char * const buf, size_t
STORE_HEADER_SIZE(safe_storage, p);
int3store(p, to_be_sent);
int1store(p + 3, net->packet_no);
- ret = conn->net->m.network_write(conn, p, to_be_sent + MYSQLND_HEADER_SIZE TSRMLS_CC);
+ bytes_sent = net->m.network_write_ex(net, p, to_be_sent + MYSQLND_HEADER_SIZE, conn_stats, error_info TSRMLS_CC);
RESTORE_HEADER_SIZE(p, safe_storage);
net->compressed_envelope_packet_no++;
}
@@ -327,26 +392,25 @@ MYSQLND_METHOD(mysqlnd_net, send)(MYSQLND * const conn, char * const buf, size_t
indeed it then loop once more, then to_be_sent will become 0, left will stay 0. Empty
packet will be sent and this loop will end.
*/
- } while (ret && (left > 0 || to_be_sent == MYSQLND_MAX_PACKET_SIZE));
+ } while (bytes_sent && (left > 0 || to_be_sent == MYSQLND_MAX_PACKET_SIZE));
DBG_INF_FMT("packet_size="MYSQLND_SZ_T_SPEC" packet_no=%u", left, net->packet_no);
- /* Even for zero size payload we have to send a packet */
- if (!ret) {
- DBG_ERR_FMT("Can't %u send bytes", count);
- conn->state = CONN_QUIT_SENT;
- SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
- }
- MYSQLND_INC_CONN_STATISTIC_W_VALUE3(conn->stats,
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE3(conn_stats,
STAT_BYTES_SENT, count + packets_sent * MYSQLND_HEADER_SIZE,
STAT_PROTOCOL_OVERHEAD_OUT, packets_sent * MYSQLND_HEADER_SIZE,
STAT_PACKETS_SENT, packets_sent);
- net->stream->chunk_size = old_chunk_size;
if (compress_buf) {
mnd_efree(compress_buf);
}
- DBG_RETURN(ret);
+
+ /* Even for zero size payload we have to send a packet */
+ if (!bytes_sent) {
+ DBG_ERR_FMT("Can't %u send bytes", count);
+ SET_CLIENT_ERROR(*error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ }
+ DBG_RETURN(bytes_sent);
}
/* }}} */
@@ -416,19 +480,19 @@ mysqlnd_create_read_buffer(size_t count TSRMLS_DC)
/* }}} */
-/* {{{ mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer */
+/* {{{ mysqlnd_net::read_compressed_packet_from_stream_and_fill_read_buffer */
static enum_func_status
-mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer(MYSQLND * conn, size_t net_payload_size TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_net, read_compressed_packet_from_stream_and_fill_read_buffer)
+ (MYSQLND_NET * net, size_t net_payload_size, MYSQLND_STATS * conn_stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC)
{
- MYSQLND_NET * net = conn->net;
size_t decompressed_size;
enum_func_status ret = PASS;
zend_uchar * compressed_data = NULL;
zend_uchar comp_header[COMPRESSED_HEADER_SIZE];
- DBG_ENTER("mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer");
+ DBG_ENTER("mysqlnd_net::read_compressed_packet_from_stream_and_fill_read_buffe");
/* Read the compressed header */
- if (FAIL == conn->net->m.network_read(conn, comp_header, COMPRESSED_HEADER_SIZE TSRMLS_CC)) {
+ if (FAIL == net->m.network_read_ex(net, comp_header, COMPRESSED_HEADER_SIZE, conn_stats, error_info TSRMLS_CC)) {
DBG_RETURN(FAIL);
}
decompressed_size = uint3korr(comp_header);
@@ -438,7 +502,7 @@ mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer(MYSQLND * conn,
if (decompressed_size) {
compressed_data = mnd_emalloc(net_payload_size);
- if (FAIL == conn->net->m.network_read(conn, compressed_data, net_payload_size TSRMLS_CC)) {
+ if (FAIL == net->m.network_read_ex(net, compressed_data, net_payload_size, conn_stats, error_info TSRMLS_CC)) {
ret = FAIL;
goto end;
}
@@ -450,7 +514,7 @@ mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer(MYSQLND * conn,
} else {
DBG_INF_FMT("The server decided not to compress the data. Our job is easy. Copying %u bytes", net_payload_size);
net->uncompressed_data = mysqlnd_create_read_buffer(net_payload_size TSRMLS_CC);
- if (FAIL == conn->net->m.network_read(conn, net->uncompressed_data->data, net_payload_size TSRMLS_CC)) {
+ if (FAIL == net->m.network_read_ex(net, net->uncompressed_data->data, net_payload_size, conn_stats, error_info TSRMLS_CC)) {
ret = FAIL;
goto end;
}
@@ -467,8 +531,8 @@ end:
/* {{{ mysqlnd_net::decode */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_net, decode)(zend_uchar * uncompressed_data, size_t uncompressed_data_len,
- const zend_uchar * const compressed_data, size_t compressed_data_len TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_net, decode)(zend_uchar * uncompressed_data, const size_t uncompressed_data_len,
+ const zend_uchar * const compressed_data, const size_t compressed_data_len TSRMLS_DC)
{
#ifdef MYSQLND_COMPRESSION_ENABLED
int error;
@@ -492,7 +556,7 @@ MYSQLND_METHOD(mysqlnd_net, decode)(zend_uchar * uncompressed_data, size_t uncom
/* {{{ mysqlnd_net::encode */
static enum_func_status
MYSQLND_METHOD(mysqlnd_net, encode)(zend_uchar * compress_buffer, size_t * compress_buffer_len,
- const zend_uchar * const uncompressed_data, size_t uncompressed_data_len TSRMLS_DC)
+ const zend_uchar * const uncompressed_data, const size_t uncompressed_data_len TSRMLS_DC)
{
#ifdef MYSQLND_COMPRESSION_ENABLED
int error;
@@ -516,15 +580,15 @@ MYSQLND_METHOD(mysqlnd_net, encode)(zend_uchar * compress_buffer, size_t * compr
/* }}} */
-/* {{{ mysqlnd_net::receive */
+/* {{{ mysqlnd_net::receive_ex */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_net, receive)(MYSQLND * conn, zend_uchar * buffer, size_t count TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_net, receive_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count,
+ MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
{
size_t to_read = count;
zend_uchar * p = buffer;
- MYSQLND_NET * net = conn->net;
- DBG_ENTER("mysqlnd_net::receive");
+ DBG_ENTER("mysqlnd_net::receive_ex");
#ifdef MYSQLND_COMPRESSION_ENABLED
if (net->compressed) {
if (net->uncompressed_data) {
@@ -546,7 +610,7 @@ MYSQLND_METHOD(mysqlnd_net, receive)(MYSQLND * conn, zend_uchar * buffer, size_t
size_t net_payload_size;
zend_uchar packet_no;
- if (FAIL == net->m.network_read(conn, net_header, MYSQLND_HEADER_SIZE TSRMLS_CC)) {
+ if (FAIL == net->m.network_read_ex(net, net_header, MYSQLND_HEADER_SIZE, conn_stats, error_info TSRMLS_CC)) {
DBG_RETURN(FAIL);
}
net_payload_size = uint3korr(net_header);
@@ -564,7 +628,7 @@ MYSQLND_METHOD(mysqlnd_net, receive)(MYSQLND * conn, zend_uchar * buffer, size_t
DBG_INF_FMT("HEADER: hwd_packet_no=%u size=%3u", packet_no, (unsigned long) net_payload_size);
#endif
/* Now let's read from the wire, decompress it and fill the read buffer */
- mysqlnd_read_compressed_packet_from_stream_and_fill_read_buffer(conn, net_payload_size TSRMLS_CC);
+ net->m.read_compressed_packet_from_stream_and_fill_read_buffer(net, net_payload_size, conn_stats, error_info TSRMLS_CC);
/*
Now a bit of recursion - read from the read buffer,
@@ -572,12 +636,12 @@ MYSQLND_METHOD(mysqlnd_net, receive)(MYSQLND * conn, zend_uchar * buffer, size_t
is not enough, then the recursive call will try to
satisfy it until it is satisfied.
*/
- DBG_RETURN(net->m.receive(conn, p, to_read TSRMLS_CC));
+ DBG_RETURN(net->m.receive_ex(net, p, to_read, conn_stats, error_info TSRMLS_CC));
}
DBG_RETURN(PASS);
}
#endif /* MYSQLND_COMPRESSION_ENABLED */
- DBG_RETURN(net->m.network_read(conn, p, to_read TSRMLS_CC));
+ DBG_RETURN(net->m.network_read_ex(net, p, to_read, conn_stats, error_info TSRMLS_CC));
}
/* }}} */
@@ -668,13 +732,11 @@ MYSQLND_METHOD(mysqlnd_net, set_client_option)(MYSQLND_NET * const net, enum mys
case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
net->options.ssl_verify_peer = value? ((*(zend_bool *)value)? TRUE:FALSE): FALSE;
break;
-#ifdef WHEN_SUPPORTED_BY_MYSQLI
case MYSQL_OPT_READ_TIMEOUT:
- DBG_INF("MYSQL_OPT_READ_TIMEOUT");
net->options.timeout_read = *(unsigned int*) value;
break;
+#ifdef WHEN_SUPPORTED_BY_MYSQLI
case MYSQL_OPT_WRITE_TIMEOUT:
- DBG_INF("MYSQL_OPT_WRITE_TIMEOUT");
net->options.timeout_write = *(unsigned int*) value;
break;
#endif
@@ -744,7 +806,7 @@ static enum_func_status
MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
{
#ifdef MYSQLND_SSL_SUPPORTED
- php_stream_context *context = php_stream_context_alloc();
+ php_stream_context *context = php_stream_context_alloc(TSRMLS_C);
DBG_ENTER("mysqlnd_net::enable_ssl");
if (!context) {
DBG_RETURN(FAIL);
@@ -753,19 +815,16 @@ MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
if (net->options.ssl_key) {
zval key_zval;
ZVAL_STRING(&key_zval, net->options.ssl_key, 0);
- DBG_INF("key");
php_stream_context_set_option(context, "ssl", "local_pk", &key_zval);
}
if (net->options.ssl_verify_peer) {
zval verify_peer_zval;
ZVAL_TRUE(&verify_peer_zval);
- DBG_INF("verify peer");
php_stream_context_set_option(context, "ssl", "verify_peer", &verify_peer_zval);
}
if (net->options.ssl_cert) {
zval cert_zval;
ZVAL_STRING(&cert_zval, net->options.ssl_cert, 0);
- DBG_INF_FMT("local_cert=%s", net->options.ssl_cert);
php_stream_context_set_option(context, "ssl", "local_cert", &cert_zval);
if (!net->options.ssl_key) {
php_stream_context_set_option(context, "ssl", "local_pk", &cert_zval);
@@ -774,13 +833,11 @@ MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
if (net->options.ssl_ca) {
zval cafile_zval;
ZVAL_STRING(&cafile_zval, net->options.ssl_ca, 0);
- DBG_INF_FMT("cafile=%s", net->options.ssl_ca);
php_stream_context_set_option(context, "ssl", "cafile", &cafile_zval);
}
if (net->options.ssl_capath) {
zval capath_zval;
ZVAL_STRING(&capath_zval, net->options.ssl_capath, 0);
- DBG_INF_FMT("capath=%s", net->options.ssl_capath);
php_stream_context_set_option(context, "ssl", "cafile", &capath_zval);
}
if (net->options.ssl_passphrase) {
@@ -791,7 +848,6 @@ MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
if (net->options.ssl_cipher) {
zval cipher_zval;
ZVAL_STRING(&cipher_zval, net->options.ssl_cipher, 0);
- DBG_INF_FMT("ciphers=%s", net->options.ssl_cipher);
php_stream_context_set_option(context, "ssl", "ciphers", &cipher_zval);
}
php_stream_context_set(net->stream, context);
@@ -838,7 +894,7 @@ MYSQLND_METHOD(mysqlnd_net, disable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
/* }}} */
-/* {{{ mysqlnd_net::set_client_option */
+/* {{{ mysqlnd_net::free_contents */
static void
MYSQLND_METHOD(mysqlnd_net, free_contents)(MYSQLND_NET * net TSRMLS_DC)
{
@@ -875,70 +931,72 @@ MYSQLND_METHOD(mysqlnd_net, free_contents)(MYSQLND_NET * net TSRMLS_DC)
}
/* }}} */
-static
-MYSQLND_CLASS_METHODS_START(mysqlnd_net)
- MYSQLND_METHOD(mysqlnd_net, connect),
- MYSQLND_METHOD(mysqlnd_net, send),
- MYSQLND_METHOD(mysqlnd_net, receive),
- MYSQLND_METHOD(mysqlnd_net, set_client_option),
- MYSQLND_METHOD(mysqlnd_net, network_read),
- MYSQLND_METHOD(mysqlnd_net, network_write),
- MYSQLND_METHOD(mysqlnd_net, decode),
- MYSQLND_METHOD(mysqlnd_net, encode),
- MYSQLND_METHOD(mysqlnd_net, consume_uneaten_data),
- MYSQLND_METHOD(mysqlnd_net, free_contents),
- MYSQLND_METHOD(mysqlnd_net, enable_ssl),
- MYSQLND_METHOD(mysqlnd_net, disable_ssl)
-MYSQLND_CLASS_METHODS_END;
-
-/* {{{ mysqlnd_net_init */
-PHPAPI MYSQLND_NET *
-mysqlnd_net_init(zend_bool persistent TSRMLS_DC)
+/* {{{ mysqlnd_net::close_stream */
+static void
+MYSQLND_METHOD(mysqlnd_net, close_stream)(MYSQLND_NET * const net, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
{
- size_t alloc_size = sizeof(MYSQLND_NET) + mysqlnd_plugin_count() * sizeof(void *);
- MYSQLND_NET * net = mnd_pecalloc(1, alloc_size, persistent);
-
- DBG_ENTER("mysqlnd_net_init");
- DBG_INF_FMT("persistent=%u", persistent);
- if (net) {
- net->persistent = persistent;
- net->m = mysqlnd_mysqlnd_net_methods;
-
- {
- unsigned int buf_size = MYSQLND_G(net_cmd_buffer_size); /* this is long, cast to unsigned int*/
- net->m.set_client_option(net, MYSQLND_OPT_NET_CMD_BUFFER_SIZE, (char *) &buf_size TSRMLS_CC);
+ DBG_ENTER("mysqlnd_net::close_stream");
+ if (net && net->stream) {
+ zend_bool pers = net->persistent;
+ DBG_INF_FMT("Freeing stream. abstract=%p", net->stream->abstract);
+ if (pers) {
+ if (EG(active)) {
+ php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR);
+ } else {
+ /*
+ otherwise we will crash because the EG(persistent_list) has been freed already,
+ before the modules are shut down
+ */
+ php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR);
+ }
+ } else {
+ php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE);
}
+ net->stream = NULL;
}
- DBG_RETURN(net);
+
+ DBG_VOID_RETURN;
}
/* }}} */
-/* {{{ mysqlnd_net_free */
-PHPAPI void
-mysqlnd_net_free(MYSQLND_NET * const net TSRMLS_DC)
+/* {{{ mysqlnd_net::init */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_net, init)(MYSQLND_NET * const net, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
{
- DBG_ENTER("mysqlnd_net_free");
+ unsigned int buf_size;
+ DBG_ENTER("mysqlnd_net::init");
+
+ buf_size = MYSQLND_G(net_cmd_buffer_size); /* this is long, cast to unsigned int*/
+ net->m.set_client_option(net, MYSQLND_OPT_NET_CMD_BUFFER_SIZE, (char *) &buf_size TSRMLS_CC);
+
+ buf_size = MYSQLND_G(net_read_buffer_size); /* this is long, cast to unsigned int*/
+ net->m.set_client_option(net, MYSQLND_OPT_NET_READ_BUFFER_SIZE, (char *)&buf_size TSRMLS_CC);
+ buf_size = MYSQLND_G(net_read_timeout); /* this is long, cast to unsigned int*/
+ net->m.set_client_option(net, MYSQL_OPT_READ_TIMEOUT, (char *)&buf_size TSRMLS_CC);
+
+ DBG_RETURN(PASS);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_net::dtor */
+static void
+MYSQLND_METHOD(mysqlnd_net, dtor)(MYSQLND_NET * const net, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC)
+{
+ DBG_ENTER("mysqlnd_net::dtor");
if (net) {
zend_bool pers = net->persistent;
-
+
net->m.free_contents(net TSRMLS_CC);
+ net->m.close_stream(net, stats, error_info TSRMLS_CC);
if (net->cmd_buffer.buffer) {
DBG_INF("Freeing cmd buffer");
mnd_pefree(net->cmd_buffer.buffer, pers);
net->cmd_buffer.buffer = NULL;
}
- if (net->stream) {
- DBG_INF_FMT("Freeing stream. abstract=%p", net->stream->abstract);
- if (pers) {
- php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR);
- } else {
- php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE);
- }
- net->stream = NULL;
- }
mnd_pefree(net, pers);
}
DBG_VOID_RETURN;
@@ -946,28 +1004,61 @@ mysqlnd_net_free(MYSQLND_NET * const net TSRMLS_DC)
/* }}} */
-/* {{{ _mysqlnd_plugin_get_plugin_net_data */
-PHPAPI void ** _mysqlnd_plugin_get_plugin_net_data(const MYSQLND_NET * net, unsigned int plugin_id TSRMLS_DC)
+MYSQLND_CLASS_METHODS_START(mysqlnd_net)
+ MYSQLND_METHOD(mysqlnd_net, init),
+ MYSQLND_METHOD(mysqlnd_net, dtor),
+ MYSQLND_METHOD(mysqlnd_net, connect_ex),
+ MYSQLND_METHOD(mysqlnd_net, close_stream),
+ MYSQLND_METHOD(mysqlnd_net, open_pipe),
+ MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix),
+ NULL, /* unused 1 */
+ NULL, /* unused 2 */
+ MYSQLND_METHOD(mysqlnd_net, post_connect_set_opt),
+ MYSQLND_METHOD(mysqlnd_net, set_client_option),
+ MYSQLND_METHOD(mysqlnd_net, decode),
+ MYSQLND_METHOD(mysqlnd_net, encode),
+ MYSQLND_METHOD(mysqlnd_net, consume_uneaten_data),
+ MYSQLND_METHOD(mysqlnd_net, free_contents),
+ MYSQLND_METHOD(mysqlnd_net, enable_ssl),
+ MYSQLND_METHOD(mysqlnd_net, disable_ssl),
+ MYSQLND_METHOD(mysqlnd_net, network_read_ex),
+ MYSQLND_METHOD(mysqlnd_net, network_write_ex),
+ MYSQLND_METHOD(mysqlnd_net, send_ex),
+ MYSQLND_METHOD(mysqlnd_net, receive_ex),
+#ifdef MYSQLND_COMPRESSION_ENABLED
+ MYSQLND_METHOD(mysqlnd_net, read_compressed_packet_from_stream_and_fill_read_buffer)
+#else
+ NULL
+#endif
+MYSQLND_CLASS_METHODS_END;
+
+
+/* {{{ mysqlnd_net_init */
+PHPAPI MYSQLND_NET *
+mysqlnd_net_init(zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC)
{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_net_data");
- DBG_INF_FMT("plugin_id=%u", plugin_id);
- if (!net || plugin_id >= mysqlnd_plugin_count()) {
- return NULL;
- }
- DBG_RETURN((void *)((char *)net + sizeof(MYSQLND_NET) + plugin_id * sizeof(void *)));
+ MYSQLND_NET * net;
+ DBG_ENTER("mysqlnd_net_init");
+ net = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_io_channel(persistent, stats, error_info TSRMLS_CC);
+ DBG_RETURN(net);
}
/* }}} */
-/* {{{ mysqlnd_net_get_methods */
-PHPAPI struct st_mysqlnd_net_methods *
-mysqlnd_net_get_methods()
+/* {{{ mysqlnd_net_free */
+PHPAPI void
+mysqlnd_net_free(MYSQLND_NET * const net, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC)
{
- return &mysqlnd_mysqlnd_net_methods;
+ DBG_ENTER("mysqlnd_net_free");
+ if (net) {
+ net->m.dtor(net, stats, error_info TSRMLS_CC);
+ }
+ DBG_VOID_RETURN;
}
/* }}} */
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/mysqlnd/mysqlnd_net.h b/ext/mysqlnd/mysqlnd_net.h
index 4c20111a66..568a0e18b2 100644
--- a/ext/mysqlnd/mysqlnd_net.h
+++ b/ext/mysqlnd/mysqlnd_net.h
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -23,10 +23,8 @@
#ifndef MYSQLND_NET_H
#define MYSQLND_NET_H
-PHPAPI MYSQLND_NET * mysqlnd_net_init(zend_bool persistent TSRMLS_DC);
-PHPAPI void mysqlnd_net_free(MYSQLND_NET * const net TSRMLS_DC);
-
-PHPAPI struct st_mysqlnd_net_methods * mysqlnd_net_get_methods();
+PHPAPI MYSQLND_NET * mysqlnd_net_init(zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC);
+PHPAPI void mysqlnd_net_free(MYSQLND_NET * const net, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC);
#endif /* MYSQLND_NET_H */
diff --git a/ext/mysqlnd/mysqlnd_plugin.c b/ext/mysqlnd/mysqlnd_plugin.c
new file mode 100644
index 0000000000..f32fe4afdc
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_plugin.c
@@ -0,0 +1,209 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd.c 306407 2010-12-16 12:56:19Z andrey $ */
+#include "php.h"
+#include "mysqlnd.h"
+#include "mysqlnd_priv.h"
+#include "mysqlnd_statistics.h"
+#include "mysqlnd_debug.h"
+
+/*--------------------------------------------------------------------*/
+
+static enum_func_status mysqlnd_example_plugin_end(void * p TSRMLS_DC);
+
+static MYSQLND_STATS * mysqlnd_plugin_example_stats = NULL;
+
+enum mysqlnd_plugin_example_collected_stats
+{
+ EXAMPLE_STAT1,
+ EXAMPLE_STAT2,
+ EXAMPLE_STAT_LAST
+};
+
+static const MYSQLND_STRING mysqlnd_plugin_example_stats_values_names[EXAMPLE_STAT_LAST] =
+{
+ { MYSQLND_STR_W_LEN("stat1") },
+ { MYSQLND_STR_W_LEN("stat2") }
+};
+
+static struct st_mysqlnd_typeii_plugin_example mysqlnd_example_plugin =
+{
+ {
+ MYSQLND_PLUGIN_API_VERSION,
+ "example",
+ 10001L,
+ "1.00.01",
+ "PHP License",
+ "Andrey Hristov <andrey@php.net>",
+ {
+ NULL, /* will be filled later */
+ mysqlnd_plugin_example_stats_values_names,
+ },
+ {
+ mysqlnd_example_plugin_end
+ }
+ },
+ NULL, /* methods */
+};
+
+
+/* {{{ mysqlnd_example_plugin_end */
+static
+enum_func_status mysqlnd_example_plugin_end(void * p TSRMLS_DC)
+{
+ struct st_mysqlnd_typeii_plugin_example * plugin = (struct st_mysqlnd_typeii_plugin_example *) p;
+ DBG_ENTER("mysqlnd_example_plugin_end");
+ mysqlnd_stats_end(plugin->plugin_header.plugin_stats.values);
+ plugin->plugin_header.plugin_stats.values = NULL;
+ DBG_RETURN(PASS);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_example_plugin_register */
+void
+mysqlnd_example_plugin_register(TSRMLS_D)
+{
+ mysqlnd_stats_init(&mysqlnd_plugin_example_stats, EXAMPLE_STAT_LAST);
+ mysqlnd_example_plugin.plugin_header.plugin_stats.values = mysqlnd_plugin_example_stats;
+ mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_example_plugin TSRMLS_CC);
+}
+/* }}} */
+
+/*--------------------------------------------------------------------*/
+
+static HashTable mysqlnd_registered_plugins;
+
+static unsigned int mysqlnd_plugins_counter = 0;
+
+
+/* {{{ mysqlnd_plugin_subsystem_init */
+void
+mysqlnd_plugin_subsystem_init(TSRMLS_D)
+{
+ zend_hash_init(&mysqlnd_registered_plugins, 4 /* initial hash size */, NULL /* hash_func */, NULL /* dtor */, TRUE /* pers */);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_plugin_end_apply_func */
+int
+mysqlnd_plugin_end_apply_func(void *pDest TSRMLS_DC)
+{
+ struct st_mysqlnd_plugin_header * plugin_header = *(struct st_mysqlnd_plugin_header **) pDest;
+ if (plugin_header->m.plugin_shutdown) {
+ plugin_header->m.plugin_shutdown(plugin_header TSRMLS_CC);
+ }
+ return ZEND_HASH_APPLY_REMOVE;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_plugin_subsystem_end */
+void
+mysqlnd_plugin_subsystem_end(TSRMLS_D)
+{
+ zend_hash_apply(&mysqlnd_registered_plugins, mysqlnd_plugin_end_apply_func TSRMLS_CC);
+ zend_hash_destroy(&mysqlnd_registered_plugins);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_plugin_register */
+PHPAPI unsigned int mysqlnd_plugin_register()
+{
+ TSRMLS_FETCH();
+ return mysqlnd_plugin_register_ex(NULL TSRMLS_CC);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_plugin_register_ex */
+PHPAPI unsigned int mysqlnd_plugin_register_ex(struct st_mysqlnd_plugin_header * plugin TSRMLS_DC)
+{
+ if (plugin) {
+ if (plugin->plugin_api_version == MYSQLND_PLUGIN_API_VERSION) {
+ zend_hash_update(&mysqlnd_registered_plugins, plugin->plugin_name, strlen(plugin->plugin_name) + 1, &plugin, sizeof(void *), NULL);
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Plugin API version mismatch while loading plugin %s. Expected %d, got %d",
+ plugin->plugin_name, MYSQLND_PLUGIN_API_VERSION, plugin->plugin_api_version);
+ return 0xCAFE;
+ }
+ }
+ return mysqlnd_plugins_counter++;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_plugin_find */
+PHPAPI void * _mysqlnd_plugin_find(const char * const name TSRMLS_DC)
+{
+ void * plugin;
+ if (SUCCESS == zend_hash_find(&mysqlnd_registered_plugins, name, strlen(name) + 1, (void **) &plugin)) {
+ return (void *)*(char **) plugin;
+ }
+ return NULL;
+
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_plugin_apply_with_argument */
+PHPAPI void _mysqlnd_plugin_apply_with_argument(apply_func_arg_t apply_func, void * argument TSRMLS_DC)
+{
+ /* Note: We want to be thread-safe (read-only), so we can use neither
+ * zend_hash_apply_with_argument nor zend_hash_internal_pointer_reset and
+ * friends
+ */
+ Bucket *p;
+
+ p = mysqlnd_registered_plugins.pListHead;
+ while (p != NULL) {
+ int result = apply_func(p->pData, argument TSRMLS_CC);
+
+ if (result & ZEND_HASH_APPLY_REMOVE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "mysqlnd_plugin_apply_with_argument must not remove table entries");
+ }
+ p = p->pListNext;
+ if (result & ZEND_HASH_APPLY_STOP) {
+ break;
+ }
+ }
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_plugin_count */
+PHPAPI unsigned int mysqlnd_plugin_count()
+{
+ return mysqlnd_plugins_counter;
+}
+/* }}} */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_priv.h b/ext/mysqlnd/mysqlnd_priv.h
index 336e73acb1..190ed697b6 100644
--- a/ext/mysqlnd/mysqlnd_priv.h
+++ b/ext/mysqlnd/mysqlnd_priv.h
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -47,10 +47,6 @@
#define pestrndup(s, length, persistent) ((persistent)?zend_strndup((s),(length)):estrndup((s),(length)))
#endif
-#define MYSQLND_CLASS_METHOD_TABLE_NAME(class) mysqlnd_##class##_methods
-#define MYSQLND_CLASS_METHODS_START(class) struct st_##class##_methods MYSQLND_CLASS_METHOD_TABLE_NAME(class) = {
-#define MYSQLND_CLASS_METHODS_END }
-
#if MYSQLND_UNICODE
#define mysqlnd_array_init(arg, field_count) \
{ \
@@ -67,6 +63,7 @@
}
#endif
+#define MYSQLND_STR_W_LEN(str) str, (sizeof(str) - 1)
#define MYSQLND_DEBUG_DUMP_TIME 1
#define MYSQLND_DEBUG_DUMP_TRACE 2
@@ -102,7 +99,7 @@
#define MAX_CHARSET_LEN 32
-#define SET_ERROR_AFF_ROWS(s) (s)->upsert_status.affected_rows = (uint64_t) ~0
+#define SET_ERROR_AFF_ROWS(s) (s)->upsert_status->affected_rows = (uint64_t) ~0
/* Error handling */
#define SET_NEW_MESSAGE(buf, buf_len, message, len, persistent) \
@@ -133,19 +130,45 @@
(error_info).error_no = 0; \
(error_info).error[0] = '\0'; \
strlcpy((error_info).sqlstate, "00000", sizeof((error_info).sqlstate)); \
+ if ((error_info).error_list) { \
+ zend_llist_clean((error_info).error_list); \
+ } \
}
+
#define SET_CLIENT_ERROR(error_info, a, b, c) \
- { \
+{ \
+ if (0 == (a)) { \
+ SET_EMPTY_ERROR((error_info)); \
+ } else { \
(error_info).error_no = (a); \
strlcpy((error_info).sqlstate, (b), sizeof((error_info).sqlstate)); \
strlcpy((error_info).error, (c), sizeof((error_info).error)); \
+ if ((error_info).error_list) {\
+ MYSQLND_ERROR_LIST_ELEMENT error_for_the_list = {0}; \
+ \
+ error_for_the_list.error_no = (a); \
+ strlcpy(error_for_the_list.sqlstate, (b), sizeof(error_for_the_list.sqlstate)); \
+ error_for_the_list.error = mnd_pestrdup((c), TRUE); \
+ if (error_for_the_list.error) { \
+ DBG_INF_FMT("adding error [%s] to the list", error_for_the_list.error); \
+ zend_llist_add_element((error_info).error_list, &error_for_the_list); \
+ } \
+ } \
+ } \
+}
+
+
+#define COPY_CLIENT_ERROR(error_info_to, error_info_from) \
+ { \
+ SET_CLIENT_ERROR((error_info_to), (error_info_from).error_no, (error_info_from).sqlstate, (error_info_from).error); \
}
+
#define SET_OOM_ERROR(error_info) SET_CLIENT_ERROR((error_info), CR_OUT_OF_MEMORY, UNKNOWN_SQLSTATE, mysqlnd_out_of_memory)
-#define SET_STMT_ERROR(stmt, a, b, c) SET_CLIENT_ERROR((stmt)->error_info, a, b, c)
+#define SET_STMT_ERROR(stmt, a, b, c) SET_CLIENT_ERROR(*(stmt)->error_info, a, b, c)
#define CONN_GET_STATE(c) (c)->m->get_state((c) TSRMLS_CC)
#define CONN_SET_STATE(c, s) (c)->m->set_state((c), (s) TSRMLS_CC)
@@ -170,7 +193,14 @@ PHPAPI extern const char * const mysqlnd_out_of_sync;
PHPAPI extern const char * const mysqlnd_server_gone;
PHPAPI extern const char * const mysqlnd_out_of_memory;
-enum_func_status mysqlnd_handle_local_infile(MYSQLND *conn, const char *filename, zend_bool *is_warning TSRMLS_DC);
+extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_object_factory);
+extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_conn);
+extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_conn_data);
+extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_res);
+extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_protocol);
+extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_net);
+
+enum_func_status mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char *filename, zend_bool *is_warning TSRMLS_DC);
@@ -181,6 +211,55 @@ void ps_fetch_from_1_to_8_bytes(zval *zv, const MYSQLND_FIELD * const field,
unsigned int pack_len, zend_uchar **row, zend_bool as_unicode,
unsigned int byte_count TSRMLS_DC);
+void mysqlnd_plugin_subsystem_init(TSRMLS_D);
+void mysqlnd_plugin_subsystem_end(TSRMLS_D);
+
+void mysqlnd_register_builtin_authentication_plugins(TSRMLS_D);
+
+void mysqlnd_example_plugin_register(TSRMLS_D);
+
+struct st_mysqlnd_packet_greet;
+struct st_mysqlnd_authentication_plugin;
+
+enum_func_status
+mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
+ const char * const user,
+ const char * const passwd,
+ const size_t passwd_len,
+ const char * const db,
+ const size_t db_len,
+ const MYSQLND_OPTIONS * const options,
+ unsigned long mysql_flags,
+ unsigned int server_charset_no,
+ zend_bool use_full_blown_auth_packet,
+ const char * const auth_protocol,
+ const zend_uchar * const auth_plugin_data,
+ const size_t auth_plugin_data_len,
+ char ** switch_to_auth_protocol,
+ size_t * switch_to_auth_protocol_len,
+ zend_uchar ** switch_to_auth_protocol_data,
+ size_t * switch_to_auth_protocol_data_len
+ TSRMLS_DC);
+
+enum_func_status
+mysqlnd_auth_change_user(MYSQLND_CONN_DATA * const conn,
+ const char * const user,
+ const size_t user_len,
+ const char * const passwd,
+ const size_t passwd_len,
+ const char * const db,
+ const size_t db_len,
+ const zend_bool silent,
+ zend_bool use_full_blown_auth_packet,
+ const char * const auth_protocol,
+ zend_uchar * auth_plugin_data,
+ size_t auth_plugin_data_len,
+ char ** switch_to_auth_protocol,
+ size_t * switch_to_auth_protocol_len,
+ zend_uchar ** switch_to_auth_protocol_data,
+ size_t * switch_to_auth_protocol_data_len
+ TSRMLS_DC);
+
#endif /* MYSQLND_PRIV_H */
diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c
index c553aa55a7..99bd021593 100644
--- a/ext/mysqlnd/mysqlnd_ps.c
+++ b/ext/mysqlnd/mysqlnd_ps.c
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -28,7 +28,7 @@
#include "mysqlnd_statistics.h"
#include "mysqlnd_debug.h"
#include "mysqlnd_block_alloc.h"
-
+#include "mysqlnd_ext_plugin.h"
#define MYSQLND_SILENT
@@ -36,8 +36,6 @@
const char * const mysqlnd_not_bound_as_blob = "Can't send long data for non-string/non-binary data types";
const char * const mysqlnd_stmt_not_prepared = "Statement not prepared";
-static struct st_mysqlnd_stmt_methods *mysqlnd_stmt_methods;
-
/* Exported by mysqlnd_ps_codec.c */
enum_func_status mysqlnd_stmt_execute_generate_request(MYSQLND_STMT * const s, zend_uchar ** request, size_t *request_len, zend_bool * free_buffer TSRMLS_DC);
@@ -52,15 +50,15 @@ enum_func_status mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param,
static void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const stmt TSRMLS_DC);
static void mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const stmt, unsigned int param_no TSRMLS_DC);
+
/* {{{ mysqlnd_stmt::store_result */
static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
enum_func_status ret;
- MYSQLND * conn;
+ MYSQLND_CONN_DATA * conn;
MYSQLND_RES * result;
- zend_bool to_cache = FALSE;
DBG_ENTER("mysqlnd_stmt::store_result");
if (!stmt || !stmt->conn || !stmt->result) {
@@ -84,33 +82,34 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s TSRMLS_DC)
if (CONN_GET_STATE(conn) != CONN_FETCHING_DATA ||
stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE)
{
- SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
+ SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_RETURN(NULL);
}
stmt->default_rset_handler = s->m->store_result;
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*conn->error_info);
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_PS_BUFFERED_SETS);
result = stmt->result;
result->type = MYSQLND_RES_PS_BUF;
result->m.fetch_row = mysqlnd_stmt_fetch_row_buffered;
result->m.fetch_lengths = NULL;/* makes no sense */
+ result->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol;
result->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC);
- ret = result->m.store_result_fetch_data(conn, result, result->meta, TRUE, to_cache TSRMLS_CC);
+ ret = result->m.store_result_fetch_data(conn, result, result->meta, TRUE TSRMLS_CC);
if (PASS == ret) {
/* libmysql API docs say it should be so for SELECT statements */
- stmt->upsert_status.affected_rows = stmt->result->stored_data->row_count;
+ stmt->upsert_status->affected_rows = stmt->result->stored_data->row_count;
stmt->state = MYSQLND_STMT_USE_OR_STORE_CALLED;
} else {
- conn->error_info = result->stored_data->error_info;
+ COPY_CLIENT_ERROR(*conn->error_info, result->stored_data->error_info);
stmt->result->m.free_result_contents(stmt->result TSRMLS_CC);
mnd_efree(stmt->result);
stmt->result = NULL;
@@ -127,7 +126,7 @@ static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- MYSQLND * conn;
+ MYSQLND_CONN_DATA * conn;
MYSQLND_RES *result;
DBG_ENTER("mysqlnd_stmt::get_result");
@@ -150,34 +149,34 @@ MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const s TSRMLS_DC)
/* Nothing to store for UPSERT/LOAD DATA*/
if (CONN_GET_STATE(conn) != CONN_FETCHING_DATA || stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE) {
- SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
+ SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_RETURN(NULL);
}
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*conn->error_info);
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_BUFFERED_SETS);
do {
result = conn->m->result_init(stmt->result->field_count, stmt->persistent TSRMLS_CC);
if (!result) {
- SET_OOM_ERROR(stmt->conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
break;
}
result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE TSRMLS_CC);
if (!result->meta) {
- SET_OOM_ERROR(stmt->conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
break;
}
if ((result = result->m.store_result(result, conn, TRUE TSRMLS_CC))) {
- stmt->upsert_status.affected_rows = result->stored_data->row_count;
+ stmt->upsert_status->affected_rows = result->stored_data->row_count;
stmt->state = MYSQLND_STMT_PREPARED;
result->type = MYSQLND_RES_PS_BUF;
} else {
- stmt->error_info = conn->error_info;
+ COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
stmt->state = MYSQLND_STMT_PREPARED;
break;
}
@@ -199,8 +198,7 @@ MYSQLND_METHOD(mysqlnd_stmt, more_results)(const MYSQLND_STMT * s TSRMLS_DC)
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
DBG_ENTER("mysqlnd_stmt::more_results");
/* (conn->state == CONN_NEXT_RESULT_PENDING) too */
- DBG_RETURN((stmt && stmt->conn && (stmt->conn->upsert_status.server_status &
- SERVER_MORE_RESULTS_EXISTS))?
+ DBG_RETURN((stmt && stmt->conn && (stmt->conn->m->get_server_status(stmt->conn TSRMLS_CC) & SERVER_MORE_RESULTS_EXISTS))?
TRUE:
FALSE);
}
@@ -212,7 +210,7 @@ static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, next_result)(MYSQLND_STMT * s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- MYSQLND * conn;
+ MYSQLND_CONN_DATA * conn;
DBG_ENTER("mysqlnd_stmt::next_result");
if (!stmt || !stmt->conn || !stmt->result) {
@@ -221,12 +219,11 @@ MYSQLND_METHOD(mysqlnd_stmt, next_result)(MYSQLND_STMT * s TSRMLS_DC)
conn = stmt->conn;
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
- if (CONN_GET_STATE(conn) != CONN_NEXT_RESULT_PENDING || !(conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS)) {
+ if (CONN_GET_STATE(conn) != CONN_NEXT_RESULT_PENDING || !(conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS)) {
DBG_RETURN(FAIL);
}
- DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status.server_status, stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS);
- DBG_INF_FMT("server_status=%u cursor=%u", conn->upsert_status.server_status, conn->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS);
+ DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status->server_status, stmt->upsert_status->server_status & SERVER_STATUS_CURSOR_EXISTS);
/* Free space for next result */
s->m->free_stmt_content(s TSRMLS_CC);
@@ -256,8 +253,8 @@ mysqlnd_stmt_skip_metadata(MYSQLND_STMT * s TSRMLS_DC)
field_packet = stmt->conn->protocol->m.get_result_field_packet(stmt->conn->protocol, FALSE TSRMLS_CC);
if (!field_packet) {
- SET_OOM_ERROR(stmt->error_info);
- SET_OOM_ERROR(stmt->conn->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
+ SET_OOM_ERROR(*stmt->conn->error_info);
} else {
ret = PASS;
field_packet->skip_parsing = TRUE;
@@ -291,8 +288,8 @@ mysqlnd_stmt_read_prepare_response(MYSQLND_STMT * s TSRMLS_DC)
prepare_resp = stmt->conn->protocol->m.get_prepare_response_packet(stmt->conn->protocol, FALSE TSRMLS_CC);
if (!prepare_resp) {
- SET_OOM_ERROR(stmt->error_info);
- SET_OOM_ERROR(stmt->conn->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
+ SET_OOM_ERROR(*stmt->conn->error_info);
goto done;
}
@@ -301,12 +298,13 @@ mysqlnd_stmt_read_prepare_response(MYSQLND_STMT * s TSRMLS_DC)
}
if (0xFF == prepare_resp->error_code) {
- stmt->error_info = stmt->conn->error_info = prepare_resp->error_info;
+ COPY_CLIENT_ERROR(*stmt->error_info, prepare_resp->error_info);
+ COPY_CLIENT_ERROR(*stmt->conn->error_info, prepare_resp->error_info);
goto done;
}
ret = PASS;
stmt->stmt_id = prepare_resp->stmt_id;
- stmt->warning_count = stmt->conn->upsert_status.warning_count = prepare_resp->warning_count;
+ stmt->warning_count = stmt->conn->upsert_status->warning_count = prepare_resp->warning_count;
stmt->field_count = stmt->conn->field_count = prepare_resp->field_count;
stmt->param_count = prepare_resp->param_count;
done:
@@ -333,8 +331,8 @@ mysqlnd_stmt_prepare_read_eof(MYSQLND_STMT * s TSRMLS_DC)
fields_eof = stmt->conn->protocol->m.get_eof_packet(stmt->conn->protocol, FALSE TSRMLS_CC);
if (!fields_eof) {
- SET_OOM_ERROR(stmt->error_info);
- SET_OOM_ERROR(stmt->conn->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
+ SET_OOM_ERROR(*stmt->conn->error_info);
} else {
if (FAIL == (ret = PACKET_READ(fields_eof, stmt->conn))) {
if (stmt->result) {
@@ -344,8 +342,8 @@ mysqlnd_stmt_prepare_read_eof(MYSQLND_STMT * s TSRMLS_DC)
stmt->state = MYSQLND_STMT_INITTED;
}
} else {
- stmt->upsert_status.server_status = fields_eof->server_status;
- stmt->upsert_status.warning_count = fields_eof->warning_count;
+ stmt->upsert_status->server_status = fields_eof->server_status;
+ stmt->upsert_status->warning_count = fields_eof->warning_count;
stmt->state = MYSQLND_STMT_PREPARED;
}
PACKET_FREE(fields_eof);
@@ -369,12 +367,13 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const
DBG_RETURN(FAIL);
}
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
+ DBG_INF_FMT("query=%s", query);
SET_ERROR_AFF_ROWS(stmt);
SET_ERROR_AFF_ROWS(stmt->conn);
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
if (stmt->state > MYSQLND_STMT_INITTED) {
/* See if we have to clean the wire */
@@ -398,7 +397,7 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const
stmt_to_prepare = s_to_prepare->data;
}
- if (FAIL == stmt_to_prepare->conn->m->simple_command(stmt_to_prepare->conn, COM_STMT_PREPARE, query, query_len, PROT_LAST, FALSE, TRUE TSRMLS_CC) ||
+ if (FAIL == stmt_to_prepare->conn->m->simple_command(stmt_to_prepare->conn, COM_STMT_PREPARE, (const zend_uchar *) query, query_len, PROT_LAST, FALSE, TRUE TSRMLS_CC) ||
FAIL == mysqlnd_stmt_read_prepare_response(s_to_prepare TSRMLS_CC))
{
goto fail;
@@ -420,7 +419,7 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const
if (stmt_to_prepare->field_count) {
MYSQLND_RES * result = stmt->conn->m->result_init(stmt_to_prepare->field_count, stmt_to_prepare->persistent TSRMLS_CC);
if (!result) {
- SET_OOM_ERROR(stmt->conn->error_info);
+ SET_OOM_ERROR(*stmt->conn->error_info);
goto fail;
}
/* Allocate the result now as it is needed for the reading of metadata */
@@ -474,7 +473,7 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
enum_func_status ret;
- MYSQLND * conn;
+ MYSQLND_CONN_DATA * conn;
DBG_ENTER("mysqlnd_stmt_execute_parse_response");
if (!stmt || !stmt->conn) {
@@ -485,8 +484,8 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s TSRMLS_DC)
ret = mysqlnd_query_read_result_set_header(stmt->conn, s TSRMLS_CC);
if (ret == FAIL) {
- stmt->error_info = conn->error_info;
- stmt->upsert_status.affected_rows = conn->upsert_status.affected_rows;
+ COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
+ stmt->upsert_status->affected_rows = conn->upsert_status->affected_rows;
if (CONN_GET_STATE(conn) == CONN_QUIT_SENT) {
/* close the statement here, the connection has been closed */
}
@@ -500,9 +499,9 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s TSRMLS_DC)
value is > LONG_MAX or < LONG_MIN, there is string conversion and we have
to resend the types. Next execution will also need to resend the type.
*/
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
- stmt->upsert_status = conn->upsert_status;
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
+ *stmt->upsert_status = *conn->upsert_status; /* copy status */
stmt->state = MYSQLND_STMT_EXECUTED;
if (conn->last_query_type == QUERY_UPSERT || conn->last_query_type == QUERY_LOAD_LOCAL) {
DBG_INF("PASS");
@@ -528,10 +527,10 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s TSRMLS_DC)
use_result() or store_result() and we should be able to scrap the
data on the line, if he just decides to close the statement.
*/
- DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status.server_status,
- stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS);
+ DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status->server_status,
+ stmt->upsert_status->server_status & SERVER_STATUS_CURSOR_EXISTS);
- if (stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS) {
+ if (stmt->upsert_status->server_status & SERVER_STATUS_CURSOR_EXISTS) {
DBG_INF("cursor exists");
stmt->cursor_exists = TRUE;
CONN_SET_STATE(conn, CONN_READY);
@@ -562,7 +561,7 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s TSRMLS_DC)
}
}
#ifndef MYSQLND_DONT_SKIP_OUT_PARAMS_RESULTSET
- if (stmt->upsert_status.server_status & SERVER_PS_OUT_PARAMS) {
+ if (stmt->upsert_status->server_status & SERVER_PS_OUT_PARAMS) {
s->m->free_stmt_content(s TSRMLS_CC);
DBG_INF("PS OUT Variable RSet, skipping");
/* OUT params result set. Skip for now to retain compatibility */
@@ -582,7 +581,7 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
enum_func_status ret;
- MYSQLND * conn;
+ MYSQLND_CONN_DATA * conn;
zend_uchar *request = NULL;
size_t request_len;
zend_bool free_request;
@@ -629,27 +628,7 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s TSRMLS_DC)
}
#endif
- /*
- If right after execute() we have to call the appropriate
- use_result() or store_result() and clean.
- */
- if (stmt->state == MYSQLND_STMT_WAITING_USE_OR_STORE) {
- DBG_INF("fetching result set header");
- /* Do implicit use_result and then flush the result */
- stmt->default_rset_handler = s->m->use_result;
- stmt->default_rset_handler(s TSRMLS_CC);
- }
-
- if (stmt->state > MYSQLND_STMT_WAITING_USE_OR_STORE) {
- DBG_INF("skipping result");
- /* Flush if anything is left and unbuffered set */
- stmt->result->m.skip_result(stmt->result TSRMLS_CC);
- }
-
- if (stmt->state > MYSQLND_STMT_PREPARED) {
- /* As the buffers have been freed, we should go back to PREPARED */
- stmt->state = MYSQLND_STMT_PREPARED;
- }
+ s->m->flush(s TSRMLS_CC);
/*
Executed, but the user hasn't started to fetch
@@ -657,9 +636,11 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s TSRMLS_DC)
have it again.
*/
stmt->result->m.free_result_buffers(stmt->result TSRMLS_CC);
+
+ stmt->state = MYSQLND_STMT_PREPARED;
} else if (stmt->state < MYSQLND_STMT_PREPARED) {
/* Only initted - error */
- SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
+ SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
mysqlnd_out_of_sync);
SET_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_INF("FAIL");
@@ -681,11 +662,11 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s TSRMLS_DC)
}
if (not_bound) {
char * msg;
- spprintf(&msg, 0, "No data supplied for %u parameter%s in prepared statement",
- not_bound, not_bound>1 ?"s":"");
+ mnd_sprintf(&msg, 0, "No data supplied for %u parameter%s in prepared statement",
+ not_bound, not_bound>1 ?"s":"");
SET_STMT_ERROR(stmt, CR_PARAMS_NOT_BOUND, UNKNOWN_SQLSTATE, msg);
if (msg) {
- efree(msg); /* allocated by spprintf */
+ mnd_sprintf_free(msg);
}
DBG_INF("FAIL");
DBG_RETURN(FAIL);
@@ -694,7 +675,7 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s TSRMLS_DC)
ret = s->m->generate_execute_request(s, &request, &request_len, &free_request TSRMLS_CC);
if (ret == PASS) {
/* support for buffer types should be added here ! */
- ret = stmt->conn->m->simple_command(stmt->conn, COM_STMT_EXECUTE, (char *)request, request_len,
+ ret = stmt->conn->m->simple_command(stmt->conn, COM_STMT_EXECUTE, request, request_len,
PROT_LAST /* we will handle the response packet*/,
FALSE, FALSE TSRMLS_CC);
} else {
@@ -706,7 +687,7 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s TSRMLS_DC)
}
if (ret == FAIL) {
- stmt->error_info = conn->error_info;
+ COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
DBG_INF("FAIL");
DBG_RETURN(FAIL);
}
@@ -714,10 +695,10 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s TSRMLS_DC)
ret = s->m->parse_execute_response(s TSRMLS_CC);
- DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status.server_status, stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS);
+ DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status->server_status, stmt->upsert_status->server_status & SERVER_STATUS_CURSOR_EXISTS);
- if (ret == PASS && conn->last_query_type == QUERY_UPSERT && stmt->upsert_status.affected_rows) {
- MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_PS, stmt->upsert_status.affected_rows);
+ if (ret == PASS && conn->last_query_type == QUERY_UPSERT && stmt->upsert_status->affected_rows) {
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_PS, stmt->upsert_status->affected_rows);
}
DBG_RETURN(ret);
}
@@ -753,9 +734,8 @@ mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES *result, void *param, unsigned int f
current_row,
meta->field_count,
meta->fields,
- result->stored_data->persistent,
- result->conn->options.numeric_and_datetime_as_unicode,
- result->conn->options.int_and_float_native,
+ result->conn->options->numeric_and_datetime_as_unicode,
+ result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC);
if (PASS != rc) {
DBG_RETURN(FAIL);
@@ -838,11 +818,11 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
if (result->unbuf->eof_reached) {
/* No more rows obviously */
- DBG_INF("eof reached");
+ DBG_INF("EOF already reached");
DBG_RETURN(PASS);
}
if (CONN_GET_STATE(result->conn) != CONN_FETCHING_DATA) {
- SET_CLIENT_ERROR(result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
+ SET_CLIENT_ERROR(*result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_ERR("command out of sync");
DBG_RETURN(FAIL);
@@ -864,7 +844,6 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
if (!row_packet->skip_extraction) {
result->m.unbuffered_free_last_data(result TSRMLS_CC);
- DBG_INF("extracting data");
result->unbuf->last_row_data = row_packet->fields;
result->unbuf->last_row_buffer = row_packet->row_buffer;
row_packet->fields = NULL;
@@ -874,9 +853,8 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
result->unbuf->last_row_data,
row_packet->field_count,
row_packet->fields_metadata,
- FALSE,
- result->conn->options.numeric_and_datetime_as_unicode,
- result->conn->options.int_and_float_native,
+ result->conn->options->numeric_and_datetime_as_unicode,
+ result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC))
{
DBG_RETURN(FAIL);
@@ -926,8 +904,8 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
*fetched_anything = TRUE;
} else if (ret == FAIL) {
if (row_packet->error_info.error_no) {
- stmt->conn->error_info = row_packet->error_info;
- stmt->error_info = row_packet->error_info;
+ COPY_CLIENT_ERROR(*stmt->conn->error_info, row_packet->error_info);
+ COPY_CLIENT_ERROR(*stmt->error_info, row_packet->error_info);
}
CONN_SET_STATE(result->conn, CONN_READY);
result->unbuf->eof_reached = TRUE; /* so next time we won't get an error */
@@ -935,13 +913,13 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
DBG_INF("EOF");
/* Mark the connection as usable again */
result->unbuf->eof_reached = TRUE;
- result->conn->upsert_status.warning_count = row_packet->warning_count;
- result->conn->upsert_status.server_status = row_packet->server_status;
+ result->conn->upsert_status->warning_count = row_packet->warning_count;
+ result->conn->upsert_status->server_status = row_packet->server_status;
/*
result->row_packet will be cleaned when
destroying the result object
*/
- if (result->conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS) {
+ if (result->conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
CONN_SET_STATE(result->conn, CONN_NEXT_RESULT_PENDING);
} else {
CONN_SET_STATE(result->conn, CONN_READY);
@@ -959,8 +937,8 @@ static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_stmt, use_result)(MYSQLND_STMT * s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- MYSQLND_RES *result;
- MYSQLND * conn;
+ MYSQLND_RES * result;
+ MYSQLND_CONN_DATA * conn;
DBG_ENTER("mysqlnd_stmt::use_result");
if (!stmt || !stmt->conn || !stmt->result) {
@@ -975,18 +953,17 @@ MYSQLND_METHOD(mysqlnd_stmt, use_result)(MYSQLND_STMT * s TSRMLS_DC)
(stmt->cursor_exists && CONN_GET_STATE(conn) != CONN_READY) ||
(stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE))
{
- SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
+ SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_ERR("command out of sync");
DBG_RETURN(NULL);
}
- SET_EMPTY_ERROR(stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
MYSQLND_INC_CONN_STATISTIC(stmt->conn->stats, STAT_PS_UNBUFFERED_SETS);
result = stmt->result;
- DBG_INF_FMT("%scursor exists", stmt->cursor_exists? "":"no ");
result->m.use_result(stmt->result, TRUE TSRMLS_CC);
result->m.fetch_row = stmt->cursor_exists? mysqlnd_fetch_stmt_row_cursor:
mysqlnd_stmt_fetch_row_unbuffered;
@@ -1021,7 +998,7 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
if (stmt->state < MYSQLND_STMT_USER_FETCHING) {
/* Only initted - error */
- SET_CLIENT_ERROR(stmt->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
+ SET_CLIENT_ERROR(*stmt->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
mysqlnd_out_of_sync);
DBG_ERR("command out of sync");
DBG_RETURN(FAIL);
@@ -1030,16 +1007,16 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
DBG_RETURN(FAIL);
}
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
int4store(buf, stmt->stmt_id);
int4store(buf + STMT_ID_LENGTH, 1); /* for now fetch only one row */
- if (FAIL == stmt->conn->m->simple_command(stmt->conn, COM_STMT_FETCH, (char *)buf, sizeof(buf),
+ if (FAIL == stmt->conn->m->simple_command(stmt->conn, COM_STMT_FETCH, buf, sizeof(buf),
PROT_LAST /* we will handle the response packet*/,
FALSE, TRUE TSRMLS_CC)) {
- stmt->error_info = stmt->conn->error_info;
+ COPY_CLIENT_ERROR(*stmt->error_info, *stmt->conn->error_info);
DBG_RETURN(FAIL);
}
@@ -1048,11 +1025,9 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) {
unsigned int i, field_count = result->field_count;
- DBG_INF_FMT("skip_extraction=%u", row_packet->skip_extraction);
if (!row_packet->skip_extraction) {
result->m.unbuffered_free_last_data(result TSRMLS_CC);
- DBG_INF("extracting data");
result->unbuf->last_row_data = row_packet->fields;
result->unbuf->last_row_buffer = row_packet->row_buffer;
row_packet->fields = NULL;
@@ -1062,9 +1037,8 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
result->unbuf->last_row_data,
row_packet->field_count,
row_packet->fields_metadata,
- FALSE,
- result->conn->options.numeric_and_datetime_as_unicode,
- result->conn->options.int_and_float_native,
+ result->conn->options->numeric_and_datetime_as_unicode,
+ result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC))
{
DBG_RETURN(FAIL);
@@ -1123,21 +1097,21 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
} else {
*fetched_anything = FALSE;
- stmt->upsert_status.warning_count =
- stmt->conn->upsert_status.warning_count =
+ stmt->upsert_status->warning_count =
+ stmt->conn->upsert_status->warning_count =
row_packet->warning_count;
- stmt->upsert_status.server_status =
- stmt->conn->upsert_status.server_status =
+ stmt->upsert_status->server_status =
+ stmt->conn->upsert_status->server_status =
row_packet->server_status;
result->unbuf->eof_reached = row_packet->eof;
}
- stmt->upsert_status.warning_count =
- stmt->conn->upsert_status.warning_count =
+ stmt->upsert_status->warning_count =
+ stmt->conn->upsert_status->warning_count =
row_packet->warning_count;
- stmt->upsert_status.server_status =
- stmt->conn->upsert_status.server_status =
+ stmt->upsert_status->server_status =
+ stmt->conn->upsert_status->server_status =
row_packet->server_status;
DBG_INF_FMT("ret=%s fetched=%u server_status=%u warnings=%u eof=%u",
@@ -1174,8 +1148,8 @@ MYSQLND_METHOD(mysqlnd_stmt, fetch)(MYSQLND_STMT * const s, zend_bool * const fe
}
stmt->state = MYSQLND_STMT_USER_FETCHING;
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
DBG_INF_FMT("result_bind=%p separated_once=%u", stmt->result_bind, stmt->result_zvals_separated_once);
/*
@@ -1217,11 +1191,11 @@ MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const s TSRMLS_DC)
}
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
if (stmt->stmt_id) {
- MYSQLND * conn = stmt->conn;
+ MYSQLND_CONN_DATA * conn = stmt->conn;
if (stmt->param_bind) {
unsigned int i;
DBG_INF("resetting long data");
@@ -1233,6 +1207,43 @@ MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const s TSRMLS_DC)
}
}
+ s->m->flush(s TSRMLS_CC);
+
+ /*
+ Don't free now, let the result be usable. When the stmt will again be
+ executed then the result set will be cleaned, the bound variables will
+ be separated before that.
+ */
+
+ int4store(cmd_buf, stmt->stmt_id);
+ if (CONN_GET_STATE(conn) == CONN_READY &&
+ FAIL == (ret = conn->m->simple_command(conn, COM_STMT_RESET, cmd_buf,
+ sizeof(cmd_buf), PROT_OK_PACKET,
+ FALSE, TRUE TSRMLS_CC))) {
+ COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
+ }
+ *stmt->upsert_status = *conn->upsert_status;
+ }
+ DBG_INF(ret == PASS? "PASS":"FAIL");
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_stmt::flush */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_stmt, flush)(MYSQLND_STMT * const s TSRMLS_DC)
+{
+ MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ enum_func_status ret = PASS;
+
+ DBG_ENTER("mysqlnd_stmt::flush");
+ if (!stmt || !stmt->conn) {
+ DBG_RETURN(FAIL);
+ }
+ DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
+
+ if (stmt->stmt_id) {
/*
If the user decided to close the statement right after execute()
We have to call the appropriate use_result() or store_result() and
@@ -1250,21 +1261,6 @@ MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const s TSRMLS_DC)
stmt->result->m.skip_result(stmt->result TSRMLS_CC);
}
} while (mysqlnd_stmt_more_results(s) && mysqlnd_stmt_next_result(s) == PASS);
-
- /*
- Don't free now, let the result be usable. When the stmt will again be
- executed then the result set will be cleaned, the bound variables will
- be separated before that.
- */
-
- int4store(cmd_buf, stmt->stmt_id);
- if (CONN_GET_STATE(conn) == CONN_READY &&
- FAIL == (ret = conn->m->simple_command(conn, COM_STMT_RESET, (char *)cmd_buf,
- sizeof(cmd_buf), PROT_OK_PACKET,
- FALSE, TRUE TSRMLS_CC))) {
- stmt->error_info = conn->error_info;
- }
- stmt->upsert_status = conn->upsert_status;
}
DBG_INF(ret == PASS? "PASS":"FAIL");
DBG_RETURN(ret);
@@ -1279,8 +1275,8 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned in
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
enum_func_status ret = FAIL;
- MYSQLND * conn;
- zend_uchar *cmd_buf;
+ MYSQLND_CONN_DATA * conn;
+ zend_uchar * cmd_buf;
enum php_mysqlnd_server_command cmd = COM_STMT_SEND_LONG_DATA;
DBG_ENTER("mysqlnd_stmt::send_long_data");
@@ -1291,8 +1287,8 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned in
conn = stmt->conn;
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
if (stmt->state < MYSQLND_STMT_PREPARED) {
SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
@@ -1304,7 +1300,6 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned in
DBG_ERR("command out of sync");
DBG_RETURN(FAIL);
}
-
if (param_no >= stmt->param_count) {
SET_STMT_ERROR(stmt, CR_INVALID_PARAMETER_NO, UNKNOWN_SQLSTATE, "Invalid parameter number");
DBG_ERR("invalid param_no");
@@ -1337,15 +1332,15 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned in
memcpy(cmd_buf + STMT_ID_LENGTH + 2, data, length);
/* COM_STMT_SEND_LONG_DATA doesn't send an OK packet*/
- ret = conn->m->simple_command(conn, cmd, (char *)cmd_buf, packet_len, PROT_LAST , FALSE, TRUE TSRMLS_CC);
+ ret = conn->m->simple_command(conn, cmd, cmd_buf, packet_len, PROT_LAST , FALSE, TRUE TSRMLS_CC);
mnd_efree(cmd_buf);
if (FAIL == ret) {
- stmt->error_info = conn->error_info;
+ COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
}
} else {
ret = FAIL;
- SET_OOM_ERROR(stmt->error_info);
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
+ SET_OOM_ERROR(*conn->error_info);
}
/*
Cover protocol error: COM_STMT_SEND_LONG_DATA was designed to be quick and not
@@ -1405,8 +1400,8 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_parameters)(MYSQLND_STMT * const s, MYSQLND_PA
DBG_RETURN(FAIL);
}
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
if (stmt->param_count) {
unsigned int i = 0;
@@ -1423,8 +1418,7 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_parameters)(MYSQLND_STMT * const s, MYSQLND_PA
*/
for (i = 0; i < stmt->param_count; i++) {
/*
- We may have the last reference, then call zval_ptr_dtor()
- or we may leak memory.
+ We may have the last reference, then call zval_ptr_dtor() or we may leak memory.
Switching from bind_one_parameter to bind_parameters may result in zv being NULL
*/
if (stmt->param_bind[i].zv) {
@@ -1466,8 +1460,7 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_one_parameter)(MYSQLND_STMT * const s, unsigne
if (!stmt || !stmt->conn) {
DBG_RETURN(FAIL);
}
- DBG_INF_FMT("stmt=%lu param_no=%u param_count=%u type=%u",
- stmt->stmt_id, param_no, stmt->param_count, type);
+ DBG_INF_FMT("stmt=%lu param_no=%u param_count=%u type=%u", stmt->stmt_id, param_no, stmt->param_count, type);
if (stmt->state < MYSQLND_STMT_PREPARED) {
SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
@@ -1480,8 +1473,8 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_one_parameter)(MYSQLND_STMT * const s, unsigne
DBG_ERR("invalid param_no");
DBG_RETURN(FAIL);
}
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
if (stmt->param_count) {
if (!stmt->param_bind) {
@@ -1531,13 +1524,12 @@ MYSQLND_METHOD(mysqlnd_stmt, refresh_bind_param)(MYSQLND_STMT * const s TSRMLS_D
DBG_RETURN(FAIL);
}
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
if (stmt->param_count) {
stmt->send_types_to_server = 1;
}
- DBG_INF("PASS");
DBG_RETURN(PASS);
}
/* }}} */
@@ -1564,8 +1556,8 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const s,
DBG_RETURN(FAIL);
}
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
if (stmt->field_count) {
unsigned int i = 0;
@@ -1621,8 +1613,8 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_one_result)(MYSQLND_STMT * const s, unsigned i
DBG_RETURN(FAIL);
}
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
if (stmt->field_count) {
mysqlnd_stmt_separate_one_result_bind(s, param_no TSRMLS_CC);
@@ -1654,7 +1646,7 @@ static uint64_t
MYSQLND_METHOD(mysqlnd_stmt, insert_id)(const MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- return stmt? stmt->upsert_status.last_insert_id : 0;
+ return stmt? stmt->upsert_status->last_insert_id : 0;
}
/* }}} */
@@ -1664,7 +1656,7 @@ static uint64_t
MYSQLND_METHOD(mysqlnd_stmt, affected_rows)(const MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- return stmt? stmt->upsert_status.affected_rows : 0;
+ return stmt? stmt->upsert_status->affected_rows : 0;
}
/* }}} */
@@ -1684,7 +1676,7 @@ static unsigned int
MYSQLND_METHOD(mysqlnd_stmt, warning_count)(const MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- return stmt? stmt->upsert_status.warning_count : 0;
+ return stmt? stmt->upsert_status->warning_count : 0;
}
/* }}} */
@@ -1694,7 +1686,7 @@ static unsigned int
MYSQLND_METHOD(mysqlnd_stmt, server_status)(const MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- return stmt? stmt->upsert_status.server_status : 0;
+ return stmt? stmt->upsert_status->server_status : 0;
}
/* }}} */
@@ -1724,7 +1716,7 @@ static unsigned int
MYSQLND_METHOD(mysqlnd_stmt, errno)(const MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- return stmt? stmt->error_info.error_no : 0;
+ return stmt? stmt->error_info->error_no : 0;
}
/* }}} */
@@ -1734,7 +1726,7 @@ static const char *
MYSQLND_METHOD(mysqlnd_stmt, error)(const MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- return stmt? stmt->error_info.error : 0;
+ return stmt? stmt->error_info->error : 0;
}
/* }}} */
@@ -1744,7 +1736,7 @@ static const char *
MYSQLND_METHOD(mysqlnd_stmt, sqlstate)(const MYSQLND_STMT * const s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- return stmt && stmt->error_info.sqlstate[0] ? stmt->error_info.sqlstate:MYSQLND_SQLSTATE_NULL;
+ return stmt && stmt->error_info->sqlstate[0] ? stmt->error_info->sqlstate:MYSQLND_SQLSTATE_NULL;
}
/* }}} */
@@ -1824,7 +1816,7 @@ MYSQLND_METHOD(mysqlnd_stmt, result_metadata)(MYSQLND_STMT * const s TSRMLS_DC)
DBG_RETURN(result);
} while (0);
- SET_OOM_ERROR(stmt->conn->error_info);
+ SET_OOM_ERROR(*stmt->conn->error_info);
if (result) {
result->m.free_result(result, TRUE TSRMLS_CC);
}
@@ -1919,6 +1911,7 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_get)(const MYSQLND_STMT * const s,
}
/* }}} */
+
/* free_result() doesn't actually free stmt->result but only the buffers */
/* {{{ mysqlnd_stmt::free_result */
static enum_func_status
@@ -1985,8 +1978,7 @@ mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const s TSRMLS_DC)
if (!stmt) {
DBG_VOID_RETURN;
}
- DBG_INF_FMT("stmt=%lu result_bind=%p field_count=%u",
- stmt->stmt_id, stmt->result_bind, stmt->field_count);
+ DBG_INF_FMT("stmt=%lu result_bind=%p field_count=%u", stmt->stmt_id, stmt->result_bind, stmt->field_count);
if (!stmt->result_bind) {
DBG_VOID_RETURN;
@@ -2040,8 +2032,7 @@ mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const s, unsigned int param
if (!stmt) {
DBG_VOID_RETURN;
}
- DBG_INF_FMT("stmt=%lu result_bind=%p field_count=%u param_no=%u",
- stmt->stmt_id, stmt->result_bind, stmt->field_count, param_no);
+ DBG_INF_FMT("stmt=%lu result_bind=%p field_count=%u param_no=%u", stmt->stmt_id, stmt->result_bind, stmt->field_count, param_no);
if (!stmt->result_bind) {
DBG_VOID_RETURN;
@@ -2091,8 +2082,7 @@ MYSQLND_METHOD(mysqlnd_stmt, free_stmt_content)(MYSQLND_STMT * const s TSRMLS_DC
if (!stmt) {
DBG_VOID_RETURN;
}
- DBG_INF_FMT("stmt=%lu param_bind=%p param_count=%u",
- stmt->stmt_id, stmt->param_bind, stmt->param_count);
+ DBG_INF_FMT("stmt=%lu param_bind=%p param_count=%u", stmt->stmt_id, stmt->param_bind, stmt->param_count);
/* Destroy the input bind */
if (stmt->param_bind) {
@@ -2125,6 +2115,11 @@ MYSQLND_METHOD(mysqlnd_stmt, free_stmt_content)(MYSQLND_STMT * const s TSRMLS_DC
stmt->result->m.free_result_internal(stmt->result TSRMLS_CC);
stmt->result = NULL;
}
+ if (stmt->error_info->error_list) {
+ zend_llist_clean(stmt->error_info->error_list);
+ mnd_pefree(stmt->error_info->error_list, s->persistent);
+ stmt->error_info->error_list = NULL;
+ }
DBG_VOID_RETURN;
}
@@ -2136,7 +2131,7 @@ static enum_func_status
MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const s, zend_bool implicit TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- MYSQLND * conn;
+ MYSQLND_CONN_DATA * conn;
zend_uchar cmd_buf[STMT_ID_LENGTH /* statement id */];
enum_mysqlnd_collected_stats statistic = STAT_LAST;
@@ -2148,8 +2143,8 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const s, zend_boo
conn = stmt->conn;
- SET_EMPTY_ERROR(stmt->error_info);
- SET_EMPTY_ERROR(stmt->conn->error_info);
+ SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(*stmt->conn->error_info);
/*
If the user decided to close the statement right after execute()
@@ -2157,7 +2152,6 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const s, zend_boo
clean.
*/
do {
- DBG_INF_FMT("stmt->state=%u", stmt->state);
if (stmt->state == MYSQLND_STMT_WAITING_USE_OR_STORE) {
DBG_INF("fetching result set header");
stmt->default_rset_handler(s TSRMLS_CC);
@@ -2180,10 +2174,10 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const s, zend_boo
int4store(cmd_buf, stmt->stmt_id);
if (CONN_GET_STATE(conn) == CONN_READY &&
- FAIL == conn->m->simple_command(conn, COM_STMT_CLOSE, (char *)cmd_buf, sizeof(cmd_buf),
+ FAIL == conn->m->simple_command(conn, COM_STMT_CLOSE, cmd_buf, sizeof(cmd_buf),
PROT_LAST /* COM_STMT_CLOSE doesn't send an OK packet*/,
FALSE, TRUE TSRMLS_CC)) {
- stmt->error_info = conn->error_info;
+ COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
DBG_RETURN(FAIL);
}
}
@@ -2227,7 +2221,6 @@ MYSQLND_METHOD(mysqlnd_stmt, dtor)(MYSQLND_STMT * const s, zend_bool implicit TS
DBG_ENTER("mysqlnd_stmt::dtor");
if (stmt) {
-
DBG_INF_FMT("stmt=%p", stmt);
MYSQLND_INC_GLOBAL_STATISTIC(implicit == TRUE? STAT_STMT_CLOSE_IMPLICIT:
@@ -2345,68 +2338,19 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_stmt)
MYSQLND_METHOD(mysqlnd_stmt, server_status),
mysqlnd_stmt_execute_generate_request,
mysqlnd_stmt_execute_parse_response,
- MYSQLND_METHOD(mysqlnd_stmt, free_stmt_content)
+ MYSQLND_METHOD(mysqlnd_stmt, free_stmt_content),
+ MYSQLND_METHOD(mysqlnd_stmt, flush)
MYSQLND_CLASS_METHODS_END;
/* {{{ _mysqlnd_stmt_init */
-MYSQLND_STMT * _mysqlnd_stmt_init(MYSQLND * const conn TSRMLS_DC)
+MYSQLND_STMT *
+_mysqlnd_stmt_init(MYSQLND_CONN_DATA * const conn TSRMLS_DC)
{
- size_t alloc_size = sizeof(MYSQLND_STMT) + mysqlnd_plugin_count() * sizeof(void *);
- MYSQLND_STMT * ret = mnd_pecalloc(1, alloc_size, conn->persistent);
- MYSQLND_STMT_DATA * stmt = NULL;
-
+ MYSQLND_STMT * ret;
DBG_ENTER("_mysqlnd_stmt_init");
- do {
- if (!ret) {
- break;
- }
- ret->m = mysqlnd_stmt_methods;
- ret->persistent = conn->persistent;
-
- stmt = ret->data = mnd_pecalloc(1, sizeof(MYSQLND_STMT_DATA), conn->persistent);
- DBG_INF_FMT("stmt=%p", stmt);
- if (!stmt) {
- break;
- }
- stmt->persistent = conn->persistent;
- stmt->state = MYSQLND_STMT_INITTED;
- stmt->execute_cmd_buffer.length = 4096;
- stmt->execute_cmd_buffer.buffer = mnd_pemalloc(stmt->execute_cmd_buffer.length, stmt->persistent);
- if (!stmt->execute_cmd_buffer.buffer) {
- break;
- }
-
- stmt->prefetch_rows = MYSQLND_DEFAULT_PREFETCH_ROWS;
- /*
- Mark that we reference the connection, thus it won't be
- be destructed till there is open statements. The last statement
- or normal query result will close it then.
- */
- stmt->conn = conn->m->get_reference(conn TSRMLS_CC);
-
- DBG_RETURN(ret);
- } while (0);
-
- SET_OOM_ERROR(conn->error_info);
- if (ret) {
- ret->m->dtor(ret, TRUE TSRMLS_CC);
- ret = NULL;
- }
- DBG_RETURN(NULL);
-}
-/* }}} */
-
-
-/* {{{ _mysqlnd_plugin_get_plugin_stmt_data */
-PHPAPI void ** _mysqlnd_plugin_get_plugin_stmt_data(const MYSQLND_STMT * stmt, unsigned int plugin_id TSRMLS_DC)
-{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_stmt_data");
- DBG_INF_FMT("plugin_id=%u", plugin_id);
- if (!stmt || plugin_id >= mysqlnd_plugin_count()) {
- return NULL;
- }
- DBG_RETURN((void *)((char *)stmt + sizeof(MYSQLND_STMT) + plugin_id * sizeof(void *)));
+ ret = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_prepared_statement(conn TSRMLS_CC);
+ DBG_RETURN(ret);
}
/* }}} */
@@ -2414,28 +2358,12 @@ PHPAPI void ** _mysqlnd_plugin_get_plugin_stmt_data(const MYSQLND_STMT * stmt, u
/* {{{ _mysqlnd_init_ps_subsystem */
void _mysqlnd_init_ps_subsystem()
{
- mysqlnd_stmt_methods = &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_stmt);
+ mysqlnd_stmt_set_methods(&MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_stmt));
_mysqlnd_init_ps_fetch_subsystem();
}
/* }}} */
-/* {{{ mysqlnd_conn_get_methods */
-PHPAPI struct st_mysqlnd_stmt_methods * mysqlnd_stmt_get_methods()
-{
- return mysqlnd_stmt_methods;
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_conn_set_methods */
-PHPAPI void mysqlnd_stmt_set_methods(struct st_mysqlnd_stmt_methods *methods)
-{
- mysqlnd_stmt_methods = methods;
-}
-/* }}} */
-
-
/*
* Local variables:
* tab-width: 4
diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c
index eb4b32cdfe..5ead1b0bcc 100644
--- a/ext/mysqlnd/mysqlnd_ps_codec.c
+++ b/ext/mysqlnd/mysqlnd_ps_codec.c
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -258,18 +258,14 @@ void ps_fetch_time(zval *zv, const MYSQLND_FIELD * const field,
t.time_type = MYSQLND_TIMESTAMP_TIME;
}
- /*
- QQ : How to make this unicode without copying two times the buffer -
- Unicode equivalent of spprintf?
- */
- length = spprintf(&value, 0, "%s%02u:%02u:%02u", (t.neg ? "-" : ""), t.hour, t.minute, t.second);
+ length = mnd_sprintf(&value, 0, "%s%02u:%02u:%02u", (t.neg ? "-" : ""), t.hour, t.minute, t.second);
DBG_INF_FMT("%s", value);
#if MYSQLND_UNICODE
if (!as_unicode) {
#endif
ZVAL_STRINGL(zv, value, length, 1);
- efree(value); /* allocated by spprintf */
+ mnd_sprintf_free(value);
#if MYSQLND_UNICODE
} else {
ZVAL_UTF8_STRINGL(zv, value, length, ZSTR_AUTOFREE);
@@ -309,18 +305,14 @@ void ps_fetch_date(zval *zv, const MYSQLND_FIELD * const field,
t.time_type = MYSQLND_TIMESTAMP_DATE;
}
- /*
- QQ : How to make this unicode without copying two times the buffer -
- Unicode equivalent of spprintf?
- */
- length = spprintf(&value, 0, "%04u-%02u-%02u", t.year, t.month, t.day);
+ length = mnd_sprintf(&value, 0, "%04u-%02u-%02u", t.year, t.month, t.day);
DBG_INF_FMT("%s", value);
#if MYSQLND_UNICODE
if (!as_unicode) {
#endif
ZVAL_STRINGL(zv, value, length, 1);
- efree(value); /* allocated by spprintf */
+ mnd_sprintf_free(value);
#if MYSQLND_UNICODE
} else {
ZVAL_UTF8_STRINGL(zv, value, length, ZSTR_AUTOFREE);
@@ -367,19 +359,14 @@ void ps_fetch_datetime(zval *zv, const MYSQLND_FIELD * const field,
t.time_type = MYSQLND_TIMESTAMP_DATETIME;
}
- /*
- QQ : How to make this unicode without copying two times the buffer -
- Unicode equivalent of spprintf?
- */
- length = spprintf(&value, 0, "%04u-%02u-%02u %02u:%02u:%02u",
- t.year, t.month, t.day, t.hour, t.minute, t.second);
+ length = mnd_sprintf(&value, 0, "%04u-%02u-%02u %02u:%02u:%02u", t.year, t.month, t.day, t.hour, t.minute, t.second);
DBG_INF_FMT("%s", value);
#if MYSQLND_UNICODE
if (!as_unicode) {
#endif
ZVAL_STRINGL(zv, value, length, 1);
- efree(value); /* allocated by spprintf */
+ mnd_sprintf_free(value);
#if MYSQLND_UNICODE
} else {
ZVAL_UTF8_STRINGL(zv, to, length, ZSTR_AUTOFREE);
@@ -621,7 +608,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar
*buf_len = offset + null_count + 20;
tmp_buf = mnd_emalloc(*buf_len);
if (!tmp_buf) {
- SET_OOM_ERROR(stmt->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
goto end;
}
memcpy(tmp_buf, *buf, offset);
@@ -655,7 +642,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar
if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG &&
PASS != mysqlnd_stmt_copy_it(&copies, stmt->param_bind[i].zv, stmt->param_count, i TSRMLS_CC))
{
- SET_OOM_ERROR(stmt->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
goto end;
}
/*
@@ -683,7 +670,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar
*buf_len = offset + stmt->param_count * 2 + 20;
tmp_buf = mnd_emalloc(*buf_len);
if (!tmp_buf) {
- SET_OOM_ERROR(stmt->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
goto end;
}
memcpy(tmp_buf, *buf, offset);
@@ -746,7 +733,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar
/* Double binding of the same zval, make a copy */
if (!copies || !copies[i]) {
if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
- SET_OOM_ERROR(stmt->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
goto end;
}
}
@@ -760,7 +747,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar
if (Z_TYPE_P(the_var) != IS_DOUBLE) {
if (!copies || !copies[i]) {
if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
- SET_OOM_ERROR(stmt->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
goto end;
}
}
@@ -807,7 +794,7 @@ use_string:
{
if (!copies || !copies[i]) {
if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
- SET_OOM_ERROR(stmt->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
goto end;
}
}
@@ -832,7 +819,7 @@ use_string:
*buf_len = offset + data_size + 10; /* Allocate + 10 for safety */
tmp_buf = mnd_emalloc(*buf_len);
if (!tmp_buf) {
- SET_OOM_ERROR(stmt->error_info);
+ SET_OOM_ERROR(*stmt->error_info);
goto end;
}
memcpy(tmp_buf, *buf, offset);
diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c
index 884de8bcee..2e289062a9 100644
--- a/ext/mysqlnd/mysqlnd_result.c
+++ b/ext/mysqlnd/mysqlnd_result.c
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -28,6 +28,7 @@
#include "mysqlnd_result_meta.h"
#include "mysqlnd_statistics.h"
#include "mysqlnd_debug.h"
+#include "mysqlnd_ext_plugin.h"
#define MYSQLND_SILENT
@@ -54,9 +55,8 @@ MYSQLND_METHOD(mysqlnd_res, initialize_result_set_rest)(MYSQLND_RES * const resu
data_cursor,
result->meta->field_count,
result->meta->fields,
- result->stored_data->persistent,
- result->conn->options.numeric_and_datetime_as_unicode,
- result->conn->options.int_and_float_native,
+ result->conn->options->numeric_and_datetime_as_unicode,
+ result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC);
if (rc != PASS) {
ret = FAIL;
@@ -150,13 +150,11 @@ MYSQLND_METHOD(mysqlnd_res, unbuffered_free_last_data)(MYSQLND_RES * result TSRM
DBG_VOID_RETURN;
}
- DBG_INF_FMT("last_row_data=%p", unbuf->last_row_data);
if (unbuf->last_row_data) {
unsigned int i, ctor_called_count = 0;
zend_bool copy_ctor_called;
MYSQLND_STATS *global_stats = result->conn? result->conn->stats:NULL;
- DBG_INF_FMT("%u columns to free", result->field_count);
for (i = 0; i < result->field_count; i++) {
mysqlnd_rset_zval_ptr_dtor(&(unbuf->last_row_data[i]), result->type, &copy_ctor_called TSRMLS_CC);
if (copy_ctor_called) {
@@ -197,12 +195,10 @@ MYSQLND_METHOD(mysqlnd_res, free_buffered_data)(MYSQLND_RES * result TSRMLS_DC)
DBG_ENTER("mysqlnd_res::free_buffered_data");
DBG_INF_FMT("Freeing "MYSQLND_LLU_SPEC" row(s)", set->row_count);
- DBG_INF("Freeing data & row_buffer");
if (set->data) {
unsigned int copy_on_write_performed = 0;
unsigned int copy_on_write_saved = 0;
- DBG_INF_FMT("before: real_usage=%lu usage=%lu", zend_memory_usage(TRUE TSRMLS_CC), zend_memory_usage(FALSE TSRMLS_CC));
for (row = set->row_count - 1; row >= 0; row--) {
zval **current_row = set->data + row * field_count;
MYSQLND_MEMORY_POOL_CHUNK *current_buffer = set->row_buffers[row];
@@ -213,9 +209,6 @@ MYSQLND_METHOD(mysqlnd_res, free_buffered_data)(MYSQLND_RES * result TSRMLS_DC)
if (current_row[col]) {
zend_bool copy_ctor_called;
mysqlnd_rset_zval_ptr_dtor(&(current_row[col]), result->type, &copy_ctor_called TSRMLS_CC);
-#if MYSQLND_DEBUG_MEMORY
- DBG_INF_FMT("Copy_ctor_called=%u", copy_ctor_called);
-#endif
if (copy_ctor_called) {
++copy_on_write_performed;
} else {
@@ -224,29 +217,24 @@ MYSQLND_METHOD(mysqlnd_res, free_buffered_data)(MYSQLND_RES * result TSRMLS_DC)
}
}
}
-#if MYSQLND_DEBUG_MEMORY
- DBG_INF("Freeing current_row & current_buffer");
-#endif
current_buffer->free_chunk(current_buffer TSRMLS_CC);
}
MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_COPY_ON_WRITE_PERFORMED, copy_on_write_performed,
STAT_COPY_ON_WRITE_SAVED, copy_on_write_saved);
- mnd_pefree(set->data, set->persistent);
+ mnd_efree(set->data);
set->data = NULL;
}
if (set->row_buffers) {
- mnd_pefree(set->row_buffers, set->persistent);
+ mnd_efree(set->row_buffers);
set->row_buffers = NULL;
}
set->data_cursor = NULL;
set->row_count = 0;
- DBG_INF("Freeing set");
- mnd_pefree(set, set->persistent);
+ mnd_efree(set);
- DBG_INF_FMT("after: real_usage=%lu usage=%lu", zend_memory_usage(TRUE TSRMLS_CC), zend_memory_usage(FALSE TSRMLS_CC));
DBG_VOID_RETURN;
}
/* }}} */
@@ -274,13 +262,11 @@ MYSQLND_METHOD(mysqlnd_res, free_result_buffers)(MYSQLND_RES * result TSRMLS_DC)
}
if (result->row_packet) {
- DBG_INF("Freeing packet");
PACKET_FREE(result->row_packet);
result->row_packet = NULL;
}
if (result->result_set_memory_pool) {
- DBG_INF("Freeing memory pool");
mysqlnd_mempool_destroy(result->result_set_memory_pool TSRMLS_CC);
result->result_set_memory_pool = NULL;
}
@@ -329,7 +315,7 @@ void mysqlnd_internal_free_result(MYSQLND_RES * result TSRMLS_DC)
/* {{{ mysqlnd_res::read_result_metadata */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_res, read_result_metadata)(MYSQLND_RES * result, MYSQLND *conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_res, read_result_metadata)(MYSQLND_RES * result, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
DBG_ENTER("mysqlnd_res::read_result_metadata");
@@ -346,7 +332,7 @@ MYSQLND_METHOD(mysqlnd_res, read_result_metadata)(MYSQLND_RES * result, MYSQLND
result->meta = result->m.result_meta_init(result->field_count, result->persistent TSRMLS_CC);
if (!result->meta) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(FAIL);
}
@@ -374,7 +360,7 @@ MYSQLND_METHOD(mysqlnd_res, read_result_metadata)(MYSQLND_RES * result, MYSQLND
/* {{{ mysqlnd_query_read_result_set_header */
enum_func_status
-mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
+mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s ? s->data:NULL;
enum_func_status ret;
@@ -388,7 +374,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
do {
rset_header = conn->protocol->m.get_rset_header_packet(conn->protocol, FALSE TSRMLS_CC);
if (!rset_header) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
break;
}
@@ -410,19 +396,19 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
a multi-statement or a stored procedure, so it should be
safe to unconditionally turn off the flag here.
*/
- conn->upsert_status.server_status &= ~SERVER_MORE_RESULTS_EXISTS;
+ conn->upsert_status->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
/*
This will copy the error code and the messages, as they
are buffers in the struct
*/
- conn->error_info = rset_header->error_info;
+ COPY_CLIENT_ERROR(*conn->error_info, rset_header->error_info);
ret = FAIL;
DBG_ERR_FMT("error=%s", rset_header->error_info.error);
/* Return back from CONN_QUERY_SENT */
CONN_SET_STATE(conn, CONN_READY);
break;
}
- conn->error_info.error_no = 0;
+ conn->error_info->error_no = 0;
switch (rset_header->field_count) {
case MYSQLND_NULL_LENGTH: { /* LOAD DATA LOCAL INFILE */
@@ -440,15 +426,15 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
DBG_INF("UPSERT");
conn->last_query_type = QUERY_UPSERT;
conn->field_count = rset_header->field_count;
- conn->upsert_status.warning_count = rset_header->warning_count;
- conn->upsert_status.server_status = rset_header->server_status;
- conn->upsert_status.affected_rows = rset_header->affected_rows;
- conn->upsert_status.last_insert_id = rset_header->last_insert_id;
+ conn->upsert_status->warning_count = rset_header->warning_count;
+ conn->upsert_status->server_status = rset_header->server_status;
+ conn->upsert_status->affected_rows = rset_header->affected_rows;
+ conn->upsert_status->last_insert_id = rset_header->last_insert_id;
SET_NEW_MESSAGE(conn->last_message, conn->last_message_len,
rset_header->info_or_local_file, rset_header->info_or_local_file_len,
conn->persistent);
/* Result set can follow UPSERT statement, check server_status */
- if (conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS) {
+ if (conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
CONN_SET_STATE(conn, CONN_NEXT_RESULT_PENDING);
} else {
CONN_SET_STATE(conn, CONN_READY);
@@ -464,7 +450,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
SET_EMPTY_MESSAGE(conn->last_message, conn->last_message_len, conn->persistent);
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_RSET_QUERY);
- memset(&conn->upsert_status, 0, sizeof(conn->upsert_status));
+ memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
/* restore after zeroing */
SET_ERROR_AFF_ROWS(conn);
@@ -500,7 +486,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
result = stmt->result;
}
if (!result) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
break;
}
@@ -518,7 +504,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
/* Check for SERVER_STATUS_MORE_RESULTS if needed */
fields_eof = conn->protocol->m.get_eof_packet(conn->protocol, FALSE TSRMLS_CC);
if (!fields_eof) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
break;
}
@@ -537,7 +523,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
unsigned int to_log = MYSQLND_G(log_mask);
to_log &= fields_eof->server_status;
DBG_INF_FMT("warnings=%u server_status=%u", fields_eof->warning_count, fields_eof->server_status);
- conn->upsert_status.warning_count = fields_eof->warning_count;
+ conn->upsert_status->warning_count = fields_eof->warning_count;
/*
If SERVER_MORE_RESULTS_EXISTS is set then this is either MULTI_QUERY or a CALL()
The first packet after sending the query/com_execute has the bit set only
@@ -545,7 +531,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT * s TSRMLS_DC)
will include many result sets. What actually matters are the bits set at the end
of every result set (the EOF packet).
*/
- conn->upsert_status.server_status = fields_eof->server_status;
+ conn->upsert_status->server_status = fields_eof->server_status;
if (fields_eof->server_status & SERVER_QUERY_NO_GOOD_INDEX_USED) {
statistic = STAT_BAD_INDEX_USED;
} else if (fields_eof->server_status & SERVER_QUERY_NO_INDEX_USED) {
@@ -648,7 +634,7 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES * result TSRMLS_DC)
DBG_RETURN(retrow);
}
if (CONN_GET_STATE(result->conn) != CONN_FETCHING_DATA) {
- SET_CLIENT_ERROR(result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
+ SET_CLIENT_ERROR(*result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_RETURN(retrow);
}
@@ -683,9 +669,8 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES * result TSRMLS_DC)
result->unbuf->last_row_data,
row_packet->field_count,
row_packet->fields_metadata,
- FALSE,
- result->conn->options.numeric_and_datetime_as_unicode,
- result->conn->options.int_and_float_native,
+ result->conn->options->numeric_and_datetime_as_unicode,
+ result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC);
if (PASS != rc) {
DBG_RETURN(retrow);
@@ -715,27 +700,27 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES * result TSRMLS_DC)
}
}
} else {
- SET_OOM_ERROR(result->conn->error_info);
+ SET_OOM_ERROR(*result->conn->error_info);
}
}
} else if (ret == FAIL) {
if (row_packet->error_info.error_no) {
- result->conn->error_info = row_packet->error_info;
+ COPY_CLIENT_ERROR(*result->conn->error_info, row_packet->error_info);
DBG_ERR_FMT("errorno=%u error=%s", row_packet->error_info.error_no, row_packet->error_info.error);
}
CONN_SET_STATE(result->conn, CONN_READY);
result->unbuf->eof_reached = TRUE; /* so next time we won't get an error */
} else if (row_packet->eof) {
/* Mark the connection as usable again */
- DBG_INF_FMT("warningss=%u server_status=%u", row_packet->warning_count, row_packet->server_status);
+ DBG_INF_FMT("warnings=%u server_status=%u", row_packet->warning_count, row_packet->server_status);
result->unbuf->eof_reached = TRUE;
- result->conn->upsert_status.warning_count = row_packet->warning_count;
- result->conn->upsert_status.server_status = row_packet->server_status;
+ result->conn->upsert_status->warning_count = row_packet->warning_count;
+ result->conn->upsert_status->server_status = row_packet->server_status;
/*
result->row_packet will be cleaned when
destroying the result object
*/
- if (result->conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS) {
+ if (result->conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
CONN_SET_STATE(result->conn, CONN_NEXT_RESULT_PENDING);
} else {
CONN_SET_STATE(result->conn, CONN_READY);
@@ -757,7 +742,6 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla
MYSQLND_PACKET_ROW *row_packet = result->row_packet;
DBG_ENTER("mysqlnd_fetch_row_unbuffered");
- DBG_INF_FMT("flags=%u", flags);
*fetched_anything = FALSE;
if (result->unbuf->eof_reached) {
@@ -765,7 +749,7 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla
DBG_RETURN(PASS);
}
if (CONN_GET_STATE(result->conn) != CONN_FETCHING_DATA) {
- SET_CLIENT_ERROR(result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ SET_CLIENT_ERROR(*result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_RETURN(FAIL);
}
if (!row_packet) {
@@ -800,9 +784,8 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla
result->unbuf->last_row_data,
field_count,
row_packet->fields_metadata,
- FALSE,
- result->conn->options.numeric_and_datetime_as_unicode,
- result->conn->options.int_and_float_native,
+ result->conn->options->numeric_and_datetime_as_unicode,
+ result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC);
if (PASS != rc) {
DBG_RETURN(FAIL);
@@ -857,7 +840,7 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla
result->unbuf->row_count++;
} else if (ret == FAIL) {
if (row_packet->error_info.error_no) {
- result->conn->error_info = row_packet->error_info;
+ COPY_CLIENT_ERROR(*result->conn->error_info, row_packet->error_info);
DBG_ERR_FMT("errorno=%u error=%s", row_packet->error_info.error_no, row_packet->error_info.error);
}
CONN_SET_STATE(result->conn, CONN_READY);
@@ -866,13 +849,13 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla
/* Mark the connection as usable again */
DBG_INF_FMT("warnings=%u server_status=%u", row_packet->warning_count, row_packet->server_status);
result->unbuf->eof_reached = TRUE;
- result->conn->upsert_status.warning_count = row_packet->warning_count;
- result->conn->upsert_status.server_status = row_packet->server_status;
+ result->conn->upsert_status->warning_count = row_packet->warning_count;
+ result->conn->upsert_status->server_status = row_packet->server_status;
/*
result->row_packet will be cleaned when
destroying the result object
*/
- if (result->conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS) {
+ if (result->conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
CONN_SET_STATE(result->conn, CONN_NEXT_RESULT_PENDING);
} else {
CONN_SET_STATE(result->conn, CONN_READY);
@@ -891,10 +874,8 @@ static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps TSRMLS_DC)
{
DBG_ENTER("mysqlnd_res::use_result");
- DBG_INF_FMT("ps=%u", ps);
-
- SET_EMPTY_ERROR(result->conn->error_info);
+ SET_EMPTY_ERROR(*result->conn->error_info);
if (ps == FALSE) {
result->type = MYSQLND_RES_NORMAL;
@@ -939,7 +920,7 @@ MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps
DBG_RETURN(result);
oom:
- SET_OOM_ERROR(result->conn->error_info);
+ SET_OOM_ERROR(*result->conn->error_info);
DBG_RETURN(NULL);
}
/* }}} */
@@ -969,9 +950,8 @@ mysqlnd_fetch_row_buffered_c(MYSQLND_RES * result TSRMLS_DC)
current_row,
result->meta->field_count,
result->meta->fields,
- FALSE,
- result->conn->options.numeric_and_datetime_as_unicode,
- result->conn->options.int_and_float_native,
+ result->conn->options->numeric_and_datetime_as_unicode,
+ result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC);
if (rc != PASS) {
DBG_RETURN(ret);
@@ -1028,7 +1008,6 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES * result, void *param, unsigned int flags
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_fetch_row_buffered");
- DBG_INF_FMT("flags=%u row=%p", flags, row);
/* If we haven't read everything */
if (set->data_cursor &&
@@ -1044,9 +1023,8 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES * result, void *param, unsigned int flags
current_row,
result->meta->field_count,
result->meta->fields,
- result->stored_data->persistent,
- result->conn->options.numeric_and_datetime_as_unicode,
- result->conn->options.int_and_float_native,
+ result->conn->options->numeric_and_datetime_as_unicode,
+ result->conn->options->int_and_float_native,
result->conn->stats TSRMLS_CC);
if (rc != PASS) {
DBG_RETURN(FAIL);
@@ -1124,10 +1102,9 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES * result, void *param, unsigned int flags
/* {{{ mysqlnd_res::store_result_fetch_data */
enum_func_status
-MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND * const conn, MYSQLND_RES * result,
+MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const conn, MYSQLND_RES * result,
MYSQLND_RES_METADATA *meta,
- zend_bool binary_protocol,
- zend_bool to_cache TSRMLS_DC)
+ zend_bool binary_protocol TSRMLS_DC)
{
enum_func_status ret;
MYSQLND_PACKET_ROW *row_packet = NULL;
@@ -1135,33 +1112,27 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND * const conn, MYSQL
MYSQLND_RES_BUFFERED *set;
DBG_ENTER("mysqlnd_res::store_result_fetch_data");
- DBG_INF_FMT("conn=%llu binary_proto=%u to_cache=%u",
- conn->thread_id, binary_protocol, to_cache);
- result->stored_data = set = mnd_pecalloc(1, sizeof(MYSQLND_RES_BUFFERED), to_cache);
+ result->stored_data = set = mnd_ecalloc(1, sizeof(MYSQLND_RES_BUFFERED));
if (!set) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
goto end;
}
if (free_rows) {
- set->row_buffers = mnd_pemalloc((size_t)(free_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)), to_cache);
+ set->row_buffers = mnd_emalloc((size_t)(free_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)));
if (!set->row_buffers) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
goto end;
}
}
- set->persistent = to_cache;
set->references = 1;
- result->m.row_decoder = binary_protocol? php_mysqlnd_rowp_read_binary_protocol:
- php_mysqlnd_rowp_read_text_protocol;
-
/* non-persistent */
row_packet = conn->protocol->m.get_row_packet(conn->protocol, FALSE TSRMLS_CC);
if (!row_packet) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
goto end;
}
@@ -1182,15 +1153,13 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND * const conn, MYSQL
/* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */
if (total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *) > SIZE_MAX) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
goto end;
}
- new_row_buffers = mnd_perealloc(set->row_buffers,
- (size_t)(total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)),
- set->persistent);
+ new_row_buffers = mnd_erealloc(set->row_buffers, (size_t)(total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)));
if (!new_row_buffers) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
goto end;
}
@@ -1216,14 +1185,14 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND * const conn, MYSQL
if (set->row_count) {
/* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */
if (set->row_count * meta->field_count * sizeof(zval *) > SIZE_MAX) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
goto end;
}
/* if pecalloc is used valgrind barks gcc version 4.3.1 20080507 (prerelease) [gcc-4_3-branch revision 135036] (SUSE Linux) */
- set->data = mnd_pemalloc((size_t)(set->row_count * meta->field_count * sizeof(zval *)), to_cache);
+ set->data = mnd_emalloc((size_t)(set->row_count * meta->field_count * sizeof(zval *)));
if (!set->data) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
goto end;
}
@@ -1237,39 +1206,37 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND * const conn, MYSQL
/* Finally clean */
if (row_packet->eof) {
- conn->upsert_status.warning_count = row_packet->warning_count;
- conn->upsert_status.server_status = row_packet->server_status;
+ conn->upsert_status->warning_count = row_packet->warning_count;
+ conn->upsert_status->server_status = row_packet->server_status;
}
/* save some memory */
if (free_rows) {
/* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */
if (set->row_count * sizeof(MYSQLND_MEMORY_POOL_CHUNK *) > SIZE_MAX) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
goto end;
}
- set->row_buffers = mnd_perealloc(set->row_buffers,
- (size_t) (set->row_count * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)),
- set->persistent);
+ set->row_buffers = mnd_erealloc(set->row_buffers, (size_t) (set->row_count * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)));
}
- if (conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS) {
+ if (conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
CONN_SET_STATE(conn, CONN_NEXT_RESULT_PENDING);
} else {
CONN_SET_STATE(conn, CONN_READY);
}
if (ret == FAIL) {
- set->error_info = row_packet->error_info;
+ COPY_CLIENT_ERROR(set->error_info, row_packet->error_info);
} else {
/* Position at the first row */
set->data_cursor = set->data;
/* libmysql's documentation says it should be so for SELECT statements */
- conn->upsert_status.affected_rows = set->row_count;
+ conn->upsert_status->affected_rows = set->row_count;
}
DBG_INF_FMT("ret=%s row_count=%u warnings=%u server_status=%u",
- ret == PASS? "PASS":"FAIL", (uint) set->row_count, conn->upsert_status.warning_count, conn->upsert_status.server_status);
+ ret == PASS? "PASS":"FAIL", (uint) set->row_count, conn->upsert_status->warning_count, conn->upsert_status->server_status);
end:
PACKET_FREE(row_packet);
@@ -1281,41 +1248,42 @@ end:
/* {{{ mysqlnd_res::store_result */
static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
- MYSQLND * const conn,
+ MYSQLND_CONN_DATA * const conn,
zend_bool ps_protocol TSRMLS_DC)
{
enum_func_status ret;
- zend_bool to_cache = FALSE;
DBG_ENTER("mysqlnd_res::store_result");
- DBG_INF_FMT("conn=%u ps_protocol=%u", conn->thread_id, ps_protocol);
/* We need the conn because we are doing lazy zval initialization in buffered_fetch_row */
result->conn = conn->m->get_reference(conn TSRMLS_CC);
result->type = MYSQLND_RES_NORMAL;
result->m.fetch_row = result->m.fetch_row_normal_buffered;
result->m.fetch_lengths = mysqlnd_fetch_lengths_buffered;
+ result->m.row_decoder = ps_protocol? php_mysqlnd_rowp_read_binary_protocol:
+ php_mysqlnd_rowp_read_text_protocol;
result->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC);
result->lengths = mnd_ecalloc(result->field_count, sizeof(unsigned long));
+
if (!result->result_set_memory_pool || !result->lengths) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(NULL);
}
CONN_SET_STATE(conn, CONN_FETCHING_DATA);
- ret = result->m.store_result_fetch_data(conn, result, result->meta, ps_protocol, to_cache TSRMLS_CC);
+ ret = result->m.store_result_fetch_data(conn, result, result->meta, ps_protocol TSRMLS_CC);
if (FAIL == ret) {
if (result->stored_data) {
- conn->error_info = result->stored_data->error_info;
+ COPY_CLIENT_ERROR(*conn->error_info, result->stored_data->error_info);
} else {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
}
DBG_RETURN(NULL);
}
/* libmysql's documentation says it should be so for SELECT statements */
- conn->upsert_status.affected_rows = result->stored_data->row_count;
+ conn->upsert_status->affected_rows = result->stored_data->row_count;
DBG_RETURN(result);
}
@@ -1357,7 +1325,6 @@ static enum_func_status
MYSQLND_METHOD(mysqlnd_res, free_result)(MYSQLND_RES * result, zend_bool implicit TSRMLS_DC)
{
DBG_ENTER("mysqlnd_res::free_result");
- DBG_INF_FMT("implicit=%u", implicit);
result->m.skip_result(result TSRMLS_CC);
MYSQLND_INC_CONN_STATISTIC(result->conn? result->conn->stats : NULL,
@@ -1522,9 +1489,6 @@ MYSQLND_METHOD(mysqlnd_res, field_tell)(const MYSQLND_RES * const result TSRMLS_
/* }}} */
-/* for php_addslashes */
-#include "ext/standard/php_string.h"
-
/* {{{ mysqlnd_res::fetch_into */
static void
MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, unsigned int flags,
@@ -1534,7 +1498,6 @@ MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, unsigned int flags
zend_bool fetched_anything;
DBG_ENTER("mysqlnd_res::fetch_into");
- DBG_INF_FMT("flags=%u mysqlnd_extension=%u", flags, extension);
if (!result->m.fetch_row) {
RETVAL_NULL();
@@ -1559,7 +1522,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, unsigned int flags
break;
default:exit(0);
}
- }
+ }
/*
return_value is IS_NULL for no more data and an array for data. Thus it's ok
to return here.
@@ -1599,12 +1562,11 @@ MYSQLND_METHOD(mysqlnd_res, fetch_all)(MYSQLND_RES * result, unsigned int flags,
MYSQLND_RES_BUFFERED *set = result->stored_data;
DBG_ENTER("mysqlnd_res::fetch_all");
- DBG_INF_FMT("flags=%u", flags);
if ((!result->unbuf && !set)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "fetch_all can be used only with buffered sets");
if (result->conn) {
- SET_CLIENT_ERROR(result->conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "fetch_all can be used only with buffered sets");
+ SET_CLIENT_ERROR(*result->conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "fetch_all can be used only with buffered sets");
}
RETVAL_NULL();
DBG_VOID_RETURN;
@@ -1672,7 +1634,6 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field_data)(MYSQLND_RES * result, unsigned int
/* }}} */
-static
MYSQLND_CLASS_METHODS_START(mysqlnd_res)
NULL, /* fetch_row */
mysqlnd_fetch_row_buffered,
@@ -1717,7 +1678,6 @@ mysqlnd_result_init(unsigned int field_count, zend_bool persistent TSRMLS_DC)
MYSQLND_RES *ret = mnd_pecalloc(1, alloc_size, persistent);
DBG_ENTER("mysqlnd_result_init");
- DBG_INF_FMT("field_count=%u", field_count);
if (!ret) {
DBG_RETURN(NULL);
@@ -1725,34 +1685,13 @@ mysqlnd_result_init(unsigned int field_count, zend_bool persistent TSRMLS_DC)
ret->persistent = persistent;
ret->field_count = field_count;
- ret->m = mysqlnd_mysqlnd_res_methods;
+ ret->m = *mysqlnd_result_get_methods();
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ _mysqlnd_plugin_get_plugin_result_data */
-PHPAPI void ** _mysqlnd_plugin_get_plugin_result_data(const MYSQLND_RES * result, unsigned int plugin_id TSRMLS_DC)
-{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_result_data");
- DBG_INF_FMT("plugin_id=%u", plugin_id);
- if (!result || plugin_id >= mysqlnd_plugin_count()) {
- return NULL;
- }
- DBG_RETURN((void *)((char *)result + sizeof(MYSQLND_RES) + plugin_id * sizeof(void *)));
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_result_get_methods */
-PHPAPI struct st_mysqlnd_res_methods *
-mysqlnd_result_get_methods()
-{
- return &mysqlnd_mysqlnd_res_methods;
-}
-/* }}} */
-
/*
* Local variables:
* tab-width: 4
diff --git a/ext/mysqlnd/mysqlnd_result.h b/ext/mysqlnd/mysqlnd_result.h
index afddab4621..f821b916ea 100644
--- a/ext/mysqlnd/mysqlnd_result.h
+++ b/ext/mysqlnd/mysqlnd_result.h
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -24,9 +24,8 @@
#define MYSQLND_RESULT_H
PHPAPI MYSQLND_RES * mysqlnd_result_init(unsigned int field_count, zend_bool persistent TSRMLS_DC);
-PHPAPI struct st_mysqlnd_res_methods * mysqlnd_result_get_methods();
-enum_func_status mysqlnd_query_read_result_set_header(MYSQLND * conn, MYSQLND_STMT * stmt TSRMLS_DC);
+enum_func_status mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * stmt TSRMLS_DC);
#endif /* MYSQLND_RESULT_H */
diff --git a/ext/mysqlnd/mysqlnd_result_meta.c b/ext/mysqlnd/mysqlnd_result_meta.c
index 23663a226f..1d22e6cc05 100644
--- a/ext/mysqlnd/mysqlnd_result_meta.c
+++ b/ext/mysqlnd/mysqlnd_result_meta.c
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -138,7 +138,7 @@ mysqlnd_unicode_is_key_numeric(UChar *key, size_t length, long *idx)
/* {{{ mysqlnd_res_meta::read_metadata */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND *conn TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
unsigned int i = 0;
MYSQLND_PACKET_RES_FIELD * field_packet;
@@ -151,7 +151,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met
field_packet = conn->protocol->m.get_result_field_packet(conn->protocol, FALSE TSRMLS_CC);
if (!field_packet) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(FAIL);
}
field_packet->persistent_alloc = meta->persistent;
@@ -170,7 +170,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met
DBG_RETURN(FAIL);
}
if (field_packet->error_info.error_no) {
- conn->error_info = field_packet->error_info;
+ COPY_CLIENT_ERROR(*conn->error_info, field_packet->error_info);
/* Return back from CONN_QUERY_SENT */
PACKET_FREE(field_packet);
DBG_RETURN(FAIL);
diff --git a/ext/mysqlnd/mysqlnd_result_meta.h b/ext/mysqlnd/mysqlnd_result_meta.h
index 1ebbabd948..8fa9989700 100644
--- a/ext/mysqlnd/mysqlnd_result_meta.h
+++ b/ext/mysqlnd/mysqlnd_result_meta.h
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
diff --git a/ext/mysqlnd/mysqlnd_reverse_api.c b/ext/mysqlnd/mysqlnd_reverse_api.c
new file mode 100644
index 0000000000..daa43ec513
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_reverse_api.c
@@ -0,0 +1,100 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id: mysqlnd.c 317989 2011-10-10 20:49:28Z andrey $ */
+#include "php.h"
+#include "mysqlnd.h"
+#include "mysqlnd_priv.h"
+#include "mysqlnd_debug.h"
+#include "mysqlnd_reverse_api.h"
+
+
+static HashTable mysqlnd_api_ext_ht;
+
+
+/* {{{ mysqlnd_reverse_api_init */
+PHPAPI void
+mysqlnd_reverse_api_init(TSRMLS_D)
+{
+ zend_hash_init(&mysqlnd_api_ext_ht, 3, NULL, NULL, 1);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_reverse_api_end */
+PHPAPI void
+mysqlnd_reverse_api_end(TSRMLS_D)
+{
+ zend_hash_destroy(&mysqlnd_api_ext_ht);
+}
+/* }}} */
+
+
+/* {{{ myslqnd_get_api_extensions */
+PHPAPI HashTable *
+mysqlnd_reverse_api_get_api_list(TSRMLS_D)
+{
+ return &mysqlnd_api_ext_ht;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_reverse_api_register_api */
+PHPAPI void
+mysqlnd_reverse_api_register_api(MYSQLND_REVERSE_API * apiext TSRMLS_DC)
+{
+ zend_hash_add(&mysqlnd_api_ext_ht, apiext->module->name, strlen(apiext->module->name) + 1, &apiext,
+ sizeof(MYSQLND_REVERSE_API), NULL);
+}
+/* }}} */
+
+
+/* {{{ zval_to_mysqlnd */
+PHPAPI MYSQLND *
+zval_to_mysqlnd(zval * zv TSRMLS_DC)
+{
+ MYSQLND * retval;
+ MYSQLND_REVERSE_API ** elem;
+
+ for (zend_hash_internal_pointer_reset(&mysqlnd_api_ext_ht);
+ zend_hash_get_current_data(&mysqlnd_api_ext_ht, (void **)&elem) == SUCCESS;
+ zend_hash_move_forward(&mysqlnd_api_ext_ht))
+ {
+ if ((*elem)->conversion_cb) {
+ retval = (*elem)->conversion_cb(zv TSRMLS_CC);
+ if (retval) {
+ return retval;
+ }
+ }
+ }
+
+ return NULL;
+}
+/* }}} */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_reverse_api.h b/ext/mysqlnd/mysqlnd_reverse_api.h
new file mode 100644
index 0000000000..dd23555b94
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_reverse_api.h
@@ -0,0 +1,50 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+/* $Id: mysqlnd.h 318051 2011-10-12 16:18:02Z andrey $ */
+
+#ifndef MYSQLND_REVERSE_API_H
+#define MYSQLND_REVERSE_API_H
+typedef struct st_mysqlnd_reverse_api
+{
+ zend_module_entry * module;
+ MYSQLND *(*conversion_cb)(zval * zv TSRMLS_DC);
+} MYSQLND_REVERSE_API;
+
+
+PHPAPI void mysqlnd_reverse_api_init(TSRMLS_D);
+PHPAPI void mysqlnd_reverse_api_end(TSRMLS_D);
+
+PHPAPI HashTable * mysqlnd_reverse_api_get_api_list(TSRMLS_D);
+
+PHPAPI void mysqlnd_reverse_api_register_api(MYSQLND_REVERSE_API * apiext TSRMLS_DC);
+
+PHPAPI MYSQLND * zval_to_mysqlnd(zval * zv TSRMLS_DC);
+
+#endif /* MYSQLND_REVERSE_API_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
+
diff --git a/ext/mysqlnd/mysqlnd_statistics.c b/ext/mysqlnd/mysqlnd_statistics.c
index eaabaa6e66..271cb29717 100644
--- a/ext/mysqlnd/mysqlnd_statistics.c
+++ b/ext/mysqlnd/mysqlnd_statistics.c
@@ -26,173 +26,171 @@
#include "mysqlnd_debug.h"
-#define STR_W_LEN(str) str, (sizeof(str) - 1)
-
/* {{{ mysqlnd_stats_values_names
*/
const MYSQLND_STRING mysqlnd_stats_values_names[STAT_LAST] =
{
- { STR_W_LEN("bytes_sent") },
- { STR_W_LEN("bytes_received") },
- { STR_W_LEN("packets_sent") },
- { STR_W_LEN("packets_received") },
- { STR_W_LEN("protocol_overhead_in") },
- { STR_W_LEN("protocol_overhead_out") },
- { STR_W_LEN("bytes_received_ok_packet") },
- { STR_W_LEN("bytes_received_eof_packet") },
- { STR_W_LEN("bytes_received_rset_header_packet") },
- { STR_W_LEN("bytes_received_rset_field_meta_packet") },
- { STR_W_LEN("bytes_received_rset_row_packet") },
- { STR_W_LEN("bytes_received_prepare_response_packet") },
- { STR_W_LEN("bytes_received_change_user_packet") },
- { STR_W_LEN("packets_sent_command") },
- { STR_W_LEN("packets_received_ok") },
- { STR_W_LEN("packets_received_eof") },
- { STR_W_LEN("packets_received_rset_header") },
- { STR_W_LEN("packets_received_rset_field_meta") },
- { STR_W_LEN("packets_received_rset_row") },
- { STR_W_LEN("packets_received_prepare_response") },
- { STR_W_LEN("packets_received_change_user") },
- { STR_W_LEN("result_set_queries") },
- { STR_W_LEN("non_result_set_queries") },
- { STR_W_LEN("no_index_used") },
- { STR_W_LEN("bad_index_used") },
- { STR_W_LEN("slow_queries") },
- { STR_W_LEN("buffered_sets") },
- { STR_W_LEN("unbuffered_sets") },
- { STR_W_LEN("ps_buffered_sets") },
- { STR_W_LEN("ps_unbuffered_sets") },
- { STR_W_LEN("flushed_normal_sets") },
- { STR_W_LEN("flushed_ps_sets") },
- { STR_W_LEN("ps_prepared_never_executed") },
- { STR_W_LEN("ps_prepared_once_executed") },
- { STR_W_LEN("rows_fetched_from_server_normal") },
- { STR_W_LEN("rows_fetched_from_server_ps") },
- { STR_W_LEN("rows_buffered_from_client_normal") },
- { STR_W_LEN("rows_buffered_from_client_ps") },
- { STR_W_LEN("rows_fetched_from_client_normal_buffered") },
- { STR_W_LEN("rows_fetched_from_client_normal_unbuffered") },
- { STR_W_LEN("rows_fetched_from_client_ps_buffered") },
- { STR_W_LEN("rows_fetched_from_client_ps_unbuffered") },
- { STR_W_LEN("rows_fetched_from_client_ps_cursor") },
- { STR_W_LEN("rows_affected_normal") },
- { STR_W_LEN("rows_affected_ps") },
- { STR_W_LEN("rows_skipped_normal") },
- { STR_W_LEN("rows_skipped_ps") },
- { STR_W_LEN("copy_on_write_saved") },
- { STR_W_LEN("copy_on_write_performed") },
- { STR_W_LEN("command_buffer_too_small") },
- { STR_W_LEN("connect_success") },
- { STR_W_LEN("connect_failure") },
- { STR_W_LEN("connection_reused") },
- { STR_W_LEN("reconnect") },
- { STR_W_LEN("pconnect_success") },
- { STR_W_LEN("active_connections") },
- { STR_W_LEN("active_persistent_connections") },
- { STR_W_LEN("explicit_close") },
- { STR_W_LEN("implicit_close") },
- { STR_W_LEN("disconnect_close") },
- { STR_W_LEN("in_middle_of_command_close") },
- { STR_W_LEN("explicit_free_result") },
- { STR_W_LEN("implicit_free_result") },
- { STR_W_LEN("explicit_stmt_close") },
- { STR_W_LEN("implicit_stmt_close") },
- { STR_W_LEN("mem_emalloc_count") },
- { STR_W_LEN("mem_emalloc_amount") },
- { STR_W_LEN("mem_ecalloc_count") },
- { STR_W_LEN("mem_ecalloc_amount") },
- { STR_W_LEN("mem_erealloc_count") },
- { STR_W_LEN("mem_erealloc_amount") },
- { STR_W_LEN("mem_efree_count") },
- { STR_W_LEN("mem_efree_amount") },
- { STR_W_LEN("mem_malloc_count") },
- { STR_W_LEN("mem_malloc_amount") },
- { STR_W_LEN("mem_calloc_count") },
- { STR_W_LEN("mem_calloc_amount") },
- { STR_W_LEN("mem_realloc_count") },
- { STR_W_LEN("mem_realloc_amount") },
- { STR_W_LEN("mem_free_count") },
- { STR_W_LEN("mem_free_amount") },
- { STR_W_LEN("mem_estrndup_count") },
- { STR_W_LEN("mem_strndup_count") },
- { STR_W_LEN("mem_estndup_count") },
- { STR_W_LEN("mem_strdup_count") },
- { STR_W_LEN("proto_text_fetched_null") },
- { STR_W_LEN("proto_text_fetched_bit") },
- { STR_W_LEN("proto_text_fetched_tinyint") },
- { STR_W_LEN("proto_text_fetched_short") },
- { STR_W_LEN("proto_text_fetched_int24") },
- { STR_W_LEN("proto_text_fetched_int") },
- { STR_W_LEN("proto_text_fetched_bigint") },
- { STR_W_LEN("proto_text_fetched_decimal") },
- { STR_W_LEN("proto_text_fetched_float") },
- { STR_W_LEN("proto_text_fetched_double") },
- { STR_W_LEN("proto_text_fetched_date") },
- { STR_W_LEN("proto_text_fetched_year") },
- { STR_W_LEN("proto_text_fetched_time") },
- { STR_W_LEN("proto_text_fetched_datetime") },
- { STR_W_LEN("proto_text_fetched_timestamp") },
- { STR_W_LEN("proto_text_fetched_string") },
- { STR_W_LEN("proto_text_fetched_blob") },
- { STR_W_LEN("proto_text_fetched_enum") },
- { STR_W_LEN("proto_text_fetched_set") },
- { STR_W_LEN("proto_text_fetched_geometry") },
- { STR_W_LEN("proto_text_fetched_other") },
- { STR_W_LEN("proto_binary_fetched_null") },
- { STR_W_LEN("proto_binary_fetched_bit") },
- { STR_W_LEN("proto_binary_fetched_tinyint") },
- { STR_W_LEN("proto_binary_fetched_short") },
- { STR_W_LEN("proto_binary_fetched_int24") },
- { STR_W_LEN("proto_binary_fetched_int") },
- { STR_W_LEN("proto_binary_fetched_bigint") },
- { STR_W_LEN("proto_binary_fetched_decimal") },
- { STR_W_LEN("proto_binary_fetched_float") },
- { STR_W_LEN("proto_binary_fetched_double") },
- { STR_W_LEN("proto_binary_fetched_date") },
- { STR_W_LEN("proto_binary_fetched_year") },
- { STR_W_LEN("proto_binary_fetched_time") },
- { STR_W_LEN("proto_binary_fetched_datetime") },
- { STR_W_LEN("proto_binary_fetched_timestamp") },
- { STR_W_LEN("proto_binary_fetched_string") },
- { STR_W_LEN("proto_binary_fetched_blob") },
- { STR_W_LEN("proto_binary_fetched_enum") },
- { STR_W_LEN("proto_binary_fetched_set") },
- { STR_W_LEN("proto_binary_fetched_geometry") },
- { STR_W_LEN("proto_binary_fetched_other") },
- { STR_W_LEN("init_command_executed_count") },
- { STR_W_LEN("init_command_failed_count") },
- { STR_W_LEN("com_quit") },
- { STR_W_LEN("com_init_db") },
- { STR_W_LEN("com_query") },
- { STR_W_LEN("com_field_list") },
- { STR_W_LEN("com_create_db") },
- { STR_W_LEN("com_drop_db") },
- { STR_W_LEN("com_refresh") },
- { STR_W_LEN("com_shutdown") },
- { STR_W_LEN("com_statistics") },
- { STR_W_LEN("com_process_info") },
- { STR_W_LEN("com_connect") },
- { STR_W_LEN("com_process_kill") },
- { STR_W_LEN("com_debug") },
- { STR_W_LEN("com_ping") },
- { STR_W_LEN("com_time") },
- { STR_W_LEN("com_delayed_insert") },
- { STR_W_LEN("com_change_user") },
- { STR_W_LEN("com_binlog_dump") },
- { STR_W_LEN("com_table_dump") },
- { STR_W_LEN("com_connect_out") },
- { STR_W_LEN("com_register_slave") },
- { STR_W_LEN("com_stmt_prepare") },
- { STR_W_LEN("com_stmt_execute") },
- { STR_W_LEN("com_stmt_send_long_data") },
- { STR_W_LEN("com_stmt_close") },
- { STR_W_LEN("com_stmt_reset") },
- { STR_W_LEN("com_stmt_set_option") },
- { STR_W_LEN("com_stmt_fetch") },
- { STR_W_LEN("com_deamon") },
- { STR_W_LEN("bytes_received_real_data_normal") },
- { STR_W_LEN("bytes_received_real_data_ps") }
+ { MYSQLND_STR_W_LEN("bytes_sent") },
+ { MYSQLND_STR_W_LEN("bytes_received") },
+ { MYSQLND_STR_W_LEN("packets_sent") },
+ { MYSQLND_STR_W_LEN("packets_received") },
+ { MYSQLND_STR_W_LEN("protocol_overhead_in") },
+ { MYSQLND_STR_W_LEN("protocol_overhead_out") },
+ { MYSQLND_STR_W_LEN("bytes_received_ok_packet") },
+ { MYSQLND_STR_W_LEN("bytes_received_eof_packet") },
+ { MYSQLND_STR_W_LEN("bytes_received_rset_header_packet") },
+ { MYSQLND_STR_W_LEN("bytes_received_rset_field_meta_packet") },
+ { MYSQLND_STR_W_LEN("bytes_received_rset_row_packet") },
+ { MYSQLND_STR_W_LEN("bytes_received_prepare_response_packet") },
+ { MYSQLND_STR_W_LEN("bytes_received_change_user_packet") },
+ { MYSQLND_STR_W_LEN("packets_sent_command") },
+ { MYSQLND_STR_W_LEN("packets_received_ok") },
+ { MYSQLND_STR_W_LEN("packets_received_eof") },
+ { MYSQLND_STR_W_LEN("packets_received_rset_header") },
+ { MYSQLND_STR_W_LEN("packets_received_rset_field_meta") },
+ { MYSQLND_STR_W_LEN("packets_received_rset_row") },
+ { MYSQLND_STR_W_LEN("packets_received_prepare_response") },
+ { MYSQLND_STR_W_LEN("packets_received_change_user") },
+ { MYSQLND_STR_W_LEN("result_set_queries") },
+ { MYSQLND_STR_W_LEN("non_result_set_queries") },
+ { MYSQLND_STR_W_LEN("no_index_used") },
+ { MYSQLND_STR_W_LEN("bad_index_used") },
+ { MYSQLND_STR_W_LEN("slow_queries") },
+ { MYSQLND_STR_W_LEN("buffered_sets") },
+ { MYSQLND_STR_W_LEN("unbuffered_sets") },
+ { MYSQLND_STR_W_LEN("ps_buffered_sets") },
+ { MYSQLND_STR_W_LEN("ps_unbuffered_sets") },
+ { MYSQLND_STR_W_LEN("flushed_normal_sets") },
+ { MYSQLND_STR_W_LEN("flushed_ps_sets") },
+ { MYSQLND_STR_W_LEN("ps_prepared_never_executed") },
+ { MYSQLND_STR_W_LEN("ps_prepared_once_executed") },
+ { MYSQLND_STR_W_LEN("rows_fetched_from_server_normal") },
+ { MYSQLND_STR_W_LEN("rows_fetched_from_server_ps") },
+ { MYSQLND_STR_W_LEN("rows_buffered_from_client_normal") },
+ { MYSQLND_STR_W_LEN("rows_buffered_from_client_ps") },
+ { MYSQLND_STR_W_LEN("rows_fetched_from_client_normal_buffered") },
+ { MYSQLND_STR_W_LEN("rows_fetched_from_client_normal_unbuffered") },
+ { MYSQLND_STR_W_LEN("rows_fetched_from_client_ps_buffered") },
+ { MYSQLND_STR_W_LEN("rows_fetched_from_client_ps_unbuffered") },
+ { MYSQLND_STR_W_LEN("rows_fetched_from_client_ps_cursor") },
+ { MYSQLND_STR_W_LEN("rows_affected_normal") },
+ { MYSQLND_STR_W_LEN("rows_affected_ps") },
+ { MYSQLND_STR_W_LEN("rows_skipped_normal") },
+ { MYSQLND_STR_W_LEN("rows_skipped_ps") },
+ { MYSQLND_STR_W_LEN("copy_on_write_saved") },
+ { MYSQLND_STR_W_LEN("copy_on_write_performed") },
+ { MYSQLND_STR_W_LEN("command_buffer_too_small") },
+ { MYSQLND_STR_W_LEN("connect_success") },
+ { MYSQLND_STR_W_LEN("connect_failure") },
+ { MYSQLND_STR_W_LEN("connection_reused") },
+ { MYSQLND_STR_W_LEN("reconnect") },
+ { MYSQLND_STR_W_LEN("pconnect_success") },
+ { MYSQLND_STR_W_LEN("active_connections") },
+ { MYSQLND_STR_W_LEN("active_persistent_connections") },
+ { MYSQLND_STR_W_LEN("explicit_close") },
+ { MYSQLND_STR_W_LEN("implicit_close") },
+ { MYSQLND_STR_W_LEN("disconnect_close") },
+ { MYSQLND_STR_W_LEN("in_middle_of_command_close") },
+ { MYSQLND_STR_W_LEN("explicit_free_result") },
+ { MYSQLND_STR_W_LEN("implicit_free_result") },
+ { MYSQLND_STR_W_LEN("explicit_stmt_close") },
+ { MYSQLND_STR_W_LEN("implicit_stmt_close") },
+ { MYSQLND_STR_W_LEN("mem_emalloc_count") },
+ { MYSQLND_STR_W_LEN("mem_emalloc_amount") },
+ { MYSQLND_STR_W_LEN("mem_ecalloc_count") },
+ { MYSQLND_STR_W_LEN("mem_ecalloc_amount") },
+ { MYSQLND_STR_W_LEN("mem_erealloc_count") },
+ { MYSQLND_STR_W_LEN("mem_erealloc_amount") },
+ { MYSQLND_STR_W_LEN("mem_efree_count") },
+ { MYSQLND_STR_W_LEN("mem_efree_amount") },
+ { MYSQLND_STR_W_LEN("mem_malloc_count") },
+ { MYSQLND_STR_W_LEN("mem_malloc_amount") },
+ { MYSQLND_STR_W_LEN("mem_calloc_count") },
+ { MYSQLND_STR_W_LEN("mem_calloc_amount") },
+ { MYSQLND_STR_W_LEN("mem_realloc_count") },
+ { MYSQLND_STR_W_LEN("mem_realloc_amount") },
+ { MYSQLND_STR_W_LEN("mem_free_count") },
+ { MYSQLND_STR_W_LEN("mem_free_amount") },
+ { MYSQLND_STR_W_LEN("mem_estrndup_count") },
+ { MYSQLND_STR_W_LEN("mem_strndup_count") },
+ { MYSQLND_STR_W_LEN("mem_estndup_count") },
+ { MYSQLND_STR_W_LEN("mem_strdup_count") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_null") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_bit") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_tinyint") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_short") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_int24") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_int") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_bigint") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_decimal") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_float") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_double") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_date") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_year") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_time") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_datetime") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_timestamp") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_string") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_blob") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_enum") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_set") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_geometry") },
+ { MYSQLND_STR_W_LEN("proto_text_fetched_other") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_null") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_bit") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_tinyint") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_short") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_int24") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_int") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_bigint") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_decimal") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_float") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_double") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_date") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_year") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_time") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_datetime") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_timestamp") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_string") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_blob") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_enum") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_set") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_geometry") },
+ { MYSQLND_STR_W_LEN("proto_binary_fetched_other") },
+ { MYSQLND_STR_W_LEN("init_command_executed_count") },
+ { MYSQLND_STR_W_LEN("init_command_failed_count") },
+ { MYSQLND_STR_W_LEN("com_quit") },
+ { MYSQLND_STR_W_LEN("com_init_db") },
+ { MYSQLND_STR_W_LEN("com_query") },
+ { MYSQLND_STR_W_LEN("com_field_list") },
+ { MYSQLND_STR_W_LEN("com_create_db") },
+ { MYSQLND_STR_W_LEN("com_drop_db") },
+ { MYSQLND_STR_W_LEN("com_refresh") },
+ { MYSQLND_STR_W_LEN("com_shutdown") },
+ { MYSQLND_STR_W_LEN("com_statistics") },
+ { MYSQLND_STR_W_LEN("com_process_info") },
+ { MYSQLND_STR_W_LEN("com_connect") },
+ { MYSQLND_STR_W_LEN("com_process_kill") },
+ { MYSQLND_STR_W_LEN("com_debug") },
+ { MYSQLND_STR_W_LEN("com_ping") },
+ { MYSQLND_STR_W_LEN("com_time") },
+ { MYSQLND_STR_W_LEN("com_delayed_insert") },
+ { MYSQLND_STR_W_LEN("com_change_user") },
+ { MYSQLND_STR_W_LEN("com_binlog_dump") },
+ { MYSQLND_STR_W_LEN("com_table_dump") },
+ { MYSQLND_STR_W_LEN("com_connect_out") },
+ { MYSQLND_STR_W_LEN("com_register_slave") },
+ { MYSQLND_STR_W_LEN("com_stmt_prepare") },
+ { MYSQLND_STR_W_LEN("com_stmt_execute") },
+ { MYSQLND_STR_W_LEN("com_stmt_send_long_data") },
+ { MYSQLND_STR_W_LEN("com_stmt_close") },
+ { MYSQLND_STR_W_LEN("com_stmt_reset") },
+ { MYSQLND_STR_W_LEN("com_stmt_set_option") },
+ { MYSQLND_STR_W_LEN("com_stmt_fetch") },
+ { MYSQLND_STR_W_LEN("com_deamon") },
+ { MYSQLND_STR_W_LEN("bytes_received_real_data_normal") },
+ { MYSQLND_STR_W_LEN("bytes_received_real_data_ps") }
};
/* }}} */
@@ -257,7 +255,6 @@ mysqlnd_stats_init(MYSQLND_STATS ** stats, size_t statistic_count)
#ifdef ZTS
(*stats)->LOCK_access = tsrm_mutex_alloc();
#endif
-
}
/* }}} */
diff --git a/ext/mysqlnd/mysqlnd_statistics.h b/ext/mysqlnd/mysqlnd_statistics.h
index 4c105011f6..d1fd03b00e 100644
--- a/ext/mysqlnd/mysqlnd_statistics.h
+++ b/ext/mysqlnd/mysqlnd_statistics.h
@@ -26,12 +26,6 @@
PHPAPI extern MYSQLND_STATS * mysqlnd_global_stats;
-typedef struct st_mysqlnd_string
-{
- char *s;
- size_t l;
-} MYSQLND_STRING;
-
extern const MYSQLND_STRING mysqlnd_stats_values_names[];
#ifdef ZTS
diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h
index 6c093ce8c8..5c07a3c3c9 100644
--- a/ext/mysqlnd/mysqlnd_structs.h
+++ b/ext/mysqlnd/mysqlnd_structs.h
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -25,6 +25,12 @@
#define MYSQLND_TYPEDEFED_METHODS
+#define MYSQLND_CLASS_METHOD_TABLE_NAME(class) mysqlnd_##class##_methods
+#define MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(class) struct st_##class##_methods MYSQLND_CLASS_METHOD_TABLE_NAME(class)
+
+#define MYSQLND_CLASS_METHODS_START(class) MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(class) = {
+#define MYSQLND_CLASS_METHODS_END }
+
typedef struct st_mysqlnd_memory_pool MYSQLND_MEMORY_POOL;
typedef struct st_mysqlnd_memory_pool_chunk MYSQLND_MEMORY_POOL_CHUNK;
typedef struct st_mysqlnd_memory_pool_chunk_llist MYSQLND_MEMORY_POOL_CHUNK_LLIST;
@@ -102,9 +108,18 @@ typedef struct st_mysqlnd_error_info
char error[MYSQLND_ERRMSG_SIZE+1];
char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
unsigned int error_no;
+ zend_llist * error_list;
} MYSQLND_ERROR_INFO;
+typedef struct st_mysqlnd_error_list_element
+{
+ char * error;
+ char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
+ unsigned int error_no;
+} MYSQLND_ERROR_LIST_ELEMENT;
+
+
typedef struct st_mysqlnd_infile_info
{
php_stream *fd;
@@ -132,7 +147,7 @@ typedef struct st_mysqlnd_charset
typedef struct st_mysqlnd_infile
{
int (*local_infile_init)(void **ptr, char *filename, void **userdata TSRMLS_DC);
- int (*local_infile_read)(void *ptr, char *buf, unsigned int buf_len TSRMLS_DC);
+ int (*local_infile_read)(void *ptr, zend_uchar * buf, unsigned int buf_len TSRMLS_DC);
int (*local_infile_error)(void *ptr, char *error_msg, unsigned int error_msg_len TSRMLS_DC);
void (*local_infile_end)(void *ptr TSRMLS_DC);
zval *callback;
@@ -151,12 +166,12 @@ typedef struct st_mysqlnd_options
char *cfg_file;
char *cfg_section;
+ char *auth_protocol;
/*
We need to keep these because otherwise st_mysqlnd_conn will be changed.
The ABI will be broken and the methods structure will be somewhere else
in the memory which can crash external code. Feel free to reuse these.
*/
- char * unused1;
char * unused2;
char * unused3;
char * unused4;
@@ -196,6 +211,7 @@ typedef struct st_mysqlnd_net_options
typedef struct st_mysqlnd_connection MYSQLND;
+typedef struct st_mysqlnd_connection_data MYSQLND_CONN_DATA;
typedef struct st_mysqlnd_net MYSQLND_NET;
typedef struct st_mysqlnd_protocol MYSQLND_PROTOCOL;
typedef struct st_mysqlnd_res MYSQLND_RES;
@@ -251,28 +267,39 @@ typedef struct st_mysqlnd_read_buffer {
-typedef enum_func_status (*func_mysqlnd_net__connect)(MYSQLND_NET * net, const char * const scheme, size_t scheme_len, zend_bool persistent, char **errstr, int * errcode TSRMLS_DC);
-typedef size_t (*func_mysqlnd_net__send)(MYSQLND * const conn, char * const buf, size_t count TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_net__receive)(MYSQLND * conn, zend_uchar * buffer, size_t count TSRMLS_DC);
typedef enum_func_status (*func_mysqlnd_net__set_client_option)(MYSQLND_NET * const net, enum_mysqlnd_option option, const char * const value TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_net__network_read)(MYSQLND * conn, zend_uchar * buffer, size_t count TSRMLS_DC);
-typedef size_t (*func_mysqlnd_net__network_write)(MYSQLND * const conn, const zend_uchar * const buf, size_t count TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_net__decode)(zend_uchar * uncompressed_data, size_t uncompressed_data_len, const zend_uchar * const compressed_data, size_t compressed_data_len TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_net__encode)(zend_uchar * compress_buffer, size_t * compress_buffer_len, const zend_uchar * const uncompressed_data, size_t uncompressed_data_len TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_net__decode)(zend_uchar * uncompressed_data, const size_t uncompressed_data_len, const zend_uchar * const compressed_data, const size_t compressed_data_len TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_net__encode)(zend_uchar * compress_buffer, size_t * compress_buffer_len, const zend_uchar * const uncompressed_data, const size_t uncompressed_data_len TSRMLS_DC);
typedef size_t (*func_mysqlnd_net__consume_uneaten_data)(MYSQLND_NET * const net, enum php_mysqlnd_server_command cmd TSRMLS_DC);
typedef void (*func_mysqlnd_net__free_contents)(MYSQLND_NET * net TSRMLS_DC);
typedef enum_func_status (*func_mysqlnd_net__enable_ssl)(MYSQLND_NET * const net TSRMLS_DC);
typedef enum_func_status (*func_mysqlnd_net__disable_ssl)(MYSQLND_NET * const net TSRMLS_DC);
-
+typedef enum_func_status (*func_mysqlnd_net__network_read_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef size_t (*func_mysqlnd_net__network_write_ex)(MYSQLND_NET * const net, const zend_uchar * const buf, const size_t count, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef size_t (*func_mysqlnd_net__send_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_net__receive_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_net__init)(MYSQLND_NET * const net, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef void (*func_mysqlnd_net__dtor)(MYSQLND_NET * const net, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_net__connect_ex)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, const zend_bool persistent, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef void (*func_mysqlnd_net__close_stream)(MYSQLND_NET * const net, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_net__open_stream)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, const zend_bool persistent, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef void (*func_mysqlnd_net__post_connect_set_opt)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_net__read_compressed_packet_from_stream_and_fill_read_buffer)(MYSQLND_NET * net, size_t net_payload_size, MYSQLND_STATS * conn_stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC);
struct st_mysqlnd_net_methods
{
- func_mysqlnd_net__connect connect;
- func_mysqlnd_net__send send;
- func_mysqlnd_net__receive receive;
+ func_mysqlnd_net__init init;
+ func_mysqlnd_net__dtor dtor;
+ func_mysqlnd_net__connect_ex connect_ex;
+ func_mysqlnd_net__close_stream close_stream;
+ func_mysqlnd_net__open_stream open_pipe;
+ func_mysqlnd_net__open_stream open_tcp_or_unix;
+
+ void * unused1;
+ void * unused2;
+ func_mysqlnd_net__post_connect_set_opt post_connect_set_opt;
+
func_mysqlnd_net__set_client_option set_client_option;
- func_mysqlnd_net__network_read network_read;
- func_mysqlnd_net__network_write network_write;
func_mysqlnd_net__decode decode;
func_mysqlnd_net__encode encode;
func_mysqlnd_net__consume_uneaten_data consume_uneaten_data;
@@ -280,11 +307,18 @@ struct st_mysqlnd_net_methods
func_mysqlnd_net__enable_ssl enable_ssl;
func_mysqlnd_net__disable_ssl disable_ssl;
- void * unused1;
- void * unused2;
+ func_mysqlnd_net__network_read_ex network_read_ex;
+ func_mysqlnd_net__network_write_ex network_write_ex;
+ func_mysqlnd_net__send_ex send_ex;
+ func_mysqlnd_net__receive_ex receive_ex;
+
+ func_mysqlnd_net__read_compressed_packet_from_stream_and_fill_read_buffer read_compressed_packet_from_stream_and_fill_read_buffer;
+
void * unused3;
void * unused4;
void * unused5;
+ void * unused6;
+ void * unused7;
};
@@ -300,9 +334,12 @@ struct st_mysqlnd_packet_row;
struct st_mysqlnd_packet_stats;
struct st_mysqlnd_packet_prepare_response;
struct st_mysqlnd_packet_chg_user_resp;
+struct st_mysqlnd_packet_auth_pam;
typedef struct st_mysqlnd_packet_greet * (*func_mysqlnd_protocol__get_greet_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC);
typedef struct st_mysqlnd_packet_auth * (*func_mysqlnd_protocol__get_auth_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC);
+typedef struct st_mysqlnd_packet_auth_response *(*func_mysqlnd_protocol__get_auth_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC);
+typedef struct st_mysqlnd_packet_change_auth_response * (*func_mysqlnd_protocol__get_change_auth_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC);
typedef struct st_mysqlnd_packet_ok * (*func_mysqlnd_protocol__get_ok_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC);
typedef struct st_mysqlnd_packet_command * (*func_mysqlnd_protocol__get_command_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC);
typedef struct st_mysqlnd_packet_eof * (*func_mysqlnd_protocol__get_eof_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC);
@@ -317,6 +354,8 @@ struct st_mysqlnd_protocol_methods
{
func_mysqlnd_protocol__get_greet_packet get_greet_packet;
func_mysqlnd_protocol__get_auth_packet get_auth_packet;
+ func_mysqlnd_protocol__get_auth_response_packet get_auth_response_packet;
+ func_mysqlnd_protocol__get_change_auth_response_packet get_change_auth_response_packet;
func_mysqlnd_protocol__get_ok_packet get_ok_packet;
func_mysqlnd_protocol__get_command_packet get_command_packet;
func_mysqlnd_protocol__get_eof_packet get_eof_packet;
@@ -335,161 +374,194 @@ struct st_mysqlnd_protocol_methods
};
+typedef MYSQLND * (*func_mysqlnd_object_factory__get_connection)(zend_bool persistent TSRMLS_DC);
+typedef MYSQLND * (*func_mysqlnd_object_factory__clone_connection_object)(MYSQLND * conn TSRMLS_DC);
+typedef MYSQLND_STMT * (*func_mysqlnd_object_factory__get_prepared_statement)(MYSQLND_CONN_DATA * conn TSRMLS_DC);
+typedef MYSQLND_NET * (*func_mysqlnd_object_factory__get_io_channel)(zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC);
+typedef MYSQLND_PROTOCOL * (*func_mysqlnd_object_factory__get_protocol_decoder)(zend_bool persistent TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__init)(MYSQLND * conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__connect)(MYSQLND *conn, const char *host, const char * user, const char * passwd, unsigned int passwd_len, const char * db, unsigned int db_len, unsigned int port, const char * socket_or_pipe, unsigned int mysql_flags TSRMLS_DC);
-typedef ulong (*func_mysqlnd_conn__escape_string)(MYSQLND * const conn, char *newstr, const char *escapestr, size_t escapestr_len TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__set_charset)(MYSQLND * const conn, const char * const charset TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__query)(MYSQLND *conn, const char *query, unsigned int query_len TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__send_query)(MYSQLND *conn, const char *query, unsigned int query_len TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__reap_query)(MYSQLND *conn TSRMLS_DC);
-typedef MYSQLND_RES * (*func_mysqlnd_conn__use_result)(MYSQLND * const conn TSRMLS_DC);
-typedef MYSQLND_RES * (*func_mysqlnd_conn__store_result)(MYSQLND * const conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__next_result)(MYSQLND * const conn TSRMLS_DC);
-typedef zend_bool (*func_mysqlnd_conn__more_results)(const MYSQLND * const conn TSRMLS_DC);
-
-typedef MYSQLND_STMT * (*func_mysqlnd_conn__stmt_init)(MYSQLND * const conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__shutdown_server)(MYSQLND * const conn, uint8_t level TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__refresh_server)(MYSQLND * const conn, uint8_t options TSRMLS_DC);
-
-typedef enum_func_status (*func_mysqlnd_conn__ping)(MYSQLND * const conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__kill_connection)(MYSQLND *conn, unsigned int pid TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__select_db)(MYSQLND * const conn, const char * const db, unsigned int db_len TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__server_dump_debug_information)(MYSQLND * const conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__change_user)(MYSQLND * const conn, const char * user, const char * passwd, const char * db, zend_bool silent TSRMLS_DC);
+struct st_mysqlnd_object_factory_methods
+{
+ func_mysqlnd_object_factory__get_connection get_connection;
+ func_mysqlnd_object_factory__clone_connection_object clone_connection_object;
+ func_mysqlnd_object_factory__get_prepared_statement get_prepared_statement;
+ func_mysqlnd_object_factory__get_io_channel get_io_channel;
+ func_mysqlnd_object_factory__get_protocol_decoder get_protocol_decoder;
+};
-typedef unsigned int (*func_mysqlnd_conn__get_error_no)(const MYSQLND * const conn TSRMLS_DC);
-typedef const char * (*func_mysqlnd_conn__get_error_str)(const MYSQLND * const conn TSRMLS_DC);
-typedef const char * (*func_mysqlnd_conn__get_sqlstate)(const MYSQLND * const conn TSRMLS_DC);
-typedef uint64_t (*func_mysqlnd_conn__get_thread_id)(const MYSQLND * const conn TSRMLS_DC);
-typedef void (*func_mysqlnd_conn__get_statistics)(const MYSQLND * const conn, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC);
-typedef unsigned long (*func_mysqlnd_conn__get_server_version)(const MYSQLND * const conn TSRMLS_DC);
-typedef const char * (*func_mysqlnd_conn__get_server_information)(const MYSQLND * const conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__get_server_statistics)(MYSQLND *conn, char **message, unsigned int * message_len TSRMLS_DC);
-typedef const char * (*func_mysqlnd_conn__get_host_information)(const MYSQLND * const conn TSRMLS_DC);
-typedef unsigned int (*func_mysqlnd_conn__get_protocol_information)(const MYSQLND * const conn TSRMLS_DC);
-typedef const char * (*func_mysqlnd_conn__get_last_message)(const MYSQLND * const conn TSRMLS_DC);
-typedef const char * (*func_mysqlnd_conn__charset_name)(const MYSQLND * const conn TSRMLS_DC);
-typedef MYSQLND_RES * (*func_mysqlnd_conn__list_fields)(MYSQLND *conn, const char *table, const char *achtung_wild TSRMLS_DC);
-typedef MYSQLND_RES * (*func_mysqlnd_conn__list_method)(MYSQLND *conn, const char *query, const char *achtung_wild, char *par1 TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__init)(MYSQLND_CONN_DATA * conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__connect)(MYSQLND_CONN_DATA * conn, const char * host, const char * user, const char * passwd, unsigned int passwd_len, const char * db, unsigned int db_len, unsigned int port, const char * socket_or_pipe, unsigned int mysql_flags TSRMLS_DC);
+typedef ulong (*func_mysqlnd_conn_data__escape_string)(MYSQLND_CONN_DATA * const conn, char *newstr, const char *escapestr, size_t escapestr_len TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__set_charset)(MYSQLND_CONN_DATA * const conn, const char * const charset TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__query)(MYSQLND_CONN_DATA * conn, const char * query, unsigned int query_len TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__send_query)(MYSQLND_CONN_DATA * conn, const char *query, unsigned int query_len TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__reap_query)(MYSQLND_CONN_DATA * conn TSRMLS_DC);
+typedef MYSQLND_RES * (*func_mysqlnd_conn_data__use_result)(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef MYSQLND_RES * (*func_mysqlnd_conn_data__store_result)(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__next_result)(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef zend_bool (*func_mysqlnd_conn_data__more_results)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
-typedef uint64_t (*func_mysqlnd_conn__get_last_insert_id)(const MYSQLND * const conn TSRMLS_DC);
-typedef uint64_t (*func_mysqlnd_conn__get_affected_rows)(const MYSQLND * const conn TSRMLS_DC);
-typedef unsigned int (*func_mysqlnd_conn__get_warning_count)(const MYSQLND * const conn TSRMLS_DC);
+typedef MYSQLND_STMT * (*func_mysqlnd_conn_data__stmt_init)(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
-typedef unsigned int (*func_mysqlnd_conn__get_field_count)(const MYSQLND * const conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__shutdown_server)(MYSQLND_CONN_DATA * const conn, uint8_t level TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__refresh_server)(MYSQLND_CONN_DATA * const conn, uint8_t options TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__set_server_option)(MYSQLND * const conn, enum_mysqlnd_server_option option TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__set_client_option)(MYSQLND * const conn, enum_mysqlnd_option option, const char * const value TSRMLS_DC);
-typedef void (*func_mysqlnd_conn__free_contents)(MYSQLND *conn TSRMLS_DC); /* private */
-typedef void (*func_mysqlnd_conn__free_options)(MYSQLND * conn TSRMLS_DC); /* private */
-typedef enum_func_status (*func_mysqlnd_conn__close)(MYSQLND *conn, enum_connection_close_type close_type TSRMLS_DC);
-typedef void (*func_mysqlnd_conn__dtor)(MYSQLND *conn TSRMLS_DC); /* private */
+typedef enum_func_status (*func_mysqlnd_conn_data__ping)(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__kill_connection)(MYSQLND_CONN_DATA * conn, unsigned int pid TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__select_db)(MYSQLND_CONN_DATA * const conn, const char * const db, unsigned int db_len TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__server_dump_debug_information)(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__change_user)(MYSQLND_CONN_DATA * const conn, const char * user, const char * passwd, const char * db, zend_bool silent, size_t passwd_len TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__query_read_result_set_header)(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC);
+typedef unsigned int (*func_mysqlnd_conn_data__get_error_no)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef const char * (*func_mysqlnd_conn_data__get_error_str)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef const char * (*func_mysqlnd_conn_data__get_sqlstate)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef uint64_t (*func_mysqlnd_conn_data__get_thread_id)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef void (*func_mysqlnd_conn_data__get_statistics)(const MYSQLND_CONN_DATA * const conn, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC);
-typedef MYSQLND * (*func_mysqlnd_conn__get_reference)(MYSQLND * const conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__free_reference)(MYSQLND * const conn TSRMLS_DC);
-typedef enum mysqlnd_connection_state (*func_mysqlnd_conn__get_state)(MYSQLND * const conn TSRMLS_DC);
-typedef void (*func_mysqlnd_conn__set_state)(MYSQLND * const conn, enum mysqlnd_connection_state new_state TSRMLS_DC);
+typedef unsigned long (*func_mysqlnd_conn_data__get_server_version)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef const char * (*func_mysqlnd_conn_data__get_server_information)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__get_server_statistics)(MYSQLND_CONN_DATA * conn, char **message, unsigned int * message_len TSRMLS_DC);
+typedef const char * (*func_mysqlnd_conn_data__get_host_information)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef unsigned int (*func_mysqlnd_conn_data__get_protocol_information)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef const char * (*func_mysqlnd_conn_data__get_last_message)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef const char * (*func_mysqlnd_conn_data__charset_name)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef MYSQLND_RES * (*func_mysqlnd_conn_data__list_fields)(MYSQLND_CONN_DATA * conn, const char * table, const char * achtung_wild TSRMLS_DC);
+typedef MYSQLND_RES * (*func_mysqlnd_conn_data__list_method)(MYSQLND_CONN_DATA * conn, const char * query, const char * achtung_wild, char *par1 TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__simple_command)(MYSQLND *conn, enum php_mysqlnd_server_command command, const char * const arg, size_t arg_len, enum mysqlnd_packet_type ok_packet, zend_bool silent, zend_bool ignore_upsert_status TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__simple_command_handle_response)(MYSQLND *conn, enum mysqlnd_packet_type ok_packet, zend_bool silent, enum php_mysqlnd_server_command command, zend_bool ignore_upsert_status TSRMLS_DC);
+typedef uint64_t (*func_mysqlnd_conn_data__get_last_insert_id)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef uint64_t (*func_mysqlnd_conn_data__get_affected_rows)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef unsigned int (*func_mysqlnd_conn_data__get_warning_count)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__restart_psession)(MYSQLND *conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__end_psession)(MYSQLND *conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__send_close)(MYSQLND * conn TSRMLS_DC);
+typedef unsigned int (*func_mysqlnd_conn_data__get_field_count)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__ssl_set)(MYSQLND * const conn, const char * key, const char * const cert, const char * const ca, const char * const capath, const char * const cipher TSRMLS_DC);
+typedef unsigned int (*func_mysqlnd_conn_data__get_server_status)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__set_server_option)(MYSQLND_CONN_DATA * const conn, enum_mysqlnd_server_option option TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__set_client_option)(MYSQLND_CONN_DATA * const conn, enum_mysqlnd_option option, const char * const value TSRMLS_DC);
+typedef void (*func_mysqlnd_conn_data__free_contents)(MYSQLND_CONN_DATA * conn TSRMLS_DC);/* private */
+typedef void (*func_mysqlnd_conn_data__free_options)(MYSQLND_CONN_DATA * conn TSRMLS_DC); /* private */
+typedef void (*func_mysqlnd_conn_data__dtor)(MYSQLND_CONN_DATA * conn TSRMLS_DC); /* private */
-typedef MYSQLND_RES * (*func_mysqlnd_conn__result_init)(unsigned int field_count, zend_bool persistent TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__query_read_result_set_header)(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * stmt TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__set_autocommit)(MYSQLND * conn, unsigned int mode TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__tx_commit)(MYSQLND * conn TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_conn__tx_rollback)(MYSQLND * conn TSRMLS_DC);
+typedef MYSQLND_CONN_DATA * (*func_mysqlnd_conn_data__get_reference)(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__free_reference)(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef enum mysqlnd_connection_state (*func_mysqlnd_conn_data__get_state)(MYSQLND_CONN_DATA * const conn TSRMLS_DC);
+typedef void (*func_mysqlnd_conn_data__set_state)(MYSQLND_CONN_DATA * const conn, enum mysqlnd_connection_state new_state TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__simple_command)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command, const zend_uchar * const arg, size_t arg_len, enum mysqlnd_packet_type ok_packet, zend_bool silent, zend_bool ignore_upsert_status TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__simple_command_handle_response)(MYSQLND_CONN_DATA * conn, enum mysqlnd_packet_type ok_packet, zend_bool silent, enum php_mysqlnd_server_command command, zend_bool ignore_upsert_status TSRMLS_DC);
-struct st_mysqlnd_conn_methods
-{
- func_mysqlnd_conn__init init;
- func_mysqlnd_conn__connect connect;
- func_mysqlnd_conn__escape_string escape_string;
- func_mysqlnd_conn__set_charset set_charset;
- func_mysqlnd_conn__query query;
- func_mysqlnd_conn__send_query send_query;
- func_mysqlnd_conn__reap_query reap_query;
- func_mysqlnd_conn__use_result use_result;
- func_mysqlnd_conn__store_result store_result;
- func_mysqlnd_conn__next_result next_result;
- func_mysqlnd_conn__more_results more_results;
-
- func_mysqlnd_conn__stmt_init stmt_init;
-
- func_mysqlnd_conn__shutdown_server shutdown_server;
- func_mysqlnd_conn__refresh_server refresh_server;
-
- func_mysqlnd_conn__ping ping;
- func_mysqlnd_conn__kill_connection kill_connection;
- func_mysqlnd_conn__select_db select_db;
- func_mysqlnd_conn__server_dump_debug_information server_dump_debug_information;
- func_mysqlnd_conn__change_user change_user;
-
- func_mysqlnd_conn__get_error_no get_error_no;
- func_mysqlnd_conn__get_error_str get_error_str;
- func_mysqlnd_conn__get_sqlstate get_sqlstate;
- func_mysqlnd_conn__get_thread_id get_thread_id;
- func_mysqlnd_conn__get_statistics get_statistics;
-
- func_mysqlnd_conn__get_server_version get_server_version;
- func_mysqlnd_conn__get_server_information get_server_information;
- func_mysqlnd_conn__get_server_statistics get_server_statistics;
- func_mysqlnd_conn__get_host_information get_host_information;
- func_mysqlnd_conn__get_protocol_information get_protocol_information;
- func_mysqlnd_conn__get_last_message get_last_message;
- func_mysqlnd_conn__charset_name charset_name;
- func_mysqlnd_conn__list_fields list_fields;
- func_mysqlnd_conn__list_method list_method;
-
- func_mysqlnd_conn__get_last_insert_id get_last_insert_id;
- func_mysqlnd_conn__get_affected_rows get_affected_rows;
- func_mysqlnd_conn__get_warning_count get_warning_count;
-
- func_mysqlnd_conn__get_field_count get_field_count;
-
- func_mysqlnd_conn__set_server_option set_server_option;
- func_mysqlnd_conn__set_client_option set_client_option;
- func_mysqlnd_conn__free_contents free_contents;
- func_mysqlnd_conn__free_options free_options;
- func_mysqlnd_conn__close close;
- func_mysqlnd_conn__dtor dtor;
+typedef enum_func_status (*func_mysqlnd_conn_data__restart_psession)(MYSQLND_CONN_DATA * conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__end_psession)(MYSQLND_CONN_DATA * conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__send_close)(MYSQLND_CONN_DATA * conn TSRMLS_DC);
- func_mysqlnd_conn__query_read_result_set_header query_read_result_set_header;
+typedef enum_func_status (*func_mysqlnd_conn_data__ssl_set)(MYSQLND_CONN_DATA * const conn, const char * key, const char * const cert, const char * const ca, const char * const capath, const char * const cipher TSRMLS_DC);
- func_mysqlnd_conn__get_reference get_reference;
- func_mysqlnd_conn__free_reference free_reference;
- func_mysqlnd_conn__get_state get_state;
- func_mysqlnd_conn__set_state set_state;
+typedef MYSQLND_RES * (*func_mysqlnd_conn_data__result_init)(unsigned int field_count, zend_bool persistent TSRMLS_DC);
- func_mysqlnd_conn__simple_command simple_command;
- func_mysqlnd_conn__simple_command_handle_response simple_command_handle_response;
+typedef enum_func_status (*func_mysqlnd_conn_data__set_autocommit)(MYSQLND_CONN_DATA * conn, unsigned int mode TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__tx_commit)(MYSQLND_CONN_DATA * conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__tx_rollback)(MYSQLND_CONN_DATA * conn TSRMLS_DC);
- func_mysqlnd_conn__restart_psession restart_psession;
- func_mysqlnd_conn__end_psession end_psession;
- func_mysqlnd_conn__send_close send_close;
+typedef enum_func_status (*func_mysqlnd_conn_data__local_tx_start)(MYSQLND_CONN_DATA * conn, size_t this_func TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn_data__local_tx_end)(MYSQLND_CONN_DATA * conn, size_t this_func, enum_func_status status TSRMLS_DC);
- func_mysqlnd_conn__ssl_set ssl_set;
- func_mysqlnd_conn__result_init result_init;
-#ifdef AUTOCOMMIT_TX_COMMIT_ROLLBACK
- func_mysqlnd_conn__set_autocommit set_autocommit;
- func_mysqlnd_conn__tx_commit tx_commit;
- func_mysqlnd_conn__tx_rollback tx_rollback;
-#endif
+struct st_mysqlnd_conn_data_methods
+{
+ func_mysqlnd_conn_data__init init;
+ func_mysqlnd_conn_data__connect connect;
+ func_mysqlnd_conn_data__escape_string escape_string;
+ func_mysqlnd_conn_data__set_charset set_charset;
+ func_mysqlnd_conn_data__query query;
+ func_mysqlnd_conn_data__send_query send_query;
+ func_mysqlnd_conn_data__reap_query reap_query;
+ func_mysqlnd_conn_data__use_result use_result;
+ func_mysqlnd_conn_data__store_result store_result;
+ func_mysqlnd_conn_data__next_result next_result;
+ func_mysqlnd_conn_data__more_results more_results;
+
+ func_mysqlnd_conn_data__stmt_init stmt_init;
+
+ func_mysqlnd_conn_data__shutdown_server shutdown_server;
+ func_mysqlnd_conn_data__refresh_server refresh_server;
+
+ func_mysqlnd_conn_data__ping ping;
+ func_mysqlnd_conn_data__kill_connection kill_connection;
+ func_mysqlnd_conn_data__select_db select_db;
+ func_mysqlnd_conn_data__server_dump_debug_information server_dump_debug_information;
+ func_mysqlnd_conn_data__change_user change_user;
+
+ func_mysqlnd_conn_data__get_error_no get_error_no;
+ func_mysqlnd_conn_data__get_error_str get_error_str;
+ func_mysqlnd_conn_data__get_sqlstate get_sqlstate;
+ func_mysqlnd_conn_data__get_thread_id get_thread_id;
+ func_mysqlnd_conn_data__get_statistics get_statistics;
+
+ func_mysqlnd_conn_data__get_server_version get_server_version;
+ func_mysqlnd_conn_data__get_server_information get_server_information;
+ func_mysqlnd_conn_data__get_server_statistics get_server_statistics;
+ func_mysqlnd_conn_data__get_host_information get_host_information;
+ func_mysqlnd_conn_data__get_protocol_information get_protocol_information;
+ func_mysqlnd_conn_data__get_last_message get_last_message;
+ func_mysqlnd_conn_data__charset_name charset_name;
+ func_mysqlnd_conn_data__list_fields list_fields;
+ func_mysqlnd_conn_data__list_method list_method;
+
+ func_mysqlnd_conn_data__get_last_insert_id get_last_insert_id;
+ func_mysqlnd_conn_data__get_affected_rows get_affected_rows;
+ func_mysqlnd_conn_data__get_warning_count get_warning_count;
+
+ func_mysqlnd_conn_data__get_field_count get_field_count;
+
+ func_mysqlnd_conn_data__get_server_status get_server_status;
+
+ func_mysqlnd_conn_data__set_server_option set_server_option;
+ func_mysqlnd_conn_data__set_client_option set_client_option;
+ func_mysqlnd_conn_data__free_contents free_contents;
+ func_mysqlnd_conn_data__free_options free_options;
+ func_mysqlnd_conn_data__dtor dtor;
+
+ func_mysqlnd_conn_data__query_read_result_set_header query_read_result_set_header;
+
+ func_mysqlnd_conn_data__get_reference get_reference;
+ func_mysqlnd_conn_data__free_reference free_reference;
+ func_mysqlnd_conn_data__get_state get_state;
+ func_mysqlnd_conn_data__set_state set_state;
+
+ func_mysqlnd_conn_data__simple_command simple_command;
+ func_mysqlnd_conn_data__simple_command_handle_response simple_command_handle_response;
+
+ func_mysqlnd_conn_data__restart_psession restart_psession;
+ func_mysqlnd_conn_data__end_psession end_psession;
+ func_mysqlnd_conn_data__send_close send_close;
+
+ func_mysqlnd_conn_data__ssl_set ssl_set;
+
+ func_mysqlnd_conn_data__result_init result_init;
+ func_mysqlnd_conn_data__set_autocommit set_autocommit;
+ func_mysqlnd_conn_data__tx_commit tx_commit;
+ func_mysqlnd_conn_data__tx_rollback tx_rollback;
+
+ func_mysqlnd_conn_data__local_tx_start local_tx_start;
+ func_mysqlnd_conn_data__local_tx_end local_tx_end;
};
+typedef enum_func_status (*func_mysqlnd_data__connect)(MYSQLND * conn, const char * host, const char * user, const char * passwd, unsigned int passwd_len, const char * db, unsigned int db_len, unsigned int port, const char * socket_or_pipe, unsigned int mysql_flags TSRMLS_DC);
+typedef MYSQLND * (*func_mysqlnd_conn__clone_object)(MYSQLND * const conn TSRMLS_DC);
+typedef void (*func_mysqlnd_conn__dtor)(MYSQLND * conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_conn__close)(MYSQLND * conn, enum_connection_close_type close_type TSRMLS_DC);
+
+struct st_mysqlnd_conn_methods
+{
+ func_mysqlnd_data__connect connect;
+ func_mysqlnd_conn__clone_object clone_object;
+ func_mysqlnd_conn__dtor dtor;
+ func_mysqlnd_conn__close close;
+};
typedef mysqlnd_fetch_row_func fetch_row;
@@ -497,7 +569,7 @@ typedef mysqlnd_fetch_row_func fetch_row_normal_buffered; /* private */
typedef mysqlnd_fetch_row_func fetch_row_normal_unbuffered; /* private */
typedef MYSQLND_RES * (*func_mysqlnd_res__use_result)(MYSQLND_RES * const result, zend_bool ps_protocol TSRMLS_DC);
-typedef MYSQLND_RES * (*func_mysqlnd_res__store_result)(MYSQLND_RES * result, MYSQLND * const conn, zend_bool ps TSRMLS_DC);
+typedef MYSQLND_RES * (*func_mysqlnd_res__store_result)(MYSQLND_RES * result, MYSQLND_CONN_DATA * const conn, zend_bool ps TSRMLS_DC);
typedef void (*func_mysqlnd_res__fetch_into)(MYSQLND_RES *result, unsigned int flags, zval *return_value, enum_mysqlnd_extension ext TSRMLS_DC ZEND_FILE_LINE_DC);
typedef MYSQLND_ROW_C (*func_mysqlnd_res__fetch_row_c)(MYSQLND_RES *result TSRMLS_DC);
typedef void (*func_mysqlnd_res__fetch_all)(MYSQLND_RES *result, unsigned int flags, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC);
@@ -512,9 +584,9 @@ typedef const MYSQLND_FIELD *(*func_mysqlnd_res__fetch_field)(MYSQLND_RES * cons
typedef const MYSQLND_FIELD *(*func_mysqlnd_res__fetch_field_direct)(MYSQLND_RES * const result, MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC);
typedef const MYSQLND_FIELD *(*func_mysqlnd_res__fetch_fields)(MYSQLND_RES * const result TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_res__read_result_metadata)(MYSQLND_RES *result, MYSQLND * conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_res__read_result_metadata)(MYSQLND_RES * result, MYSQLND_CONN_DATA * conn TSRMLS_DC);
typedef unsigned long * (*func_mysqlnd_res__fetch_lengths)(MYSQLND_RES * const result TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_res__store_result_fetch_data)(MYSQLND * const conn, MYSQLND_RES *result, MYSQLND_RES_METADATA *meta, zend_bool binary_protocol, zend_bool to_cache TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_res__store_result_fetch_data)(MYSQLND_CONN_DATA * const conn, MYSQLND_RES * result, MYSQLND_RES_METADATA *meta, zend_bool binary_protocol TSRMLS_DC);
typedef enum_func_status (*func_mysqlnd_res__initialize_result_set_rest)(MYSQLND_RES * const result TSRMLS_DC);
typedef void (*func_mysqlnd_res__free_result_buffers)(MYSQLND_RES * result TSRMLS_DC); /* private */
@@ -527,7 +599,6 @@ typedef void (*func_mysqlnd_res__unbuffered_free_last_data)(MYSQLND_RES *resu
/* for decoding - binary or text protocol */
typedef enum_func_status (*func_mysqlnd_res__row_decoder)(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
- zend_bool persistent,
zend_bool as_unicode, zend_bool as_int_or_float,
MYSQLND_STATS * stats TSRMLS_DC);
@@ -582,7 +653,7 @@ typedef const MYSQLND_FIELD * (*func_mysqlnd_res_meta__fetch_field)(MYSQLND_RES_
typedef const MYSQLND_FIELD * (*func_mysqlnd_res_meta__fetch_field_direct)(const MYSQLND_RES_METADATA * const meta, MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC);
typedef const MYSQLND_FIELD * (*func_mysqlnd_res_meta__fetch_fields)(MYSQLND_RES_METADATA * const meta TSRMLS_DC);
typedef MYSQLND_FIELD_OFFSET (*func_mysqlnd_res_meta__field_tell)(const MYSQLND_RES_METADATA * const meta TSRMLS_DC);
-typedef enum_func_status (*func_mysqlnd_res_meta__read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND * conn TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_res_meta__read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND_CONN_DATA * conn TSRMLS_DC);
typedef MYSQLND_RES_METADATA * (*func_mysqlnd_res_meta__clone_metadata)(const MYSQLND_RES_METADATA * const meta, zend_bool persistent TSRMLS_DC);
typedef void (*func_mysqlnd_res_meta__free_metadata)(MYSQLND_RES_METADATA * meta TSRMLS_DC);
@@ -638,6 +709,7 @@ typedef unsigned int (*func_mysqlnd_stmt__server_status)(const MYSQLND_STMT * c
typedef enum_func_status (*func_mysqlnd_stmt__generate_execute_request)(MYSQLND_STMT * const s, zend_uchar ** request, size_t *request_len, zend_bool * free_buffer TSRMLS_DC);
typedef enum_func_status (*func_mysqlnd_stmt__parse_execute_response)(MYSQLND_STMT * const s TSRMLS_DC);
typedef void (*func_mysqlnd_stmt__free_stmt_content)(MYSQLND_STMT * const s TSRMLS_DC);
+typedef enum_func_status (*func_mysqlnd_stmt__flush)(MYSQLND_STMT * const stmt TSRMLS_DC);
struct st_mysqlnd_stmt_methods
{
@@ -691,23 +763,27 @@ struct st_mysqlnd_stmt_methods
func_mysqlnd_stmt__parse_execute_response parse_execute_response;
func_mysqlnd_stmt__free_stmt_content free_stmt_content;
+
+ func_mysqlnd_stmt__flush flush;
};
struct st_mysqlnd_net
{
php_stream *stream;
- struct st_mysqlnd_net_methods m;
-
/* sequence for simple checking of correct packets */
zend_uchar packet_no;
zend_bool compressed;
zend_uchar compressed_envelope_packet_no;
#ifdef MYSQLND_COMPRESSION_ENABLED
MYSQLND_READ_BUFFER * uncompressed_data;
+#else
+ void * unused_pad1;
#endif
#ifdef MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND
zend_uchar last_command;
+#else
+ zend_uchar unused_pad2;
#endif
/* cmd buffer */
MYSQLND_CMD_BUFFER cmd_buffer;
@@ -715,17 +791,19 @@ struct st_mysqlnd_net
MYSQLND_NET_OPTIONS options;
zend_bool persistent;
+
+ struct st_mysqlnd_net_methods m;
};
struct st_mysqlnd_protocol
{
- struct st_mysqlnd_protocol_methods m;
zend_bool persistent;
+ struct st_mysqlnd_protocol_methods m;
};
-struct st_mysqlnd_connection
+struct st_mysqlnd_connection_data
{
/* Operation related */
MYSQLND_NET * net;
@@ -745,7 +823,8 @@ struct st_mysqlnd_connection
uint64_t thread_id;
char *server_version;
char *host_info;
- unsigned char *scramble;
+ zend_uchar *auth_plugin_data;
+ size_t auth_plugin_data_len;
const MYSQLND_CHARSET *charset;
const MYSQLND_CHARSET *greet_charset;
char *connect_or_select_db;
@@ -758,12 +837,14 @@ struct st_mysqlnd_connection
unsigned long server_capabilities;
/* For UPSERT queries */
- MYSQLND_UPSERT_STATUS upsert_status;
+ MYSQLND_UPSERT_STATUS * upsert_status;
+ MYSQLND_UPSERT_STATUS upsert_status_impl;
char *last_message;
unsigned int last_message_len;
/* If error packet, we use these */
- MYSQLND_ERROR_INFO error_info;
+ MYSQLND_ERROR_INFO * error_info;
+ MYSQLND_ERROR_INFO error_info_impl;
/*
To prevent queries during unbuffered fetches. Also to
@@ -790,12 +871,21 @@ struct st_mysqlnd_connection
zend_bool persistent;
/* options */
- MYSQLND_OPTIONS options;
+ MYSQLND_OPTIONS * options;
+ MYSQLND_OPTIONS options_impl;
/* stats */
MYSQLND_STATS * stats;
- struct st_mysqlnd_conn_methods *m;
+ struct st_mysqlnd_conn_data_methods * m;
+};
+
+
+struct st_mysqlnd_connection
+{
+ MYSQLND_CONN_DATA * data;
+ zend_bool persistent;
+ struct st_mysqlnd_conn_methods * m;
};
@@ -832,7 +922,6 @@ struct st_mysqlnd_buffered_result
MYSQLND_MEMORY_POOL_CHUNK **row_buffers;
uint64_t row_count;
uint64_t initialized_rows;
- zend_bool persistent;
unsigned int references;
@@ -853,9 +942,7 @@ struct st_mysqlnd_unbuffered_result
struct st_mysqlnd_res
{
- struct st_mysqlnd_res_methods m;
-
- MYSQLND *conn;
+ MYSQLND_CONN_DATA *conn;
enum_mysqlnd_res_type type;
unsigned int field_count;
@@ -876,6 +963,8 @@ struct st_mysqlnd_res
MYSQLND_MEMORY_POOL * result_set_memory_pool;
zend_bool persistent;
+
+ struct st_mysqlnd_res_methods m;
};
@@ -895,7 +984,7 @@ struct st_mysqlnd_result_bind
struct st_mysqlnd_stmt_data
{
- MYSQLND *conn;
+ MYSQLND_CONN_DATA *conn;
unsigned long stmt_id;
unsigned long flags;/* cursor is set here */
enum_mysqlnd_stmt_state state;
@@ -909,9 +998,11 @@ struct st_mysqlnd_stmt_data
zend_bool result_zvals_separated_once;
zend_bool persistent;
- MYSQLND_UPSERT_STATUS upsert_status;
+ MYSQLND_UPSERT_STATUS * upsert_status;
+ MYSQLND_UPSERT_STATUS upsert_status_impl;
- MYSQLND_ERROR_INFO error_info;
+ MYSQLND_ERROR_INFO * error_info;
+ MYSQLND_ERROR_INFO error_info_impl;
zend_bool update_max_length;
unsigned long prefetch_rows;
@@ -931,4 +1022,64 @@ struct st_mysqlnd_stmt
zend_bool persistent;
};
+
+typedef struct st_mysqlnd_string
+{
+ char *s;
+ size_t l;
+} MYSQLND_STRING;
+
+
+struct st_mysqlnd_plugin_header
+{
+ unsigned int plugin_api_version;
+ const char * plugin_name;
+ unsigned long plugin_version;
+ const char * plugin_string_version;
+ const char * plugin_license;
+ const char * plugin_author;
+ struct
+ {
+ MYSQLND_STATS * values;
+ const MYSQLND_STRING * names;
+ } plugin_stats;
+
+ struct
+ {
+ enum_func_status (*plugin_shutdown)(void * plugin TSRMLS_DC);
+ } m;
+};
+
+
+struct st_mysqlnd_plugin_core
+{
+ struct st_mysqlnd_plugin_header plugin_header;
+};
+
+
+struct st_mysqlnd_typeii_plugin_example
+{
+ struct st_mysqlnd_plugin_header plugin_header;
+ void * methods;
+ unsigned int counter;
+};
+
+struct st_mysqlnd_authentication_plugin;
+
+typedef zend_uchar * (*func_auth_plugin__get_auth_data)(struct st_mysqlnd_authentication_plugin * self,
+ size_t * auth_data_len,
+ MYSQLND_CONN_DATA * conn, const char * const user, const char * const passwd,
+ const size_t passwd_len, zend_uchar * auth_plugin_data, size_t auth_plugin_data_len,
+ const MYSQLND_OPTIONS * const options, unsigned long mysql_flags
+ TSRMLS_DC);
+
+struct st_mysqlnd_authentication_plugin
+{
+ struct st_mysqlnd_plugin_header plugin_header;
+ struct {
+ func_auth_plugin__get_auth_data get_auth_data;
+ } methods;
+};
+
+
#endif /* MYSQLND_STRUCTS_H */
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c
index d78191ac7e..d0ab9fe731 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.c
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.c
@@ -12,11 +12,13 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
+
+/* $Id$ */
#include "php.h"
#include "php_globals.h"
#include "mysqlnd.h"
@@ -24,7 +26,6 @@
#include "mysqlnd_wireprotocol.h"
#include "mysqlnd_statistics.h"
#include "mysqlnd_debug.h"
-#include "ext/standard/sha1.h"
#include "zend_ini.h"
#define MYSQLND_SILENT 1
@@ -34,9 +35,9 @@
#define PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_size, packet_type_as_text, packet_type) \
{ \
DBG_INF_FMT("buf=%p size=%u", (buf), (buf_size)); \
- if (FAIL == mysqlnd_read_header((conn), &((packet)->header) TSRMLS_CC)) {\
+ if (FAIL == mysqlnd_read_header((conn)->net, &((packet)->header), (conn)->stats, ((conn)->error_info) TSRMLS_CC)) {\
CONN_SET_STATE(conn, CONN_QUIT_SENT); \
- SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);\
+ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);\
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mysqlnd_server_gone); \
DBG_ERR_FMT("Can't read %s's header", (packet_type_as_text)); \
DBG_RETURN(FAIL);\
@@ -46,9 +47,9 @@
(buf_size), (packet)->header.size, (packet)->header.size - (buf_size)); \
DBG_RETURN(FAIL); \
}\
- if (FAIL == conn->net->m.receive((conn), (buf), (packet)->header.size TSRMLS_CC)) { \
+ if (FAIL == conn->net->m.receive_ex((conn)->net, (buf), (packet)->header.size, (conn)->stats, ((conn)->error_info) TSRMLS_CC)) { \
CONN_SET_STATE(conn, CONN_QUIT_SENT); \
- SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);\
+ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);\
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mysqlnd_server_gone); \
DBG_ERR_FMT("Empty '%s' packet body", (packet_type_as_text)); \
DBG_RETURN(FAIL);\
@@ -257,14 +258,14 @@ end:
/* {{{ mysqlnd_read_header */
static enum_func_status
-mysqlnd_read_header(MYSQLND * conn, MYSQLND_PACKET_HEADER * header TSRMLS_DC)
+mysqlnd_read_header(MYSQLND_NET * net, MYSQLND_PACKET_HEADER * header,
+ MYSQLND_STATS * conn_stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC)
{
- MYSQLND_NET * net = conn->net;
zend_uchar buffer[MYSQLND_HEADER_SIZE];
- DBG_ENTER("mysqlnd_read_header_name");
- DBG_INF_FMT("compressed=%u conn_id=%u", net->compressed, conn->thread_id);
- if (FAIL == net->m.receive(conn, buffer, MYSQLND_HEADER_SIZE TSRMLS_CC)) {
+ DBG_ENTER(mysqlnd_read_header_name);
+ DBG_INF_FMT("compressed=%u", net->compressed);
+ if (FAIL == net->m.receive_ex(net, buffer, MYSQLND_HEADER_SIZE, conn_stats, error_info TSRMLS_CC)) {
DBG_RETURN(FAIL);
}
@@ -274,7 +275,7 @@ mysqlnd_read_header(MYSQLND * conn, MYSQLND_PACKET_HEADER * header TSRMLS_DC)
#ifdef MYSQLND_DUMP_HEADER_N_BODY
DBG_INF_FMT("HEADER: prot_packet_no=%u size=%3u", header->packet_no, header->size);
#endif
- MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn->stats,
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn_stats,
STAT_PROTOCOL_OVERHEAD_IN, MYSQLND_HEADER_SIZE,
STAT_PACKETS_RECEIVED, 1);
@@ -300,11 +301,12 @@ mysqlnd_read_header(MYSQLND * conn, MYSQLND_PACKET_HEADER * header TSRMLS_DC)
/* {{{ php_mysqlnd_greet_read */
static enum_func_status
-php_mysqlnd_greet_read(void *_packet, MYSQLND *conn TSRMLS_DC)
+php_mysqlnd_greet_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
zend_uchar buf[2048];
zend_uchar *p = buf;
zend_uchar *begin = buf;
+ zend_uchar *pad_start = NULL;
MYSQLND_PACKET_GREET *packet= (MYSQLND_PACKET_GREET *) _packet;
DBG_ENTER("php_mysqlnd_greet_read");
@@ -312,6 +314,17 @@ php_mysqlnd_greet_read(void *_packet, MYSQLND *conn TSRMLS_DC)
PACKET_READ_HEADER_AND_BODY(packet, conn, buf, sizeof(buf), "greeting", PROT_GREET_PACKET);
BAIL_IF_NO_MORE_DATA;
+ packet->auth_plugin_data = packet->intern_auth_plugin_data;
+ packet->auth_plugin_data_len = sizeof(packet->intern_auth_plugin_data);
+
+ if (packet->header.size < sizeof(buf)) {
+ /*
+ Null-terminate the string, so strdup can work even if the packets have a string at the end,
+ which is not ASCIIZ
+ */
+ buf[packet->header.size] = '\0';
+ }
+
packet->protocol_version = uint1korr(p);
p++;
BAIL_IF_NO_MORE_DATA;
@@ -340,8 +353,8 @@ php_mysqlnd_greet_read(void *_packet, MYSQLND *conn TSRMLS_DC)
p+=4;
BAIL_IF_NO_MORE_DATA;
- memcpy(packet->scramble_buf, p, SCRAMBLE_LENGTH_323);
- p+= 8;
+ memcpy(packet->auth_plugin_data, p, SCRAMBLE_LENGTH_323);
+ p+= SCRAMBLE_LENGTH_323;
BAIL_IF_NO_MORE_DATA;
/* pad1 */
@@ -361,22 +374,56 @@ php_mysqlnd_greet_read(void *_packet, MYSQLND *conn TSRMLS_DC)
BAIL_IF_NO_MORE_DATA;
/* pad2 */
+ pad_start = p;
p+= 13;
BAIL_IF_NO_MORE_DATA;
if ((size_t) (p - buf) < packet->header.size) {
- /* scramble_buf is split into two parts */
- memcpy(packet->scramble_buf + SCRAMBLE_LENGTH_323,
- p, SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
+ /* auth_plugin_data is split into two parts */
+ memcpy(packet->auth_plugin_data + SCRAMBLE_LENGTH_323, p, SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
+ p+= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323;
+ p++; /* 0x0 at the end of the scramble and thus last byte in the packet in 5.1 and previous */
} else {
packet->pre41 = TRUE;
}
+ /* Is this a 5.5+ server ? */
+ if ((size_t) (p - buf) < packet->header.size) {
+ /* backtrack one byte, the 0x0 at the end of the scramble in 5.1 and previous */
+ p--;
+
+ /* Additional 16 bits for server capabilities */
+ packet->server_capabilities |= uint2korr(pad_start) << 16;
+ /* And a length of the server scramble in one byte */
+ packet->auth_plugin_data_len = uint1korr(pad_start + 2);
+ if (packet->auth_plugin_data_len > SCRAMBLE_LENGTH) {
+ /* more data*/
+ zend_uchar * new_auth_plugin_data = emalloc(packet->auth_plugin_data_len);
+ if (!new_auth_plugin_data) {
+ goto premature_end;
+ }
+ /* copy what we already have */
+ memcpy(new_auth_plugin_data, packet->auth_plugin_data, SCRAMBLE_LENGTH);
+ /* add additional scramble data 5.5+ sent us */
+ memcpy(new_auth_plugin_data + SCRAMBLE_LENGTH, p, packet->auth_plugin_data_len - SCRAMBLE_LENGTH);
+ p+= (packet->auth_plugin_data_len - SCRAMBLE_LENGTH);
+ packet->auth_plugin_data = new_auth_plugin_data;
+ }
+ }
+
+ if (packet->server_capabilities & CLIENT_PLUGIN_AUTH) {
+ BAIL_IF_NO_MORE_DATA;
+ /* The server is 5.5.x and supports authentication plugins */
+ packet->auth_protocol = estrdup((char *)p);
+ p+= strlen(packet->auth_protocol) + 1; /* eat the '\0' */
+ }
+
DBG_INF_FMT("proto=%u server=%s thread_id=%u",
packet->protocol_version, packet->server_version, packet->thread_id);
- DBG_INF_FMT("server_capabilities=%u charset_no=%u server_status=%i",
- packet->server_capabilities, packet->charset_no, packet->server_status);
+ DBG_INF_FMT("server_capabilities=%u charset_no=%u server_status=%i auth_protocol=%s scramble_length=%u",
+ packet->server_capabilities, packet->charset_no, packet->server_status,
+ packet->auth_protocol? packet->auth_protocol:"n/a", packet->auth_plugin_data_len);
DBG_RETURN(PASS);
premature_end:
@@ -390,13 +437,21 @@ premature_end:
/* {{{ php_mysqlnd_greet_free_mem */
static
-void php_mysqlnd_greet_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+void php_mysqlnd_greet_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
MYSQLND_PACKET_GREET *p= (MYSQLND_PACKET_GREET *) _packet;
if (p->server_version) {
efree(p->server_version);
p->server_version = NULL;
}
+ if (p->auth_plugin_data && p->auth_plugin_data != p->intern_auth_plugin_data) {
+ efree(p->auth_plugin_data);
+ p->auth_plugin_data = NULL;
+ }
+ if (p->auth_protocol) {
+ efree(p->auth_protocol);
+ p->auth_protocol = NULL;
+ }
if (!stack_allocation) {
mnd_pefree(p, p->header.persistent);
}
@@ -404,110 +459,109 @@ void php_mysqlnd_greet_free_mem(void *_packet, zend_bool stack_allocation TSRMLS
/* }}} */
-/* {{{ php_mysqlnd_crypt */
-static void
-php_mysqlnd_crypt(zend_uchar *buffer, const zend_uchar *s1, const zend_uchar *s2, size_t len)
-{
- const zend_uchar *s1_end = s1 + len;
- while (s1 < s1_end) {
- *buffer++= *s1++ ^ *s2++;
- }
-}
-/* }}} */
-
-
-/* {{{ php_mysqlnd_scramble */
-void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const password)
-{
- PHP_SHA1_CTX context;
- zend_uchar sha1[SHA1_MAX_LENGTH];
- zend_uchar sha2[SHA1_MAX_LENGTH];
-
-
- /* Phase 1: hash password */
- PHP_SHA1Init(&context);
- PHP_SHA1Update(&context, password, strlen((char *)password));
- PHP_SHA1Final(sha1, &context);
-
- /* Phase 2: hash sha1 */
- PHP_SHA1Init(&context);
- PHP_SHA1Update(&context, (zend_uchar*)sha1, SHA1_MAX_LENGTH);
- PHP_SHA1Final(sha2, &context);
-
- /* Phase 3: hash scramble + sha2 */
- PHP_SHA1Init(&context);
- PHP_SHA1Update(&context, scramble, SCRAMBLE_LENGTH);
- PHP_SHA1Update(&context, (zend_uchar*)sha2, SHA1_MAX_LENGTH);
- PHP_SHA1Final(buffer, &context);
-
- /* let's crypt buffer now */
- php_mysqlnd_crypt(buffer, (const zend_uchar *)buffer, (const zend_uchar *)sha1, SHA1_MAX_LENGTH);
-}
-/* }}} */
-
-
-#define AUTH_WRITE_BUFFER_LEN (MYSQLND_HEADER_SIZE + MYSQLND_MAX_ALLOWED_USER_LEN + SHA1_MAX_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1 + 128)
+#define AUTH_WRITE_BUFFER_LEN (MYSQLND_HEADER_SIZE + MYSQLND_MAX_ALLOWED_USER_LEN + SCRAMBLE_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1 + 1024)
/* {{{ php_mysqlnd_auth_write */
static
-size_t php_mysqlnd_auth_write(void *_packet, MYSQLND * conn TSRMLS_DC)
+size_t php_mysqlnd_auth_write(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
- char buffer[AUTH_WRITE_BUFFER_LEN];
- register char *p= buffer + MYSQLND_HEADER_SIZE; /* start after the header */
+ zend_uchar buffer[AUTH_WRITE_BUFFER_LEN];
+ zend_uchar *p = buffer + MYSQLND_HEADER_SIZE; /* start after the header */
int len;
- register MYSQLND_PACKET_AUTH *packet= (MYSQLND_PACKET_AUTH *) _packet;
+ MYSQLND_PACKET_AUTH * packet= (MYSQLND_PACKET_AUTH *) _packet;
DBG_ENTER("php_mysqlnd_auth_write");
- int4store(p, packet->client_flags);
- p+= 4;
+ if (!packet->is_change_user_packet) {
+ int4store(p, packet->client_flags);
+ p+= 4;
- int4store(p, packet->max_packet_size);
- p+= 4;
+ int4store(p, packet->max_packet_size);
+ p+= 4;
- int1store(p, packet->charset_no);
- p++;
+ int1store(p, packet->charset_no);
+ p++;
- memset(p, 0, 23); /* filler */
- p+= 23;
+ memset(p, 0, 23); /* filler */
+ p+= 23;
+ }
- if (!packet->send_half_packet) {
+ if (packet->send_auth_data || packet->is_change_user_packet) {
len = MIN(strlen(packet->user), MYSQLND_MAX_ALLOWED_USER_LEN);
memcpy(p, packet->user, len);
p+= len;
*p++ = '\0';
- /* copy scrambled pass*/
- if (packet->password && packet->password[0]) {
- /* In 4.1 we use CLIENT_SECURE_CONNECTION and thus the len of the buf should be passed */
- int1store(p, SHA1_MAX_LENGTH);
- p++;
- php_mysqlnd_scramble((zend_uchar*)p, packet->server_scramble_buf, (zend_uchar*)packet->password);
- p+= SHA1_MAX_LENGTH;
- } else {
- /* Zero length */
- int1store(p, 0);
- p++;
+ /* defensive coding */
+ if (packet->auth_data == NULL) {
+ packet->auth_data_len = 0;
+ }
+ if (packet->auth_data_len > 0xFF) {
+ const char * const msg = "Authentication data too long. "
+ "Won't fit into the buffer and will be truncated. Authentication will thus fail";
+ SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, msg);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", msg);
+ DBG_RETURN(0);
+ }
+
+ int1store(p, packet->auth_data_len);
+ ++p;
+/*!!!!! is the buffer big enough ??? */
+ if ((sizeof(buffer) - (p - buffer)) < packet->auth_data_len) {
+ DBG_ERR("the stack buffer was not enough!!");
+ DBG_RETURN(0);
+ }
+ if (packet->auth_data_len) {
+ memcpy(p, packet->auth_data, packet->auth_data_len);
+ p+= packet->auth_data_len;
}
if (packet->db) {
+ /* CLIENT_CONNECT_WITH_DB should have been set */
size_t real_db_len = MIN(MYSQLND_MAX_ALLOWED_DB_LEN, packet->db_len);
memcpy(p, packet->db, real_db_len);
p+= real_db_len;
*p++= '\0';
+ } else if (packet->is_change_user_packet) {
+ *p++= '\0';
}
- /* Handle CLIENT_CONNECT_WITH_DB */
/* no \0 for no DB */
- }
- DBG_RETURN(conn->net->m.send(conn, buffer, p - buffer - MYSQLND_HEADER_SIZE TSRMLS_CC));
+ if (packet->is_change_user_packet) {
+ if (packet->charset_no) {
+ int2store(p, packet->charset_no);
+ p+= 2;
+ }
+ }
+
+ if (packet->auth_plugin_name) {
+ size_t len = MIN(strlen(packet->auth_plugin_name), sizeof(buffer) - (p - buffer) - 1);
+ memcpy(p, packet->auth_plugin_name, len);
+ p+= len;
+ *p++= '\0';
+ }
+ }
+ if (packet->is_change_user_packet) {
+ if (PASS != conn->m->simple_command(conn, COM_CHANGE_USER, buffer + MYSQLND_HEADER_SIZE, p - buffer - MYSQLND_HEADER_SIZE,
+ PROT_LAST /* the caller will handle the OK packet */,
+ packet->silent, TRUE TSRMLS_CC)) {
+ DBG_RETURN(0);
+ }
+ DBG_RETURN(p - buffer - MYSQLND_HEADER_SIZE);
+ } else {
+ size_t sent = conn->net->m.send_ex(conn->net, buffer, p - buffer - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info TSRMLS_CC);
+ if (!sent) {
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ }
+ DBG_RETURN(sent);
+ }
}
/* }}} */
/* {{{ php_mysqlnd_auth_free_mem */
static
-void php_mysqlnd_auth_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+void php_mysqlnd_auth_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
if (!stack_allocation) {
MYSQLND_PACKET_AUTH * p = (MYSQLND_PACKET_AUTH *) _packet;
@@ -517,11 +571,174 @@ void php_mysqlnd_auth_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_
/* }}} */
+#define AUTH_RESP_BUFFER_SIZE 2048
+
+/* {{{ php_mysqlnd_auth_response_read */
+static enum_func_status
+php_mysqlnd_auth_response_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
+{
+ zend_uchar local_buf[AUTH_RESP_BUFFER_SIZE];
+ size_t buf_len = conn->net->cmd_buffer.buffer? conn->net->cmd_buffer.length: AUTH_RESP_BUFFER_SIZE;
+ zend_uchar *buf = conn->net->cmd_buffer.buffer? (zend_uchar *) conn->net->cmd_buffer.buffer : local_buf;
+ zend_uchar *p = buf;
+ zend_uchar *begin = buf;
+ unsigned long i;
+ register MYSQLND_PACKET_AUTH_RESPONSE * packet= (MYSQLND_PACKET_AUTH_RESPONSE *) _packet;
+
+ DBG_ENTER("php_mysqlnd_auth_response_read");
+
+ /* leave space for terminating safety \0 */
+ buf_len--;
+ PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "OK", PROT_OK_PACKET);
+ BAIL_IF_NO_MORE_DATA;
+
+ /*
+ zero-terminate the buffer for safety. We are sure there is place for the \0
+ because buf_len is -1 the size of the buffer pointed
+ */
+ buf[packet->header.size] = '\0';
+
+ /* Should be always 0x0 or ERROR_MARKER for error */
+ packet->response_code = uint1korr(p);
+ p++;
+ BAIL_IF_NO_MORE_DATA;
+
+ if (ERROR_MARKER == packet->response_code) {
+ php_mysqlnd_read_error_from_line(p, packet->header.size - 1,
+ packet->error, sizeof(packet->error),
+ &packet->error_no, packet->sqlstate
+ TSRMLS_CC);
+ DBG_RETURN(PASS);
+ }
+ if (0xFE == packet->response_code) {
+ /* Authentication Switch Response */
+ if (packet->header.size > (size_t) (p - buf)) {
+ packet->new_auth_protocol = mnd_pestrdup((char *)p, FALSE);
+ packet->new_auth_protocol_len = strlen(packet->new_auth_protocol);
+ p+= packet->new_auth_protocol_len + 1; /* +1 for the \0 */
+
+ packet->new_auth_protocol_data_len = packet->header.size - (size_t) (p - buf);
+ if (packet->new_auth_protocol_data_len) {
+ packet->new_auth_protocol_data = mnd_emalloc(packet->new_auth_protocol_data_len);
+ memcpy(packet->new_auth_protocol_data, p, packet->new_auth_protocol_data_len);
+ }
+ DBG_INF_FMT("The server requested switching auth plugin to : %s", packet->new_auth_protocol);
+ DBG_INF_FMT("Server salt : [%*s]", packet->new_auth_protocol_data_len, packet->new_auth_protocol_data);
+ }
+ } else {
+ /* Everything was fine! */
+ packet->affected_rows = php_mysqlnd_net_field_length_ll(&p);
+ BAIL_IF_NO_MORE_DATA;
+
+ packet->last_insert_id = php_mysqlnd_net_field_length_ll(&p);
+ BAIL_IF_NO_MORE_DATA;
+
+ packet->server_status = uint2korr(p);
+ p+= 2;
+ BAIL_IF_NO_MORE_DATA;
+
+ packet->warning_count = uint2korr(p);
+ p+= 2;
+ BAIL_IF_NO_MORE_DATA;
+
+ /* There is a message */
+ if (packet->header.size > (size_t) (p - buf) && (i = php_mysqlnd_net_field_length(&p))) {
+ packet->message_len = MIN(i, buf_len - (p - begin));
+ packet->message = mnd_pestrndup((char *)p, packet->message_len, FALSE);
+ } else {
+ packet->message = NULL;
+ packet->message_len = 0;
+ }
+
+ DBG_INF_FMT("OK packet: aff_rows=%lld last_ins_id=%ld server_status=%u warnings=%u",
+ packet->affected_rows, packet->last_insert_id, packet->server_status,
+ packet->warning_count);
+ }
+
+ DBG_RETURN(PASS);
+premature_end:
+ DBG_ERR_FMT("OK packet %d bytes shorter than expected", p - begin - packet->header.size);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "AUTH_RESPONSE packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected",
+ p - begin - packet->header.size);
+ DBG_RETURN(FAIL);
+}
+/* }}} */
+
+
+/* {{{ php_mysqlnd_auth_response_free_mem */
+static void
+php_mysqlnd_auth_response_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
+{
+ MYSQLND_PACKET_AUTH_RESPONSE * p = (MYSQLND_PACKET_AUTH_RESPONSE *) _packet;
+ if (p->message) {
+ mnd_efree(p->message);
+ p->message = NULL;
+ }
+ if (p->new_auth_protocol) {
+ mnd_efree(p->new_auth_protocol);
+ p->new_auth_protocol = NULL;
+ }
+ p->new_auth_protocol_len = 0;
+
+ if (p->new_auth_protocol_data) {
+ mnd_efree(p->new_auth_protocol_data);
+ p->new_auth_protocol_data = NULL;
+ }
+ p->new_auth_protocol_data_len = 0;
+
+ if (!stack_allocation) {
+ mnd_pefree(p, p->header.persistent);
+ }
+}
+/* }}} */
+
+
+/* {{{ php_mysqlnd_change_auth_response_write */
+static size_t
+php_mysqlnd_change_auth_response_write(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
+{
+ MYSQLND_PACKET_CHANGE_AUTH_RESPONSE *packet= (MYSQLND_PACKET_CHANGE_AUTH_RESPONSE *) _packet;
+ zend_uchar * buffer = conn->net->cmd_buffer.length >= packet->auth_data_len? conn->net->cmd_buffer.buffer : mnd_emalloc(packet->auth_data_len);
+ zend_uchar *p = buffer + MYSQLND_HEADER_SIZE; /* start after the header */
+
+ DBG_ENTER("php_mysqlnd_change_auth_response_write");
+
+ if (packet->auth_data_len) {
+ memcpy(p, packet->auth_data, packet->auth_data_len);
+ p+= packet->auth_data_len;
+ }
+
+ {
+ size_t sent = conn->net->m.send_ex(conn->net, buffer, p - buffer - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info TSRMLS_CC);
+ if (buffer != conn->net->cmd_buffer.buffer) {
+ mnd_efree(buffer);
+ }
+ if (!sent) {
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ }
+ DBG_RETURN(sent);
+ }
+}
+/* }}} */
+
+
+/* {{{ php_mysqlnd_change_auth_response_free_mem */
+static void
+php_mysqlnd_change_auth_response_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
+{
+ if (!stack_allocation) {
+ MYSQLND_PACKET_CHANGE_AUTH_RESPONSE * p = (MYSQLND_PACKET_CHANGE_AUTH_RESPONSE *) _packet;
+ mnd_pefree(p, p->header.persistent);
+ }
+}
+/* }}} */
+
+
#define OK_BUFFER_SIZE 2048
/* {{{ php_mysqlnd_ok_read */
static enum_func_status
-php_mysqlnd_ok_read(void *_packet, MYSQLND *conn TSRMLS_DC)
+php_mysqlnd_ok_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
zend_uchar local_buf[OK_BUFFER_SIZE];
size_t buf_len = conn->net->cmd_buffer.buffer? conn->net->cmd_buffer.length : OK_BUFFER_SIZE;
@@ -590,7 +807,7 @@ premature_end:
/* {{{ php_mysqlnd_ok_free_mem */
static void
-php_mysqlnd_ok_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+php_mysqlnd_ok_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
MYSQLND_PACKET_OK *p= (MYSQLND_PACKET_OK *) _packet;
if (p->message) {
@@ -606,7 +823,7 @@ php_mysqlnd_ok_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
/* {{{ php_mysqlnd_eof_read */
static enum_func_status
-php_mysqlnd_eof_read(void *_packet, MYSQLND *conn TSRMLS_DC)
+php_mysqlnd_eof_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
/*
EOF packet is since 4.1 five bytes long,
@@ -673,7 +890,7 @@ premature_end:
/* {{{ php_mysqlnd_eof_free_mem */
static
-void php_mysqlnd_eof_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+void php_mysqlnd_eof_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
if (!stack_allocation) {
mnd_pefree(_packet, ((MYSQLND_PACKET_EOF *)_packet)->header.persistent);
@@ -683,13 +900,13 @@ void php_mysqlnd_eof_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_D
/* {{{ php_mysqlnd_cmd_write */
-size_t php_mysqlnd_cmd_write(void *_packet, MYSQLND *conn TSRMLS_DC)
+size_t php_mysqlnd_cmd_write(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
/* Let's have some space, which we can use, if not enough, we will allocate new buffer */
- MYSQLND_PACKET_COMMAND *packet= (MYSQLND_PACKET_COMMAND *) _packet;
- MYSQLND_NET *net = conn->net;
+ MYSQLND_PACKET_COMMAND * packet= (MYSQLND_PACKET_COMMAND *) _packet;
+ MYSQLND_NET * net = conn->net;
unsigned int error_reporting = EG(error_reporting);
- size_t written = 0;
+ size_t sent = 0;
DBG_ENTER("php_mysqlnd_cmd_write");
/*
@@ -710,12 +927,12 @@ size_t php_mysqlnd_cmd_write(void *_packet, MYSQLND *conn TSRMLS_DC)
#endif
if (!packet->argument || !packet->arg_len) {
- char buffer[MYSQLND_HEADER_SIZE + 1];
+ zend_uchar buffer[MYSQLND_HEADER_SIZE + 1];
int1store(buffer + MYSQLND_HEADER_SIZE, packet->command);
- written = conn->net->m.send(conn, buffer, 1 TSRMLS_CC);
+ sent = net->m.send_ex(net, buffer, 1, conn->stats, conn->error_info TSRMLS_CC);
} else {
- size_t tmp_len = packet->arg_len + 1 + MYSQLND_HEADER_SIZE, ret;
+ size_t tmp_len = packet->arg_len + 1 + MYSQLND_HEADER_SIZE;
zend_uchar *tmp, *p;
tmp = (tmp_len > net->cmd_buffer.length)? mnd_emalloc(tmp_len):net->cmd_buffer.buffer;
if (!tmp) {
@@ -728,26 +945,28 @@ size_t php_mysqlnd_cmd_write(void *_packet, MYSQLND *conn TSRMLS_DC)
memcpy(p, packet->argument, packet->arg_len);
- ret = conn->net->m.send(conn, (char *)tmp, tmp_len - MYSQLND_HEADER_SIZE TSRMLS_CC);
+ sent = net->m.send_ex(net, tmp, tmp_len - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info TSRMLS_CC);
if (tmp != net->cmd_buffer.buffer) {
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_CMD_BUFFER_TOO_SMALL);
mnd_efree(tmp);
}
- written = ret;
}
end:
if (error_reporting) {
/* restore error reporting */
EG(error_reporting) = error_reporting;
}
- DBG_RETURN(written);
+ if (!sent) {
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ }
+ DBG_RETURN(sent);
}
/* }}} */
/* {{{ php_mysqlnd_cmd_free_mem */
static
-void php_mysqlnd_cmd_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+void php_mysqlnd_cmd_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
if (!stack_allocation) {
MYSQLND_PACKET_COMMAND * p = (MYSQLND_PACKET_COMMAND *) _packet;
@@ -759,7 +978,7 @@ void php_mysqlnd_cmd_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_D
/* {{{ php_mysqlnd_rset_header_read */
static enum_func_status
-php_mysqlnd_rset_header_read(void *_packet, MYSQLND *conn TSRMLS_DC)
+php_mysqlnd_rset_header_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
enum_func_status ret = PASS;
size_t buf_len = conn->net->cmd_buffer.length;
@@ -809,8 +1028,8 @@ php_mysqlnd_rset_header_read(void *_packet, MYSQLND *conn TSRMLS_DC)
packet->info_or_local_file[len] = '\0';
packet->info_or_local_file_len = len;
} else {
- SET_OOM_ERROR(conn->error_info);
- ret = FAIL;
+ SET_OOM_ERROR(*conn->error_info);
+ ret = FAIL;
}
break;
case 0x00:
@@ -836,7 +1055,7 @@ php_mysqlnd_rset_header_read(void *_packet, MYSQLND *conn TSRMLS_DC)
packet->info_or_local_file[len] = '\0';
packet->info_or_local_file_len = len;
} else {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
}
}
@@ -863,7 +1082,7 @@ premature_end:
/* {{{ php_mysqlnd_rset_header_free_mem */
static
-void php_mysqlnd_rset_header_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+void php_mysqlnd_rset_header_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
MYSQLND_PACKET_RSET_HEADER *p= (MYSQLND_PACKET_RSET_HEADER *) _packet;
DBG_ENTER("php_mysqlnd_rset_header_free_mem");
@@ -897,7 +1116,7 @@ static size_t rset_field_offsets[] =
/* {{{ php_mysqlnd_rset_field_read */
static enum_func_status
-php_mysqlnd_rset_field_read(void *_packet, MYSQLND *conn TSRMLS_DC)
+php_mysqlnd_rset_field_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
/* Should be enough for the metadata of a single row */
MYSQLND_PACKET_RES_FIELD *packet= (MYSQLND_PACKET_RES_FIELD *) _packet;
@@ -1013,8 +1232,8 @@ php_mysqlnd_rset_field_read(void *_packet, MYSQLND *conn TSRMLS_DC)
DBG_INF_FMT("Def found, length %lu, persistent=%u", len, packet->persistent_alloc);
meta->def = mnd_pemalloc(len + 1, packet->persistent_alloc);
if (!meta->def) {
- SET_OOM_ERROR(conn->error_info);
- DBG_RETURN(FAIL);
+ SET_OOM_ERROR(*conn->error_info);
+ DBG_RETURN(FAIL);
}
memcpy(meta->def, p, len);
meta->def[len] = '\0';
@@ -1025,10 +1244,10 @@ php_mysqlnd_rset_field_read(void *_packet, MYSQLND *conn TSRMLS_DC)
DBG_INF_FMT("allocing root. persistent=%u", packet->persistent_alloc);
root_ptr = meta->root = mnd_pemalloc(total_len, packet->persistent_alloc);
if (!root_ptr) {
- SET_OOM_ERROR(conn->error_info);
- DBG_RETURN(FAIL);
+ SET_OOM_ERROR(*conn->error_info);
+ DBG_RETURN(FAIL);
}
-
+
meta->root_len = total_len;
/* Now do allocs */
if (meta->catalog && meta->catalog != mysqlnd_empty_string) {
@@ -1094,7 +1313,7 @@ premature_end:
/* {{{ php_mysqlnd_rset_field_free_mem */
static
-void php_mysqlnd_rset_field_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+void php_mysqlnd_rset_field_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
MYSQLND_PACKET_RES_FIELD *p= (MYSQLND_PACKET_RES_FIELD *) _packet;
/* p->metadata was passed to us as temporal buffer */
@@ -1107,14 +1326,14 @@ void php_mysqlnd_rset_field_free_mem(void *_packet, zend_bool stack_allocation T
/* {{{ php_mysqlnd_read_row_ex */
static enum_func_status
-php_mysqlnd_read_row_ex(MYSQLND * conn, MYSQLND_MEMORY_POOL * result_set_memory_pool,
- MYSQLND_MEMORY_POOL_CHUNK **buffer,
- size_t *data_size, zend_bool persistent_alloc,
+php_mysqlnd_read_row_ex(MYSQLND_CONN_DATA * conn, MYSQLND_MEMORY_POOL * result_set_memory_pool,
+ MYSQLND_MEMORY_POOL_CHUNK ** buffer,
+ size_t * data_size, zend_bool persistent_alloc,
unsigned int prealloc_more_bytes TSRMLS_DC)
{
enum_func_status ret = PASS;
MYSQLND_PACKET_HEADER header;
- zend_uchar *p = NULL;
+ zend_uchar * p = NULL;
zend_bool first_iteration = TRUE;
DBG_ENTER("php_mysqlnd_read_row_ex");
@@ -1129,7 +1348,7 @@ php_mysqlnd_read_row_ex(MYSQLND * conn, MYSQLND_MEMORY_POOL * result_set_memory_
*data_size = prealloc_more_bytes;
while (1) {
- if (FAIL == mysqlnd_read_header(conn , &header TSRMLS_CC)) {
+ if (FAIL == mysqlnd_read_header(conn->net, &header, conn->stats, conn->error_info TSRMLS_CC)) {
ret = FAIL;
break;
}
@@ -1161,7 +1380,7 @@ php_mysqlnd_read_row_ex(MYSQLND * conn, MYSQLND_MEMORY_POOL * result_set_memory_
to be able to implement read-only variables.
*/
if (FAIL == (*buffer)->resize_chunk((*buffer), *data_size + 1 TSRMLS_CC)) {
- SET_OOM_ERROR(conn->error_info);
+ SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
break;
}
@@ -1169,7 +1388,7 @@ php_mysqlnd_read_row_ex(MYSQLND * conn, MYSQLND_MEMORY_POOL * result_set_memory_
p = (*buffer)->ptr + (*data_size - header.size);
}
- if (PASS != (ret = conn->net->m.receive(conn, p, header.size TSRMLS_CC))) {
+ if (PASS != (ret = conn->net->m.receive_ex(conn->net, p, header.size, conn->stats, conn->error_info TSRMLS_CC))) {
DBG_ERR("Empty row packet body");
php_error(E_WARNING, "Empty row packet body");
break;
@@ -1193,13 +1412,12 @@ php_mysqlnd_read_row_ex(MYSQLND * conn, MYSQLND_MEMORY_POOL * result_set_memory_
enum_func_status
php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
- zend_bool persistent,
zend_bool as_unicode, zend_bool as_int_or_float,
MYSQLND_STATS * stats TSRMLS_DC)
{
unsigned int i;
- zend_uchar *p = row_buffer->ptr;
- zend_uchar *null_ptr, bit;
+ zend_uchar * p = row_buffer->ptr;
+ zend_uchar * null_ptr, bit;
zval **current_field, **end_field, **start_field;
DBG_ENTER("php_mysqlnd_rowp_read_binary_protocol");
@@ -1293,16 +1511,15 @@ php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zv
enum_func_status
php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
- zend_bool persistent,
zend_bool as_unicode, zend_bool as_int_or_float,
MYSQLND_STATS * stats TSRMLS_DC)
{
unsigned int i;
zend_bool last_field_was_string = FALSE;
zval **current_field, **end_field, **start_field;
- zend_uchar *p = row_buffer->ptr;
+ zend_uchar * p = row_buffer->ptr;
size_t data_size = row_buffer->app;
- zend_uchar *bit_area = (zend_uchar*) row_buffer->ptr + data_size + 1; /* we allocate from here */
+ zend_uchar * bit_area = (zend_uchar*) row_buffer->ptr + data_size + 1; /* we allocate from here */
DBG_ENTER("php_mysqlnd_rowp_read_text_protocol");
@@ -1525,9 +1742,9 @@ php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval
if PS => packet->fields is passed from outside
*/
static enum_func_status
-php_mysqlnd_rowp_read(void *_packet, MYSQLND *conn TSRMLS_DC)
+php_mysqlnd_rowp_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
- MYSQLND_NET *net = conn->net;
+ MYSQLND_NET * net = conn->net;
zend_uchar *p;
enum_func_status ret = PASS;
size_t old_chunk_size = net->stream->chunk_size;
@@ -1620,7 +1837,7 @@ end:
/* {{{ php_mysqlnd_rowp_free_mem */
static void
-php_mysqlnd_rowp_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+php_mysqlnd_rowp_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
MYSQLND_PACKET_ROW *p;
@@ -1648,7 +1865,7 @@ php_mysqlnd_rowp_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
/* {{{ php_mysqlnd_stats_read */
static enum_func_status
-php_mysqlnd_stats_read(void *_packet, MYSQLND *conn TSRMLS_DC)
+php_mysqlnd_stats_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
MYSQLND_PACKET_STATS *packet= (MYSQLND_PACKET_STATS *) _packet;
size_t buf_len = conn->net->cmd_buffer.length;
@@ -1670,7 +1887,7 @@ php_mysqlnd_stats_read(void *_packet, MYSQLND *conn TSRMLS_DC)
/* {{{ php_mysqlnd_stats_free_mem */
static
-void php_mysqlnd_stats_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+void php_mysqlnd_stats_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
MYSQLND_PACKET_STATS *p= (MYSQLND_PACKET_STATS *) _packet;
if (p->message) {
@@ -1690,7 +1907,7 @@ void php_mysqlnd_stats_free_mem(void *_packet, zend_bool stack_allocation TSRMLS
/* {{{ php_mysqlnd_prepare_read */
static enum_func_status
-php_mysqlnd_prepare_read(void *_packet, MYSQLND *conn TSRMLS_DC)
+php_mysqlnd_prepare_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
/* In case of an error, we should have place to put it */
size_t buf_len = conn->net->cmd_buffer.length;
@@ -1766,7 +1983,7 @@ premature_end:
/* {{{ php_mysqlnd_prepare_free_mem */
static void
-php_mysqlnd_prepare_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+php_mysqlnd_prepare_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
MYSQLND_PACKET_PREPARE_RESPONSE *p= (MYSQLND_PACKET_PREPARE_RESPONSE *) _packet;
if (!stack_allocation) {
@@ -1778,7 +1995,7 @@ php_mysqlnd_prepare_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC
/* {{{ php_mysqlnd_chg_user_read */
static enum_func_status
-php_mysqlnd_chg_user_read(void *_packet, MYSQLND *conn TSRMLS_DC)
+php_mysqlnd_chg_user_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
{
/* There could be an error message */
size_t buf_len = conn->net->cmd_buffer.length;
@@ -1798,7 +2015,7 @@ php_mysqlnd_chg_user_read(void *_packet, MYSQLND *conn TSRMLS_DC)
*/
/* Should be always 0x0 or ERROR_MARKER for error */
- packet->field_count= uint1korr(p);
+ packet->response_code = uint1korr(p);
p++;
if (packet->header.size == 1 && buf[0] == EODATA_MARKER && packet->server_capabilities & CLIENT_SECURE_CONNECTION) {
@@ -1807,7 +2024,7 @@ php_mysqlnd_chg_user_read(void *_packet, MYSQLND *conn TSRMLS_DC)
DBG_RETURN(FAIL);
}
- if (ERROR_MARKER == packet->field_count) {
+ if (ERROR_MARKER == packet->response_code) {
php_mysqlnd_read_error_from_line(p, packet->header.size - 1,
packet->error_info.error,
sizeof(packet->error_info.error),
@@ -1816,6 +2033,18 @@ php_mysqlnd_chg_user_read(void *_packet, MYSQLND *conn TSRMLS_DC)
TSRMLS_CC);
}
BAIL_IF_NO_MORE_DATA;
+ if (packet->response_code == 0xFE && packet->header.size > (size_t) (p - buf)) {
+ packet->new_auth_protocol = mnd_pestrdup((char *)p, FALSE);
+ packet->new_auth_protocol_len = strlen(packet->new_auth_protocol);
+ p+= packet->new_auth_protocol_len + 1; /* +1 for the \0 */
+ packet->new_auth_protocol_data_len = packet->header.size - (size_t) (p - buf);
+ if (packet->new_auth_protocol_data_len) {
+ packet->new_auth_protocol_data = mnd_emalloc(packet->new_auth_protocol_data_len);
+ memcpy(packet->new_auth_protocol_data, p, packet->new_auth_protocol_data_len);
+ }
+ DBG_INF_FMT("The server requested switching auth plugin to : %s", packet->new_auth_protocol);
+ DBG_INF_FMT("Server salt : [%*s]", packet->new_auth_protocol_data_len, packet->new_auth_protocol_data);
+ }
DBG_RETURN(PASS);
premature_end:
@@ -1829,10 +2058,24 @@ premature_end:
/* {{{ php_mysqlnd_chg_user_free_mem */
static void
-php_mysqlnd_chg_user_free_mem(void *_packet, zend_bool stack_allocation TSRMLS_DC)
+php_mysqlnd_chg_user_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC)
{
+ MYSQLND_PACKET_CHG_USER_RESPONSE * p = (MYSQLND_PACKET_CHG_USER_RESPONSE *) _packet;
+
+ if (p->new_auth_protocol) {
+ mnd_efree(p->new_auth_protocol);
+ p->new_auth_protocol = NULL;
+ }
+ p->new_auth_protocol_len = 0;
+
+ if (p->new_auth_protocol_data) {
+ mnd_efree(p->new_auth_protocol_data);
+ p->new_auth_protocol_data = NULL;
+ }
+ p->new_auth_protocol_data_len = 0;
+
if (!stack_allocation) {
- mnd_pefree(_packet, ((MYSQLND_PACKET_CHG_USER_RESPONSE *)_packet)->header.persistent);
+ mnd_pefree(p, p->header.persistent);
}
}
/* }}} */
@@ -1855,6 +2098,18 @@ mysqlnd_packet_methods packet_methods[PROT_LAST] =
php_mysqlnd_auth_free_mem,
}, /* PROT_AUTH_PACKET */
{
+ sizeof(MYSQLND_PACKET_AUTH_RESPONSE),
+ php_mysqlnd_auth_response_read, /* read */
+ NULL, /* write */
+ php_mysqlnd_auth_response_free_mem,
+ }, /* PROT_AUTH_RESP_PACKET */
+ {
+ sizeof(MYSQLND_PACKET_CHANGE_AUTH_RESPONSE),
+ NULL, /* read */
+ php_mysqlnd_change_auth_response_write, /* write */
+ php_mysqlnd_change_auth_response_free_mem,
+ }, /* PROT_CHANGE_AUTH_RESP_PACKET */
+ {
sizeof(MYSQLND_PACKET_OK),
php_mysqlnd_ok_read, /* read */
NULL, /* write */
@@ -1942,6 +2197,36 @@ MYSQLND_METHOD(mysqlnd_protocol, get_auth_packet)(MYSQLND_PROTOCOL * const proto
/* }}} */
+/* {{{ mysqlnd_protocol::get_auth_response_packet */
+static struct st_mysqlnd_packet_auth_response *
+MYSQLND_METHOD(mysqlnd_protocol, get_auth_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC)
+{
+ struct st_mysqlnd_packet_auth_response * packet = mnd_pecalloc(1, packet_methods[PROT_AUTH_RESP_PACKET].struct_size, persistent);
+ DBG_ENTER("mysqlnd_protocol::get_auth_response_packet");
+ if (packet) {
+ packet->header.m = &packet_methods[PROT_AUTH_RESP_PACKET];
+ packet->header.persistent = persistent;
+ }
+ DBG_RETURN(packet);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_protocol::get_change_auth_response_packet */
+static struct st_mysqlnd_packet_change_auth_response *
+MYSQLND_METHOD(mysqlnd_protocol, get_change_auth_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC)
+{
+ struct st_mysqlnd_packet_change_auth_response * packet = mnd_pecalloc(1, packet_methods[PROT_CHANGE_AUTH_RESP_PACKET].struct_size, persistent);
+ DBG_ENTER("mysqlnd_protocol::get_change_auth_response_packet");
+ if (packet) {
+ packet->header.m = &packet_methods[PROT_CHANGE_AUTH_RESP_PACKET];
+ packet->header.persistent = persistent;
+ }
+ DBG_RETURN(packet);
+}
+/* }}} */
+
+
/* {{{ mysqlnd_protocol::get_ok_packet */
static struct st_mysqlnd_packet_ok *
MYSQLND_METHOD(mysqlnd_protocol, get_ok_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC)
@@ -2077,10 +2362,11 @@ MYSQLND_METHOD(mysqlnd_protocol, get_change_user_response_packet)(MYSQLND_PROTOC
/* }}} */
-static
MYSQLND_CLASS_METHODS_START(mysqlnd_protocol)
MYSQLND_METHOD(mysqlnd_protocol, get_greet_packet),
MYSQLND_METHOD(mysqlnd_protocol, get_auth_packet),
+ MYSQLND_METHOD(mysqlnd_protocol, get_auth_response_packet),
+ MYSQLND_METHOD(mysqlnd_protocol, get_change_auth_response_packet),
MYSQLND_METHOD(mysqlnd_protocol, get_ok_packet),
MYSQLND_METHOD(mysqlnd_protocol, get_command_packet),
MYSQLND_METHOD(mysqlnd_protocol, get_eof_packet),
@@ -2097,16 +2383,9 @@ MYSQLND_CLASS_METHODS_END;
PHPAPI MYSQLND_PROTOCOL *
mysqlnd_protocol_init(zend_bool persistent TSRMLS_DC)
{
- size_t alloc_size = sizeof(MYSQLND_PROTOCOL) + mysqlnd_plugin_count() * sizeof(void *);
- MYSQLND_PROTOCOL *ret = mnd_pecalloc(1, alloc_size, persistent);
-
+ MYSQLND_PROTOCOL * ret;
DBG_ENTER("mysqlnd_protocol_init");
- DBG_INF_FMT("persistent=%u", persistent);
- if (ret) {
- ret->persistent = persistent;
- ret->m = mysqlnd_mysqlnd_protocol_methods;
- }
-
+ ret = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_protocol_decoder(persistent TSRMLS_CC);
DBG_RETURN(ret);
}
/* }}} */
@@ -2127,29 +2406,6 @@ mysqlnd_protocol_free(MYSQLND_PROTOCOL * const protocol TSRMLS_DC)
/* }}} */
-/* {{{ _mysqlnd_plugin_get_plugin_protocol_data */
-PHPAPI void **
-_mysqlnd_plugin_get_plugin_protocol_data(const MYSQLND_PROTOCOL * protocol, unsigned int plugin_id TSRMLS_DC)
-{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_protocol_data");
- DBG_INF_FMT("plugin_id=%u", plugin_id);
- if (!protocol || plugin_id >= mysqlnd_plugin_count()) {
- return NULL;
- }
- DBG_RETURN((void *)((char *)protocol + sizeof(MYSQLND_PROTOCOL) + plugin_id * sizeof(void *)));
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_protocol_get_methods */
-PHPAPI struct st_mysqlnd_protocol_methods *
-mysqlnd_protocol_get_methods()
-{
- return &mysqlnd_mysqlnd_protocol_methods;
-}
-/* }}} */
-
-
/*
* Local variables:
* tab-width: 4
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.h b/ext/mysqlnd/mysqlnd_wireprotocol.h
index 34e79d0bb0..253784c364 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.h
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.h
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -51,8 +51,8 @@ PHPAPI extern const char * const mysqlnd_command_to_text[COM_END];
/* Low-level extraction functionality */
typedef struct st_mysqlnd_packet_methods {
size_t struct_size;
- enum_func_status (*read_from_net)(void *packet, MYSQLND *conn TSRMLS_DC);
- size_t (*write_to_net)(void *packet, MYSQLND *conn TSRMLS_DC);
+ enum_func_status (*read_from_net)(void * packet, MYSQLND_CONN_DATA * conn TSRMLS_DC);
+ size_t (*write_to_net)(void * packet, MYSQLND_CONN_DATA * conn TSRMLS_DC);
void (*free_mem)(void *packet, zend_bool stack_allocation TSRMLS_DC);
} mysqlnd_packet_methods;
@@ -70,17 +70,20 @@ typedef struct st_mysqlnd_packet_greet {
uint8_t protocol_version;
char *server_version;
uint32_t thread_id;
- zend_uchar scramble_buf[SCRAMBLE_LENGTH];
+ zend_uchar intern_auth_plugin_data[SCRAMBLE_LENGTH];
+ zend_uchar * auth_plugin_data;
+ size_t auth_plugin_data_len;
/* 1 byte pad */
- uint16_t server_capabilities;
+ uint32_t server_capabilities;
uint8_t charset_no;
uint16_t server_status;
- /* 13 byte pad*/
+ /* 13 byte pad, in 5.5 first 2 bytes are more capabilities followed by 1 byte scramble_length */
zend_bool pre41;
/* If error packet, we use these */
char error[MYSQLND_ERRMSG_SIZE+1];
char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
- unsigned int error_no;
+ unsigned int error_no;
+ char *auth_protocol;
} MYSQLND_PACKET_GREET;
@@ -89,21 +92,50 @@ typedef struct st_mysqlnd_packet_auth {
MYSQLND_PACKET_HEADER header;
uint32_t client_flags;
uint32_t max_packet_size;
- uint8_t charset_no;
- /* 23 byte pad */
+ uint8_t charset_no;
const char *user;
- /* 8 byte scramble */
+ const zend_uchar *auth_data;
+ size_t auth_data_len;
const char *db;
- /* 12 byte scramble */
-
+ const char *auth_plugin_name;
/* Here the packet ends. This is user supplied data */
- const char *password;
- /* +1 for \0 because of scramble() */
- unsigned char *server_scramble_buf;
- size_t db_len;
- zend_bool send_half_packet;
+ size_t db_len;
+ zend_bool send_auth_data;
+ zend_bool is_change_user_packet;
+ zend_bool silent;
+
} MYSQLND_PACKET_AUTH;
+/* Auth response packet */
+typedef struct st_mysqlnd_packet_auth_response {
+ MYSQLND_PACKET_HEADER header;
+ uint8_t response_code;
+ uint64_t affected_rows;
+ uint64_t last_insert_id;
+ uint16_t server_status;
+ uint16_t warning_count;
+ char *message;
+ size_t message_len;
+ /* If error packet, we use these */
+ char error[MYSQLND_ERRMSG_SIZE+1];
+ char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
+ unsigned int error_no;
+
+ char *new_auth_protocol;
+ size_t new_auth_protocol_len;
+ zend_uchar *new_auth_protocol_data;
+ size_t new_auth_protocol_data_len;
+} MYSQLND_PACKET_AUTH_RESPONSE;
+
+
+/* Auth response packet */
+typedef struct st_mysqlnd_packet_change_auth_response {
+ MYSQLND_PACKET_HEADER header;
+ const zend_uchar *auth_data;
+ size_t auth_data_len;
+} MYSQLND_PACKET_CHANGE_AUTH_RESPONSE;
+
+
/* OK packet */
typedef struct st_mysqlnd_packet_ok {
MYSQLND_PACKET_HEADER header;
@@ -125,7 +157,7 @@ typedef struct st_mysqlnd_packet_ok {
typedef struct st_mysqlnd_packet_command {
MYSQLND_PACKET_HEADER header;
enum php_mysqlnd_server_command command;
- const char *argument;
+ const zend_uchar *argument;
size_t arg_len;
} MYSQLND_PACKET_COMMAND;
@@ -239,17 +271,22 @@ typedef struct st_mysqlnd_packet_prepare_response {
/* Statistics packet */
typedef struct st_mysqlnd_packet_chg_user_resp {
MYSQLND_PACKET_HEADER header;
- uint32_t field_count;
+ uint32_t response_code;
/* message_len is not part of the packet*/
uint16_t server_capabilities;
/* If error packet, we use these */
MYSQLND_ERROR_INFO error_info;
zend_bool server_asked_323_auth;
+
+ char *new_auth_protocol;
+ size_t new_auth_protocol_len;
+ zend_uchar *new_auth_protocol_data;
+ size_t new_auth_protocol_data_len;
} MYSQLND_PACKET_CHG_USER_RESPONSE;
-PHPAPI void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const pass);
+PHPAPI void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const pass, size_t pass_len);
unsigned long php_mysqlnd_net_field_length(zend_uchar **packet);
zend_uchar * php_mysqlnd_net_store_length(zend_uchar *packet, uint64_t length);
@@ -259,21 +296,18 @@ PHPAPI const extern char * const mysqlnd_empty_string;
enum_func_status php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
- zend_bool persistent,
zend_bool as_unicode, zend_bool as_int_or_float,
MYSQLND_STATS * stats TSRMLS_DC);
enum_func_status php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
unsigned int field_count, MYSQLND_FIELD *fields_metadata,
- zend_bool persistent,
zend_bool as_unicode, zend_bool as_int_or_float,
MYSQLND_STATS * stats TSRMLS_DC);
PHPAPI MYSQLND_PROTOCOL * mysqlnd_protocol_init(zend_bool persistent TSRMLS_DC);
PHPAPI void mysqlnd_protocol_free(MYSQLND_PROTOCOL * const protocol TSRMLS_DC);
-PHPAPI struct st_mysqlnd_protocol_methods * mysqlnd_protocol_get_methods();
#endif /* MYSQLND_WIREPROTOCOL_H */
diff --git a/ext/mysqlnd/php_mysqlnd.c b/ext/mysqlnd/php_mysqlnd.c
index 77880ed0f2..002135566c 100644
--- a/ext/mysqlnd/php_mysqlnd.c
+++ b/ext/mysqlnd/php_mysqlnd.c
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
@@ -24,7 +24,10 @@
#include "mysqlnd.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_debug.h"
+#include "mysqlnd_statistics.h"
+#include "mysqlnd_reverse_api.h"
#include "ext/standard/info.h"
+#include "ext/standard/php_smart_str.h"
/* {{{ mysqlnd_functions[]
*
@@ -92,12 +95,71 @@ PHPAPI void mysqlnd_minfo_print_hash(zval *values)
/* }}} */
+/* {{{ mysqlnd_minfo_dump_plugin_stats */
+static int
+mysqlnd_minfo_dump_plugin_stats(void *pDest, void * argument TSRMLS_DC)
+{
+ struct st_mysqlnd_plugin_header * plugin_header = *(struct st_mysqlnd_plugin_header **) pDest;
+ if (plugin_header->plugin_stats.values) {
+ char buf[64];
+ zval values;
+ snprintf(buf, sizeof(buf), "%s statistics", plugin_header->plugin_name);
+
+ mysqlnd_fill_stats_hash(plugin_header->plugin_stats.values, plugin_header->plugin_stats.names, &values TSRMLS_CC ZEND_FILE_LINE_CC);
+
+ php_info_print_table_start();
+ php_info_print_table_header(2, buf, "");
+ mysqlnd_minfo_print_hash(&values);
+ php_info_print_table_end();
+ zval_dtor(&values);
+ }
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_minfo_dump_loaded_plugins */
+static int
+mysqlnd_minfo_dump_loaded_plugins(void *pDest, void * buf TSRMLS_DC)
+{
+ smart_str * buffer = (smart_str *) buf;
+ struct st_mysqlnd_plugin_header * plugin_header = *(struct st_mysqlnd_plugin_header **) pDest;
+ if (plugin_header->plugin_name) {
+ if (buffer->len) {
+ smart_str_appendc(buffer, ',');
+ }
+ smart_str_appends(buffer, plugin_header->plugin_name);
+ }
+ return ZEND_HASH_APPLY_KEEP;
+}
+/* }}} */
+
+/* {{{ mysqlnd_minfo_dump_api_plugins */
+static void
+mysqlnd_minfo_dump_api_plugins(smart_str * buffer TSRMLS_DC)
+{
+ HashTable *ht = mysqlnd_reverse_api_get_api_list(TSRMLS_C);
+ Bucket *p;
+
+ p = ht->pListHead;
+ while(p != NULL) {
+ MYSQLND_REVERSE_API * ext = *(MYSQLND_REVERSE_API **) p->pData;
+ if (buffer->len) {
+ smart_str_appendc(buffer, ',');
+ }
+ smart_str_appends(buffer, ext->module->name);
+
+ p = p->pListNext;
+ }
+}
+/* }}} */
+
+
/* {{{ PHP_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(mysqlnd)
{
char buf[32];
- zval values;
php_info_print_table_start();
php_info_print_table_header(2, "mysqlnd", "enabled");
@@ -124,16 +186,26 @@ PHP_MINFO_FUNCTION(mysqlnd)
php_info_print_table_row(2, "Collecting memory statistics", MYSQLND_G(collect_memory_statistics)? "Yes":"No");
php_info_print_table_row(2, "Tracing", MYSQLND_G(debug)? MYSQLND_G(debug):"n/a");
- php_info_print_table_end();
- /* Print client stats */
- php_info_print_table_start();
- php_info_print_table_header(2, "Client statistics", "");
- mysqlnd_get_client_stats(&values);
- mysqlnd_minfo_print_hash(&values);
+ /* loaded plugins */
+ {
+ smart_str tmp_str = {0, 0, 0};
+ mysqlnd_plugin_apply_with_argument(mysqlnd_minfo_dump_loaded_plugins, &tmp_str);
+ smart_str_0(&tmp_str);
+ php_info_print_table_row(2, "Loaded plugins", tmp_str.c);
+ smart_str_free(&tmp_str);
+
+ mysqlnd_minfo_dump_api_plugins(&tmp_str TSRMLS_CC);
+ smart_str_0(&tmp_str);
+ php_info_print_table_row(2, "API Extensions", tmp_str.c);
+ smart_str_free(&tmp_str);
+ }
- zval_dtor(&values);
php_info_print_table_end();
+
+
+ /* Print client stats */
+ mysqlnd_plugin_apply_with_argument(mysqlnd_minfo_dump_plugin_stats, NULL);
}
/* }}} */
@@ -187,7 +259,7 @@ PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("mysqlnd.log_mask", "0", PHP_INI_ALL, OnUpdateLong, log_mask, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_ENTRY("mysqlnd.mempool_default_size","16000", PHP_INI_ALL, OnUpdateLong, mempool_default_size, zend_mysqlnd_globals, mysqlnd_globals)
-#ifdef PHP_DEBUG
+#if PHP_DEBUG
STD_PHP_INI_ENTRY("mysqlnd.debug_emalloc_fail_threshold","-1", PHP_INI_SYSTEM, OnUpdateLong, debug_emalloc_fail_threshold, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_ENTRY("mysqlnd.debug_ecalloc_fail_threshold","-1", PHP_INI_SYSTEM, OnUpdateLong, debug_ecalloc_fail_threshold, zend_mysqlnd_globals, mysqlnd_globals)
STD_PHP_INI_ENTRY("mysqlnd.debug_erealloc_fail_threshold","-1", PHP_INI_SYSTEM, OnUpdateLong, debug_erealloc_fail_threshold, zend_mysqlnd_globals, mysqlnd_globals)
@@ -224,28 +296,30 @@ static PHP_MSHUTDOWN_FUNCTION(mysqlnd)
/* }}} */
-#if defined(PHP_DEBUG)
+#if PHP_DEBUG
/* {{{ PHP_RINIT_FUNCTION
*/
static PHP_RINIT_FUNCTION(mysqlnd)
{
-#if defined(PHP_DEBUG)
if (MYSQLND_G(debug)) {
- MYSQLND_DEBUG *dbg = mysqlnd_debug_init(mysqlnd_debug_std_no_trace_funcs TSRMLS_CC);
- if (!dbg) {
- return FAILURE;
+ struct st_mysqlnd_plugin_trace_log * trace_log_plugin = mysqlnd_plugin_find("debug_trace");
+ MYSQLND_G(dbg) = NULL;
+ if (trace_log_plugin) {
+ MYSQLND_DEBUG * dbg = trace_log_plugin->methods.trace_instance_init(mysqlnd_debug_std_no_trace_funcs TSRMLS_CC);
+ if (!dbg) {
+ return FAILURE;
+ }
+ dbg->m->set_mode(dbg, MYSQLND_G(debug));
+ MYSQLND_G(dbg) = dbg;
}
- dbg->m->set_mode(dbg, MYSQLND_G(debug));
- MYSQLND_G(dbg) = dbg;
}
-#endif
return SUCCESS;
}
/* }}} */
#endif
-#if defined(PHP_DEBUG)
+#if PHP_DEBUG
/* {{{ PHP_RSHUTDOWN_FUNCTION
*/
static PHP_RSHUTDOWN_FUNCTION(mysqlnd)
@@ -279,12 +353,12 @@ zend_module_entry mysqlnd_module_entry = {
mysqlnd_functions,
PHP_MINIT(mysqlnd),
PHP_MSHUTDOWN(mysqlnd),
-#if defined(PHP_DEBUG)
+#if PHP_DEBUG
PHP_RINIT(mysqlnd),
#else
NULL,
#endif
-#ifdef PHP_DEBUG
+#if PHP_DEBUG
PHP_RSHUTDOWN(mysqlnd),
#else
NULL,
diff --git a/ext/mysqlnd/php_mysqlnd.h b/ext/mysqlnd/php_mysqlnd.h
index d07700e1aa..14ad234e1b 100644
--- a/ext/mysqlnd/php_mysqlnd.h
+++ b/ext/mysqlnd/php_mysqlnd.h
@@ -12,9 +12,9 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@php.net> |
- | Andrey Hristov <andrey@php.net> |
- | Ulf Wendel <uw@php.net> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
$Id$