summaryrefslogtreecommitdiff
path: root/ext/mysqlnd
diff options
context:
space:
mode:
Diffstat (limited to 'ext/mysqlnd')
-rw-r--r--ext/mysqlnd/config.w321
-rw-r--r--ext/mysqlnd/config9.m42
-rw-r--r--ext/mysqlnd/mysqlnd.c82
-rw-r--r--ext/mysqlnd/mysqlnd.h5
-rw-r--r--ext/mysqlnd/mysqlnd_alloc.c8
-rw-r--r--ext/mysqlnd/mysqlnd_auth.c13
-rw-r--r--ext/mysqlnd/mysqlnd_bt.c240
-rw-r--r--ext/mysqlnd/mysqlnd_debug.c62
-rw-r--r--ext/mysqlnd/mysqlnd_debug.h2
-rw-r--r--ext/mysqlnd/mysqlnd_loaddata.c22
-rw-r--r--ext/mysqlnd/mysqlnd_net.c64
-rw-r--r--ext/mysqlnd/mysqlnd_plugin.c22
-rw-r--r--ext/mysqlnd/mysqlnd_priv.h7
-rw-r--r--ext/mysqlnd/mysqlnd_ps.c157
-rw-r--r--ext/mysqlnd/mysqlnd_ps_codec.c117
-rw-r--r--ext/mysqlnd/mysqlnd_result.c225
-rw-r--r--ext/mysqlnd/mysqlnd_result_meta.c80
-rw-r--r--ext/mysqlnd/mysqlnd_reverse_api.c33
-rw-r--r--ext/mysqlnd/mysqlnd_statistics.c4
-rw-r--r--ext/mysqlnd/mysqlnd_structs.h35
-rw-r--r--ext/mysqlnd/mysqlnd_wireprotocol.c198
-rw-r--r--ext/mysqlnd/mysqlnd_wireprotocol.h9
-rw-r--r--ext/mysqlnd/php_mysqlnd.c59
23 files changed, 488 insertions, 959 deletions
diff --git a/ext/mysqlnd/config.w32 b/ext/mysqlnd/config.w32
index a910a0e509..c803042ee1 100644
--- a/ext/mysqlnd/config.w32
+++ b/ext/mysqlnd/config.w32
@@ -10,7 +10,6 @@ if (PHP_MYSQLND != "no") {
"mysqlnd_alloc.c " +
"mysqlnd_auth.c " +
"mysqlnd_block_alloc.c " +
- "mysqlnd_bt.c " +
"mysqlnd_charset.c " +
"mysqlnd_debug.c " +
"mysqlnd_driver.c " +
diff --git a/ext/mysqlnd/config9.m4 b/ext/mysqlnd/config9.m4
index 78e1bf1df0..816f4431f5 100644
--- a/ext/mysqlnd/config9.m4
+++ b/ext/mysqlnd/config9.m4
@@ -18,7 +18,7 @@ fi
dnl If some extension uses mysqlnd it will get compiled in PHP core
if test "$PHP_MYSQLND" != "no" || test "$PHP_MYSQLND_ENABLED" = "yes"; then
mysqlnd_ps_sources="mysqlnd_ps.c mysqlnd_ps_codec.c"
- mysqlnd_base_sources="mysqlnd.c mysqlnd_alloc.c mysqlnd_bt.c mysqlnd_charset.c mysqlnd_wireprotocol.c \
+ mysqlnd_base_sources="mysqlnd.c mysqlnd_alloc.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\
diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c
index 5d5e77f9bb..e05d6844bc 100644
--- a/ext/mysqlnd/mysqlnd.c
+++ b/ext/mysqlnd/mysqlnd.c
@@ -113,7 +113,6 @@ MYSQLND_METHOD(mysqlnd_conn_data, free_contents)(MYSQLND_CONN_DATA * conn TSRMLS
DBG_ENTER("mysqlnd_conn_data::free_contents");
- mysqlnd_local_infile_default(conn);
if (conn->current_result) {
conn->current_result->m.free_result(conn->current_result, TRUE TSRMLS_CC);
conn->current_result = NULL;
@@ -998,8 +997,8 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,
*/
net->data->compressed = mysql_flags & CLIENT_COMPRESS? TRUE:FALSE;
- conn->user = mnd_pestrdup(user, conn->persistent);
- conn->user_len = strlen(conn->user);
+ conn->user_len = strlen(user);
+ conn->user = mnd_pestrndup(user, conn->user_len, conn->persistent);
conn->passwd = mnd_pestrndup(passwd, passwd_len, conn->persistent);
conn->passwd_len = passwd_len;
conn->port = port;
@@ -1012,12 +1011,12 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,
}
if (!unix_socket && !named_pipe) {
- conn->host = mnd_pestrdup(host, conn->persistent);
+ conn->host = mnd_pestrndup(host, host_len, conn->persistent);
if (!conn->host) {
SET_OOM_ERROR(*conn->error_info);
goto err; /* OOM */
}
- conn->host_len = strlen(conn->host);
+ conn->host_len = host_len;
{
char *p;
mnd_sprintf(&p, 0, "%s via TCP/IP", conn->host);
@@ -1025,7 +1024,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,
SET_OOM_ERROR(*conn->error_info);
goto err; /* OOM */
}
- conn->host_info = mnd_pestrdup(p, conn->persistent);
+ conn->host_info = mnd_pestrdup(p, conn->persistent);
mnd_sprintf_free(p);
if (!conn->host_info) {
SET_OOM_ERROR(*conn->error_info);
@@ -1728,7 +1727,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, ping)(MYSQLND_CONN_DATA * const conn TSRMLS_DC
/* {{{ mysqlnd_conn_data::statistic */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn_data, statistic)(MYSQLND_CONN_DATA * conn, char **message, unsigned int * message_len TSRMLS_DC)
+MYSQLND_METHOD(mysqlnd_conn_data, statistic)(MYSQLND_CONN_DATA * conn, zend_string **message TSRMLS_DC)
{
size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, get_server_statistics);
enum_func_status ret = FAIL;
@@ -1751,9 +1750,8 @@ MYSQLND_METHOD(mysqlnd_conn_data, statistic)(MYSQLND_CONN_DATA * conn, char **me
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);
+ *message = STR_INIT(stats_header->message, stats_header->message_len, 0);
+ DBG_INF((*message)->val);
}
PACKET_FREE(stats_header);
} while (0);
@@ -2283,7 +2281,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, change_user)(MYSQLND_CONN_DATA * const conn,
}
/* XXX: passwords that have \0 inside work during auth, but in this case won't work with change user */
- ret = mysqlnd_run_authentication(conn, user, passwd, strlen(passwd), db, strlen(db),
+ ret = mysqlnd_run_authentication(conn, user, passwd, passwd_len, db, strlen(db),
conn->auth_plugin_data, conn->auth_plugin_data_len, conn->options->auth_protocol,
0 /*charset not used*/, conn->options, conn->server_capabilities, silent, TRUE/*is_change*/ TSRMLS_CC);
@@ -2445,7 +2443,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option)(MYSQLND_CONN_DATA * const c
case MYSQL_OPT_CONNECT_ATTR_DELETE:
if (conn->options->connect_attr && value) {
DBG_INF_FMT("Before delete %d attribute(s)", zend_hash_num_elements(conn->options->connect_attr));
- zend_hash_del(conn->options->connect_attr, value, strlen(value));
+ zend_hash_str_del(conn->options->connect_attr, value, strlen(value));
DBG_INF_FMT("%d left", zend_hash_num_elements(conn->options->connect_attr));
}
break;
@@ -2469,34 +2467,6 @@ end:
/* }}} */
-/* {{{ connect_attr_item_edtor */
-static void
-connect_attr_item_edtor(void * pDest)
-{
-#ifdef ZTS
- TSRMLS_FETCH();
-#endif
- DBG_ENTER("connect_attr_item_edtor");
- mnd_efree(*(char **) pDest);
- DBG_VOID_RETURN;
-}
-/* }}} */
-
-
-/* {{{ connect_attr_item_pdtor */
-static void
-connect_attr_item_pdtor(void * pDest)
-{
-#ifdef ZTS
- TSRMLS_FETCH();
-#endif
- DBG_ENTER("connect_attr_item_pdtor");
- mnd_pefree(*(char **) pDest, 1);
- DBG_VOID_RETURN;
-}
-/* }}} */
-
-
/* {{{ mysqlnd_conn_data::set_client_option_2d */
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, set_client_option_2d)(MYSQLND_CONN_DATA * const conn,
@@ -2521,15 +2491,13 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option_2d)(MYSQLND_CONN_DATA * cons
if (!conn->options->connect_attr) {
goto oom;
}
- zend_hash_init(conn->options->connect_attr, 0, NULL, conn->persistent? connect_attr_item_pdtor:connect_attr_item_edtor, conn->persistent);
+ zend_hash_init(conn->options->connect_attr, 0, NULL, ZVAL_PTR_DTOR, conn->persistent);
}
DBG_INF_FMT("Adding [%s][%s]", key, value);
{
- const char * copyv = mnd_pestrdup(value, conn->persistent);
- if (!copyv) {
- goto oom;
- }
- zend_hash_update(conn->options->connect_attr, key, strlen(key), &copyv, sizeof(char *), NULL);
+ zval attrz;
+ ZVAL_STR(&attrz, STR_INIT(value, strlen(value), 1));
+ zend_hash_str_update(conn->options->connect_attr, key, strlen(key), &attrz);
}
break;
default:
@@ -2698,24 +2666,24 @@ static void
MYSQLND_METHOD(mysqlnd_conn_data, tx_cor_options_to_string)(const MYSQLND_CONN_DATA * const conn, smart_str * str, const unsigned int mode TSRMLS_DC)
{
if (mode & TRANS_COR_AND_CHAIN && !(mode & TRANS_COR_AND_NO_CHAIN)) {
- if (str->len) {
+ if (str->s && str->s->len) {
smart_str_appendl(str, " ", sizeof(" ") - 1);
}
smart_str_appendl(str, "AND CHAIN", sizeof("AND CHAIN") - 1);
} else if (mode & TRANS_COR_AND_NO_CHAIN && !(mode & TRANS_COR_AND_CHAIN)) {
- if (str->len) {
+ if (str->s && str->s->len) {
smart_str_appendl(str, " ", sizeof(" ") - 1);
}
smart_str_appendl(str, "AND NO CHAIN", sizeof("AND NO CHAIN") - 1);
}
if (mode & TRANS_COR_RELEASE && !(mode & TRANS_COR_NO_RELEASE)) {
- if (str->len) {
+ if (str->s && str->s->len) {
smart_str_appendl(str, " ", sizeof(" ") - 1);
}
smart_str_appendl(str, "RELEASE", sizeof("RELEASE") - 1);
} else if (mode & TRANS_COR_NO_RELEASE && !(mode & TRANS_COR_RELEASE)) {
- if (str->len) {
+ if (str->s && str->s->len) {
smart_str_appendl(str, " ", sizeof(" ") - 1);
}
smart_str_appendl(str, "NO RELEASE", sizeof("NO RELEASE") - 1);
@@ -2778,7 +2746,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_commit_or_rollback)(MYSQLND_CONN_DATA * con
if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
do {
- smart_str tmp_str = {0, 0, 0};
+ smart_str tmp_str = {0, 0};
conn->m->tx_cor_options_to_string(conn, &tmp_str, flags TSRMLS_CC);
smart_str_0(&tmp_str);
@@ -2789,7 +2757,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_commit_or_rollback)(MYSQLND_CONN_DATA * con
char * name_esc = mysqlnd_escape_string_for_tx_name_in_comment(name TSRMLS_CC);
query_len = mnd_sprintf(&query, 0, (commit? "COMMIT%s %s":"ROLLBACK%s %s"),
- name_esc? name_esc:"", tmp_str.c? tmp_str.c:"");
+ name_esc? name_esc:"", tmp_str.s? tmp_str.s->val:"");
smart_str_free(&tmp_str);
if (name_esc) {
mnd_efree(name_esc);
@@ -2822,9 +2790,9 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_begin)(MYSQLND_CONN_DATA * conn, const unsi
if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) {
do {
- smart_str tmp_str = {0, 0, 0};
+ smart_str tmp_str = {0, 0};
if (mode & TRANS_START_WITH_CONSISTENT_SNAPSHOT) {
- if (tmp_str.len) {
+ if (tmp_str.s) {
smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
}
smart_str_appendl(&tmp_str, "WITH CONSISTENT SNAPSHOT", sizeof("WITH CONSISTENT SNAPSHOT") - 1);
@@ -2836,12 +2804,12 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_begin)(MYSQLND_CONN_DATA * conn, const unsi
smart_str_free(&tmp_str);
break;
} else if (mode & TRANS_START_READ_WRITE) {
- if (tmp_str.len) {
+ if (tmp_str.s->len) {
smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
}
smart_str_appendl(&tmp_str, "READ WRITE", sizeof("READ WRITE") - 1);
} else if (mode & TRANS_START_READ_ONLY) {
- if (tmp_str.len) {
+ if (tmp_str.s->len) {
smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
}
smart_str_appendl(&tmp_str, "READ ONLY", sizeof("READ ONLY") - 1);
@@ -2852,7 +2820,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_begin)(MYSQLND_CONN_DATA * conn, const unsi
{
char * name_esc = mysqlnd_escape_string_for_tx_name_in_comment(name TSRMLS_CC);
char * query;
- unsigned int query_len = mnd_sprintf(&query, 0, "START TRANSACTION%s %s", name_esc? name_esc:"", tmp_str.c? tmp_str.c:"");
+ unsigned int query_len = mnd_sprintf(&query, 0, "START TRANSACTION%s %s", name_esc? name_esc:"", tmp_str.s? tmp_str.s->val:"");
smart_str_free(&tmp_str);
if (name_esc) {
mnd_efree(name_esc);
diff --git a/ext/mysqlnd/mysqlnd.h b/ext/mysqlnd/mysqlnd.h
index f373ea5dd5..94620d9369 100644
--- a/ext/mysqlnd/mysqlnd.h
+++ b/ext/mysqlnd/mysqlnd.h
@@ -188,8 +188,7 @@ 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_DATA * conn);
-PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND_CONN_DATA * const conn, const char * const funcname);
+void mysqlnd_local_infile_default(MYSQLND_CONN_DATA * conn);
/* Simple commands */
#define mysqlnd_autocommit(conn, mode) ((conn)->data)->m->set_autocommit((conn)->data, (mode) TSRMLS_CC)
@@ -209,7 +208,7 @@ PHPAPI void mysqlnd_set_local_infile_handler(MYSQLND_CONN_DATA * const conn, con
#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_stat(conn, msg) ((conn)->data)->m->get_server_statistics(((conn)->data), (msg) TSRMLS_CC)
#define mysqlnd_options(conn, opt, value) ((conn)->data)->m->set_client_option((conn)->data, (opt), (value) TSRMLS_CC)
#define mysqlnd_options4(conn, opt, k, v) ((conn)->data)->m->set_client_option_2d((conn)->data, (opt), (k), (v) TSRMLS_CC)
#define mysqlnd_set_server_option(conn, op) ((conn)->data)->m->set_server_option((conn)->data, (op) TSRMLS_CC)
diff --git a/ext/mysqlnd/mysqlnd_alloc.c b/ext/mysqlnd/mysqlnd_alloc.c
index 42ce55a36a..c3228aa4f1 100644
--- a/ext/mysqlnd/mysqlnd_alloc.c
+++ b/ext/mysqlnd/mysqlnd_alloc.c
@@ -582,7 +582,7 @@ char * _mysqlnd_pestrndup(const char * const ptr, size_t length, zend_bool persi
char * _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D)
{
char * ret;
- smart_str tmp_str = {0, 0, 0};
+ smart_str tmp_str = {0, 0};
const char * p = ptr;
zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
TRACE_ALLOC_ENTER(mysqlnd_pestrdup_name);
@@ -597,11 +597,11 @@ char * _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_ME
smart_str_appendc(&tmp_str, *p);
} while (*p++);
- ret = (persistent) ? __zend_malloc(tmp_str.len + sizeof(size_t)) : _emalloc(REAL_SIZE(tmp_str.len + sizeof(size_t)) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
- memcpy(FAKE_PTR(ret), tmp_str.c, tmp_str.len);
+ ret = (persistent) ? __zend_malloc(tmp_str.s->len + sizeof(size_t)) : _emalloc(REAL_SIZE(tmp_str.s->len + sizeof(size_t)) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ memcpy(FAKE_PTR(ret), tmp_str.s->val, tmp_str.s->len);
if (ret && collect_memory_statistics) {
- *(size_t *) ret = tmp_str.len;
+ *(size_t *) ret = tmp_str.s->len;
MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRDUP_COUNT : STAT_MEM_ESTRDUP_COUNT);
}
smart_str_free(&tmp_str);
diff --git a/ext/mysqlnd/mysqlnd_auth.c b/ext/mysqlnd/mysqlnd_auth.c
index 7f554dcb7b..1ac05930f7 100644
--- a/ext/mysqlnd/mysqlnd_auth.c
+++ b/ext/mysqlnd/mysqlnd_auth.c
@@ -485,7 +485,6 @@ mysqlnd_sha256_get_rsa_key(MYSQLND_CONN_DATA * conn,
TSRMLS_DC)
{
RSA * ret = NULL;
- int len;
const char * fname = (net_options->sha256_server_public_key && net_options->sha256_server_public_key[0] != '\0')?
net_options->sha256_server_public_key:
MYSQLND_G(sha256_server_public_key);
@@ -543,20 +542,18 @@ mysqlnd_sha256_get_rsa_key(MYSQLND_CONN_DATA * conn,
DBG_ERR("server_public_key is not set");
DBG_RETURN(NULL);
} else {
- char * key_str = NULL;
+ zend_string * key_str;
DBG_INF_FMT("Key in a file. [%s]", fname);
stream = php_stream_open_wrapper((char *) fname, "rb", REPORT_ERRORS, NULL);
if (stream) {
- if ((len = php_stream_copy_to_mem(stream, &key_str, PHP_STREAM_COPY_ALL, 0)) >= 0 ) {
- BIO * bio = BIO_new_mem_buf(key_str, len);
+ if ((key_str = php_stream_copy_to_mem(stream, PHP_STREAM_COPY_ALL, 0)) != NULL) {
+ BIO * bio = BIO_new_mem_buf(key_str->val, key_str->len);
ret = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);
BIO_free(bio);
DBG_INF("Successfully loaded");
- }
- if (key_str) {
- DBG_INF_FMT("Public key:%*.s", len, key_str);
- efree(key_str);
+ DBG_INF_FMT("Public key:%*.s", key_str->len, key_str->val);
+ STR_RELEASE(key_str);
}
php_stream_free(stream, PHP_STREAM_FREE_CLOSE);
}
diff --git a/ext/mysqlnd/mysqlnd_bt.c b/ext/mysqlnd/mysqlnd_bt.c
deleted file mode 100644
index a93af6b395..0000000000
--- a/ext/mysqlnd/mysqlnd_bt.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 2006-2014 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 */
-
-/* {{{ 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;
-}
-/* }}} */
-
-
-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_debug.c b/ext/mysqlnd/mysqlnd_debug.c
index 9fbcc4768f..92121cf247 100644
--- a/ext/mysqlnd/mysqlnd_debug.c
+++ b/ext/mysqlnd/mysqlnd_debug.c
@@ -26,6 +26,7 @@
#include "mysqlnd_debug.h"
static const char * const mysqlnd_debug_default_trace_file = "/tmp/mysqlnd.trace";
+static const char * const mysqlnd_debug_empty_string = "";
#ifdef ZTS
#define MYSQLND_ZTS(self) TSRMLS_D = (self)->TSRMLS_C
@@ -269,11 +270,11 @@ MYSQLND_METHOD(mysqlnd_debug, func_enter)(MYSQLND_DEBUG * self,
const char ** p = self->skip_functions;
while (*p) {
if (*p == func_name) {
- zend_stack_push(&self->call_stack, "", sizeof(""));
+ zend_stack_push(&self->call_stack, &mysqlnd_debug_empty_string);
#ifndef MYSQLND_PROFILING_DISABLED
if (self->flags & MYSQLND_DEBUG_PROFILE_CALLS) {
uint64_t some_time = 0;
- zend_stack_push(&self->call_time_stack, &some_time, sizeof(some_time));
+ zend_stack_push(&self->call_time_stack, &some_time);
}
#endif
return FALSE;
@@ -282,16 +283,16 @@ MYSQLND_METHOD(mysqlnd_debug, func_enter)(MYSQLND_DEBUG * self,
}
}
- zend_stack_push(&self->call_stack, func_name, func_name_len + 1);
+ zend_stack_push(&self->call_stack, &func_name);
#ifndef MYSQLND_PROFILING_DISABLED
if (self->flags & MYSQLND_DEBUG_PROFILE_CALLS) {
uint64_t some_time = 0;
- zend_stack_push(&self->call_time_stack, &some_time, sizeof(some_time));
+ zend_stack_push(&self->call_time_stack, &some_time);
}
#endif
if (zend_hash_num_elements(&self->not_filtered_functions) &&
- 0 == zend_hash_exists(&self->not_filtered_functions, func_name, strlen(func_name) + 1))
+ 0 == zend_hash_str_exists(&self->not_filtered_functions, func_name, strlen(func_name)))
{
return FALSE;
}
@@ -324,7 +325,7 @@ struct st_mysqlnd_dbg_function_profile {
static enum_func_status
MYSQLND_METHOD(mysqlnd_debug, func_leave)(MYSQLND_DEBUG * self, unsigned int line, const char * const file, uint64_t call_time)
{
- char *func_name;
+ char **func_name;
uint64_t * parent_non_own_time_ptr = NULL, * mine_non_own_time_ptr = NULL;
uint64_t mine_non_own_time = 0;
zend_bool profile_calls = self->flags & MYSQLND_DEBUG_PROFILE_CALLS? TRUE:FALSE;
@@ -336,38 +337,38 @@ MYSQLND_METHOD(mysqlnd_debug, func_leave)(MYSQLND_DEBUG * self, unsigned int lin
return PASS;
}
- zend_stack_top(&self->call_stack, (void **)&func_name);
+ func_name = zend_stack_top(&self->call_stack);
#ifndef MYSQLND_PROFILING_DISABLED
if (profile_calls) {
- zend_stack_top(&self->call_time_stack, (void **)&mine_non_own_time_ptr);
+ mine_non_own_time_ptr = zend_stack_top(&self->call_time_stack);
mine_non_own_time = *mine_non_own_time_ptr;
zend_stack_del_top(&self->call_time_stack); /* callee - removing ourselves */
}
#endif
- if (func_name[0] == '\0') {
+ if ((*func_name)[0] == '\0') {
; /* don't log that function */
} else if (!zend_hash_num_elements(&self->not_filtered_functions) ||
- 1 == zend_hash_exists(&self->not_filtered_functions, func_name, strlen(func_name) + 1))
+ 1 == zend_hash_str_exists(&self->not_filtered_functions, (*func_name), strlen((*func_name))))
{
#ifndef MYSQLND_PROFILING_DISABLED
if (FALSE == profile_calls) {
#endif
- self->m->log_va(self, line, file, zend_stack_count(&self->call_stack) - 1, NULL, "<%s", func_name);
+ self->m->log_va(self, line, file, zend_stack_count(&self->call_stack) - 1, NULL, "<%s", *func_name);
#ifndef MYSQLND_PROFILING_DISABLED
} else {
struct st_mysqlnd_dbg_function_profile f_profile_stack = {0};
struct st_mysqlnd_dbg_function_profile * f_profile = NULL;
uint64_t own_time = call_time - mine_non_own_time;
- uint func_name_len = strlen(func_name);
+ uint func_name_len = strlen(*func_name);
self->m->log_va(self, line, file, zend_stack_count(&self->call_stack) - 1, NULL, "<%s (total=%u own=%u in_calls=%u)",
- func_name, (unsigned int) call_time, (unsigned int) own_time, (unsigned int) mine_non_own_time
+ *func_name, (unsigned int) call_time, (unsigned int) own_time, (unsigned int) mine_non_own_time
);
- if (SUCCESS == zend_hash_find(&self->function_profiles, func_name, func_name_len + 1, (void **) &f_profile)) {
+ if ((f_profile = zend_hash_str_find_ptr(&self->function_profiles, *func_name, func_name_len)) != NULL) {
/* found */
if (f_profile) {
if (mine_non_own_time < f_profile->min_in_calls) {
@@ -411,16 +412,16 @@ MYSQLND_METHOD(mysqlnd_debug, func_leave)(MYSQLND_DEBUG * self, unsigned int lin
f_profile->min_total = f_profile->max_total = f_profile->avg_total = call_time;
f_profile->min_own = f_profile->max_own = f_profile->avg_own = own_time;
f_profile->calls = 1;
- zend_hash_add(&self->function_profiles, func_name, func_name_len+1, f_profile, sizeof(struct st_mysqlnd_dbg_function_profile), NULL);
+ zend_hash_str_add_mem(&self->function_profiles, *func_name, func_name_len, f_profile, sizeof(struct st_mysqlnd_dbg_function_profile));
}
if ((uint) zend_stack_count(&self->call_time_stack)) {
uint64_t parent_non_own_time = 0;
- zend_stack_top(&self->call_time_stack, (void **)&parent_non_own_time_ptr);
+ parent_non_own_time_ptr = zend_stack_top(&self->call_time_stack);
parent_non_own_time = *parent_non_own_time_ptr;
parent_non_own_time += call_time;
zend_stack_del_top(&self->call_time_stack); /* the caller */
- zend_stack_push(&self->call_time_stack, &parent_non_own_time, sizeof(parent_non_own_time)); /* add back the caller */
+ zend_stack_push(&self->call_time_stack, &parent_non_own_time); /* add back the caller */
}
}
#endif
@@ -440,29 +441,22 @@ MYSQLND_METHOD(mysqlnd_debug, close)(MYSQLND_DEBUG * self)
#ifndef MYSQLND_PROFILING_DISABLED
if (!(self->flags & MYSQLND_DEBUG_FLUSH) && (self->flags & MYSQLND_DEBUG_PROFILE_CALLS)) {
struct st_mysqlnd_dbg_function_profile * f_profile;
- HashPosition pos_values;
+ zend_string *string_key = NULL;
self->m->log_va(self, __LINE__, __FILE__, 0, "info : ",
"number of functions: %d", zend_hash_num_elements(&self->function_profiles));
- zend_hash_internal_pointer_reset_ex(&self->function_profiles, &pos_values);
- while (zend_hash_get_current_data_ex(&self->function_profiles, (void **) &f_profile, &pos_values) == SUCCESS) {
- char *string_key = NULL;
- uint string_key_len;
- ulong num_key;
-
- zend_hash_get_current_key_ex(&self->function_profiles, &string_key, &string_key_len, &num_key, 0, &pos_values);
-
+ ZEND_HASH_FOREACH_STR_KEY_PTR(&self->function_profiles, string_key, f_profile) {
self->m->log_va(self, __LINE__, __FILE__, -1, "info : ",
"%-40s\tcalls=%5llu own_slow=%5llu in_calls_slow=%5llu total_slow=%5llu"
" min_own=%5llu max_own=%7llu avg_own=%7llu "
" min_in_calls=%5llu max_in_calls=%7llu avg_in_calls=%7llu"
" min_total=%5llu max_total=%7llu avg_total=%7llu"
- ,string_key
+ ,string_key->val
,(uint64_t) f_profile->calls
,(uint64_t) f_profile->own_underporm_calls
,(uint64_t) f_profile->in_calls_underporm_calls
,(uint64_t) f_profile->total_underporm_calls
-
+
,(uint64_t) f_profile->min_own
,(uint64_t) f_profile->max_own
,(uint64_t) f_profile->avg_own
@@ -473,8 +467,7 @@ MYSQLND_METHOD(mysqlnd_debug, close)(MYSQLND_DEBUG * self)
,(uint64_t) f_profile->max_total
,(uint64_t) f_profile->avg_total
);
- zend_hash_move_forward_ex(&self->function_profiles, &pos_values);
- }
+ } ZEND_HASH_FOREACH_END();
}
#endif
@@ -592,8 +585,8 @@ MYSQLND_METHOD(mysqlnd_debug, set_mode)(MYSQLND_DEBUG * self, const char * const
memcpy(func_name, mode + i + 1, func_name_len);
func_name[func_name_len] = '\0';
- zend_hash_add_empty_element(&self->not_filtered_functions,
- func_name, func_name_len + 1);
+ zend_hash_str_add_empty_element(&self->not_filtered_functions,
+ func_name, func_name_len);
i = j;
}
if (mode[j] == ':') {
@@ -730,8 +723,8 @@ mysqlnd_debug_init(const char * skip_functions[] TSRMLS_DC)
#endif
ret->nest_level_limit = 0;
ret->pid = getpid();
- zend_stack_init(&ret->call_stack);
- zend_stack_init(&ret->call_time_stack);
+ zend_stack_init(&ret->call_stack, sizeof(char *));
+ zend_stack_init(&ret->call_time_stack, sizeof(uint64_t));
zend_hash_init(&ret->not_filtered_functions, 0, NULL, NULL, 0);
zend_hash_init(&ret->function_profiles, 0, NULL, NULL, 0);
@@ -792,7 +785,6 @@ static struct st_mysqlnd_plugin_trace_log mysqlnd_plugin_trace_log_plugin =
},
{/* methods */
mysqlnd_debug_init,
- mysqlnd_get_backtrace
}
};
diff --git a/ext/mysqlnd/mysqlnd_debug.h b/ext/mysqlnd/mysqlnd_debug.h
index 861851378b..6f073b1489 100644
--- a/ext/mysqlnd/mysqlnd_debug.h
+++ b/ext/mysqlnd/mysqlnd_debug.h
@@ -66,7 +66,6 @@ struct st_mysqlnd_plugin_trace_log
struct
{
MYSQLND_DEBUG * (*trace_instance_init)(const char * skip_functions[] TSRMLS_DC);
- char * (*get_backtrace)(uint max_levels, size_t * length TSRMLS_DC);
} methods;
};
@@ -74,7 +73,6 @@ 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);
#if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 1400))
#ifdef PHP_WIN32
diff --git a/ext/mysqlnd/mysqlnd_loaddata.c b/ext/mysqlnd/mysqlnd_loaddata.c
index 94d69a4008..ab7a1ae9eb 100644
--- a/ext/mysqlnd/mysqlnd_loaddata.c
+++ b/ext/mysqlnd/mysqlnd_loaddata.c
@@ -27,7 +27,7 @@
/* {{{ 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, const char * const filename TSRMLS_DC)
{
MYSQLND_INFILE_INFO *info;
php_stream_context *context = NULL;
@@ -73,7 +73,7 @@ int mysqlnd_local_infile_read(void * ptr, zend_uchar * buf, unsigned int buf_len
DBG_ENTER("mysqlnd_local_infile_read");
- count = (int)php_stream_read(info->fd, (char *) buf, buf_len);
+ count = (int) php_stream_read(info->fd, (char *) buf, buf_len);
if (count < 0) {
strcpy(info->error_msg, "Error reading file");
@@ -125,7 +125,7 @@ void mysqlnd_local_infile_end(void * ptr TSRMLS_DC)
/* {{{ mysqlnd_local_infile_default */
-PHPAPI void
+void
mysqlnd_local_infile_default(MYSQLND_CONN_DATA * conn)
{
conn->infile.local_infile_init = mysqlnd_local_infile_init;
@@ -136,20 +136,6 @@ mysqlnd_local_infile_default(MYSQLND_CONN_DATA * conn)
/* }}} */
-/* {{{ mysqlnd_set_local_infile_handler */
-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);
- } else {
- zval_dtor(conn->infile.callback);
- }
- ZVAL_STRING(conn->infile.callback, (char*) funcname, 1);
-}
-/* }}} */
-
-
static const char *lost_conn = "Lost connection to MySQL server during LOAD DATA of local file";
@@ -184,7 +170,7 @@ mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zen
*is_warning = FALSE;
/* init handler: allocate read buffer and open file */
- if (infile.local_infile_init(&info, (char *)filename, conn->infile.userdata TSRMLS_CC)) {
+ if (infile.local_infile_init(&info, (char *)filename TSRMLS_CC)) {
char tmp_buf[sizeof(conn->error_info->error)];
int tmp_error_no;
*is_warning = TRUE;
diff --git a/ext/mysqlnd/mysqlnd_net.c b/ext/mysqlnd/mysqlnd_net.c
index a0beed8b97..84757f88c1 100644
--- a/ext/mysqlnd/mysqlnd_net.c
+++ b/ext/mysqlnd/mysqlnd_net.c
@@ -105,6 +105,7 @@ MYSQLND_METHOD(mysqlnd_net, network_write_ex)(MYSQLND_NET * const net, const zen
}
/* }}} */
+
/* {{{ mysqlnd_net::open_pipe */
static php_stream *
MYSQLND_METHOD(mysqlnd_net, open_pipe)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len,
@@ -116,6 +117,7 @@ MYSQLND_METHOD(mysqlnd_net, open_pipe)(MYSQLND_NET * const net, const char * con
#else
unsigned int streams_options = 0;
#endif
+ dtor_func_t origin_dtor;
php_stream * net_stream = NULL;
DBG_ENTER("mysqlnd_net::open_pipe");
@@ -131,12 +133,13 @@ MYSQLND_METHOD(mysqlnd_net, open_pipe)(MYSQLND_NET * const net, const char * con
/*
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.
+ unregistered until 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;
-
+ origin_dtor = EG(regular_list).pDestructor;
+ EG(regular_list).pDestructor = NULL;
+ zend_hash_index_del(&EG(regular_list), net_stream->res->handle); /* ToDO: should it be res->handle, do streams register with addref ?*/
+ EG(regular_list).pDestructor = origin_dtor;
+ net_stream->res = NULL;
DBG_RETURN(net_stream);
}
@@ -157,9 +160,10 @@ MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix)(MYSQLND_NET * const net, const cha
unsigned int streams_flags = STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT;
char * hashed_details = NULL;
int hashed_details_len = 0;
- char * errstr = NULL;
+ zend_string *errstr = NULL;
int errcode = 0;
struct timeval tv;
+ dtor_func_t origin_dtor;
php_stream * net_stream = NULL;
DBG_ENTER("mysqlnd_net::open_tcp_or_unix");
@@ -186,10 +190,10 @@ MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix)(MYSQLND_NET * const net, const cha
mnd_sprintf_free(hashed_details);
}
errcode = CR_CONNECTION_ERROR;
- SET_CLIENT_ERROR(*error_info, errcode? errcode:CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, errstr);
+ SET_CLIENT_ERROR(*error_info, errcode? errcode:CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, errstr->val);
if (errstr) {
/* no mnd_ since we don't allocate it */
- efree(errstr);
+ STR_RELEASE(errstr);
}
DBG_RETURN(NULL);
}
@@ -199,17 +203,19 @@ MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix)(MYSQLND_NET * const net, const cha
This is unwanted. ext/mysql or ext/mysqli are responsible to clean,
whatever they have to.
*/
- zend_rsrc_list_entry *le;
+ zend_resource *le;
- if (zend_hash_find(&EG(persistent_list), hashed_details, hashed_details_len + 1, (void*) &le) == SUCCESS) {
+ if ((le = zend_hash_str_find_ptr(&EG(persistent_list), hashed_details, hashed_details_len))) {
+ origin_dtor = EG(persistent_list).pDestructor;
/*
in_free will let streams code skip destructing - big HACK,
but STREAMS suck big time regarding persistent streams.
Just not compatible for extensions that need persistency.
*/
- net_stream->in_free = 1;
- zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_len + 1);
- net_stream->in_free = 0;
+ EG(persistent_list).pDestructor = NULL;
+ zend_hash_str_del(&EG(persistent_list), hashed_details, hashed_details_len);
+ EG(persistent_list).pDestructor = origin_dtor;
+ pefree(le, 1);
}
#if ZEND_DEBUG
/* Shut-up the streams, they don't know what they are doing */
@@ -221,12 +227,14 @@ MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix)(MYSQLND_NET * const net, const cha
/*
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.
+ unregistered until 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;
-
+ origin_dtor = EG(regular_list).pDestructor;
+ EG(regular_list).pDestructor = NULL;
+ zend_hash_index_del(&EG(regular_list), net_stream->res->handle); /* ToDO: should it be res->handle, do streams register with addref ?*/
+ efree(net_stream->res);
+ net_stream->res = NULL;
+ EG(regular_list).pDestructor = origin_dtor;
DBG_RETURN(net_stream);
}
/* }}} */
@@ -869,7 +877,7 @@ MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
if (net->data->options.ssl_key) {
zval key_zval;
- ZVAL_STRING(&key_zval, net->data->options.ssl_key, 0);
+ ZVAL_STRING(&key_zval, net->data->options.ssl_key);
php_stream_context_set_option(context, "ssl", "local_pk", &key_zval);
}
if (net->data->options.ssl_verify_peer) {
@@ -879,7 +887,7 @@ MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
}
if (net->data->options.ssl_cert) {
zval cert_zval;
- ZVAL_STRING(&cert_zval, net->data->options.ssl_cert, 0);
+ ZVAL_STRING(&cert_zval, net->data->options.ssl_cert);
php_stream_context_set_option(context, "ssl", "local_cert", &cert_zval);
if (!net->data->options.ssl_key) {
php_stream_context_set_option(context, "ssl", "local_pk", &cert_zval);
@@ -887,25 +895,29 @@ MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
}
if (net->data->options.ssl_ca) {
zval cafile_zval;
- ZVAL_STRING(&cafile_zval, net->data->options.ssl_ca, 0);
+ ZVAL_STRING(&cafile_zval, net->data->options.ssl_ca);
php_stream_context_set_option(context, "ssl", "cafile", &cafile_zval);
}
if (net->data->options.ssl_capath) {
zval capath_zval;
- ZVAL_STRING(&capath_zval, net->data->options.ssl_capath, 0);
+ ZVAL_STRING(&capath_zval, net->data->options.ssl_capath);
php_stream_context_set_option(context, "ssl", "cafile", &capath_zval);
}
if (net->data->options.ssl_passphrase) {
zval passphrase_zval;
- ZVAL_STRING(&passphrase_zval, net->data->options.ssl_passphrase, 0);
+ ZVAL_STRING(&passphrase_zval, net->data->options.ssl_passphrase);
php_stream_context_set_option(context, "ssl", "passphrase", &passphrase_zval);
}
if (net->data->options.ssl_cipher) {
zval cipher_zval;
- ZVAL_STRING(&cipher_zval, net->data->options.ssl_cipher, 0);
+ ZVAL_STRING(&cipher_zval, net->data->options.ssl_cipher);
php_stream_context_set_option(context, "ssl", "ciphers", &cipher_zval);
}
+#if PHP_API_VERSION >= 20131106
+ php_stream_context_set(net_stream, context TSRMLS_CC);
+#else
php_stream_context_set(net_stream, context);
+#endif
if (php_stream_xport_crypto_setup(net_stream, STREAM_CRYPTO_METHOD_TLS_CLIENT, NULL TSRMLS_CC) < 0 ||
php_stream_xport_crypto_enable(net_stream, 1 TSRMLS_CC) < 0)
{
@@ -921,7 +933,11 @@ MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC)
of the context, which means usage of already freed memory, bad. Actually we don't need this
context anymore after we have enabled SSL on the connection. Thus it is very simple, we remove it.
*/
+#if PHP_API_VERSION >= 20131106
+ php_stream_context_set(net_stream, NULL TSRMLS_CC);
+#else
php_stream_context_set(net_stream, NULL);
+#endif
if (net->data->options.timeout_read) {
struct timeval tv;
diff --git a/ext/mysqlnd/mysqlnd_plugin.c b/ext/mysqlnd/mysqlnd_plugin.c
index 86543a05c2..7f5fb9b03f 100644
--- a/ext/mysqlnd/mysqlnd_plugin.c
+++ b/ext/mysqlnd/mysqlnd_plugin.c
@@ -106,9 +106,9 @@ mysqlnd_plugin_subsystem_init(TSRMLS_D)
/* {{{ mysqlnd_plugin_end_apply_func */
int
-mysqlnd_plugin_end_apply_func(void *pDest TSRMLS_DC)
+mysqlnd_plugin_end_apply_func(zval *el TSRMLS_DC)
{
- struct st_mysqlnd_plugin_header * plugin_header = *(struct st_mysqlnd_plugin_header **) pDest;
+ struct st_mysqlnd_plugin_header * plugin_header = (struct st_mysqlnd_plugin_header *)Z_PTR_P(el);
if (plugin_header->m.plugin_shutdown) {
plugin_header->m.plugin_shutdown(plugin_header TSRMLS_CC);
}
@@ -141,7 +141,7 @@ PHPAPI unsigned int mysqlnd_plugin_register_ex(struct st_mysqlnd_plugin_header *
{
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);
+ zend_hash_str_update_ptr(&mysqlnd_registered_plugins, plugin->plugin_name, strlen(plugin->plugin_name), plugin);
} 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);
@@ -157,8 +157,8 @@ PHPAPI unsigned int mysqlnd_plugin_register_ex(struct st_mysqlnd_plugin_header *
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;
+ if ((plugin = zend_hash_str_find_ptr(&mysqlnd_registered_plugins, name, strlen(name))) != NULL) {
+ return plugin;
}
return NULL;
@@ -173,20 +173,18 @@ PHPAPI void _mysqlnd_plugin_apply_with_argument(apply_func_arg_t apply_func, voi
* 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);
+ zval *val;
+ int result;
+ ZEND_HASH_FOREACH_VAL(&mysqlnd_registered_plugins, val) {
+ result = apply_func(val, 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;
}
- }
+ } ZEND_HASH_FOREACH_END();
}
/* }}} */
diff --git a/ext/mysqlnd/mysqlnd_priv.h b/ext/mysqlnd/mysqlnd_priv.h
index a44e29d9f9..536b37caa7 100644
--- a/ext/mysqlnd/mysqlnd_priv.h
+++ b/ext/mysqlnd/mysqlnd_priv.h
@@ -41,13 +41,6 @@
#define pestrndup(s, length, persistent) ((persistent)?zend_strndup((s),(length)):estrndup((s),(length)))
#endif
-#define mysqlnd_array_init(arg, field_count) \
-{ \
- ALLOC_HASHTABLE_REL(Z_ARRVAL_P(arg));\
- zend_hash_init(Z_ARRVAL_P(arg), (field_count), NULL, ZVAL_PTR_DTOR, 0); \
- Z_TYPE_P(arg) = IS_ARRAY;\
-}
-
#define MYSQLND_STR_W_LEN(str) str, (sizeof(str) - 1)
#define MYSQLND_DEBUG_DUMP_TIME 1
diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c
index 4588165f05..986a664410 100644
--- a/ext/mysqlnd/mysqlnd_ps.c
+++ b/ext/mysqlnd/mysqlnd_ps.c
@@ -38,6 +38,7 @@ const char * const mysqlnd_stmt_not_prepared = "Statement not prepared";
/* 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);
+enum_func_status mysqlnd_stmt_execute_batch_generate_request(MYSQLND_STMT * const s, zend_uchar ** request, size_t *request_len, zend_bool * free_buffer TSRMLS_DC);
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);
@@ -109,12 +110,12 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s TSRMLS_DC)
DBG_RETURN(NULL);
}
/* if pecalloc is used valgrind barks gcc version 4.3.1 20080507 (prerelease) [gcc-4_3-branch revision 135036] (SUSE Linux) */
- set->data = mnd_emalloc((size_t)(result->stored_data->row_count * result->meta->field_count * sizeof(zval *)));
+ set->data = mnd_emalloc((size_t)(result->stored_data->row_count * result->meta->field_count * sizeof(zval)));
if (!set->data) {
SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(NULL);
}
- memset(set->data, 0, (size_t)(result->stored_data->row_count * result->meta->field_count * sizeof(zval *)));
+ memset(set->data, 0, (size_t)(result->stored_data->row_count * result->meta->field_count * sizeof(zval)));;
}
/* Position at the first row */
set->data_cursor = set->data;
@@ -642,11 +643,13 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s TSRMLS_DC)
fetch(); <-- no binding, but that's not a problem
bind_result();
execute(); <-- here we will leak because we separate without need
- */
+ */
unsigned int i;
for (i = 0; i < stmt->field_count; i++) {
if (stmt->result_bind[i].bound == TRUE) {
- zval_copy_ctor(stmt->result_bind[i].zv);
+ zval *result = &stmt->result_bind[i].zv;
+ ZVAL_DEREF(result);
+ Z_TRY_ADDREF_P(result);
}
}
}
@@ -680,7 +683,7 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s TSRMLS_DC)
DBG_RETURN(FAIL);
}
for (i = 0; i < stmt->param_count; i++) {
- if (stmt->param_bind[i].zv == NULL) {
+ if (Z_ISUNDEF(stmt->param_bind[i].zv)) {
not_bound++;
}
}
@@ -751,9 +754,9 @@ mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, unsigned int
/* The user could have skipped binding - don't crash*/
if (stmt->result_bind) {
unsigned int i;
- zval **current_row = set->data_cursor;
+ zval *current_row = set->data_cursor;
- if (NULL == current_row[0]) {
+ if (Z_ISUNDEF(current_row[0])) {
uint64_t row_num = (set->data_cursor - set->data) / field_count;
enum_func_status rc = result->stored_data->m.row_decoder(result->stored_data->row_buffers[row_num],
current_row,
@@ -772,8 +775,8 @@ mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, unsigned int
String of zero size, definitely can't be the next max_length.
Thus for NULL and zero-length we are quite efficient.
*/
- if (Z_TYPE_P(current_row[i]) >= IS_STRING) {
- unsigned long len = Z_STRLEN_P(current_row[i]);
+ if (Z_TYPE(current_row[i]) == IS_STRING) {
+ unsigned long len = Z_STRLEN(current_row[i]);
if (meta->fields[i].max_length < len) {
meta->fields[i].max_length = len;
}
@@ -783,16 +786,17 @@ mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, unsigned int
}
for (i = 0; i < result->field_count; i++) {
+ zval *result = &stmt->result_bind[i].zv;
+
+ ZVAL_DEREF(result);
/* Clean what we copied last time */
#ifndef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
- if (stmt->result_bind[i].zv) {
- zval_dtor(stmt->result_bind[i].zv);
- }
+ zval_dtor(result);
#endif
/* copy the type */
if (stmt->result_bind[i].bound == TRUE) {
- DBG_INF_FMT("i=%u type=%u", i, Z_TYPE_P(current_row[i]));
- if (Z_TYPE_P(current_row[i]) != IS_NULL) {
+ DBG_INF_FMT("i=%u type=%u", i, Z_TYPE(current_row[i]));
+ if (Z_TYPE(current_row[i]) != IS_NULL) {
/*
Copy the value.
Pre-condition is that the zvals in the result_bind buffer
@@ -801,13 +805,12 @@ mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, unsigned int
counting the user can't delete the strings the variables point to.
*/
- Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(current_row[i]);
- stmt->result_bind[i].zv->value = current_row[i]->value;
+ ZVAL_COPY_VALUE(result, &current_row[i]);
#ifndef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
- zval_copy_ctor(stmt->result_bind[i].zv);
+ Z_TRY_ADDREF_P(result);
#endif
} else {
- ZVAL_NULL(stmt->result_bind[i].zv);
+ ZVAL_NULL(result);
}
}
}
@@ -889,19 +892,23 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned i
for (i = 0; i < field_count; i++) {
if (stmt->result_bind[i].bound == TRUE) {
- zval *data = result->unbuf->last_row_data[i];
+ zval *data = &result->unbuf->last_row_data[i];
+ zval *result = &stmt->result_bind[i].zv;
+
+ ZVAL_DEREF(result);
/*
stmt->result_bind[i].zv has been already destructed
in result->unbuf->m.free_last_data()
*/
#ifndef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
- zval_dtor(stmt->result_bind[i].zv);
+ zval_dtor(result);
#endif
- if (IS_NULL != (Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(data)) ) {
- if ((Z_TYPE_P(data) == IS_STRING) && (meta->fields[i].max_length < (unsigned long) Z_STRLEN_P(data))) {
+ if (!Z_ISNULL_P(data)) {
+ if ((Z_TYPE_P(data) == IS_STRING) &&
+ (meta->fields[i].max_length < (unsigned long) Z_STRLEN_P(data))) {
meta->fields[i].max_length = Z_STRLEN_P(data);
}
- stmt->result_bind[i].zv->value = data->value;
+ ZVAL_COPY_VALUE(result, data);
/* copied data, thus also the ownership. Thus null data */
ZVAL_NULL(data);
}
@@ -1069,21 +1076,27 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int f
/* If no result bind, do nothing. We consumed the data */
for (i = 0; i < field_count; i++) {
if (stmt->result_bind[i].bound == TRUE) {
- zval *data = result->unbuf->last_row_data[i];
+ zval *data = &result->unbuf->last_row_data[i];
+ zval *result = &stmt->result_bind[i].zv;
+
+ ZVAL_DEREF(result);
/*
stmt->result_bind[i].zv has been already destructed
in result->unbuf->m.free_last_data()
*/
#ifndef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
- zval_dtor(stmt->result_bind[i].zv);
+ zval_dtor(result);
#endif
- DBG_INF_FMT("i=%u bound_var=%p type=%u refc=%u", i, stmt->result_bind[i].zv,
- Z_TYPE_P(data), Z_REFCOUNT_P(stmt->result_bind[i].zv));
- if (IS_NULL != (Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(data))) {
- if ((Z_TYPE_P(data) == IS_STRING) && (meta->fields[i].max_length < (unsigned long) Z_STRLEN_P(data))) {
+ DBG_INF_FMT("i=%u bound_var=%p type=%u refc=%u", i, &stmt->result_bind[i].zv,
+ Z_TYPE_P(data), Z_REFCOUNTED(stmt->result_bind[i].zv)?
+ Z_REFCOUNT(stmt->result_bind[i].zv) : 0);
+
+ if (!Z_ISNULL_P(data)) {
+ if ((Z_TYPE_P(data) == IS_STRING) &&
+ (meta->fields[i].max_length < (unsigned long) Z_STRLEN_P(data))) {
meta->fields[i].max_length = Z_STRLEN_P(data);
}
- stmt->result_bind[i].zv->value = data->value;
+ ZVAL_COPY_VALUE(result, data);
/* copied data, thus also the ownership. Thus null data */
ZVAL_NULL(data);
}
@@ -1167,7 +1180,7 @@ MYSQLND_METHOD(mysqlnd_stmt, fetch)(MYSQLND_STMT * const s, zend_bool * const fe
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);
+ DBG_INF_FMT("result_bind=%p separated_once=%u", &stmt->result_bind, stmt->result_zvals_separated_once);
/*
The user might have not bound any variables for result.
Do the binding once she does it.
@@ -1180,8 +1193,10 @@ MYSQLND_METHOD(mysqlnd_stmt, fetch)(MYSQLND_STMT * const s, zend_bool * const fe
*/
for (i = 0; i < stmt->result->field_count; i++) {
if (stmt->result_bind[i].bound == TRUE) {
- zval_dtor(stmt->result_bind[i].zv);
- ZVAL_NULL(stmt->result_bind[i].zv);
+ zval *result = &stmt->result_bind[i].zv;
+ ZVAL_DEREF(result);
+ zval_dtor(result);
+ ZVAL_NULL(result);
}
}
stmt->result_zvals_separated_once = TRUE;
@@ -1437,9 +1452,7 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_parameters)(MYSQLND_STMT * const s, MYSQLND_PA
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) {
- zval_ptr_dtor(&stmt->param_bind[i].zv);
- }
+ zval_ptr_dtor(&stmt->param_bind[i].zv);
}
if (stmt->param_bind != param_bind) {
s->m->free_parameter_bind(s, stmt->param_bind TSRMLS_CC);
@@ -1452,7 +1465,7 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_parameters)(MYSQLND_STMT * const s, MYSQLND_PA
DBG_INF_FMT("%u is of type %u", i, stmt->param_bind[i].type);
/* Prevent from freeing */
/* Don't update is_ref, or we will leak during conversion */
- Z_ADDREF_P(stmt->param_bind[i].zv);
+ Z_TRY_ADDREF(stmt->param_bind[i].zv);
stmt->param_bind[i].flags = 0;
if (stmt->param_bind[i].type == MYSQL_TYPE_LONG_BLOB) {
stmt->param_bind[i].flags &= ~MYSQLND_PARAM_BIND_BLOB_USED;
@@ -1502,17 +1515,15 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_one_parameter)(MYSQLND_STMT * const s, unsigne
/* Prevent from freeing */
/* Don't update is_ref, or we will leak during conversion */
- Z_ADDREF_P(zv);
+ Z_TRY_ADDREF_P(zv);
DBG_INF("Binding");
/* Release what we had, if we had */
- if (stmt->param_bind[param_no].zv) {
- zval_ptr_dtor(&stmt->param_bind[param_no].zv);
- }
+ zval_ptr_dtor(&stmt->param_bind[param_no].zv);
if (type == MYSQL_TYPE_LONG_BLOB) {
/* The client will use stmt_send_long_data */
stmt->param_bind[param_no].flags &= ~MYSQLND_PARAM_BIND_BLOB_USED;
}
- stmt->param_bind[param_no].zv = zv;
+ ZVAL_COPY_VALUE(&stmt->param_bind[param_no].zv, zv);
stmt->param_bind[param_no].type = type;
stmt->send_types_to_server = 1;
@@ -1588,8 +1599,10 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const s,
stmt->result_bind = result_bind;
for (i = 0; i < stmt->field_count; i++) {
/* Prevent from freeing */
- Z_ADDREF_P(stmt->result_bind[i].zv);
- DBG_INF_FMT("ref of %p = %u", stmt->result_bind[i].zv, Z_REFCOUNT_P(stmt->result_bind[i].zv));
+ Z_TRY_ADDREF(stmt->result_bind[i].zv);
+
+ DBG_INF_FMT("ref of %p = %u", &stmt->result_bind[i].zv,
+ Z_REFCOUNTED(stmt->result_bind[i].zv)? Z_REFCOUNT(stmt->result_bind[i].zv) : 0);
/*
Don't update is_ref !!! it's not our job
Otherwise either 009.phpt or mysqli_stmt_bind_result.phpt
@@ -1643,7 +1656,7 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_one_result)(MYSQLND_STMT * const s, unsigned i
if (!stmt->result_bind) {
DBG_RETURN(FAIL);
}
- ALLOC_INIT_ZVAL(stmt->result_bind[param_no].zv);
+ ZVAL_NULL(&stmt->result_bind[param_no].zv);
/*
Don't update is_ref !!! it's not our job
Otherwise either 009.phpt or mysqli_stmt_bind_result.phpt
@@ -2008,29 +2021,12 @@ mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const s TSRMLS_DC)
for (i = 0; i < stmt->field_count; i++) {
/* Let's try with no cache */
if (stmt->result_bind[i].bound == TRUE) {
- DBG_INF_FMT("%u has refcount=%u", i, Z_REFCOUNT_P(stmt->result_bind[i].zv));
- /*
- We have to separate the actual zval value of the bound
- variable from our allocated zvals or we will face double-free
- */
- if (Z_REFCOUNT_P(stmt->result_bind[i].zv) > 1) {
-#ifdef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
- zval_copy_ctor(stmt->result_bind[i].zv);
-#endif
- zval_ptr_dtor(&stmt->result_bind[i].zv);
- } else {
- /*
- If it is a string, what is pointed will be freed
- later in free_result(). We need to remove the variable to
- which the user has lost reference.
- */
-#ifdef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
- ZVAL_NULL(stmt->result_bind[i].zv);
-#endif
- zval_ptr_dtor(&stmt->result_bind[i].zv);
- }
+ DBG_INF_FMT("%u has refcount=%u", i,
+ Z_REFCOUNTED(stmt->result_bind[i].zv)? Z_REFCOUNT(stmt->result_bind[i].zv) : 0);
+ zval_ptr_dtor(&stmt->result_bind[i].zv);
}
}
+
s->m->free_result_bind(s, stmt->result_bind TSRMLS_CC);
stmt->result_bind = NULL;
@@ -2061,27 +2057,10 @@ mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const s, unsigned int param
*/
/* Let's try with no cache */
if (stmt->result_bind[param_no].bound == TRUE) {
- DBG_INF_FMT("%u has refcount=%u", param_no, Z_REFCOUNT_P(stmt->result_bind[param_no].zv));
- /*
- We have to separate the actual zval value of the bound
- variable from our allocated zvals or we will face double-free
- */
- if (Z_REFCOUNT_P(stmt->result_bind[param_no].zv) > 1) {
-#ifdef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
- zval_copy_ctor(stmt->result_bind[param_no].zv);
-#endif
- zval_ptr_dtor(&stmt->result_bind[param_no].zv);
- } else {
- /*
- If it is a string, what is pointed will be freed
- later in free_result(). We need to remove the variable to
- which the user has lost reference.
- */
-#ifdef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
- ZVAL_NULL(stmt->result_bind[param_no].zv);
-#endif
- zval_ptr_dtor(&stmt->result_bind[param_no].zv);
- }
+ DBG_INF_FMT("%u has refcount=%u", param_no,
+ Z_REFCOUNTED(stmt->result_bind[param_no].zv)?
+ Z_REFCOUNT(stmt->result_bind[param_no].zv) : 0);
+ zval_ptr_dtor(&stmt->result_bind[param_no].zv);
}
DBG_VOID_RETURN;
@@ -2144,9 +2123,7 @@ MYSQLND_METHOD(mysqlnd_stmt, free_stmt_content)(MYSQLND_STMT * const s TSRMLS_DC
If bind_one_parameter was used, but not everything was
bound and nothing was fetched, then some `zv` could be NULL
*/
- if (stmt->param_bind[i].zv) {
- zval_ptr_dtor(&stmt->param_bind[i].zv);
- }
+ zval_ptr_dtor(&stmt->param_bind[i].zv);
}
s->m->free_parameter_bind(s, stmt->param_bind TSRMLS_CC);
stmt->param_bind = NULL;
diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c
index 3ff0019c00..746cf01a26 100644
--- a/ext/mysqlnd/mysqlnd_ps_codec.c
+++ b/ext/mysqlnd/mysqlnd_ps_codec.c
@@ -117,7 +117,7 @@ ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, unsigne
}
if (tmp_len) {
- ZVAL_STRINGL(zv, tmp, tmp_len, 1);
+ ZVAL_STRINGL(zv, tmp, tmp_len);
}
(*row)+= byte_count;
DBG_VOID_RETURN;
@@ -277,7 +277,7 @@ ps_fetch_time(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_le
length = mnd_sprintf(&value, 0, "%s%02u:%02u:%02u", (t.neg ? "-" : ""), t.hour, t.minute, t.second);
DBG_INF_FMT("%s", value);
- ZVAL_STRINGL(zv, value, length, 1);
+ ZVAL_STRINGL(zv, value, length);
mnd_sprintf_free(value);
DBG_VOID_RETURN;
}
@@ -314,7 +314,7 @@ ps_fetch_date(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_le
length = mnd_sprintf(&value, 0, "%04u-%02u-%02u", t.year, t.month, t.day);
DBG_INF_FMT("%s", value);
- ZVAL_STRINGL(zv, value, length, 1);
+ ZVAL_STRINGL(zv, value, length);
mnd_sprintf_free(value);
DBG_VOID_RETURN;
}
@@ -358,7 +358,7 @@ ps_fetch_datetime(zval * zv, const MYSQLND_FIELD * const field, unsigned int pac
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);
- ZVAL_STRINGL(zv, value, length, 1);
+ ZVAL_STRINGL(zv, value, length);
mnd_sprintf_free(value);
DBG_VOID_RETURN;
}
@@ -377,7 +377,7 @@ ps_fetch_string(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_
DBG_ENTER("ps_fetch_string");
DBG_INF_FMT("len = %lu", length);
DBG_INF("copying from the row buffer");
- ZVAL_STRINGL(zv, (char *)*row, length, 1);
+ ZVAL_STRINGL(zv, (char *)*row, length);
(*row) += length;
DBG_VOID_RETURN;
@@ -540,16 +540,13 @@ void _mysqlnd_init_ps_fetch_subsystem()
/* {{{ mysqlnd_stmt_copy_it */
static enum_func_status
-mysqlnd_stmt_copy_it(zval *** copies, zval * original, unsigned int param_count, unsigned int current TSRMLS_DC)
+mysqlnd_stmt_copy_it(zval ** copies, zval * original, unsigned int param_count, unsigned int current TSRMLS_DC)
{
if (!*copies) {
- *copies = mnd_ecalloc(param_count, sizeof(zval *));
+ *copies = mnd_ecalloc(param_count, sizeof(zval));
}
if (*copies) {
- MAKE_STD_ZVAL((*copies)[current]);
- *(*copies)[current] = *original;
- Z_SET_REFCOUNT_P((*copies)[current], 1);
- zval_copy_ctor((*copies)[current]);
+ ZVAL_COPY(&(*copies)[current], original);
return PASS;
}
return FAIL;
@@ -559,14 +556,12 @@ mysqlnd_stmt_copy_it(zval *** copies, zval * original, unsigned int param_count,
/* {{{ mysqlnd_stmt_free_copies */
static void
-mysqlnd_stmt_free_copies(MYSQLND_STMT_DATA * stmt, zval ** copies TSRMLS_DC)
+mysqlnd_stmt_free_copies(MYSQLND_STMT_DATA * stmt, zval *copies TSRMLS_DC)
{
if (copies) {
unsigned int i;
for (i = 0; i < stmt->param_count; i++) {
- if (copies[i]) {
- zval_ptr_dtor(&copies[i]);
- }
+ zval_ptr_dtor(&copies[i]);
}
mnd_efree(copies);
}
@@ -604,39 +599,36 @@ mysqlnd_stmt_execute_check_n_enlarge_buffer(zend_uchar **buf, zend_uchar **p, si
/* {{{ mysqlnd_stmt_execute_prepare_param_types */
static enum_func_status
-mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval *** copies_param, int * resend_types_next_time TSRMLS_DC)
+mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval ** copies_param, int * resend_types_next_time TSRMLS_DC)
{
unsigned int i;
DBG_ENTER("mysqlnd_stmt_execute_prepare_param_types");
for (i = 0; i < stmt->param_count; i++) {
short current_type = stmt->param_bind[i].type;
+ zval *parameter = &stmt->param_bind[i].zv;
- if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_NULL && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) {
- zval ** copies;
+ ZVAL_DEREF(parameter);
+ if (!Z_ISNULL_P(parameter) && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) {
/* always copy the var, because we do many conversions */
- if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG &&
- PASS != mysqlnd_stmt_copy_it(copies_param, stmt->param_bind[i].zv, stmt->param_count, i TSRMLS_CC))
+ if (Z_TYPE_P(parameter) != IS_LONG &&
+ PASS != mysqlnd_stmt_copy_it(copies_param, parameter, stmt->param_count, i TSRMLS_CC))
{
SET_OOM_ERROR(*stmt->error_info);
goto end;
}
- copies = *copies_param;
/*
if it doesn't fit in a long send it as a string.
Check bug #52891 : Wrong data inserted with mysqli/mysqlnd when using bind_param, value > LONG_MAX
*/
- if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG) {
- zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;
+ if (Z_TYPE_P(parameter) != IS_LONG) {
+ zval *tmp_data = (*copies_param && !Z_ISUNDEF((*copies_param)[i]))? &(*copies_param)[i]: parameter;
/*
Because converting to double and back to long can lead
to losing precision we need second variable. Conversion to double is to see if
value is too big for a long. As said, precision could be lost.
*/
- zval *tmp_data_copy;
- MAKE_STD_ZVAL(tmp_data_copy);
- *tmp_data_copy = *tmp_data;
- Z_SET_REFCOUNT_P(tmp_data_copy, 1);
- zval_copy_ctor(tmp_data_copy);
+ zval tmp_data_copy;
+ ZVAL_COPY(&tmp_data_copy, tmp_data);
convert_to_double_ex(&tmp_data_copy);
/*
@@ -644,11 +636,11 @@ mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval *** copi
Check bug #52891 : Wrong data inserted with mysqli/mysqlnd when using bind_param, value > LONG_MAX
We do transformation here, which will be used later when sending types. The code later relies on this.
*/
- if (Z_DVAL_P(tmp_data_copy) > LONG_MAX || Z_DVAL_P(tmp_data_copy) < LONG_MIN) {
+ if (Z_DVAL(tmp_data_copy) > LONG_MAX || Z_DVAL(tmp_data_copy) < LONG_MIN) {
stmt->send_types_to_server = *resend_types_next_time = 1;
- convert_to_string_ex(&tmp_data);
+ convert_to_string_ex(tmp_data);
} else {
- convert_to_long_ex(&tmp_data);
+ convert_to_long_ex(tmp_data);
}
zval_ptr_dtor(&tmp_data_copy);
@@ -664,24 +656,26 @@ end:
/* {{{ mysqlnd_stmt_execute_store_types */
static void
-mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval ** copies, zend_uchar ** p)
+mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval * copies, zend_uchar ** p)
{
unsigned int i;
for (i = 0; i < stmt->param_count; i++) {
short current_type = stmt->param_bind[i].type;
+ zval *parameter = &stmt->param_bind[i].zv;
/* our types are not unsigned */
#if SIZEOF_LONG==8
if (current_type == MYSQL_TYPE_LONG) {
current_type = MYSQL_TYPE_LONGLONG;
}
#endif
- if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_NULL && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) {
+ ZVAL_DEREF(parameter);
+ if (!Z_ISNULL_P(parameter) && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) {
/*
if it doesn't fit in a long send it as a string.
Check bug #52891 : Wrong data inserted with mysqli/mysqlnd when using bind_param, value > LONG_MAX
*/
- if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG) {
- const zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;
+ if (Z_TYPE_P(parameter) != IS_LONG) {
+ const zval *tmp_data = (copies && !Z_ISUNDEF(copies[i]))? &copies[i] : parameter;
/*
In case of IS_LONG we do nothing, it is ok, in case of string, we just need to set current_type.
The actual transformation has been performed several dozens line above.
@@ -706,28 +700,33 @@ mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval ** copies, zend_
/* {{{ mysqlnd_stmt_execute_calculate_param_values_size */
static enum_func_status
-mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval *** copies_param, size_t * data_size TSRMLS_DC)
+mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval ** copies_param, size_t * data_size TSRMLS_DC)
{
unsigned int i;
DBG_ENTER("mysqlnd_stmt_execute_calculate_param_values_size");
for (i = 0; i < stmt->param_count; i++) {
unsigned short is_longlong = 0;
unsigned int j;
- zval *the_var = stmt->param_bind[i].zv;
+ zval *bind_var, *the_var = &stmt->param_bind[i].zv;
- if (!the_var || (stmt->param_bind[i].type != MYSQL_TYPE_LONG_BLOB && Z_TYPE_P(the_var) == IS_NULL)) {
+ bind_var = the_var;
+ ZVAL_DEREF(the_var);
+ if ((stmt->param_bind[i].type != MYSQL_TYPE_LONG_BLOB && Z_TYPE_P(the_var) == IS_NULL)) {
continue;
}
- for (j = i + 1; j < stmt->param_count; j++) {
- if (stmt->param_bind[j].zv == the_var) {
- /* Double binding of the same zval, make a copy */
- if (!*copies_param || !(*copies_param)[i]) {
- if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i TSRMLS_CC)) {
- SET_OOM_ERROR(*stmt->error_info);
- goto end;
+
+ if (Z_ISREF_P(bind_var)) {
+ for (j = i + 1; j < stmt->param_count; j++) {
+ if (Z_ISREF(stmt->param_bind[j].zv) && Z_REFVAL(stmt->param_bind[j].zv) == the_var) {
+ /* Double binding of the same zval, make a copy */
+ if (!*copies_param || Z_ISUNDEF((*copies_param)[i])) {
+ if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i TSRMLS_CC)) {
+ SET_OOM_ERROR(*stmt->error_info);
+ goto end;
+ }
}
+ break;
}
- break;
}
}
@@ -735,7 +734,7 @@ mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval
case MYSQL_TYPE_DOUBLE:
*data_size += 8;
if (Z_TYPE_P(the_var) != IS_DOUBLE) {
- if (!*copies_param || !(*copies_param)[i]) {
+ if (!*copies_param || Z_ISUNDEF((*copies_param)[i])) {
if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i TSRMLS_CC)) {
SET_OOM_ERROR(*stmt->error_info);
goto end;
@@ -748,11 +747,11 @@ mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval
/* fall-through */
case MYSQL_TYPE_LONG:
{
- zval *tmp_data = (*copies_param && (*copies_param)[i])? (*copies_param)[i]: stmt->param_bind[i].zv;
+ zval *tmp_data = (*copies_param && !Z_ISUNDEF((*copies_param)[i]))? &(*copies_param)[i]: the_var;
if (Z_TYPE_P(tmp_data) == IS_STRING) {
goto use_string;
}
- convert_to_long_ex(&tmp_data);
+ convert_to_long_ex(tmp_data);
}
*data_size += 4 + is_longlong;
break;
@@ -770,15 +769,15 @@ mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval
use_string:
*data_size += 8; /* max 8 bytes for size */
if (Z_TYPE_P(the_var) != IS_STRING) {
- if (!*copies_param || !(*copies_param)[i]) {
+ if (!*copies_param || Z_ISUNDEF((*copies_param)[i])) {
if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i TSRMLS_CC)) {
SET_OOM_ERROR(*stmt->error_info);
goto end;
}
}
- the_var = (*copies_param)[i];
+ the_var = &((*copies_param)[i]);
}
- convert_to_string_ex(&the_var);
+ convert_to_string_ex(the_var);
*data_size += Z_STRLEN_P(the_var);
break;
}
@@ -792,18 +791,21 @@ end:
/* {{{ mysqlnd_stmt_execute_store_param_values */
static void
-mysqlnd_stmt_execute_store_param_values(MYSQLND_STMT_DATA * stmt, zval ** copies, zend_uchar * buf, zend_uchar ** p, size_t null_byte_offset)
+mysqlnd_stmt_execute_store_param_values(MYSQLND_STMT_DATA * stmt, zval * copies, zend_uchar * buf, zend_uchar ** p, size_t null_byte_offset)
{
unsigned int i;
for (i = 0; i < stmt->param_count; i++) {
- zval * data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;
+ zval *data, *parameter = &stmt->param_bind[i].zv;
+
+ ZVAL_DEREF(parameter);
+ data = (copies && !Z_ISUNDEF(copies[i]))? &copies[i]: parameter;
/* Handle long data */
- if (stmt->param_bind[i].zv && Z_TYPE_P(data) == IS_NULL) {
+ if (!Z_ISUNDEF_P(parameter) && Z_TYPE_P(data) == IS_NULL) {
(buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7));
} else {
switch (stmt->param_bind[i].type) {
case MYSQL_TYPE_DOUBLE:
- convert_to_double_ex(&data);
+ convert_to_double_ex(data);
float8store(*p, Z_DVAL_P(data));
(*p) += 8;
break;
@@ -857,10 +859,9 @@ static enum_func_status
mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar **p, size_t *buf_len TSRMLS_DC)
{
MYSQLND_STMT_DATA * stmt = s->data;
- unsigned int i = 0;
zend_uchar * provided_buffer = *buf;
size_t data_size = 0;
- zval **copies = NULL;/* if there are different types */
+ zval *copies = NULL;/* if there are different types */
enum_func_status ret = FAIL;
int resend_types_next_time = 0;
size_t null_byte_offset;
diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c
index 2d4da2626b..0641d504c6 100644
--- a/ext/mysqlnd/mysqlnd_result.c
+++ b/ext/mysqlnd/mysqlnd_result.c
@@ -43,8 +43,8 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, initialize_result_set_rest)(MYSQLND
const uint64_t row_count = result->row_count;
enum_func_status rc;
- zval **data_begin = ((MYSQLND_RES_BUFFERED_ZVAL *) result)->data;
- zval **data_cursor = data_begin;
+ zval *data_begin = ((MYSQLND_RES_BUFFERED_ZVAL *) result)->data;
+ zval *data_cursor = data_begin;
DBG_ENTER("mysqlnd_result_buffered_zval::initialize_result_set_rest");
@@ -52,7 +52,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, initialize_result_set_rest)(MYSQLND
DBG_RETURN(ret);
}
while ((data_cursor - data_begin) < (int)(row_count * field_count)) {
- if (NULL == data_cursor[0]) {
+ if (Z_ISUNDEF(data_cursor[0])) {
rc = result->m.row_decoder(result->row_buffers[(data_cursor - data_begin) / field_count],
data_cursor,
field_count,
@@ -70,8 +70,8 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, initialize_result_set_rest)(MYSQLND
String of zero size, definitely can't be the next max_length.
Thus for NULL and zero-length we are quite efficient.
*/
- if (Z_TYPE_P(data_cursor[i]) >= IS_STRING) {
- unsigned long len = Z_STRLEN_P(data_cursor[i]);
+ if (Z_TYPE(data_cursor[i]) == IS_STRING) {
+ unsigned long len = Z_STRLEN(data_cursor[i]);
if (meta->fields[i].max_length < len) {
meta->fields[i].max_length = len;
}
@@ -99,7 +99,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, initialize_result_set_rest)(MYSQLND_RE
if (result->initialized_rows < row_count) {
zend_uchar * initialized = ((MYSQLND_RES_BUFFERED_C *) result)->initialized;
- zval ** current_row = mnd_emalloc(field_count * sizeof(zval *));
+ zval * current_row = mnd_emalloc(field_count * sizeof(zval));
if (!current_row) {
DBG_RETURN(FAIL);
@@ -125,8 +125,8 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, initialize_result_set_rest)(MYSQLND_RE
String of zero size, definitely can't be the next max_length.
Thus for NULL and zero-length we are quite efficient.
*/
- if (Z_TYPE_P(current_row[i]) >= IS_STRING) {
- unsigned long len = Z_STRLEN_P(current_row[i]);
+ if (Z_TYPE(current_row[i]) == IS_STRING) {
+ unsigned long len = Z_STRLEN(current_row[i]);
if (meta->fields[i].max_length < len) {
meta->fields[i].max_length = len;
}
@@ -141,52 +141,6 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, initialize_result_set_rest)(MYSQLND_RE
/* }}} */
-/* {{{ mysqlnd_rset_zval_ptr_dtor */
-static void
-mysqlnd_rset_zval_ptr_dtor(zval **zv, enum_mysqlnd_res_type type, zend_bool * copy_ctor_called TSRMLS_DC)
-{
- DBG_ENTER("mysqlnd_rset_zval_ptr_dtor");
- DBG_INF_FMT("type=%u", type);
- if (!zv || !*zv) {
- *copy_ctor_called = FALSE;
- DBG_ERR_FMT("zv was NULL");
- DBG_VOID_RETURN;
- }
- /*
- This zval is not from the cache block.
- Thus the refcount is -1 than of a zval from the cache,
- because the zvals from the cache are owned by it.
- */
- if (type == MYSQLND_RES_PS_BUF || type == MYSQLND_RES_PS_UNBUF) {
- *copy_ctor_called = FALSE;
- ; /* do nothing, zval_ptr_dtor will do the job*/
- } else if (Z_REFCOUNT_PP(zv) > 1) {
- /*
- Not a prepared statement, then we have to
- call copy_ctor and then zval_ptr_dtor()
- */
- if (Z_TYPE_PP(zv) == IS_STRING) {
- zval_copy_ctor(*zv);
- }
- *copy_ctor_called = TRUE;
- } else {
- /*
- noone but us point to this, so we can safely ZVAL_NULL the zval,
- so Zend does not try to free what the zval points to - which is
- in result set buffers
- */
- *copy_ctor_called = FALSE;
- if (Z_TYPE_PP(zv) == IS_STRING) {
- ZVAL_NULL(*zv);
- }
- }
- DBG_INF_FMT("call the dtor on zval with refc %u", Z_REFCOUNT_PP(zv));
- zval_ptr_dtor(zv);
- DBG_VOID_RETURN;
-}
-/* }}} */
-
-
/* {{{ mysqlnd_result_unbuffered::free_last_data */
static void
MYSQLND_METHOD(mysqlnd_result_unbuffered, free_last_data)(MYSQLND_RES_UNBUFFERED * unbuf, MYSQLND_STATS * const global_stats TSRMLS_DC)
@@ -199,23 +153,11 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, free_last_data)(MYSQLND_RES_UNBUFFERED
DBG_INF_FMT("field_count=%u", unbuf->field_count);
if (unbuf->last_row_data) {
- unsigned int i, ctor_called_count = 0;
- zend_bool copy_ctor_called;
-
+ unsigned int i;
for (i = 0; i < unbuf->field_count; i++) {
- mysqlnd_rset_zval_ptr_dtor(&(unbuf->last_row_data[i]), unbuf->ps ? MYSQLND_RES_PS_UNBUF : MYSQLND_RES_NORMAL, &copy_ctor_called TSRMLS_CC);
- if (copy_ctor_called) {
- ++ctor_called_count;
- }
+ zval_ptr_dtor(&(unbuf->last_row_data[i]));
}
- DBG_INF_FMT("copy_ctor_called_count=%u", ctor_called_count);
- /* By using value3 macros we hold a mutex only once, there is no value2 */
- MYSQLND_INC_CONN_STATISTIC_W_VALUE2(global_stats,
- STAT_COPY_ON_WRITE_PERFORMED,
- ctor_called_count,
- STAT_COPY_ON_WRITE_SAVED,
- unbuf->field_count - ctor_called_count);
/* Free last row's zvals */
mnd_efree(unbuf->last_row_data);
unbuf->last_row_data = NULL;
@@ -266,37 +208,25 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, free_result)(MYSQLND_RES_UNBUFFERED *
static void
MYSQLND_METHOD(mysqlnd_result_buffered_zval, free_result)(MYSQLND_RES_BUFFERED_ZVAL * const set TSRMLS_DC)
{
- zval ** data = set->data;
+ zval * data = set->data;
DBG_ENTER("mysqlnd_result_buffered_zval::free_result");
set->data = NULL; /* prevent double free if following loop is interrupted */
if (data) {
- unsigned int copy_on_write_performed = 0;
- unsigned int copy_on_write_saved = 0;
unsigned int field_count = set->field_count;
int64_t row;
for (row = set->row_count - 1; row >= 0; row--) {
- zval **current_row = data + row * field_count;
+ zval *current_row = data + row * field_count;
int64_t col;
if (current_row != NULL) {
for (col = field_count - 1; col >= 0; --col) {
- if (current_row[col]) {
- zend_bool copy_ctor_called;
- mysqlnd_rset_zval_ptr_dtor(&(current_row[col]), set->ps? MYSQLND_RES_PS_BUF : MYSQLND_RES_NORMAL, &copy_ctor_called TSRMLS_CC);
- if (copy_ctor_called) {
- ++copy_on_write_performed;
- } else {
- ++copy_on_write_saved;
- }
- }
+ zval_ptr_dtor(&(current_row[col]));
}
}
}
- 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_efree(data);
}
set->data_cursor = NULL;
@@ -630,8 +560,6 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s
stmt->state = MYSQLND_STMT_INITTED;
}
} else {
- 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;
/*
@@ -649,13 +577,6 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s
} else if (fields_eof->server_status & SERVER_QUERY_WAS_SLOW) {
statistic = STAT_QUERY_WAS_SLOW;
}
- if (to_log) {
-#if A0
- char *backtrace = mysqlnd_get_backtrace(TSRMLS_C);
- php_log_err(backtrace TSRMLS_CC);
- efree(backtrace);
-#endif
- }
MYSQLND_INC_CONN_STATISTIC(conn->stats, statistic);
}
} while (0);
@@ -813,8 +734,8 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi
unsigned long * lengths = result->unbuf->lengths;
for (i = 0; i < field_count; i++, field++) {
- zval * data = result->unbuf->last_row_data[i];
- unsigned int len = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data);
+ zval * data = &result->unbuf->last_row_data[i];
+ unsigned int len = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
/* BEGIN difference between normal normal fetch and _c */
if (Z_TYPE_P(data) != IS_NULL) {
@@ -931,12 +852,12 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void
unsigned long * lengths = result->unbuf->lengths;
for (i = 0; i < field_count; i++, field++) {
- zval * data = result->unbuf->last_row_data[i];
- unsigned int len = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data);
+ zval * data = &result->unbuf->last_row_data[i];
+ unsigned int len = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
if (flags & MYSQLND_FETCH_NUM) {
- Z_ADDREF_P(data);
- zend_hash_next_index_insert(row_ht, &data, sizeof(zval *), NULL);
+ Z_TRY_ADDREF_P(data);
+ zend_hash_next_index_insert(row_ht, data);
}
if (flags & MYSQLND_FETCH_ASSOC) {
/* zend_hash_quick_update needs length + trailing zero */
@@ -946,15 +867,11 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void
the index is a numeric and convert it to it. This however means constant
hashing of the column name, which is not needed as it can be precomputed.
*/
- Z_ADDREF_P(data);
+ Z_TRY_ADDREF_P(data);
if (meta->zend_hash_keys[i].is_numeric == FALSE) {
- zend_hash_quick_update(Z_ARRVAL_P(row),
- field->name,
- field->name_length + 1,
- meta->zend_hash_keys[i].key,
- (void *) &data, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL_P(row), meta->fields[i].sname, data);
} else {
- zend_hash_index_update(Z_ARRVAL_P(row), meta->zend_hash_keys[i].key, (void *) &data, sizeof(zval *), NULL);
+ zend_hash_index_update(Z_ARRVAL_P(row), meta->zend_hash_keys[i].key, data);
}
}
@@ -1063,10 +980,10 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void
if (set->data_cursor &&
(set->data_cursor - set->data) < (result->stored_data->row_count * field_count))
{
- zval **current_row = set->data_cursor;
+ zval *current_row = set->data_cursor;
unsigned int i;
- if (NULL == current_row[0]) {
+ if (Z_ISUNDEF(current_row[0])) {
uint64_t row_num = (set->data_cursor - set->data) / field_count;
enum_func_status rc = set->m.row_decoder(set->row_buffers[row_num],
current_row,
@@ -1084,8 +1001,8 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void
String of zero size, definitely can't be the next max_length.
Thus for NULL and zero-length we are quite efficient.
*/
- if (Z_TYPE_P(current_row[i]) >= IS_STRING) {
- unsigned long len = Z_STRLEN_P(current_row[i]);
+ if (Z_TYPE(current_row[i]) == IS_STRING) {
+ unsigned long len = Z_STRLEN(current_row[i]);
if (meta->fields[i].max_length < len) {
meta->fields[i].max_length = len;
}
@@ -1098,9 +1015,9 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void
*row = mnd_malloc(field_count * sizeof(char *));
if (*row) {
for (i = 0; i < field_count; i++) {
- zval * data = current_row[i];
+ zval * data = &current_row[i];
- set->lengths[i] = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data);
+ set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
if (Z_TYPE_P(data) != IS_NULL) {
convert_to_string(data);
@@ -1155,9 +1072,9 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, vo
(set->data_cursor - set->data) < (set->row_count * field_count))
{
unsigned int i;
- zval **current_row = set->data_cursor;
+ zval *current_row = set->data_cursor;
- if (NULL == current_row[0]) {
+ if (Z_ISUNDEF(current_row[0])) {
uint64_t row_num = (set->data_cursor - set->data) / field_count;
enum_func_status rc = set->m.row_decoder(set->row_buffers[row_num],
current_row,
@@ -1175,8 +1092,8 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, vo
String of zero size, definitely can't be the next max_length.
Thus for NULL and zero-length we are quite efficient.
*/
- if (Z_TYPE_P(current_row[i]) >= IS_STRING) {
- unsigned long len = Z_STRLEN_P(current_row[i]);
+ if (Z_TYPE(current_row[i]) == IS_STRING) {
+ unsigned long len = Z_STRLEN(current_row[i]);
if (meta->fields[i].max_length < len) {
meta->fields[i].max_length = len;
}
@@ -1185,13 +1102,13 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, vo
}
for (i = 0; i < field_count; i++) {
- zval * data = current_row[i];
+ zval * data = &current_row[i];
- set->lengths[i] = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data);
+ set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
if (flags & MYSQLND_FETCH_NUM) {
- Z_ADDREF_P(data);
- zend_hash_next_index_insert(Z_ARRVAL_P(row), &data, sizeof(zval *), NULL);
+ Z_TRY_ADDREF_P(data);
+ zend_hash_next_index_insert(Z_ARRVAL_P(row), data);
}
if (flags & MYSQLND_FETCH_ASSOC) {
/* zend_hash_quick_update needs length + trailing zero */
@@ -1201,17 +1118,11 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, vo
the index is a numeric and convert it to it. This however means constant
hashing of the column name, which is not needed as it can be precomputed.
*/
- Z_ADDREF_P(data);
+ Z_TRY_ADDREF_P(data);
if (meta->zend_hash_keys[i].is_numeric == FALSE) {
- zend_hash_quick_update(Z_ARRVAL_P(row),
- meta->fields[i].name,
- meta->fields[i].name_length + 1,
- meta->zend_hash_keys[i].key,
- (void *) &data, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL_P(row), meta->fields[i].sname, data);
} else {
- zend_hash_index_update(Z_ARRVAL_P(row),
- meta->zend_hash_keys[i].key,
- (void *) &data, sizeof(zval *), NULL);
+ zend_hash_index_update(Z_ARRVAL_P(row), meta->zend_hash_keys[i].key, data);
}
}
}
@@ -1246,11 +1157,11 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void
/* If we haven't read everything */
if (set->current_row < set->row_count) {
- zval **current_row;
+ zval *current_row;
enum_func_status rc;
unsigned int i;
- current_row = mnd_emalloc(field_count * sizeof(zval *));
+ current_row = mnd_emalloc(field_count * sizeof(zval));
if (!current_row) {
SET_OOM_ERROR(*result->conn->error_info);
DBG_RETURN(FAIL);
@@ -1276,8 +1187,8 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void
String of zero size, definitely can't be the next max_length.
Thus for NULL and zero-length we are quite efficient.
*/
- if (Z_TYPE_P(current_row[i]) >= IS_STRING) {
- unsigned long len = Z_STRLEN_P(current_row[i]);
+ if (Z_TYPE(current_row[i]) == IS_STRING) {
+ unsigned long len = Z_STRLEN(current_row[i]);
if (meta->fields[i].max_length < len) {
meta->fields[i].max_length = len;
}
@@ -1286,13 +1197,13 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void
}
for (i = 0; i < field_count; i++) {
- zval * data = current_row[i];
+ zval * data = &current_row[i];
- set->lengths[i] = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data);
+ set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
if (flags & MYSQLND_FETCH_NUM) {
- Z_ADDREF_P(data);
- zend_hash_next_index_insert(Z_ARRVAL_P(row), &data, sizeof(zval *), NULL);
+ Z_TRY_ADDREF_P(data);
+ zend_hash_next_index_insert(Z_ARRVAL_P(row), data);
}
if (flags & MYSQLND_FETCH_ASSOC) {
/* zend_hash_quick_update needs length + trailing zero */
@@ -1302,17 +1213,11 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void
the index is a numeric and convert it to it. This however means constant
hashing of the column name, which is not needed as it can be precomputed.
*/
- Z_ADDREF_P(data);
+ Z_TRY_ADDREF_P(data);
if (meta->zend_hash_keys[i].is_numeric == FALSE) {
- zend_hash_quick_update(Z_ARRVAL_P(row),
- meta->fields[i].name,
- meta->fields[i].name_length + 1,
- meta->zend_hash_keys[i].key,
- (void *) &data, sizeof(zval *), NULL);
+ zend_hash_update(Z_ARRVAL_P(row), meta->fields[i].sname, data);
} else {
- zend_hash_index_update(Z_ARRVAL_P(row),
- meta->zend_hash_keys[i].key,
- (void *) &data, sizeof(zval *), NULL);
+ zend_hash_index_update(Z_ARRVAL_P(row), meta->zend_hash_keys[i].key, data);
}
}
/*
@@ -1321,7 +1226,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void
It also simplifies the handling of Z_ADDREF_P because we don't need to check if only
either NUM or ASSOC is set but not both.
*/
- zval_ptr_dtor(&data);
+ zval_ptr_dtor(data);
}
mnd_efree(current_row);
set->current_row++;
@@ -1540,12 +1445,12 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
DBG_RETURN(NULL);
}
/* if pecalloc is used valgrind barks gcc version 4.3.1 20080507 (prerelease) [gcc-4_3-branch revision 135036] (SUSE Linux) */
- set->data = mnd_emalloc((size_t)(set->row_count * meta->field_count * sizeof(zval *)));
+ set->data = mnd_emalloc((size_t)(set->row_count * meta->field_count * sizeof(zval)));
if (!set->data) {
SET_OOM_ERROR(*conn->error_info);
DBG_RETURN(NULL);
}
- memset(set->data, 0, (size_t)(set->row_count * meta->field_count * sizeof(zval *)));
+ memset(set->data, 0, (size_t)(set->row_count * meta->field_count * sizeof(zval)));
}
/* Position at the first row */
set->data_cursor = set->data;
@@ -1819,7 +1724,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, const unsigned int
Hint Zend how many elements we will have in the hash. Thus it won't
extend and rehash the hash constantly.
*/
- mysqlnd_array_init(return_value, mysqlnd_num_fields(result) * 2);
+ array_init_size(return_value, mysqlnd_num_fields(result) * 2);
if (FAIL == result->m.fetch_row(result, (void *)return_value, flags, &fetched_anything TSRMLS_CC)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading a row");
zval_dtor(return_value);
@@ -1870,7 +1775,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_row_c)(MYSQLND_RES * result TSRMLS_DC)
static void
MYSQLND_METHOD(mysqlnd_res, fetch_all)(MYSQLND_RES * result, const unsigned int flags, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC)
{
- zval *row;
+ zval row;
ulong i = 0;
MYSQLND_RES_BUFFERED *set = result->stored_data;
@@ -1886,16 +1791,15 @@ MYSQLND_METHOD(mysqlnd_res, fetch_all)(MYSQLND_RES * result, const unsigned int
}
/* 4 is a magic value. The cast is safe, if larger then the array will be later extended - no big deal :) */
- mysqlnd_array_init(return_value, set? (unsigned int) set->row_count : 4);
+ array_init_size(return_value, set? (unsigned int) set->row_count : 4);
do {
- MAKE_STD_ZVAL(row);
- mysqlnd_fetch_into(result, flags, row, MYSQLND_MYSQLI);
- if (Z_TYPE_P(row) != IS_ARRAY) {
+ mysqlnd_fetch_into(result, flags, &row, MYSQLND_MYSQLI);
+ if (Z_TYPE(row) != IS_ARRAY) {
zval_ptr_dtor(&row);
break;
}
- add_index_zval(return_value, i++, row);
+ add_index_zval(return_value, i++, &row);
} while (1);
DBG_VOID_RETURN;
@@ -1908,7 +1812,7 @@ static void
MYSQLND_METHOD(mysqlnd_res, fetch_field_data)(MYSQLND_RES * result, unsigned int offset, zval *return_value TSRMLS_DC)
{
zval row;
- zval **entry;
+ zval *entry;
unsigned int i = 0;
DBG_ENTER("mysqlnd_res::fetch_field_data");
@@ -1917,24 +1821,21 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field_data)(MYSQLND_RES * result, unsigned int
Hint Zend how many elements we will have in the hash. Thus it won't
extend and rehash the hash constantly.
*/
- INIT_PZVAL(&row);
mysqlnd_fetch_into(result, MYSQLND_FETCH_NUM, &row, MYSQLND_MYSQL);
if (Z_TYPE(row) != IS_ARRAY) {
zval_dtor(&row);
RETVAL_NULL();
DBG_VOID_RETURN;
}
+
zend_hash_internal_pointer_reset(Z_ARRVAL(row));
while (i++ < offset) {
zend_hash_move_forward(Z_ARRVAL(row));
- zend_hash_get_current_data(Z_ARRVAL(row), (void **)&entry);
}
- zend_hash_get_current_data(Z_ARRVAL(row), (void **)&entry);
+ entry = zend_hash_get_current_data(Z_ARRVAL(row));
- *return_value = **entry;
- zval_copy_ctor(return_value);
- Z_SET_REFCOUNT_P(return_value, 1);
+ ZVAL_COPY(return_value, entry);
zval_dtor(&row);
DBG_VOID_RETURN;
diff --git a/ext/mysqlnd/mysqlnd_result_meta.c b/ext/mysqlnd/mysqlnd_result_meta.c
index 85dc3d00c4..f6e38c809e 100644
--- a/ext/mysqlnd/mysqlnd_result_meta.c
+++ b/ext/mysqlnd/mysqlnd_result_meta.c
@@ -41,57 +41,13 @@ php_mysqlnd_free_field_metadata(MYSQLND_FIELD *meta, zend_bool persistent TSRMLS
mnd_pefree(meta->def, persistent);
meta->def = NULL;
}
+ if (meta->sname) {
+ STR_RELEASE(meta->sname);
+ }
}
}
/* }}} */
-
-/* {{{ mysqlnd_handle_numeric */
-/*
- The following code is stolen from ZE - HANDLE_NUMERIC() macro from zend_hash.c
- and modified for the needs of mysqlnd.
-*/
-static zend_bool
-mysqlnd_is_key_numeric(const char * key, size_t length, long *idx)
-{
- register const char * tmp = key;
-
- if (*tmp=='-') {
- tmp++;
- }
- if ((*tmp>='0' && *tmp<='9')) {
- do { /* possibly a numeric index */
- const char *end=key+length-1;
-
- if (*tmp++=='0' && length>2) { /* don't accept numbers with leading zeros */
- break;
- }
- while (tmp<end) {
- if (!(*tmp>='0' && *tmp<='9')) {
- break;
- }
- tmp++;
- }
- if (tmp==end && *tmp=='\0') { /* a numeric index */
- if (*key=='-') {
- *idx = strtol(key, NULL, 10);
- if (*idx!=LONG_MIN) {
- return TRUE;
- }
- } else {
- *idx = strtol(key, NULL, 10);
- if (*idx!=LONG_MAX) {
- return TRUE;
- }
- }
- }
- } while (0);
- }
- return FALSE;
-}
-/* }}} */
-
-
/* {{{ mysqlnd_res_meta::read_metadata */
static enum_func_status
MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND_CONN_DATA * conn TSRMLS_DC)
@@ -179,17 +135,9 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met
}
/* For BC we have to check whether the key is numeric and use it like this */
- if ((meta->zend_hash_keys[i].is_numeric =
- mysqlnd_is_key_numeric(field_packet->metadata->name,
- field_packet->metadata->name_length + 1,
- &idx)))
- {
+ if ((meta->zend_hash_keys[i].is_numeric = ZEND_HANDLE_NUMERIC(field_packet->metadata->sname, idx))) {
meta->zend_hash_keys[i].key = idx;
- } else {
- meta->zend_hash_keys[i].key =
- zend_get_hash_value(field_packet->metadata->name,
- field_packet->metadata->name_length + 1);
- }
+ }
}
PACKET_FREE(field_packet);
@@ -270,26 +218,30 @@ MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata)(const MYSQLND_RES_METADATA * co
for (i = 0; i < meta->field_count; i++) {
/* First copy the root, then field by field adjust the pointers */
new_fields[i].root = mnd_pemalloc(orig_fields[i].root_len, persistent);
+
if (!new_fields[i].root) {
goto oom;
}
+
memcpy(new_fields[i].root, orig_fields[i].root, new_fields[i].root_len);
- if (orig_fields[i].name && orig_fields[i].name != mysqlnd_empty_string) {
- new_fields[i].name = new_fields[i].root +
- (orig_fields[i].name - orig_fields[i].root);
+ if (orig_fields[i].sname) {
+ new_fields[i].sname = STR_COPY(orig_fields[i].sname);
+ new_fields[i].name = new_fields[i].sname->val;
+ new_fields[i].name_length = new_fields[i].sname->len;
}
+
if (orig_fields[i].org_name && orig_fields[i].org_name != mysqlnd_empty_string) {
new_fields[i].org_name = new_fields[i].root +
- (orig_fields[i].org_name - orig_fields[i].root);
+ (orig_fields[i].org_name - orig_fields[i].root);
}
if (orig_fields[i].table && orig_fields[i].table != mysqlnd_empty_string) {
new_fields[i].table = new_fields[i].root +
- (orig_fields[i].table - orig_fields[i].root);
+ (orig_fields[i].table - orig_fields[i].root);
}
if (orig_fields[i].org_table && orig_fields[i].org_table != mysqlnd_empty_string) {
new_fields[i].org_table = new_fields[i].root +
- (orig_fields[i].org_table - orig_fields[i].root);
+ (orig_fields[i].org_table - orig_fields[i].root);
}
if (orig_fields[i].db && orig_fields[i].db != mysqlnd_empty_string) {
new_fields[i].db = new_fields[i].root + (orig_fields[i].db - orig_fields[i].root);
@@ -322,6 +274,7 @@ oom:
}
/* }}} */
+
/* {{{ mysqlnd_res_meta::fetch_field */
static const MYSQLND_FIELD *
MYSQLND_METHOD(mysqlnd_res_meta, fetch_field)(MYSQLND_RES_METADATA * const meta TSRMLS_DC)
@@ -371,6 +324,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, field_tell)(const MYSQLND_RES_METADATA * const
}
/* }}} */
+
/* {{{ mysqlnd_res_meta::field_seek */
static MYSQLND_FIELD_OFFSET
MYSQLND_METHOD(mysqlnd_res_meta, field_seek)(MYSQLND_RES_METADATA * const meta, const MYSQLND_FIELD_OFFSET field_offset TSRMLS_DC)
diff --git a/ext/mysqlnd/mysqlnd_reverse_api.c b/ext/mysqlnd/mysqlnd_reverse_api.c
index d8b1a41511..49684876a4 100644
--- a/ext/mysqlnd/mysqlnd_reverse_api.c
+++ b/ext/mysqlnd/mysqlnd_reverse_api.c
@@ -60,8 +60,7 @@ mysqlnd_reverse_api_get_api_list(TSRMLS_D)
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);
+ zend_hash_str_add_ptr(&mysqlnd_api_ext_ht, apiext->module->name, strlen(apiext->module->name), apiext);
}
/* }}} */
@@ -71,14 +70,11 @@ PHPAPI MYSQLND *
zval_to_mysqlnd(zval * zv, const unsigned int client_api_capabilities, unsigned int * save_client_api_capabilities 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);
+#ifdef OLD_CODE
+ MYSQLND_REVERSE_API * elem;
+ ZEND_HASH_FOREACH_PTR(&mysqlnd_api_ext_ht, elem) {
+ if (elem->conversion_cb) {
+ retval = elem->conversion_cb(zv TSRMLS_CC);
if (retval) {
if (retval->data) {
*save_client_api_capabilities = retval->data->m->negotiate_client_api_capabilities(retval->data, client_api_capabilities TSRMLS_CC);
@@ -86,8 +82,21 @@ zval_to_mysqlnd(zval * zv, const unsigned int client_api_capabilities, unsigned
return retval;
}
}
- }
-
+ } ZEND_HASH_FOREACH_END();
+#else
+ MYSQLND_REVERSE_API * api;
+ ZEND_HASH_FOREACH_PTR(&mysqlnd_api_ext_ht, api) {
+ if (api && api->conversion_cb) {
+ retval = api->conversion_cb(zv TSRMLS_CC);
+ if (retval) {
+ if (retval->data) {
+ *save_client_api_capabilities = retval->data->m->negotiate_client_api_capabilities(retval->data, client_api_capabilities TSRMLS_CC);
+ }
+ return retval;
+ }
+ }
+ } ZEND_HASH_FOREACH_END();
+#endif
return NULL;
}
/* }}} */
diff --git a/ext/mysqlnd/mysqlnd_statistics.c b/ext/mysqlnd/mysqlnd_statistics.c
index ce193275ec..a664f9b578 100644
--- a/ext/mysqlnd/mysqlnd_statistics.c
+++ b/ext/mysqlnd/mysqlnd_statistics.c
@@ -201,12 +201,12 @@ mysqlnd_fill_stats_hash(const MYSQLND_STATS * const stats, const MYSQLND_STRING
{
unsigned int i;
- mysqlnd_array_init(return_value, stats->count);
+ array_init_size(return_value, stats->count);
for (i = 0; i < stats->count; i++) {
char tmp[25];
sprintf((char *)&tmp, MYSQLND_LLU_SPEC, stats->values[i]);
- add_assoc_string_ex(return_value, names[i].s, names[i].l + 1, tmp, 1);
+ add_assoc_string_ex(return_value, names[i].s, names[i].l, tmp);
}
}
/* }}} */
diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h
index b743dada3c..9ec924ead6 100644
--- a/ext/mysqlnd/mysqlnd_structs.h
+++ b/ext/mysqlnd/mysqlnd_structs.h
@@ -72,13 +72,14 @@ typedef struct st_mysqlnd_cmd_buffer
typedef struct st_mysqlnd_field
{
- const char *name; /* Name of column */
- const char *org_name; /* Original column name, if an alias */
- const char *table; /* Table of column if column was a field */
- const char *org_table; /* Org table name, if table was an alias */
- const char *db; /* Database for table */
- const char *catalog; /* Catalog for table */
- char *def; /* Default value (set by mysql_list_fields) */
+ zend_string *sname; /* Name of column */
+ const char *name; /* Name of column in C string */
+ const char *org_name; /* Original column name, if an alias */
+ const char *table; /* Table of column if column was a field */
+ const char *org_table; /* Org table name, if table was an alias */
+ const char *db; /* Database for table */
+ const char *catalog; /* Catalog for table */
+ char *def; /* Default value (set by mysql_list_fields) */
unsigned long length; /* Width of column (create length) */
unsigned long max_length; /* Max width for selected set */
unsigned int name_length;
@@ -149,12 +150,10 @@ typedef struct st_mysqlnd_charset
/* local infile handler */
typedef struct st_mysqlnd_infile
{
- int (*local_infile_init)(void **ptr, char *filename, void **userdata TSRMLS_DC);
+ int (*local_infile_init)(void **ptr, const char * const filename 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);
+ 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;
- void *userdata;
} MYSQLND_INFILE;
typedef struct st_mysqlnd_options
@@ -444,7 +443,7 @@ typedef void (*func_mysqlnd_conn_data__get_statistics)(const MYSQLND_CONN_DAT
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 enum_func_status (*func_mysqlnd_conn_data__get_server_statistics)(MYSQLND_CONN_DATA * conn, zend_string **message 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);
@@ -618,7 +617,7 @@ struct st_mysqlnd_conn_methods
};
/* for decoding - binary or text protocol */
-typedef enum_func_status (*func_mysqlnd_res__row_decoder)(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
+typedef enum_func_status (*func_mysqlnd_res__row_decoder)(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval * fields,
unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC);
@@ -1040,8 +1039,8 @@ struct st_mysqlnd_buffered_result_zval
{
def_mysqlnd_buffered_result_parent;
- zval **data;
- zval **data_cursor;
+ zval *data;
+ zval *data_cursor;
};
@@ -1058,7 +1057,7 @@ struct st_mysqlnd_unbuffered_result
{
/* For unbuffered (both normal and PS) */
- zval **last_row_data;
+ zval *last_row_data;
MYSQLND_MEMORY_POOL_CHUNK *last_row_buffer;
/*
@@ -1103,14 +1102,14 @@ struct st_mysqlnd_res
struct st_mysqlnd_param_bind
{
- zval *zv;
+ zval zv;
zend_uchar type;
enum_param_bind_flags flags;
};
struct st_mysqlnd_result_bind
{
- zval *zv;
+ zval zv;
zend_bool bound;
};
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c
index 83ae2a7977..2aa7afde0d 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.c
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.c
@@ -69,14 +69,12 @@
static const char *unknown_sqlstate= "HY000";
-
const char * const mysqlnd_empty_string = "";
/* Used in mysqlnd_debug.c */
const char mysqlnd_read_header_name[] = "mysqlnd_read_header";
const char mysqlnd_read_body_name[] = "mysqlnd_read_body";
-
#define ERROR_MARKER 0xFF
#define EODATA_MARKER 0xFE
@@ -161,7 +159,7 @@ php_mysqlnd_net_field_length(zend_uchar **packet)
uint64_t
php_mysqlnd_net_field_length_ll(zend_uchar **packet)
{
- register zend_uchar *p= (zend_uchar *)*packet;
+ register zend_uchar *p = (zend_uchar *)*packet;
if (*p < 251) {
(*packet)++;
@@ -561,9 +559,10 @@ size_t php_mysqlnd_auth_write(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC
}
if (packet->connect_attr && zend_hash_num_elements(packet->connect_attr)) {
+ size_t ca_payload_len = 0;
+#ifdef OLD_CODE
HashPosition pos_value;
const char ** entry_value;
- size_t ca_payload_len = 0;
zend_hash_internal_pointer_reset_ex(packet->connect_attr, &pos_value);
while (SUCCESS == zend_hash_get_current_data_ex(packet->connect_attr, (void **)&entry_value, &pos_value)) {
char *s_key;
@@ -579,10 +578,28 @@ size_t php_mysqlnd_auth_write(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC
}
zend_hash_move_forward_ex(conn->options->connect_attr, &pos_value);
}
+#else
+ {
+ zend_string * key;
+ unsigned long unused_num_key;
+ zval * entry_value;
+ ZEND_HASH_FOREACH_KEY_VAL(packet->connect_attr, unused_num_key, key, entry_value) {
+ if (key) { /* HASH_KEY_IS_STRING */
+ size_t value_len = Z_STRLEN_P(entry_value);
+
+ ca_payload_len += php_mysqlnd_net_store_length_size(key->len);
+ ca_payload_len += key->len;
+ ca_payload_len += php_mysqlnd_net_store_length_size(value_len);
+ ca_payload_len += value_len;
+ }
+ } ZEND_HASH_FOREACH_END();
+ }
+#endif
if ((sizeof(buffer) - (p - buffer)) >= (ca_payload_len + php_mysqlnd_net_store_length_size(ca_payload_len))) {
p = php_mysqlnd_net_store_length(p, ca_payload_len);
+#ifdef OLD_CODE
zend_hash_internal_pointer_reset_ex(packet->connect_attr, &pos_value);
while (SUCCESS == zend_hash_get_current_data_ex(packet->connect_attr, (void **)&entry_value, &pos_value)) {
char *s_key;
@@ -601,6 +618,27 @@ size_t php_mysqlnd_auth_write(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC
}
zend_hash_move_forward_ex(conn->options->connect_attr, &pos_value);
}
+#else
+ {
+ zend_string * key;
+ unsigned long unused_num_key;
+ zval * entry_value;
+ ZEND_HASH_FOREACH_KEY_VAL(packet->connect_attr, unused_num_key, key, entry_value) {
+ if (key) { /* HASH_KEY_IS_STRING */
+ size_t value_len = Z_STRLEN_P(entry_value);
+
+ /* copy key */
+ p = php_mysqlnd_net_store_length(p, key->len);
+ memcpy(p, key->val, key->len);
+ p+= key->len;
+ /* copy value */
+ p = php_mysqlnd_net_store_length(p, value_len);
+ memcpy(p, Z_STRVAL_P(entry_value), value_len);
+ p+= value_len;
+ }
+ } ZEND_HASH_FOREACH_END();
+ }
+#endif
} else {
/* cannot put the data - skip */
}
@@ -1177,7 +1215,7 @@ static size_t rset_field_offsets[] =
STRUCT_OFFSET(MYSQLND_FIELD, name),
STRUCT_OFFSET(MYSQLND_FIELD, name_length),
STRUCT_OFFSET(MYSQLND_FIELD, org_name),
- STRUCT_OFFSET(MYSQLND_FIELD, org_name_length)
+ STRUCT_OFFSET(MYSQLND_FIELD, org_name_length),
};
@@ -1186,7 +1224,7 @@ static enum_func_status
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;
+ MYSQLND_PACKET_RES_FIELD *packet = (MYSQLND_PACKET_RES_FIELD *) _packet;
size_t buf_len = conn->net->cmd_buffer.length, total_len = 0;
zend_uchar *buf = (zend_uchar *) conn->net->cmd_buffer.buffer;
zend_uchar *p = buf;
@@ -1249,6 +1287,7 @@ php_mysqlnd_rset_field_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
DBG_ERR_FMT("Protocol error. Server sent false length. Expected 12 got %d", (int) *p);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Protocol error. Server sent false length. Expected 12");
}
+
p++;
BAIL_IF_NO_MORE_DATA;
@@ -1305,17 +1344,25 @@ php_mysqlnd_rset_field_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
memcpy(meta->def, p, len);
meta->def[len] = '\0';
meta->def_length = len;
- p += len;
- }
+ p += len;
+ }
- 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);
}
-
+
meta->root_len = total_len;
+
+ if (meta->name != mysqlnd_empty_string) {
+ meta->sname = STR_INIT(meta->name, meta->name_length, packet->persistent_alloc);
+ } else {
+ meta->sname = STR_EMPTY_ALLOC();
+ }
+ meta->name = meta->sname->val;
+ meta->name_length = meta->sname->len;
+
/* Now do allocs */
if (meta->catalog && meta->catalog != mysqlnd_empty_string) {
len = meta->catalog_length;
@@ -1345,13 +1392,6 @@ php_mysqlnd_rset_field_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
root_ptr++;
}
- if (meta->name && meta->name != mysqlnd_empty_string) {
- len = meta->name_length;
- meta->name = memcpy(root_ptr, meta->name, len);
- *(root_ptr +=len) = '\0';
- root_ptr++;
- }
-
if (meta->org_name && meta->org_name != mysqlnd_empty_string) {
len = meta->org_name_length;
meta->org_name = memcpy(root_ptr, meta->org_name, len);
@@ -1359,6 +1399,8 @@ php_mysqlnd_rset_field_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
root_ptr++;
}
+ DBG_INF_FMT("allocing root. persistent=%u", packet->persistent_alloc);
+
DBG_INF_FMT("FIELD=[%s.%s.%s]", meta->db? meta->db:"*NA*", meta->table? meta->table:"*NA*",
meta->name? meta->name:"*NA*");
@@ -1382,7 +1424,7 @@ premature_end:
static
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;
+ MYSQLND_PACKET_RES_FIELD *p = (MYSQLND_PACKET_RES_FIELD *) _packet;
/* p->metadata was passed to us as temporal buffer */
if (!stack_allocation) {
mnd_pefree(p, p->header.persistent);
@@ -1424,11 +1466,7 @@ php_mysqlnd_read_row_ex(MYSQLND_CONN_DATA * conn, MYSQLND_MEMORY_POOL * result_s
if (first_iteration) {
first_iteration = FALSE;
- /*
- We need a trailing \0 for the last string, in case of text-mode,
- to be able to implement read-only variables. Thus, we add + 1.
- */
- *buffer = result_set_memory_pool->get_chunk(result_set_memory_pool, *data_size + 1 TSRMLS_CC);
+ *buffer = result_set_memory_pool->get_chunk(result_set_memory_pool, *data_size TSRMLS_CC);
if (!*buffer) {
ret = FAIL;
break;
@@ -1442,11 +1480,8 @@ php_mysqlnd_read_row_ex(MYSQLND_CONN_DATA * conn, MYSQLND_MEMORY_POOL * result_s
/*
We have to realloc the buffer.
-
- We need a trailing \0 for the last string, in case of text-mode,
- to be able to implement read-only variables.
*/
- if (FAIL == (*buffer)->resize_chunk((*buffer), *data_size + 1 TSRMLS_CC)) {
+ if (FAIL == (*buffer)->resize_chunk((*buffer), *data_size TSRMLS_CC)) {
SET_OOM_ERROR(*conn->error_info);
ret = FAIL;
break;
@@ -1477,14 +1512,14 @@ php_mysqlnd_read_row_ex(MYSQLND_CONN_DATA * conn, MYSQLND_MEMORY_POOL * result_s
/* {{{ php_mysqlnd_rowp_read_binary_protocol */
enum_func_status
-php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
+php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval * fields,
unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
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;
- zval **current_field, **end_field, **start_field;
+ 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");
@@ -1501,28 +1536,20 @@ php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zv
bit = 4; /* first 2 bits are reserved */
for (i = 0, current_field = start_field; current_field < end_field; current_field++, i++) {
- DBG_INF("Directly creating zval");
- MAKE_STD_ZVAL(*current_field);
- if (!*current_field) {
- DBG_RETURN(FAIL);
- }
- }
-
- for (i = 0, current_field = start_field; current_field < end_field; current_field++, i++) {
enum_mysqlnd_collected_stats statistic;
zend_uchar * orig_p = p;
DBG_INF_FMT("Into zval=%p decoding column %u [%s.%s.%s] type=%u field->flags&unsigned=%u flags=%u is_bit=%u",
- *current_field, i,
+ current_field, i,
fields_metadata[i].db, fields_metadata[i].table, fields_metadata[i].name, fields_metadata[i].type,
fields_metadata[i].flags & UNSIGNED_FLAG, fields_metadata[i].flags, fields_metadata[i].type == MYSQL_TYPE_BIT);
if (*null_ptr & bit) {
DBG_INF("It's null");
- ZVAL_NULL(*current_field);
+ ZVAL_NULL(current_field);
statistic = STAT_BINARY_TYPE_FETCHED_NULL;
} else {
enum_mysqlnd_field_types type = fields_metadata[i].type;
- mysqlnd_ps_fetch_functions[type].func(*current_field, &fields_metadata[i], 0, &p TSRMLS_CC);
+ mysqlnd_ps_fetch_functions[type].func(current_field, &fields_metadata[i], 0, &p TSRMLS_CC);
if (MYSQLND_G(collect_statistics)) {
switch (fields_metadata[i].type) {
@@ -1559,8 +1586,8 @@ php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zv
}
MYSQLND_INC_CONN_STATISTIC_W_VALUE2(stats, statistic, 1,
STAT_BYTES_RECEIVED_PURE_DATA_PS,
- (Z_TYPE_PP(current_field) == IS_STRING)?
- Z_STRLEN_PP(current_field) : (p - orig_p));
+ (Z_TYPE_P(current_field) == IS_STRING)?
+ Z_STRLEN_P(current_field) : (p - orig_p));
if (!((bit<<=1) & 255)) {
bit = 1; /* to the following byte */
@@ -1572,16 +1599,15 @@ php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zv
}
/* }}} */
+
/* {{{ php_mysqlnd_rowp_read_text_protocol */
enum_func_status
-php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
+php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval * fields,
unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
- zend_bool as_int_or_float, zend_bool copy_data, MYSQLND_STATS * stats TSRMLS_DC)
+ 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;
+ zval *current_field, *end_field, *start_field;
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 */
@@ -1595,39 +1621,12 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer,
end_field = (start_field = fields) + field_count;
for (i = 0, current_field = start_field; current_field < end_field; current_field++, i++) {
- DBG_INF("Directly creating zval");
- MAKE_STD_ZVAL(*current_field);
- if (!*current_field) {
- DBG_RETURN(FAIL);
- }
- }
-
- for (i = 0, current_field = start_field; current_field < end_field; current_field++, i++) {
- /* Don't reverse the order. It is significant!*/
- zend_uchar *this_field_len_pos = p;
/* php_mysqlnd_net_field_length() call should be after *this_field_len_pos = p; */
unsigned long len = php_mysqlnd_net_field_length(&p);
- if (copy_data == FALSE && current_field > start_field && last_field_was_string) {
- /*
- Normal queries:
- We have to put \0 now to the end of the previous field, if it was
- a string. IS_NULL doesn't matter. Because we have already read our
- length, then we can overwrite it in the row buffer.
- This statement terminates the previous field, not the current one.
-
- NULL_LENGTH is encoded in one byte, so we can stick a \0 there.
- Any string's length is encoded in at least one byte, so we can stick
- a \0 there.
- */
-
- *this_field_len_pos = '\0';
- }
-
/* NULL or NOT NULL, this is the question! */
if (len == MYSQLND_NULL_LENGTH) {
- ZVAL_NULL(*current_field);
- last_field_was_string = FALSE;
+ ZVAL_NULL(current_field);
} else {
#if defined(MYSQLND_STRING_TO_INT_CONVERSION)
struct st_mysqlnd_perm_bind perm_bind =
@@ -1680,7 +1679,7 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer,
#else
_atoi64((char *) p);
#endif
- ZVAL_LONG(*current_field, (long) v); /* the cast is safe */
+ ZVAL_LONG(current_field, (long) v); /* the cast is safe */
} else {
uint64_t v =
#ifndef PHP_WIN32
@@ -1700,9 +1699,9 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer,
#error Need fix for this architecture
#endif /* SIZEOF */
{
- ZVAL_STRINGL(*current_field, (char *)p, len, 0);
+ ZVAL_STRINGL(current_field, (char *)p, len);
} else {
- ZVAL_LONG(*current_field, (long) v); /* the cast is safe */
+ ZVAL_LONG(current_field, (long) v); /* the cast is safe */
}
}
*(p + len) = save;
@@ -1710,7 +1709,7 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer,
zend_uchar save = *(p + len);
/* We have to make it ASCIIZ temporarily */
*(p + len) = '\0';
- ZVAL_DOUBLE(*current_field, atof((char *) p));
+ ZVAL_DOUBLE(current_field, atof((char *) p));
*(p + len) = save;
} else
#endif /* MYSQLND_STRING_TO_INT_CONVERSION */
@@ -1725,33 +1724,28 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer,
Definitely not nice, _hackish_ :(, but works.
*/
zend_uchar *start = bit_area;
- ps_fetch_from_1_to_8_bytes(*current_field, &(fields_metadata[i]), 0, &p, len TSRMLS_CC);
+ ps_fetch_from_1_to_8_bytes(current_field, &(fields_metadata[i]), 0, &p, len TSRMLS_CC);
/*
We have advanced in ps_fetch_from_1_to_8_bytes. We should go back because
later in this function there will be an advancement.
*/
p -= len;
- if (Z_TYPE_PP(current_field) == IS_LONG) {
- bit_area += 1 + sprintf((char *)start, "%ld", Z_LVAL_PP(current_field));
- ZVAL_STRINGL(*current_field, (char *) start, bit_area - start - 1, copy_data);
- } else if (Z_TYPE_PP(current_field) == IS_STRING){
- memcpy(bit_area, Z_STRVAL_PP(current_field), Z_STRLEN_PP(current_field));
- bit_area += Z_STRLEN_PP(current_field);
+ if (Z_TYPE_P(current_field) == IS_LONG) {
+ bit_area += 1 + sprintf((char *)start, "%ld", Z_LVAL_P(current_field));
+ ZVAL_STRINGL(current_field, (char *) start, bit_area - start - 1);
+ } else if (Z_TYPE_P(current_field) == IS_STRING){
+ memcpy(bit_area, Z_STRVAL_P(current_field), Z_STRLEN_P(current_field));
+ bit_area += Z_STRLEN_P(current_field);
*bit_area++ = '\0';
- zval_dtor(*current_field);
- ZVAL_STRINGL(*current_field, (char *) start, bit_area - start - 1, copy_data);
+ zval_dtor(current_field);
+ ZVAL_STRINGL(current_field, (char *) start, bit_area - start - 1);
}
} else {
- ZVAL_STRINGL(*current_field, (char *)p, len, copy_data);
+ ZVAL_STRINGL(current_field, (char *)p, len);
}
p += len;
- last_field_was_string = TRUE;
}
}
- if (copy_data == FALSE && last_field_was_string) {
- /* Normal queries: The buffer has one more byte at the end, because we need it */
- row_buffer->ptr[data_size] = '\0';
- }
DBG_RETURN(PASS);
}
@@ -1760,13 +1754,13 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer,
/* {{{ php_mysqlnd_rowp_read_text_protocol_zval */
enum_func_status
-php_mysqlnd_rowp_read_text_protocol_zval(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
+php_mysqlnd_rowp_read_text_protocol_zval(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval * fields,
unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC)
{
enum_func_status ret;
DBG_ENTER("php_mysqlnd_rowp_read_text_protocol_zval");
- ret = php_mysqlnd_rowp_read_text_protocol_aux(row_buffer, fields, field_count, fields_metadata, as_int_or_float, FALSE, stats TSRMLS_CC);
+ ret = php_mysqlnd_rowp_read_text_protocol_aux(row_buffer, fields, field_count, fields_metadata, as_int_or_float, stats TSRMLS_CC);
DBG_RETURN(ret);
}
/* }}} */
@@ -1774,20 +1768,18 @@ php_mysqlnd_rowp_read_text_protocol_zval(MYSQLND_MEMORY_POOL_CHUNK * row_buffer,
/* {{{ php_mysqlnd_rowp_read_text_protocol_c */
enum_func_status
-php_mysqlnd_rowp_read_text_protocol_c(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
+php_mysqlnd_rowp_read_text_protocol_c(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval * fields,
unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC)
{
enum_func_status ret;
DBG_ENTER("php_mysqlnd_rowp_read_text_protocol_c");
- ret = php_mysqlnd_rowp_read_text_protocol_aux(row_buffer, fields, field_count, fields_metadata, as_int_or_float, TRUE, stats TSRMLS_CC);
+ ret = php_mysqlnd_rowp_read_text_protocol_aux(row_buffer, fields, field_count, fields_metadata, as_int_or_float, stats TSRMLS_CC);
DBG_RETURN(ret);
}
/* }}} */
-
-
/* {{{ php_mysqlnd_rowp_read */
/*
if normal statements => packet->fields is created by this function,
@@ -1868,7 +1860,7 @@ php_mysqlnd_rowp_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC)
but mostly like old-API unbuffered and thus will populate this array with
value.
*/
- packet->fields = (zval **) mnd_pecalloc(packet->field_count, sizeof(zval *),
+ packet->fields = mnd_pecalloc(packet->field_count, sizeof(zval),
packet->persistent_alloc);
}
} else {
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.h b/ext/mysqlnd/mysqlnd_wireprotocol.h
index 7e8b9624ac..bd87d9e757 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.h
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.h
@@ -218,7 +218,7 @@ typedef struct st_mysqlnd_packet_res_field {
/* Row packet */
typedef struct st_mysqlnd_packet_row {
MYSQLND_PACKET_HEADER header;
- zval **fields;
+ zval *fields;
uint32_t field_count;
zend_bool eof;
/*
@@ -306,17 +306,16 @@ size_t php_mysqlnd_net_store_length_size(uint64_t length);
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,
+enum_func_status php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval * fields,
unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC);
-enum_func_status php_mysqlnd_rowp_read_text_protocol_zval(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
+enum_func_status php_mysqlnd_rowp_read_text_protocol_zval(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval * fields,
unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC);
-enum_func_status php_mysqlnd_rowp_read_text_protocol_c(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
+enum_func_status php_mysqlnd_rowp_read_text_protocol_c(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval * fields,
unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC);
diff --git a/ext/mysqlnd/php_mysqlnd.c b/ext/mysqlnd/php_mysqlnd.c
index c2c53604e5..e0bc6d126d 100644
--- a/ext/mysqlnd/php_mysqlnd.c
+++ b/ext/mysqlnd/php_mysqlnd.c
@@ -43,31 +43,22 @@ static zend_function_entry mysqlnd_functions[] = {
PHPAPI void
mysqlnd_minfo_print_hash(zval *values)
{
- zval **values_entry;
- HashPosition pos_values;
+ zval *values_entry;
+ zend_string *string_key;
- zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos_values);
- while (zend_hash_get_current_data_ex(Z_ARRVAL_P(values), (void **)&values_entry, &pos_values) == SUCCESS) {
- char *string_key;
- uint string_key_len;
- ulong num_key;
-
- zend_hash_get_current_key_ex(Z_ARRVAL_P(values), &string_key, &string_key_len, &num_key, 0, &pos_values);
-
- convert_to_string(*values_entry);
- php_info_print_table_row(2, string_key, Z_STRVAL_PP(values_entry));
-
- zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos_values);
- }
+ ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(values), string_key, values_entry) {
+ convert_to_string(values_entry);
+ php_info_print_table_row(2, string_key->val, Z_STRVAL_P(values_entry));
+ } ZEND_HASH_FOREACH_END();
}
/* }}} */
/* {{{ mysqlnd_minfo_dump_plugin_stats */
static int
-mysqlnd_minfo_dump_plugin_stats(void *pDest, void * argument TSRMLS_DC)
+mysqlnd_minfo_dump_plugin_stats(zval *el, void * argument TSRMLS_DC)
{
- struct st_mysqlnd_plugin_header * plugin_header = *(struct st_mysqlnd_plugin_header **) pDest;
+ struct st_mysqlnd_plugin_header * plugin_header = (struct st_mysqlnd_plugin_header *)Z_PTR_P(el);
if (plugin_header->plugin_stats.values) {
char buf[64];
zval values;
@@ -88,12 +79,12 @@ mysqlnd_minfo_dump_plugin_stats(void *pDest, void * argument TSRMLS_DC)
/* {{{ mysqlnd_minfo_dump_loaded_plugins */
static int
-mysqlnd_minfo_dump_loaded_plugins(void *pDest, void * buf TSRMLS_DC)
+mysqlnd_minfo_dump_loaded_plugins(zval *el, void * buf TSRMLS_DC)
{
smart_str * buffer = (smart_str *) buf;
- struct st_mysqlnd_plugin_header * plugin_header = *(struct st_mysqlnd_plugin_header **) pDest;
+ struct st_mysqlnd_plugin_header * plugin_header = (struct st_mysqlnd_plugin_header *)Z_PTR_P(el);
if (plugin_header->plugin_name) {
- if (buffer->len) {
+ if (buffer->s) {
smart_str_appendc(buffer, ',');
}
smart_str_appends(buffer, plugin_header->plugin_name);
@@ -102,23 +93,20 @@ mysqlnd_minfo_dump_loaded_plugins(void *pDest, void * buf TSRMLS_DC)
}
/* }}} */
+
/* {{{ 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);
- HashPosition pos;
- MYSQLND_REVERSE_API **ext;
-
- for (zend_hash_internal_pointer_reset_ex(ht, &pos);
- zend_hash_get_current_data_ex(ht, (void **) &ext, &pos) == SUCCESS;
- zend_hash_move_forward_ex(ht, &pos)
- ) {
- if (buffer->len) {
+ MYSQLND_REVERSE_API *ext;
+
+ ZEND_HASH_FOREACH_PTR(ht, ext) {
+ if (buffer->s) {
smart_str_appendc(buffer, ',');
}
- smart_str_appends(buffer, (*ext)->module->name);
- }
+ smart_str_appends(buffer, ext->module->name);
+ } ZEND_HASH_FOREACH_END();
}
/* }}} */
@@ -163,15 +151,15 @@ PHP_MINFO_FUNCTION(mysqlnd)
/* loaded plugins */
{
- smart_str tmp_str = {0, 0, 0};
+ smart_str tmp_str = {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);
+ php_info_print_table_row(2, "Loaded plugins", tmp_str.s? tmp_str.s->val : "");
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);
+ php_info_print_table_row(2, "API Extensions", tmp_str.s? tmp_str.s->val : "");
smart_str_free(&tmp_str);
}
@@ -214,6 +202,8 @@ static PHP_GINIT_FUNCTION(mysqlnd)
/* }}} */
+/* {{{ PHP_INI_MH
+ */
static PHP_INI_MH(OnUpdateNetCmdBufferSize)
{
long long_value = atol(new_value);
@@ -224,6 +214,8 @@ static PHP_INI_MH(OnUpdateNetCmdBufferSize)
return SUCCESS;
}
+/* }}} */
+
/* {{{ PHP_INI_BEGIN
*/
@@ -326,7 +318,6 @@ static PHP_RSHUTDOWN_FUNCTION(mysqlnd)
#endif
-
static const zend_module_dep mysqlnd_deps[] = {
ZEND_MOD_REQUIRED("standard")
ZEND_MOD_END