diff options
author | Xinchen Hui <laruence@php.net> | 2014-06-17 17:50:54 +0800 |
---|---|---|
committer | Xinchen Hui <laruence@php.net> | 2014-06-18 12:09:37 +0800 |
commit | 6288bb8ffefe9cf9648b8d2190729c087b5c2586 (patch) | |
tree | 39b7b4afb3b9b902e047b05b1af824161487f20e | |
parent | accaaf9d6e15e57a64a054d7b5ebc0998ee510a4 (diff) | |
download | php-git-6288bb8ffefe9cf9648b8d2190729c087b5c2586.tar.gz |
Refactoring mysqlnd (incompleted, only mysqlnd ext compilable)
-rw-r--r-- | Zend/zend.h | 15 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_debug.c | 50 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_plugin.c | 20 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_ps.c | 101 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_ps_codec.c | 93 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_result.c | 157 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_result_meta.c | 9 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_structs.h | 12 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_wireprotocol.c | 90 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_wireprotocol.h | 8 | ||||
-rw-r--r-- | ext/mysqlnd/php_mysqlnd.c | 53 |
11 files changed, 285 insertions, 323 deletions
diff --git a/Zend/zend.h b/Zend/zend.h index ea2c8f7a33..7ae85ad8cd 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -317,6 +317,21 @@ void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((nore #define Z_ADDREF(z) Z_ADDREF_P(&(z)) #define Z_DELREF(z) Z_DELREF_P(&(z)) +#define Z_TRY_ADDREF_P(pz) do { \ + if (Z_REFCOUNT_P((pz))) { \ + Z_ADDREF_P((pz)); \ + } \ +} while (0) + +#define Z_TRY_DELREF_P(pz) do { \ + if (Z_REFCOUNT_P((pz))) { \ + Z_DELREF_P((pz)); \ + } \ +} while (0) + +#define Z_TRY_ADDREF(z) Z_TRY_ADDREF_P(&(z)) +#define Z_TRY_DELREF(z) Z_TRY_DELREF_P(&(z)) + #if ZEND_DEBUG #define zend_always_inline inline #define zend_never_inline diff --git a/ext/mysqlnd/mysqlnd_debug.c b/ext/mysqlnd/mysqlnd_debug.c index 296a31dfb0..413ba30088 100644 --- a/ext/mysqlnd/mysqlnd_debug.c +++ b/ext/mysqlnd/mysqlnd_debug.c @@ -269,11 +269,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, ""); #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 +282,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; } @@ -336,11 +336,11 @@ 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 */ } @@ -349,7 +349,7 @@ MYSQLND_METHOD(mysqlnd_debug, func_leave)(MYSQLND_DEBUG * self, unsigned int lin 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) { @@ -367,7 +367,7 @@ MYSQLND_METHOD(mysqlnd_debug, func_leave)(MYSQLND_DEBUG * self, unsigned int lin 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 +411,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 +440,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 +466,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 +584,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 +722,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); diff --git a/ext/mysqlnd/mysqlnd_plugin.c b/ext/mysqlnd/mysqlnd_plugin.c index 702d591c3e..2e8f11b6b8 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,7 +157,7 @@ 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)) { + if ((plugin = zend_hash_str_find_ptr(&mysqlnd_registered_plugins, name, strlen(name))) != NULL) { return (void *)*(char **) plugin; } return NULL; @@ -173,22 +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 */ - uint idx; - Bucket *p; + zval *val; int result; - for (idx = 0; idx < mysqlnd_registered_plugins.nNumUsed; idx++) { - p = mysqlnd_registered_plugins.arData + idx; - if (!p->xData) continue; - result = apply_func(HASH_DATA(&mysqlnd_registered_plugins, p), argument TSRMLS_CC); - + 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"); } if (result & ZEND_HASH_APPLY_STOP) { break; } - } + } ZEND_HASH_FOREACH_END(); } /* }}} */ diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c index 539d1c8f83..a074bf403d 100644 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@ -648,7 +648,7 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s TSRMLS_DC) 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_copy_ctor(&stmt->result_bind[i].zv); } } } @@ -682,7 +682,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++; } } @@ -753,9 +753,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, @@ -774,8 +774,9 @@ 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) { + 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; } @@ -787,14 +788,12 @@ mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, unsigned int for (i = 0; i < result->field_count; i++) { /* 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(&stmt->result_bind[i].zv); #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 @@ -803,13 +802,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(&stmt->result_bind[i].zv, ¤t_row[i]); #ifndef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF - zval_copy_ctor(stmt->result_bind[i].zv); + zval_copy_ctor(&stmt->result_bind[i].zv); #endif } else { - ZVAL_NULL(stmt->result_bind[i].zv); + ZVAL_NULL(&stmt->result_bind[i].zv); } } } @@ -891,19 +889,20 @@ 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]; /* 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(&stmt->result_bind[i].zv); #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(&stmt->result_bind[i].zv, data); /* copied data, thus also the ownership. Thus null data */ ZVAL_NULL(data); } @@ -1071,21 +1070,23 @@ 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]; /* 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(&stmt->result_bind[i].zv); #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(&stmt->result_bind[i].zv, data); /* copied data, thus also the ownership. Thus null data */ ZVAL_NULL(data); } @@ -1169,7 +1170,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. @@ -1182,8 +1183,8 @@ 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_dtor(&stmt->result_bind[i].zv); + ZVAL_NULL(&stmt->result_bind[i].zv); } } stmt->result_zvals_separated_once = TRUE; @@ -1439,9 +1440,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); @@ -1454,7 +1453,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; @@ -1507,14 +1506,12 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_one_parameter)(MYSQLND_STMT * const s, unsigne Z_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; @@ -1590,8 +1587,9 @@ 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 @@ -1645,7 +1643,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 @@ -2010,14 +2008,15 @@ 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)); + DBG_INF_FMT("%u has refcount=%u", i, + Z_REFCOUNTED(stmt->result_bind[i].zv)? Z_REFCOUNT(stmt->result_bind[i].zv) : 0); /* 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) { + if (Z_REFCOUNTED(stmt->result_bind[i].zv) && Z_REFCOUNT(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); + zval_copy_ctor(&stmt->result_bind[i].zv); #endif zval_ptr_dtor(&stmt->result_bind[i].zv); } else { @@ -2063,14 +2062,16 @@ 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)); + 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); /* 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) { + if (Z_REFCOUNTED(stmt->result_bind[param_no].zv) && Z_REFCOUNT(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); + zval_copy_ctor(&stmt->result_bind[param_no].zv); #endif zval_ptr_dtor(&stmt->result_bind[param_no].zv); } else { @@ -2080,7 +2081,7 @@ mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const s, unsigned int param 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); + ZVAL_NULL(&stmt->result_bind[param_no].zv); #endif zval_ptr_dtor(&stmt->result_bind[param_no].zv); } @@ -2115,9 +2116,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 d96a57721c..13b44d10a9 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; @@ -236,7 +236,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; } @@ -273,7 +273,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; } @@ -317,7 +317,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; } @@ -336,7 +336,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; @@ -499,16 +499,15 @@ 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); + //????Z_SET_REFCOUNT_P((*copies)[current], 1); + //zval_copy_ctor((*copies)[current]); return PASS; } return FAIL; @@ -518,14 +517,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); } @@ -563,39 +560,34 @@ 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; - if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_NULL && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) { - zval ** copies; + if (Z_TYPE(stmt->param_bind[i].zv) != IS_NULL && (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(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)) { 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(stmt->param_bind[i].zv) != IS_LONG) { + zval *tmp_data = (*copies_param && !Z_ISUNDEF((*copies_param)[i]))? &(*copies_param)[i]: &stmt->param_bind[i].zv; /* 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); /* @@ -603,11 +595,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); @@ -623,7 +615,7 @@ 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++) { @@ -634,13 +626,13 @@ mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval ** copies, zend_ 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)) { + if (!Z_ISNULL(stmt->param_bind[i].zv) && (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(stmt->param_bind[i].zv) != IS_LONG) { + const zval *tmp_data = (copies && !Z_ISUNDEF(copies[i]))? &copies[i]: &stmt->param_bind[i].zv; /* 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. @@ -665,22 +657,22 @@ 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 *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)) { continue; } for (j = i + 1; j < stmt->param_count; j++) { - if (stmt->param_bind[j].zv == the_var) { + if (&stmt->param_bind[j].zv == the_var) { /* Double binding of the same zval, make a copy */ - 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; @@ -694,7 +686,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; @@ -707,11 +699,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]: &stmt->param_bind[i].zv; 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; @@ -729,15 +721,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; } @@ -751,18 +743,18 @@ 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 = (copies && !Z_ISUNDEF(copies[i]))? &copies[i]: &stmt->param_bind[i].zv; /* Handle long data */ - if (stmt->param_bind[i].zv && Z_TYPE_P(data) == IS_NULL) { + if (!Z_ISUNDEF(stmt->param_bind[i].zv) && 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; @@ -816,10 +808,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 68eabf7368..a8ae8be92b 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,9 @@ 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_P(data_cursor[i]) >= IS_STRING) { + 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 +100,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 +126,9 @@ 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) { + 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; } @@ -143,11 +145,11 @@ 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) +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) { + if (!zv) { *copy_ctor_called = FALSE; DBG_ERR_FMT("zv was NULL"); DBG_VOID_RETURN; @@ -160,13 +162,13 @@ mysqlnd_rset_zval_ptr_dtor(zval **zv, enum_mysqlnd_res_type type, zend_bool * co 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) { + } else if (Z_REFCOUNTED_P(zv) && Z_REFCOUNT_P(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); + if (Z_TYPE_P(zv) == IS_STRING) { + zval_copy_ctor(zv); } *copy_ctor_called = TRUE; } else { @@ -176,11 +178,12 @@ mysqlnd_rset_zval_ptr_dtor(zval **zv, enum_mysqlnd_res_type type, zend_bool * co in result set buffers */ *copy_ctor_called = FALSE; - if (Z_TYPE_PP(zv) == IS_STRING) { - ZVAL_NULL(*zv); + if (Z_TYPE_P(zv) == IS_STRING) { + ZVAL_NULL(zv); } } - DBG_INF_FMT("call the dtor on zval with refc %u", Z_REFCOUNT_PP(zv)); + + DBG_INF_FMT("call the dtor on zval with refc %u", Z_REFCOUNTED_P(zv)? Z_REFCOUNT_P(zv) : 0); zval_ptr_dtor(zv); DBG_VOID_RETURN; } @@ -266,7 +269,7 @@ 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"); @@ -278,12 +281,12 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, free_result)(MYSQLND_RES_BUFFERED_Z 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]) { + if (!Z_ISUNDEF(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, ©_ctor_called TSRMLS_CC); if (copy_ctor_called) { @@ -804,7 +807,7 @@ 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]; + zval * data = &result->unbuf->last_row_data[i]; unsigned int len = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data); /* BEGIN difference between normal normal fetch and _c */ @@ -922,12 +925,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]; + zval * data = &result->unbuf->last_row_data[i]; unsigned int len = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data); 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 */ @@ -937,15 +940,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_str_update(Z_ARRVAL_P(row), meta->fields[i].name, meta->fields[i].name_length, 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); } } @@ -1054,10 +1053,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, @@ -1075,8 +1074,9 @@ 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) { + 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; } @@ -1089,7 +1089,7 @@ 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 = ¤t_row[i]; set->lengths[i] = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data); @@ -1146,9 +1146,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, @@ -1166,8 +1166,9 @@ 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_P(current_row[i]) >= IS_STRING) { + 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; } @@ -1176,13 +1177,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 = ¤t_row[i]; set->lengths[i] = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data); 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 */ @@ -1192,17 +1193,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_str_update(Z_ARRVAL_P(row), meta->fields[i].name, meta->fields[i].name_length, 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); } } } @@ -1237,11 +1232,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); @@ -1267,8 +1262,9 @@ 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) { + 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; } @@ -1277,13 +1273,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 = ¤t_row[i]; set->lengths[i] = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data); 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 */ @@ -1293,17 +1289,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_str_update(Z_ARRVAL_P(row), meta->fields[i].name, meta->fields[i].name_length, 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); } } /* @@ -1312,7 +1302,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++; @@ -1531,12 +1521,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; @@ -1810,7 +1800,8 @@ 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); + ZVAL_NEW_ARR(return_value); + 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); @@ -1861,7 +1852,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; @@ -1877,16 +1868,16 @@ 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); + ZVAL_NEW_ARR(return_value); + 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; @@ -1899,7 +1890,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"); @@ -1908,24 +1899,22 @@ 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); + //???entry = zend_hash_get_current_data(Z_ARRVAL(row)); } - 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..9a17976b03 100644 --- a/ext/mysqlnd/mysqlnd_result_meta.c +++ b/ext/mysqlnd/mysqlnd_result_meta.c @@ -182,14 +182,9 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met if ((meta->zend_hash_keys[i].is_numeric = mysqlnd_is_key_numeric(field_packet->metadata->name, field_packet->metadata->name_length + 1, - &idx))) - { + &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); diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h index a72fccf88f..1f79ebc917 100644 --- a/ext/mysqlnd/mysqlnd_structs.h +++ b/ext/mysqlnd/mysqlnd_structs.h @@ -616,7 +616,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); @@ -1035,8 +1035,8 @@ struct st_mysqlnd_buffered_result_zval { def_mysqlnd_buffered_result_parent; - zval **data; - zval **data_cursor; + zval *data; + zval *data_cursor; }; @@ -1053,7 +1053,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; /* @@ -1098,14 +1098,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 6a22b18829..e8237050dd 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -1226,7 +1226,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; @@ -1517,14 +1517,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"); @@ -1541,28 +1541,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) { @@ -1599,8 +1591,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 */ @@ -1612,15 +1604,16 @@ 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) { 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 */ @@ -1634,14 +1627,6 @@ 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; */ @@ -1665,7 +1650,7 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, /* NULL or NOT NULL, this is the question! */ if (len == MYSQLND_NULL_LENGTH) { - ZVAL_NULL(*current_field); + ZVAL_NULL(current_field); last_field_was_string = FALSE; } else { #if defined(MYSQLND_STRING_TO_INT_CONVERSION) @@ -1719,7 +1704,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 @@ -1739,9 +1724,10 @@ 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, 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; @@ -1749,7 +1735,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 */ @@ -1764,24 +1750,34 @@ 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, copy_data); + ZVAL_STRINGL(current_field, (char *) start, bit_area - start - 1); + if (!copy_data) { + efree(start); + } + } 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); + if (!copy_data) { + efree(start); + } } } else { - ZVAL_STRINGL(*current_field, (char *)p, len, copy_data); + ZVAL_STRINGL(current_field, (char *)p, len); + if (!copy_data) { + efree(p); + } } p += len; last_field_was_string = TRUE; @@ -1799,7 +1795,7 @@ 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) { @@ -1813,7 +1809,7 @@ 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) { @@ -1825,8 +1821,6 @@ php_mysqlnd_rowp_read_text_protocol_c(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zv /* }}} */ - - /* {{{ php_mysqlnd_rowp_read */ /* if normal statements => packet->fields is created by this function, @@ -1907,7 +1901,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..165e18ba13 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; /* @@ -307,16 +307,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..d5f8b2033c 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) { + ZEND_HASH_FOREACH_PTR(ht, ext) { + if (buffer->s) { smart_str_appendc(buffer, ','); } 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->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->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 |