From 74ba88e186a0f70caa6e8e5a440a3a204afabf50 Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Tue, 26 Nov 2013 19:01:49 +0200 Subject: Fix for Bug #66141 (mysqlnd quote function is wrong with NO_BACKSLASH_ESCAPES after failed query) --- ext/mysqlnd/mysqlnd_result.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index fd2023cd10..56790b0bc1 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -426,6 +426,7 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s DBG_INF("UPSERT"); conn->last_query_type = QUERY_UPSERT; conn->field_count = rset_header->field_count; + memset(conn->upsert_status, 0, sizeof(*conn->upsert_status)); conn->upsert_status->warning_count = rset_header->warning_count; conn->upsert_status->server_status = rset_header->server_status; conn->upsert_status->affected_rows = rset_header->affected_rows; @@ -714,6 +715,7 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES * result TSRMLS_DC) /* Mark the connection as usable again */ DBG_INF_FMT("warnings=%u server_status=%u", row_packet->warning_count, row_packet->server_status); result->unbuf->eof_reached = TRUE; + memset(result->conn->upsert_status, 0, sizeof(*result->conn->upsert_status)); result->conn->upsert_status->warning_count = row_packet->warning_count; result->conn->upsert_status->server_status = row_packet->server_status; /* @@ -849,6 +851,7 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla /* Mark the connection as usable again */ DBG_INF_FMT("warnings=%u server_status=%u", row_packet->warning_count, row_packet->server_status); result->unbuf->eof_reached = TRUE; + memset(result->conn->upsert_status, 0, sizeof(*result->conn->upsert_status)); result->conn->upsert_status->warning_count = row_packet->warning_count; result->conn->upsert_status->server_status = row_packet->server_status; /* @@ -1206,6 +1209,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c /* Finally clean */ if (row_packet->eof) { + memset(conn->upsert_status, 0, sizeof(*conn->upsert_status)); conn->upsert_status->warning_count = row_packet->warning_count; conn->upsert_status->server_status = row_packet->server_status; } -- cgit v1.2.1 From c0d060f5c02db168f1de895b41afffbc6e3cacfb Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Fri, 3 Jan 2014 11:04:26 +0800 Subject: Bump year --- ext/mysqlnd/mysqlnd_result.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 56790b0bc1..cb15657601 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 2006-2013 The PHP Group | + | 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 | -- cgit v1.2.1 From 47c902777297ce895aa915c13efdb00881af3669 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Fri, 3 Jan 2014 11:06:16 +0800 Subject: Bump year --- ext/mysqlnd/mysqlnd_result.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 4d9c655932..74019b55bf 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 2006-2013 The PHP Group | + | 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 | -- cgit v1.2.1 From 2311ba7d3ff08d27bd7d4b87b51a0f96c5d62d12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Schl=C3=BCter?= Date: Tue, 21 Jan 2014 16:28:30 +0100 Subject: Fix bug #66283 (Segmentation fault after memory_limit) There are situations where mysqlnd dupliates zvals while freeing result sets. If the memory_limit is reached during this operation the engine will bailout. This patch makes sure that a later attempt (during RSHIUTDOWN) won't cause a double free, instead we rely on the engine to free emalloc()ed memory after bailout. --- ext/mysqlnd/mysqlnd_result.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index cb15657601..0814926483 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -198,9 +198,11 @@ MYSQLND_METHOD(mysqlnd_res, free_buffered_data)(MYSQLND_RES * result TSRMLS_DC) if (set->data) { unsigned int copy_on_write_performed = 0; unsigned int copy_on_write_saved = 0; + zval **data = set->data; + set->data = NULL; /* prevent double free if following loop is interrupted */ for (row = set->row_count - 1; row >= 0; row--) { - zval **current_row = set->data + row * field_count; + zval **current_row = data + row * field_count; MYSQLND_MEMORY_POOL_CHUNK *current_buffer = set->row_buffers[row]; int64_t col; @@ -222,8 +224,7 @@ MYSQLND_METHOD(mysqlnd_res, free_buffered_data)(MYSQLND_RES * result TSRMLS_DC) 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(set->data); - set->data = NULL; + mnd_efree(data); } if (set->row_buffers) { -- cgit v1.2.1 From b2cd56c3cb9e752e3d0e4accb99d0f2e1ac71632 Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Mon, 17 Feb 2014 18:37:08 +0200 Subject: Move code out, that handles the actual structure to be used for the decoded data. Will make it easier to add different structures --- ext/mysqlnd/mysqlnd_result.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index fbf8ea031c..944999b79c 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -1155,6 +1155,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c */ } /* Overflow ? */ +#if 0 if (set->row_count) { /* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */ if (set->row_count * meta->field_count * sizeof(zval *) > SIZE_MAX) { @@ -1171,7 +1172,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c } memset(set->data, 0, (size_t)(set->row_count * meta->field_count * sizeof(zval *))); } - +#endif MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, binary_protocol? STAT_ROWS_BUFFERED_FROM_CLIENT_PS: STAT_ROWS_BUFFERED_FROM_CLIENT_NORMAL, @@ -1203,9 +1204,6 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c if (ret == FAIL) { COPY_CLIENT_ERROR(set->error_info, row_packet->error_info); } else { - /* Position at the first row */ - set->data_cursor = set->data; - /* libmysql's documentation says it should be so for SELECT statements */ conn->upsert_status->affected_rows = set->row_count; } @@ -1255,7 +1253,27 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result, SET_OOM_ERROR(*conn->error_info); } DBG_RETURN(NULL); + } else { + /* Overflow ? */ + MYSQLND_RES_BUFFERED * set = result->stored_data; + if (set->row_count) { + /* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */ + if (set->row_count * result->meta->field_count * sizeof(zval *) > SIZE_MAX) { + SET_OOM_ERROR(*conn->error_info); + 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 * result->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 * result->meta->field_count * sizeof(zval *))); + } + /* Position at the first row */ + set->data_cursor = set->data; } + /* libmysql's documentation says it should be so for SELECT statements */ conn->upsert_status->affected_rows = result->stored_data->row_count; -- cgit v1.2.1 From 3e59f041dab41dab10903a57e0953fe6028e02ab Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Mon, 17 Feb 2014 19:04:01 +0200 Subject: remove dead code --- ext/mysqlnd/mysqlnd_result.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 944999b79c..a4fb9f6cf4 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -1155,24 +1155,6 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c */ } /* Overflow ? */ -#if 0 - if (set->row_count) { - /* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */ - if (set->row_count * meta->field_count * sizeof(zval *) > SIZE_MAX) { - SET_OOM_ERROR(*conn->error_info); - ret = FAIL; - goto end; - } - /* if pecalloc is used valgrind barks gcc version 4.3.1 20080507 (prerelease) [gcc-4_3-branch revision 135036] (SUSE Linux) */ - set->data = mnd_emalloc((size_t)(set->row_count * meta->field_count * sizeof(zval *))); - if (!set->data) { - SET_OOM_ERROR(*conn->error_info); - ret = FAIL; - goto end; - } - memset(set->data, 0, (size_t)(set->row_count * meta->field_count * sizeof(zval *))); - } -#endif MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, binary_protocol? STAT_ROWS_BUFFERED_FROM_CLIENT_PS: STAT_ROWS_BUFFERED_FROM_CLIENT_NORMAL, -- cgit v1.2.1 From 6b804b96b8c454954d30ed8f0cf1a05d91801c4f Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Wed, 5 Mar 2014 16:22:23 +0200 Subject: Refactor the result set data structures. Move more to the buffered and unbuffered substructures. Add methods to these too. Preparing for pluggable interface for returning data to the engine (zvals, c-style, something else) --- ext/mysqlnd/mysqlnd_result.c | 765 ++++++++++++++++++++++++++----------------- 1 file changed, 459 insertions(+), 306 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index a4fb9f6cf4..75e745665a 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -33,36 +33,37 @@ #define MYSQLND_SILENT -/* {{{ mysqlnd_res::initialize_result_set_rest */ +/* {{{ mysqlnd_result_buffered::initialize_result_set_rest */ static enum_func_status -MYSQLND_METHOD(mysqlnd_res, initialize_result_set_rest)(MYSQLND_RES * const result TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_result_buffered, initialize_result_set_rest)(MYSQLND_RES_BUFFERED * const result, MYSQLND_RES_METADATA * const meta, + MYSQLND_STATS * stats, zend_bool int_and_float_native TSRMLS_DC) { unsigned int i; - zval **data_cursor = result->stored_data? result->stored_data->data:NULL; - zval **data_begin = result->stored_data? result->stored_data->data:NULL; - unsigned int field_count = result->meta? result->meta->field_count : 0; - uint64_t row_count = result->stored_data? result->stored_data->row_count:0; + zval **data_cursor = result->data; + zval **data_begin = result->data; + unsigned int field_count = meta->field_count; + uint64_t row_count = result->row_count; enum_func_status ret = PASS; - DBG_ENTER("mysqlnd_res::initialize_result_set_rest"); + DBG_ENTER("mysqlnd_result_buffered::initialize_result_set_rest"); - if (!data_cursor || row_count == result->stored_data->initialized_rows) { + if (!data_cursor || row_count == result->initialized_rows) { DBG_RETURN(ret); } while ((data_cursor - data_begin) < (int)(row_count * field_count)) { if (NULL == data_cursor[0]) { enum_func_status rc = result->m.row_decoder( - result->stored_data->row_buffers[(data_cursor - data_begin) / field_count], + result->row_buffers[(data_cursor - data_begin) / field_count], data_cursor, - result->meta->field_count, - result->meta->fields, - result->conn->options->int_and_float_native, - result->conn->stats TSRMLS_CC); + meta->field_count, + meta->fields, + int_and_float_native, + stats TSRMLS_CC); if (rc != PASS) { ret = FAIL; break; } - result->stored_data->initialized_rows++; - for (i = 0; i < result->field_count; i++) { + result->initialized_rows++; + for (i = 0; i < meta->field_count; i++) { /* NULL fields are 0 length, 0 is not more than 0 String of zero size, definitely can't be the next max_length. @@ -70,8 +71,8 @@ MYSQLND_METHOD(mysqlnd_res, initialize_result_set_rest)(MYSQLND_RES * const resu */ if (Z_TYPE_P(data_cursor[i]) >= IS_STRING) { unsigned long len = Z_STRLEN_P(data_cursor[i]); - if (result->meta->fields[i].max_length < len) { - result->meta->fields[i].max_length = len; + if (meta->fields[i].max_length < len) { + meta->fields[i].max_length = len; } } } @@ -88,6 +89,7 @@ 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"); @@ -121,42 +123,42 @@ mysqlnd_rset_zval_ptr_dtor(zval **zv, enum_mysqlnd_res_type type, zend_bool * co 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_res::unbuffered_free_last_data */ +/* {{{ mysqlnd_result_unbuffered::free_last_data */ static void -MYSQLND_METHOD(mysqlnd_res, unbuffered_free_last_data)(MYSQLND_RES * result TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_result_unbuffered, free_last_data)(MYSQLND_RES_UNBUFFERED * unbuf, MYSQLND_STATS * const global_stats TSRMLS_DC) { - MYSQLND_RES_UNBUFFERED *unbuf = result->unbuf; - DBG_ENTER("mysqlnd_res::unbuffered_free_last_data"); if (!unbuf) { DBG_VOID_RETURN; } + 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; - MYSQLND_STATS *global_stats = result->conn? result->conn->stats:NULL; - for (i = 0; i < result->field_count; i++) { - mysqlnd_rset_zval_ptr_dtor(&(unbuf->last_row_data[i]), result->type, ©_ctor_called TSRMLS_CC); + 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, ©_ctor_called TSRMLS_CC); if (copy_ctor_called) { ++ctor_called_count; } } + 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, - result->field_count - ctor_called_count); + unbuf->field_count - ctor_called_count); /* Free last row's zvals */ mnd_efree(unbuf->last_row_data); unbuf->last_row_data = NULL; @@ -173,12 +175,41 @@ MYSQLND_METHOD(mysqlnd_res, unbuffered_free_last_data)(MYSQLND_RES * result TSRM /* }}} */ -/* {{{ mysqlnd_res::free_buffered_data */ +/* {{{ mysqlnd_result_unbuffered::free_result */ static void -MYSQLND_METHOD(mysqlnd_res, free_buffered_data)(MYSQLND_RES * result TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_result_unbuffered, free_result)(MYSQLND_RES_UNBUFFERED * const result, MYSQLND_STATS * const global_stats TSRMLS_DC) { - MYSQLND_RES_BUFFERED *set = result->stored_data; - unsigned int field_count = result->field_count; + DBG_ENTER("mysqlnd_result_unbuffered, free_result"); + result->m.free_last_data(result, global_stats TSRMLS_CC); + + if (result->lengths) { + mnd_pefree(result->lengths, result->persistent); + result->lengths = NULL; + } + + /* must be free before because references the memory pool */ + if (result->row_packet) { + PACKET_FREE(result->row_packet); + result->row_packet = NULL; + } + + if (result->result_set_memory_pool) { + mysqlnd_mempool_destroy(result->result_set_memory_pool TSRMLS_CC); + result->result_set_memory_pool = NULL; + } + + + mnd_pefree(result, result->persistent); + DBG_VOID_RETURN; +} +/* }}} */ + + +/* {{{ mysqlnd_result_buffered::free_result */ +static void +MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * const set TSRMLS_DC) +{ + unsigned int field_count = set->field_count; int64_t row; DBG_ENTER("mysqlnd_res::free_buffered_data"); @@ -199,7 +230,7 @@ MYSQLND_METHOD(mysqlnd_res, free_buffered_data)(MYSQLND_RES * result TSRMLS_DC) 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]), result->type, ©_ctor_called TSRMLS_CC); + 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) { ++copy_on_write_performed; } else { @@ -216,14 +247,26 @@ MYSQLND_METHOD(mysqlnd_res, free_buffered_data)(MYSQLND_RES * result TSRMLS_DC) mnd_efree(data); } + if (set->lengths) { + mnd_pefree(set->lengths, set->persistent); + set->lengths = NULL; + } + if (set->row_buffers) { mnd_efree(set->row_buffers); set->row_buffers = NULL; } + + if (set->result_set_memory_pool) { + mysqlnd_mempool_destroy(set->result_set_memory_pool TSRMLS_CC); + set->result_set_memory_pool = NULL; + } + + set->data_cursor = NULL; set->row_count = 0; - mnd_efree(set); + mnd_pefree(set, set->persistent); DBG_VOID_RETURN; } @@ -238,39 +281,24 @@ MYSQLND_METHOD(mysqlnd_res, free_result_buffers)(MYSQLND_RES * result TSRMLS_DC) DBG_INF_FMT("%s", result->unbuf? "unbuffered":(result->stored_data? "buffered":"unknown")); if (result->unbuf) { - result->m.unbuffered_free_last_data(result TSRMLS_CC); - mnd_efree(result->unbuf); + result->unbuf->m.free_result(result->unbuf, result->conn? result->conn->stats : NULL TSRMLS_CC); result->unbuf = NULL; } else if (result->stored_data) { - result->m.free_buffered_data(result TSRMLS_CC); + result->stored_data->m.free_result(result->stored_data TSRMLS_CC); result->stored_data = NULL; } - if (result->lengths) { - mnd_efree(result->lengths); - result->lengths = NULL; - } - - if (result->row_packet) { - PACKET_FREE(result->row_packet); - result->row_packet = NULL; - } - - if (result->result_set_memory_pool) { - mysqlnd_mempool_destroy(result->result_set_memory_pool TSRMLS_CC); - result->result_set_memory_pool = NULL; - } DBG_VOID_RETURN; } /* }}} */ -/* {{{ mysqlnd_internal_free_result_contents */ +/* {{{ mysqlnd_res::free_result_contents_internal */ static -void mysqlnd_internal_free_result_contents(MYSQLND_RES * result TSRMLS_DC) +void MYSQLND_METHOD(mysqlnd_res, free_result_contents_internal)(MYSQLND_RES * result TSRMLS_DC) { - DBG_ENTER("mysqlnd_internal_free_result_contents"); + DBG_ENTER("mysqlnd_res::free_result_contents_internal"); result->m.free_result_buffers(result TSRMLS_CC); @@ -284,11 +312,13 @@ void mysqlnd_internal_free_result_contents(MYSQLND_RES * result TSRMLS_DC) /* }}} */ -/* {{{ mysqlnd_internal_free_result */ +/* {{{ mysqlnd_res::free_result_internal */ static -void mysqlnd_internal_free_result(MYSQLND_RES * result TSRMLS_DC) +void MYSQLND_METHOD(mysqlnd_res, free_result_internal)(MYSQLND_RES * result TSRMLS_DC) { - DBG_ENTER("mysqlnd_internal_free_result"); + DBG_ENTER("mysqlnd_res::free_result_internal"); + result->m.skip_result(result TSRMLS_CC); + result->m.free_result_contents(result TSRMLS_CC); if (result->conn) { @@ -552,7 +582,7 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s /* }}} */ -/* {{{ mysqlnd_fetch_lengths_buffered */ +/* {{{ mysqlnd_result_buffered::fetch_lengths */ /* Do lazy initialization for buffered results. As PHP strings have length inside, this function makes not much sense in the context @@ -560,11 +590,11 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s completeness. */ static unsigned long * -mysqlnd_fetch_lengths_buffered(MYSQLND_RES * const result TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_result_buffered, fetch_lengths)(MYSQLND_RES_BUFFERED * const result TSRMLS_DC) { unsigned int i; zval **previous_row; - MYSQLND_RES_BUFFERED *set = result->stored_data; + MYSQLND_RES_BUFFERED *set = result; /* If: @@ -574,13 +604,13 @@ mysqlnd_fetch_lengths_buffered(MYSQLND_RES * const result TSRMLS_DC) */ if (set->data_cursor == NULL || set->data_cursor == set->data || - ((set->data_cursor - set->data) > (set->row_count * result->meta->field_count) )) + ((set->data_cursor - set->data) > (set->row_count * result->field_count) )) { return NULL;/* No rows or no more rows */ } - previous_row = set->data_cursor - result->meta->field_count; - for (i = 0; i < result->meta->field_count; i++) { + previous_row = set->data_cursor - result->field_count; + for (i = 0; i < result->field_count; i++) { result->lengths[i] = (Z_TYPE_P(previous_row[i]) == IS_NULL)? 0:Z_STRLEN_P(previous_row[i]); } @@ -589,49 +619,56 @@ mysqlnd_fetch_lengths_buffered(MYSQLND_RES * const result TSRMLS_DC) /* }}} */ -/* {{{ mysqlnd_fetch_lengths_unbuffered */ +/* {{{ mysqlnd_result_unbuffered::fetch_lengths */ static unsigned long * -mysqlnd_fetch_lengths_unbuffered(MYSQLND_RES * const result TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_lengths)(MYSQLND_RES_UNBUFFERED * const result TSRMLS_DC) { /* simulate output of libmysql */ - return (!result->unbuf || result->unbuf->last_row_data || result->unbuf->eof_reached)? result->lengths:NULL; + return (result->last_row_data || result->eof_reached)? result->lengths : NULL; } /* }}} */ /* {{{ mysqlnd_res::fetch_lengths */ -PHPAPI unsigned long * _mysqlnd_fetch_lengths(MYSQLND_RES * const result TSRMLS_DC) +static unsigned long * +MYSQLND_METHOD(mysqlnd_res, fetch_lengths)(MYSQLND_RES * const result TSRMLS_DC) { - return result->m.fetch_lengths? result->m.fetch_lengths(result TSRMLS_CC) : NULL; + unsigned long * ret; + DBG_ENTER("mysqlnd_res::fetch_lengths"); + ret = result->stored_data && result->stored_data->m.fetch_lengths ? + result->stored_data->m.fetch_lengths(result->stored_data TSRMLS_CC) : + (result->unbuf && result->unbuf->m.fetch_lengths ? + result->unbuf->m.fetch_lengths(result->unbuf TSRMLS_CC) : + NULL + ); + DBG_RETURN(ret); } /* }}} */ -/* {{{ mysqlnd_fetch_row_unbuffered_c */ -static MYSQLND_ROW_C -mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES * result TSRMLS_DC) +/* {{{ mysqlnd_result_unbuffered::fetch_row_c */ +static enum_func_status +MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) { enum_func_status ret; - MYSQLND_ROW_C retrow = NULL; - unsigned int i, - field_count = result->field_count; - MYSQLND_PACKET_ROW *row_packet = result->row_packet; - unsigned long *lengths = result->lengths; + MYSQLND_ROW_C *row = (MYSQLND_ROW_C *) param; + MYSQLND_PACKET_ROW *row_packet = result->unbuf->row_packet; + const MYSQLND_RES_METADATA * const meta = result->meta; - DBG_ENTER("mysqlnd_fetch_row_unbuffered_c"); + DBG_ENTER("mysqlnd_result_unbuffered::fetch_row_c"); + *fetched_anything = FALSE; if (result->unbuf->eof_reached) { /* No more rows obviously */ - DBG_RETURN(retrow); + DBG_RETURN(PASS); } if (CONN_GET_STATE(result->conn) != CONN_FETCHING_DATA) { - SET_CLIENT_ERROR(*result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, - UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); - DBG_RETURN(retrow); + SET_CLIENT_ERROR(*result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync); + DBG_RETURN(FAIL); } if (!row_packet) { /* Not fully initialized object that is being cleaned up */ - DBG_RETURN(retrow); + DBG_RETURN(FAIL); } /* Let the row packet fill our buffer and skip additional mnd_malloc + memcpy */ row_packet->skip_extraction = FALSE; @@ -641,9 +678,7 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES * result TSRMLS_DC) result->m.unbuffered_free_last_data() before it. The function returns always true. */ if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) { - result->unbuf->row_count++; - - result->m.unbuffered_free_last_data(result TSRMLS_CC); + result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL TSRMLS_CC); result->unbuf->last_row_data = row_packet->fields; result->unbuf->last_row_buffer = row_packet->row_buffer; @@ -653,46 +688,51 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES * result TSRMLS_DC) MYSQLND_INC_CONN_STATISTIC(result->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_UNBUF); if (!row_packet->skip_extraction) { - MYSQLND_FIELD *field = result->meta->fields; - struct mysqlnd_field_hash_key * hash_key = result->meta->zend_hash_keys; - - enum_func_status rc = result->m.row_decoder(result->unbuf->last_row_buffer, - result->unbuf->last_row_data, - row_packet->field_count, - row_packet->fields_metadata, - result->conn->options->int_and_float_native, - result->conn->stats TSRMLS_CC); + unsigned int i, field_count = meta->field_count; + + enum_func_status rc = result->unbuf->m.row_decoder(result->unbuf->last_row_buffer, + result->unbuf->last_row_data, + field_count, + row_packet->fields_metadata, + result->conn->options->int_and_float_native, + result->conn->stats TSRMLS_CC); if (PASS != rc) { - DBG_RETURN(retrow); + DBG_RETURN(FAIL); } + { + *row = mnd_malloc(field_count * sizeof(char *)); + if (*row) { + MYSQLND_FIELD * field = meta->fields; + 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); + +/* BEGIN difference between normal normal fetch and _c */ + if (Z_TYPE_P(data) != IS_NULL) { + convert_to_string(data); + (*row)[i] = Z_STRVAL_P(data); + } else { + (*row)[i] = NULL; + } +/* END difference between normal normal fetch and _c */ - retrow = mnd_malloc(result->field_count * sizeof(char *)); - if (retrow) { - for (i = 0; i < field_count; i++, field++, hash_key++) { - zval *data = result->unbuf->last_row_data[i]; - unsigned int len; - - if (Z_TYPE_P(data) != IS_NULL) { - convert_to_string(data); - retrow[i] = Z_STRVAL_P(data); - len = Z_STRLEN_P(data); - } else { - retrow[i] = NULL; - len = 0; - } - - if (lengths) { - lengths[i] = len; - } + if (lengths) { + lengths[i] = len; + } - if (field->max_length < len) { - field->max_length = len; + if (field->max_length < len) { + field->max_length = len; + } } + } else { + SET_OOM_ERROR(*result->conn->error_info); } - } else { - SET_OOM_ERROR(*result->conn->error_info); } } + result->unbuf->row_count++; + *fetched_anything = TRUE; } else if (ret == FAIL) { if (row_packet->error_info.error_no) { COPY_CLIENT_ERROR(*result->conn->error_info, row_packet->error_info); @@ -716,23 +756,25 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES * result TSRMLS_DC) } else { CONN_SET_STATE(result->conn, CONN_READY); } - result->m.unbuffered_free_last_data(result TSRMLS_CC); + result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL TSRMLS_CC); } - DBG_RETURN(retrow); + DBG_INF_FMT("ret=%s fetched=%u", ret == PASS? "PASS":"FAIL", *fetched_anything); + DBG_RETURN(PASS); } /* }}} */ -/* {{{ mysqlnd_fetch_row_unbuffered */ +/* {{{ mysqlnd_result_unbuffered::fetch_row */ static enum_func_status -mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int flags, zend_bool *fetched_anything TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) { enum_func_status ret; zval *row = (zval *) param; - MYSQLND_PACKET_ROW *row_packet = result->row_packet; + MYSQLND_PACKET_ROW *row_packet = result->unbuf->row_packet; + const MYSQLND_RES_METADATA * const meta = result->meta; - DBG_ENTER("mysqlnd_fetch_row_unbuffered"); + DBG_ENTER("mysqlnd_result_unbuffered::fetch_row"); *fetched_anything = FALSE; if (result->unbuf->eof_reached) { @@ -755,7 +797,7 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla result->m.unbuffered_free_last_data() before it. The function returns always true. */ if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) { - result->m.unbuffered_free_last_data(result TSRMLS_CC); + result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL TSRMLS_CC); result->unbuf->last_row_data = row_packet->fields; result->unbuf->last_row_buffer = row_packet->row_buffer; @@ -765,13 +807,9 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla MYSQLND_INC_CONN_STATISTIC(result->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_UNBUF); if (!row_packet->skip_extraction) { - HashTable *row_ht = Z_ARRVAL_P(row); - MYSQLND_FIELD *field = result->meta->fields; - struct mysqlnd_field_hash_key * hash_key = result->meta->zend_hash_keys; - unsigned int i, field_count = result->field_count; - unsigned long *lengths = result->lengths; + unsigned int i, field_count = meta->field_count; - enum_func_status rc = result->m.row_decoder(result->unbuf->last_row_buffer, + enum_func_status rc = result->unbuf->m.row_decoder(result->unbuf->last_row_buffer, result->unbuf->last_row_data, field_count, row_packet->fields_metadata, @@ -780,46 +818,51 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla if (PASS != rc) { DBG_RETURN(FAIL); } - for (i = 0; i < field_count; i++, field++, hash_key++) { - zval *data = result->unbuf->last_row_data[i]; - unsigned int len = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data); + { + HashTable * row_ht = Z_ARRVAL_P(row); + MYSQLND_FIELD * field = meta->fields; + 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); + + if (flags & MYSQLND_FETCH_NUM) { + Z_ADDREF_P(data); + zend_hash_next_index_insert(row_ht, &data, sizeof(zval *), NULL); + } + if (flags & MYSQLND_FETCH_ASSOC) { + /* zend_hash_quick_update needs length + trailing zero */ + /* QQ: Error handling ? */ + /* + zend_hash_quick_update does not check, as add_assoc_zval_ex do, whether + 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); + 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); + } else { + zend_hash_index_update(Z_ARRVAL_P(row), meta->zend_hash_keys[i].key, (void *) &data, sizeof(zval *), NULL); + } + } - if (lengths) { - lengths[i] = len; - } + if (lengths) { + lengths[i] = len; + } - if (flags & MYSQLND_FETCH_NUM) { - Z_ADDREF_P(data); - zend_hash_next_index_insert(row_ht, &data, sizeof(zval *), NULL); - } - if (flags & MYSQLND_FETCH_ASSOC) { - /* zend_hash_quick_update needs length + trailing zero */ - /* QQ: Error handling ? */ - /* - zend_hash_quick_update does not check, as add_assoc_zval_ex do, whether - 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); - if (hash_key->is_numeric == FALSE) { - zend_hash_quick_update(Z_ARRVAL_P(row), - field->name, - field->name_length + 1, - hash_key->key, - (void *) &data, sizeof(zval *), NULL); - } else { - zend_hash_index_update(Z_ARRVAL_P(row), - hash_key->key, - (void *) &data, sizeof(zval *), NULL); + if (field->max_length < len) { + field->max_length = len; } } - if (field->max_length < len) { - field->max_length = len; - } } } - *fetched_anything = TRUE; result->unbuf->row_count++; + *fetched_anything = TRUE; } else if (ret == FAIL) { if (row_packet->error_info.error_no) { COPY_CLIENT_ERROR(*result->conn->error_info, row_packet->error_info); @@ -843,7 +886,7 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla } else { CONN_SET_STATE(result->conn, CONN_READY); } - result->m.unbuffered_free_last_data(result TSRMLS_CC); + result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL TSRMLS_CC); } DBG_INF_FMT("ret=%s fetched=%u", ret == PASS? "PASS":"FAIL", *fetched_anything); @@ -862,44 +905,31 @@ MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps if (ps == FALSE) { result->type = MYSQLND_RES_NORMAL; - result->m.fetch_row = result->m.fetch_row_normal_unbuffered; - result->m.fetch_lengths = mysqlnd_fetch_lengths_unbuffered; - result->m.row_decoder = php_mysqlnd_rowp_read_text_protocol; - result->lengths = mnd_ecalloc(result->field_count, sizeof(unsigned long)); - if (!result->lengths) { - goto oom; - } } else { result->type = MYSQLND_RES_PS_UNBUF; - result->m.fetch_row = NULL; - /* result->m.fetch_row() will be set in mysqlnd_ps.c */ - result->m.fetch_lengths = NULL; /* makes no sense */ - result->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol; - result->lengths = NULL; } - result->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC); - result->unbuf = mnd_ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED)); - if (!result->result_set_memory_pool || !result->unbuf) { + result->unbuf = mysqlnd_result_unbuffered_init(result->field_count, ps, result->persistent TSRMLS_CC); + if (!result->unbuf) { goto oom; } /* Will be freed in the mysqlnd_internal_free_result_contents() called - by the resource destructor. mysqlnd_fetch_row_unbuffered() expects + by the resource destructor. mysqlnd_result_unbuffered::fetch_row() expects this to be not NULL. */ /* FALSE = non-persistent */ - result->row_packet = result->conn->protocol->m.get_row_packet(result->conn->protocol, FALSE TSRMLS_CC); - if (!result->row_packet) { + result->unbuf->row_packet = result->conn->protocol->m.get_row_packet(result->conn->protocol, FALSE TSRMLS_CC); + if (!result->unbuf->row_packet) { goto oom; } - result->row_packet->result_set_memory_pool = result->result_set_memory_pool; - result->row_packet->field_count = result->field_count; - result->row_packet->binary_protocol = ps; - result->row_packet->fields_metadata = result->meta->fields; - result->row_packet->bit_fields_count = result->meta->bit_fields_count; - result->row_packet->bit_fields_total_len = result->meta->bit_fields_total_len; + result->unbuf->row_packet->result_set_memory_pool = result->unbuf->result_set_memory_pool; + result->unbuf->row_packet->field_count = result->field_count; + result->unbuf->row_packet->binary_protocol = ps; + result->unbuf->row_packet->fields_metadata = result->meta->fields; + result->unbuf->row_packet->bit_fields_count = result->meta->bit_fields_count; + result->unbuf->row_packet->bit_fields_total_len = result->meta->bit_fields_total_len; DBG_RETURN(result); oom: @@ -909,37 +939,39 @@ oom: /* }}} */ -/* {{{ mysqlnd_fetch_row_buffered_c */ -static MYSQLND_ROW_C -mysqlnd_fetch_row_buffered_c(MYSQLND_RES * result TSRMLS_DC) +/* {{{ mysqlnd_result_buffered::fetch_row_c */ +static enum_func_status +MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) { - MYSQLND_ROW_C ret = NULL; - MYSQLND_RES_BUFFERED *set = result->stored_data; + MYSQLND_ROW_C * row = (MYSQLND_ROW_C *) param; + MYSQLND_RES_BUFFERED * set = result->stored_data; + const MYSQLND_RES_METADATA * const meta = result->meta; + unsigned int field_count = meta->field_count; + enum_func_status ret = FAIL; - DBG_ENTER("mysqlnd_fetch_row_buffered_c"); + DBG_ENTER("mysqlnd_result_buffered::fetch_row_c"); /* If we haven't read everything */ if (set->data_cursor && - (set->data_cursor - set->data) < (set->row_count * result->meta->field_count)) + (set->data_cursor - set->data) < (set->row_count * field_count)) { zval **current_row = set->data_cursor; - MYSQLND_FIELD *field = result->meta->fields; - struct mysqlnd_field_hash_key * hash_key = result->meta->zend_hash_keys; + MYSQLND_FIELD * field = meta->fields; unsigned int i; if (NULL == current_row[0]) { - uint64_t row_num = (set->data_cursor - set->data) / result->meta->field_count; - enum_func_status rc = result->m.row_decoder(set->row_buffers[row_num], + 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, - result->meta->field_count, - result->meta->fields, + field_count, + meta->fields, result->conn->options->int_and_float_native, result->conn->stats TSRMLS_CC); if (rc != PASS) { - DBG_RETURN(ret); + DBG_RETURN(FAIL); } set->initialized_rows++; - for (i = 0; i < result->field_count; i++) { + for (i = 0; i < field_count; i++) { /* NULL fields are 0 length, 0 is not more than 0 String of zero size, definitely can't be the next max_length. @@ -954,64 +986,72 @@ mysqlnd_fetch_row_buffered_c(MYSQLND_RES * result TSRMLS_DC) } } - set->data_cursor += result->meta->field_count; - MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF); - - ret = mnd_malloc(result->field_count * sizeof(char *)); +/* BEGIN difference between normal normal fetch and _c */ + /* there is no conn handle in this function thus we can't set OOM in error_info */ + *row = mnd_malloc(field_count * sizeof(char *)); if (ret) { - for (i = 0; i < result->field_count; i++, field++, hash_key++) { - zval *data = current_row[i]; + for (i = 0; i < field_count; i++) { + zval * data = current_row[i]; if (Z_TYPE_P(data) != IS_NULL) { convert_to_string(data); - ret[i] = Z_STRVAL_P(data); + (*row)[i] = Z_STRVAL_P(data); } else { - ret[i] = NULL; + (*row)[i] = NULL; } } } - /* there is no conn handle in this function thus we can't set OOM in error_info */ +/* END difference between normal normal fetch and _c */ + + set->data_cursor += field_count; + MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF); + *fetched_anything = TRUE; + ret = PASS; } else { set->data_cursor = NULL; DBG_INF("EOF reached"); + *fetched_anything = FALSE; + ret = PASS; } + DBG_INF_FMT("ret=PASS fetched=%u", *fetched_anything); DBG_RETURN(ret); } /* }}} */ -/* {{{ mysqlnd_fetch_row_buffered */ +/* {{{ mysqlnd_result_buffered::fetch_row */ static enum_func_status -mysqlnd_fetch_row_buffered(MYSQLND_RES * result, void *param, unsigned int flags, zend_bool *fetched_anything TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) { - unsigned int i; - zval *row = (zval *) param; - MYSQLND_RES_BUFFERED *set = result->stored_data; + zval * row = (zval *) param; + MYSQLND_RES_BUFFERED * set = result->stored_data; + const MYSQLND_RES_METADATA * const meta = result->meta; + unsigned int field_count = meta->field_count; enum_func_status ret = FAIL; - DBG_ENTER("mysqlnd_fetch_row_buffered"); + DBG_ENTER("mysqlnd_result_buffered::fetch_row"); /* If we haven't read everything */ if (set->data_cursor && - (set->data_cursor - set->data) < (set->row_count * result->meta->field_count)) + (set->data_cursor - set->data) < (set->row_count * field_count)) { zval **current_row = set->data_cursor; - MYSQLND_FIELD *field = result->meta->fields; - struct mysqlnd_field_hash_key * hash_key = result->meta->zend_hash_keys; + MYSQLND_FIELD * field = meta->fields; + unsigned int i; if (NULL == current_row[0]) { - uint64_t row_num = (set->data_cursor - set->data) / result->meta->field_count; - enum_func_status rc = result->m.row_decoder(set->row_buffers[row_num], + 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, - result->meta->field_count, - result->meta->fields, + field_count, + meta->fields, result->conn->options->int_and_float_native, result->conn->stats TSRMLS_CC); if (rc != PASS) { DBG_RETURN(FAIL); } set->initialized_rows++; - for (i = 0; i < result->field_count; i++) { + for (i = 0; i < field_count; i++) { /* NULL fields are 0 length, 0 is not more than 0 String of zero size, definitely can't be the next max_length. @@ -1026,8 +1066,8 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES * result, void *param, unsigned int flags } } - for (i = 0; i < result->field_count; i++, field++, hash_key++) { - zval *data = current_row[i]; + for (i = 0; i < field_count; i++, field++) { + zval * data = current_row[i]; if (flags & MYSQLND_FETCH_NUM) { Z_ADDREF_P(data); @@ -1042,28 +1082,28 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES * result, void *param, unsigned int flags hashing of the column name, which is not needed as it can be precomputed. */ Z_ADDREF_P(data); - if (hash_key->is_numeric == FALSE) { + if (meta->zend_hash_keys[i].is_numeric == FALSE) { zend_hash_quick_update(Z_ARRVAL_P(row), field->name, field->name_length + 1, - hash_key->key, + meta->zend_hash_keys[i].key, (void *) &data, sizeof(zval *), NULL); } else { zend_hash_index_update(Z_ARRVAL_P(row), - hash_key->key, + meta->zend_hash_keys[i].key, (void *) &data, sizeof(zval *), NULL); } } } - set->data_cursor += result->meta->field_count; - *fetched_anything = TRUE; + set->data_cursor += field_count; MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF); + *fetched_anything = TRUE; ret = PASS; } else { set->data_cursor = NULL; + DBG_INF("EOF reached"); *fetched_anything = FALSE; ret = PASS; - DBG_INF("EOF reached"); } DBG_INF_FMT("ret=PASS fetched=%u", *fetched_anything); DBG_RETURN(ret); @@ -1071,22 +1111,37 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES * result, void *param, unsigned int flags /* }}} */ +/* {{{ mysqlnd_res::fetch_row */ +static enum_func_status +MYSQLND_METHOD(mysqlnd_res, fetch_row)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool *fetched_anything TSRMLS_DC) +{ + const mysqlnd_fetch_row_func f = result->stored_data? result->stored_data->m.fetch_row:(result->unbuf? result->unbuf->m.fetch_row:NULL); + if (f) { + return f(result, param, flags, fetched_anything TSRMLS_CC); + } + *fetched_anything = FALSE; + return PASS; +} +/* }}} */ + + #define STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY 2 /* {{{ mysqlnd_res::store_result_fetch_data */ enum_func_status MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const conn, MYSQLND_RES * result, - MYSQLND_RES_METADATA *meta, + MYSQLND_RES_METADATA * meta, zend_bool binary_protocol TSRMLS_DC) { enum_func_status ret; - MYSQLND_PACKET_ROW *row_packet = NULL; + MYSQLND_PACKET_ROW * row_packet = NULL; unsigned int next_extend = STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY, free_rows = 1; MYSQLND_RES_BUFFERED *set; DBG_ENTER("mysqlnd_res::store_result_fetch_data"); - result->stored_data = set = mnd_ecalloc(1, sizeof(MYSQLND_RES_BUFFERED)); + result->stored_data = set = mysqlnd_result_buffered_init(result->field_count, binary_protocol, result->persistent TSRMLS_CC); + if (!set) { SET_OOM_ERROR(*conn->error_info); ret = FAIL; @@ -1109,7 +1164,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c ret = FAIL; goto end; } - row_packet->result_set_memory_pool = result->result_set_memory_pool; + row_packet->result_set_memory_pool = result->stored_data->result_set_memory_pool; row_packet->field_count = meta->field_count; row_packet->binary_protocol = binary_protocol; row_packet->fields_metadata = meta->fields; @@ -1210,20 +1265,9 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result, DBG_ENTER("mysqlnd_res::store_result"); /* We need the conn because we are doing lazy zval initialization in buffered_fetch_row */ - result->conn = conn->m->get_reference(conn TSRMLS_CC); - result->type = MYSQLND_RES_NORMAL; - result->m.fetch_row = result->m.fetch_row_normal_buffered; - result->m.fetch_lengths = mysqlnd_fetch_lengths_buffered; - result->m.row_decoder = ps_protocol? php_mysqlnd_rowp_read_binary_protocol: - php_mysqlnd_rowp_read_text_protocol; - - result->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC); - result->lengths = mnd_ecalloc(result->field_count, sizeof(unsigned long)); - - if (!result->result_set_memory_pool || !result->lengths) { - SET_OOM_ERROR(*conn->error_info); - DBG_RETURN(NULL); - } + /* In case of error the reference will be released in free_result_internal() called indirectly by our caller */ + result->conn = conn->m->get_reference(conn TSRMLS_CC); + result->type = MYSQLND_RES_NORMAL; CONN_SET_STATE(conn, CONN_FETCHING_DATA); @@ -1237,20 +1281,21 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result, DBG_RETURN(NULL); } else { /* Overflow ? */ + MYSQLND_RES_METADATA * meta = result->meta; MYSQLND_RES_BUFFERED * set = result->stored_data; if (set->row_count) { /* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */ - if (set->row_count * result->meta->field_count * sizeof(zval *) > SIZE_MAX) { + if (set->row_count * meta->field_count * sizeof(zval *) > SIZE_MAX) { SET_OOM_ERROR(*conn->error_info); 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 * result->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 * result->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; @@ -1276,9 +1321,7 @@ MYSQLND_METHOD(mysqlnd_res, skip_result)(MYSQLND_RES * const result TSRMLS_DC) A PS could be prepared - there is metadata and thus a stmt->result but the fetch_row function isn't actually set (NULL), thus we have to skip these. */ - if (!result->stored_data && result->unbuf && - !result->unbuf->eof_reached && result->m.fetch_row) - { + if (result->unbuf && !result->unbuf->eof_reached) { DBG_INF("skipping result"); /* We have to fetch all data to clean the line */ MYSQLND_INC_CONN_STATISTIC(result->conn->stats, @@ -1300,7 +1343,6 @@ MYSQLND_METHOD(mysqlnd_res, free_result)(MYSQLND_RES * result, zend_bool implici { DBG_ENTER("mysqlnd_res::free_result"); - result->m.skip_result(result TSRMLS_CC); MYSQLND_INC_CONN_STATISTIC(result->conn? result->conn->stats : NULL, implicit == TRUE? STAT_FREE_RESULT_IMPLICIT: STAT_FREE_RESULT_EXPLICIT); @@ -1313,20 +1355,27 @@ MYSQLND_METHOD(mysqlnd_res, free_result)(MYSQLND_RES * result, zend_bool implici /* {{{ mysqlnd_res::data_seek */ static enum_func_status -MYSQLND_METHOD(mysqlnd_res, data_seek)(MYSQLND_RES * result, uint64_t row TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_res, data_seek)(MYSQLND_RES * const result, const uint64_t row TSRMLS_DC) { DBG_ENTER("mysqlnd_res::data_seek"); DBG_INF_FMT("row=%lu", row); - if (!result->stored_data) { - return FAIL; - } + DBG_RETURN(result->stored_data? result->stored_data->m.data_seek(result->stored_data, row TSRMLS_CC) : FAIL); +} +/* }}} */ + + +/* {{{ mysqlnd_result_buffered::data_seek */ +static enum_func_status +MYSQLND_METHOD(mysqlnd_result_buffered, data_seek)(MYSQLND_RES_BUFFERED * const result, const uint64_t row TSRMLS_DC) +{ + DBG_ENTER("mysqlnd_result_buffered::data_seek"); /* libmysql just moves to the end, it does traversing of a linked list */ - if (row >= result->stored_data->row_count) { - result->stored_data->data_cursor = NULL; + if (row >= result->row_count) { + result->data_cursor = NULL; } else { - result->stored_data->data_cursor = result->stored_data->data + row * result->meta->field_count; + result->data_cursor = result->data + row * result->field_count; } DBG_RETURN(PASS); @@ -1334,12 +1383,32 @@ MYSQLND_METHOD(mysqlnd_res, data_seek)(MYSQLND_RES * result, uint64_t row TSRMLS /* }}} */ +/* {{{ mysqlnd_result_unbuffered::num_rows */ +static uint64_t +MYSQLND_METHOD(mysqlnd_result_unbuffered, num_rows)(const MYSQLND_RES_UNBUFFERED * const result TSRMLS_DC) +{ + /* Be compatible with libmysql. We count row_count, but will return 0 */ + return result->eof_reached? result->row_count:0; +} +/* }}} */ + + +/* {{{ mysqlnd_result_buffered::num_rows */ +static uint64_t +MYSQLND_METHOD(mysqlnd_result_buffered, num_rows)(const MYSQLND_RES_BUFFERED * const result TSRMLS_DC) +{ + return result->row_count; +} +/* }}} */ + + /* {{{ mysqlnd_res::num_rows */ static uint64_t MYSQLND_METHOD(mysqlnd_res, num_rows)(const MYSQLND_RES * const result TSRMLS_DC) { - /* Be compatible with libmysql. We count row_count, but will return 0 */ - return result->stored_data? result->stored_data->row_count:(result->unbuf && result->unbuf->eof_reached? result->unbuf->row_count:0); + return result->stored_data? + result->stored_data->m.num_rows(result->stored_data TSRMLS_CC) : + (result->unbuf? result->unbuf->m.num_rows(result->unbuf TSRMLS_CC) : 0); } /* }}} */ @@ -1373,7 +1442,9 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field)(MYSQLND_RES * const result TSRMLS_DC) if (result->stored_data && (result->stored_data->initialized_rows < result->stored_data->row_count)) { DBG_INF_FMT("We have decode the whole result set to be able to satisfy this meta request"); /* we have to initialize the rest to get the updated max length */ - if (PASS != result->m.initialize_result_set_rest(result TSRMLS_CC)) { + if (PASS != result->stored_data->m.initialize_result_set_rest(result->stored_data, result->meta, result->conn->stats, + result->conn->options->int_and_float_native TSRMLS_CC)) + { break; } } @@ -1387,7 +1458,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field)(MYSQLND_RES * const result TSRMLS_DC) /* {{{ mysqlnd_res::fetch_field_direct */ static const MYSQLND_FIELD * -MYSQLND_METHOD(mysqlnd_res, fetch_field_direct)(MYSQLND_RES * const result, MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_res, fetch_field_direct)(MYSQLND_RES * const result, const MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC) { DBG_ENTER("mysqlnd_res::fetch_field_direct"); do { @@ -1405,7 +1476,9 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field_direct)(MYSQLND_RES * const result, MYSQ if (result->stored_data && (result->stored_data->initialized_rows < result->stored_data->row_count)) { DBG_INF_FMT("We have decode the whole result set to be able to satisfy this meta request"); /* we have to initialized the rest to get the updated max length */ - if (PASS != result->m.initialize_result_set_rest(result TSRMLS_CC)) { + if (PASS != result->stored_data->m.initialize_result_set_rest(result->stored_data, result->meta, result->conn->stats, + result->conn->options->int_and_float_native TSRMLS_CC)) + { break; } } @@ -1427,7 +1500,9 @@ MYSQLND_METHOD(mysqlnd_res, fetch_fields)(MYSQLND_RES * const result TSRMLS_DC) if (result->meta) { if (result->stored_data && (result->stored_data->initialized_rows < result->stored_data->row_count)) { /* we have to initialize the rest to get the updated max length */ - if (PASS != result->m.initialize_result_set_rest(result TSRMLS_CC)) { + if (PASS != result->stored_data->m.initialize_result_set_rest(result->stored_data, result->meta, result->conn->stats, + result->conn->options->int_and_float_native TSRMLS_CC)) + { break; } } @@ -1439,17 +1514,11 @@ MYSQLND_METHOD(mysqlnd_res, fetch_fields)(MYSQLND_RES * const result TSRMLS_DC) /* }}} */ - /* {{{ mysqlnd_res::field_seek */ static MYSQLND_FIELD_OFFSET -MYSQLND_METHOD(mysqlnd_res, field_seek)(MYSQLND_RES * const result, MYSQLND_FIELD_OFFSET field_offset TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_res, field_seek)(MYSQLND_RES * const result, const MYSQLND_FIELD_OFFSET field_offset TSRMLS_DC) { - MYSQLND_FIELD_OFFSET return_value = 0; - if (result->meta) { - return_value = result->meta->current_field; - result->meta->current_field = field_offset; - } - return return_value; + return result->meta? result->meta->m->field_seek(result->meta, field_offset TSRMLS_CC) : 0; } /* }}} */ @@ -1473,10 +1542,6 @@ MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, unsigned int flags DBG_ENTER("mysqlnd_res::fetch_into"); - if (!result->m.fetch_row) { - RETVAL_NULL(); - DBG_VOID_RETURN; - } /* Hint Zend how many elements we will have in the hash. Thus it won't extend and rehash the hash constantly. @@ -1511,17 +1576,17 @@ MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, unsigned int flags static MYSQLND_ROW_C MYSQLND_METHOD(mysqlnd_res, fetch_row_c)(MYSQLND_RES * result TSRMLS_DC) { + zend_bool fetched_anything; MYSQLND_ROW_C ret = NULL; DBG_ENTER("mysqlnd_res::fetch_row_c"); - if (result->m.fetch_row) { - if (result->m.fetch_row == result->m.fetch_row_normal_buffered) { - DBG_RETURN(mysqlnd_fetch_row_buffered_c(result TSRMLS_CC)); - } else if (result->m.fetch_row == result->m.fetch_row_normal_unbuffered) { - DBG_RETURN(mysqlnd_fetch_row_unbuffered_c(result TSRMLS_CC)); - } else { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "result->m.fetch_row has invalid value. Report to the developers"); - } + if (result->stored_data && result->stored_data->m.fetch_row == MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row)) { + MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(result, (void *) &ret, 0, &fetched_anything TSRMLS_CC); + } else if (result->unbuf && result->unbuf->m.fetch_row == MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)) { + MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(result, (void *) &ret, 0, &fetched_anything TSRMLS_CC); + } else { + ret = NULL; + php_error_docref(NULL TSRMLS_CC, E_ERROR, "result->m.fetch_row has invalid value. Report to the developers"); } DBG_RETURN(ret); } @@ -1575,11 +1640,6 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field_data)(MYSQLND_RES * result, unsigned int DBG_ENTER("mysqlnd_res::fetch_field_data"); DBG_INF_FMT("offset=%u", offset); - - if (!result->m.fetch_row) { - RETVAL_NULL(); - DBG_VOID_RETURN; - } /* Hint Zend how many elements we will have in the hash. Thus it won't extend and rehash the hash constantly. @@ -1610,9 +1670,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field_data)(MYSQLND_RES * result, unsigned int MYSQLND_CLASS_METHODS_START(mysqlnd_res) - NULL, /* fetch_row */ - mysqlnd_fetch_row_buffered, - mysqlnd_fetch_row_unbuffered, + MYSQLND_METHOD(mysqlnd_res, fetch_row), MYSQLND_METHOD(mysqlnd_res, use_result), MYSQLND_METHOD(mysqlnd_res, store_result), MYSQLND_METHOD(mysqlnd_res, fetch_into), @@ -1629,19 +1687,34 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_res) MYSQLND_METHOD(mysqlnd_res, fetch_field_direct), MYSQLND_METHOD(mysqlnd_res, fetch_fields), MYSQLND_METHOD(mysqlnd_res, read_result_metadata), - NULL, /* fetch_lengths */ + MYSQLND_METHOD(mysqlnd_res, fetch_lengths), MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data), - MYSQLND_METHOD(mysqlnd_res, initialize_result_set_rest), MYSQLND_METHOD(mysqlnd_res, free_result_buffers), MYSQLND_METHOD(mysqlnd_res, free_result), + MYSQLND_METHOD(mysqlnd_res, free_result_internal), + MYSQLND_METHOD(mysqlnd_res, free_result_contents_internal), + mysqlnd_result_meta_init +MYSQLND_CLASS_METHODS_END; - mysqlnd_internal_free_result, /* free_result_internal */ - mysqlnd_internal_free_result_contents, /* free_result_contents */ - MYSQLND_METHOD(mysqlnd_res, free_buffered_data), - MYSQLND_METHOD(mysqlnd_res, unbuffered_free_last_data), - NULL /* row_decoder */, - mysqlnd_result_meta_init +MYSQLND_CLASS_METHODS_START(mysqlnd_result_unbuffered) + MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row), + NULL, /* row_decoder */ + MYSQLND_METHOD(mysqlnd_result_unbuffered, num_rows), + MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_lengths), + MYSQLND_METHOD(mysqlnd_result_unbuffered, free_last_data), + MYSQLND_METHOD(mysqlnd_result_unbuffered, free_result) +MYSQLND_CLASS_METHODS_END; + + +MYSQLND_CLASS_METHODS_START(mysqlnd_result_buffered) + MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row), + NULL, /* row_decoder */ + MYSQLND_METHOD(mysqlnd_result_buffered, num_rows), + MYSQLND_METHOD(mysqlnd_result_buffered, fetch_lengths), + MYSQLND_METHOD(mysqlnd_result_buffered, data_seek), + MYSQLND_METHOD(mysqlnd_result_buffered, initialize_result_set_rest), + MYSQLND_METHOD(mysqlnd_result_buffered, free_result) MYSQLND_CLASS_METHODS_END; @@ -1650,7 +1723,7 @@ PHPAPI MYSQLND_RES * mysqlnd_result_init(unsigned int field_count, zend_bool persistent TSRMLS_DC) { size_t alloc_size = sizeof(MYSQLND_RES) + mysqlnd_plugin_count() * sizeof(void *); - MYSQLND_RES *ret = mnd_pecalloc(1, alloc_size, persistent); + MYSQLND_RES * ret = mnd_pecalloc(1, alloc_size, persistent); DBG_ENTER("mysqlnd_result_init"); @@ -1667,6 +1740,86 @@ mysqlnd_result_init(unsigned int field_count, zend_bool persistent TSRMLS_DC) /* }}} */ +/* {{{ mysqlnd_result_unbuffered_init */ +PHPAPI MYSQLND_RES_UNBUFFERED * +mysqlnd_result_unbuffered_init(unsigned int field_count, zend_bool ps, zend_bool persistent TSRMLS_DC) +{ + size_t alloc_size = sizeof(MYSQLND_RES_UNBUFFERED) + mysqlnd_plugin_count() * sizeof(void *); + MYSQLND_RES_UNBUFFERED * ret = mnd_pecalloc(1, alloc_size, persistent); + + DBG_ENTER("mysqlnd_result_unbuffered_init"); + + if (!ret) { + DBG_RETURN(NULL); + } + + if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(unsigned long), persistent))) { + mnd_pefree(ret, persistent); + DBG_RETURN(NULL); + } + if (!(ret->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC))) { + mnd_efree(ret->lengths); + mnd_pefree(ret, persistent); + DBG_RETURN(NULL); + } + + ret->persistent = persistent; + ret->field_count= field_count; + ret->ps = ps; + + ret->m = *mysqlnd_result_unbuffered_get_methods(); + + if (ps) { + ret->m.fetch_lengths = NULL; /* makes no sense */ + ret->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol; + } else { + ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol; + } + + DBG_RETURN(ret); +} +/* }}} */ + + +/* {{{ mysqlnd_result_buffered_init */ +PHPAPI MYSQLND_RES_BUFFERED * +mysqlnd_result_buffered_init(unsigned int field_count, zend_bool ps, zend_bool persistent TSRMLS_DC) +{ + size_t alloc_size = sizeof(MYSQLND_RES_BUFFERED) + mysqlnd_plugin_count() * sizeof(void *); + MYSQLND_RES_BUFFERED * ret = mnd_pecalloc(1, alloc_size, persistent); + + DBG_ENTER("mysqlnd_result_buffered_init"); + + if (!ret) { + DBG_RETURN(NULL); + } + if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(unsigned long), persistent))) { + mnd_pefree(ret, persistent); + DBG_RETURN(NULL); + } + if (!(ret->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC))) { + mnd_efree(ret->lengths); + mnd_pefree(ret, persistent); + DBG_RETURN(NULL); + } + + ret->persistent = persistent; + ret->field_count= field_count; + ret->ps = ps; + ret->m = *mysqlnd_result_buffered_get_methods(); + + if (ps) { + ret->m.fetch_lengths = NULL; /* makes no sense */ + ret->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol; + } else { + ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol; + } + + DBG_RETURN(ret); +} +/* }}} */ + + /* * Local variables: * tab-width: 4 -- cgit v1.2.1 From 990f9c8f3f8ce926c9b82538be6dc538e10b6405 Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Mon, 10 Mar 2014 17:25:53 +0200 Subject: Switch from a single flag to a flag byte --- ext/mysqlnd/mysqlnd_result.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 75e745665a..2ed6acf3ab 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -1258,7 +1258,7 @@ end: static MYSQLND_RES * MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result, MYSQLND_CONN_DATA * const conn, - zend_bool ps_protocol TSRMLS_DC) + const unsigned int flags TSRMLS_DC) { enum_func_status ret; @@ -1271,7 +1271,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result, CONN_SET_STATE(conn, CONN_FETCHING_DATA); - ret = result->m.store_result_fetch_data(conn, result, result->meta, ps_protocol TSRMLS_CC); + ret = result->m.store_result_fetch_data(conn, result, result->meta, flags & MYSQLND_STORE_PS TSRMLS_CC); if (FAIL == ret) { if (result->stored_data) { COPY_CLIENT_ERROR(*conn->error_info, result->stored_data->error_info); -- cgit v1.2.1 From 73f03a47d0cd97a3c55a79b897ba55ea1ed2e90e Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Mon, 10 Mar 2014 18:18:56 +0200 Subject: DI --- ext/mysqlnd/mysqlnd_result.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 2ed6acf3ab..fc6f48581c 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -1140,10 +1140,9 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c DBG_ENTER("mysqlnd_res::store_result_fetch_data"); - result->stored_data = set = mysqlnd_result_buffered_init(result->field_count, binary_protocol, result->persistent TSRMLS_CC); + set = result->stored_data; if (!set) { - SET_OOM_ERROR(*conn->error_info); ret = FAIL; goto end; } @@ -1271,6 +1270,12 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result, CONN_SET_STATE(conn, CONN_FETCHING_DATA); + result->stored_data = mysqlnd_result_buffered_init(result->field_count, flags & MYSQLND_STORE_PS, result->persistent TSRMLS_CC); + if (!result->stored_data) { + SET_OOM_ERROR(*conn->error_info); + DBG_RETURN(NULL); + } + ret = result->m.store_result_fetch_data(conn, result, result->meta, flags & MYSQLND_STORE_PS TSRMLS_CC); if (FAIL == ret) { if (result->stored_data) { -- cgit v1.2.1 From 63791d055ad64762c3f63e08ca7ad8ba1f44e0ab Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Thu, 10 Apr 2014 16:44:54 +0300 Subject: New result fetching mode for mysqlnd, which should use less memory but implies more memory copy. The old method is still available and can be used. It stays as default. Choosing the method is through a flag to mysqli_query()/mysqli_real_query() New mode can be forced with an INI setting, for all extensions that support this mode (ext/mysql and mysqli, because PDO due to it's architecture can't support it) The setting is mysqlnd.fetch_data_copy=[0|1] --- ext/mysqlnd/mysqlnd_result.c | 594 +++++++++++++++++++++++++++++++++---------- 1 file changed, 455 insertions(+), 139 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index fc6f48581c..0112a1394d 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -32,29 +32,30 @@ #define MYSQLND_SILENT - -/* {{{ mysqlnd_result_buffered::initialize_result_set_rest */ +/* {{{ mysqlnd_result_buffered_zval::initialize_result_set_rest */ static enum_func_status -MYSQLND_METHOD(mysqlnd_result_buffered, initialize_result_set_rest)(MYSQLND_RES_BUFFERED * const result, MYSQLND_RES_METADATA * const meta, - MYSQLND_STATS * stats, zend_bool int_and_float_native TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_result_buffered_zval, initialize_result_set_rest)(MYSQLND_RES_BUFFERED * const result, MYSQLND_RES_METADATA * const meta, + MYSQLND_STATS * stats, zend_bool int_and_float_native TSRMLS_DC) { unsigned int i; - zval **data_cursor = result->data; - zval **data_begin = result->data; - unsigned int field_count = meta->field_count; - uint64_t row_count = result->row_count; enum_func_status ret = PASS; - DBG_ENTER("mysqlnd_result_buffered::initialize_result_set_rest"); + const unsigned int field_count = meta->field_count; + 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; + + DBG_ENTER("mysqlnd_result_buffered_zval::initialize_result_set_rest"); if (!data_cursor || row_count == result->initialized_rows) { DBG_RETURN(ret); } while ((data_cursor - data_begin) < (int)(row_count * field_count)) { if (NULL == data_cursor[0]) { - enum_func_status rc = result->m.row_decoder( - result->row_buffers[(data_cursor - data_begin) / field_count], + rc = result->m.row_decoder(result->row_buffers[(data_cursor - data_begin) / field_count], data_cursor, - meta->field_count, + field_count, meta->fields, int_and_float_native, stats TSRMLS_CC); @@ -63,7 +64,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered, initialize_result_set_rest)(MYSQLND_RES_ break; } result->initialized_rows++; - for (i = 0; i < meta->field_count; i++) { + for (i = 0; i < field_count; i++) { /* NULL fields are 0 length, 0 is not more than 0 String of zero size, definitely can't be the next max_length. @@ -84,6 +85,62 @@ MYSQLND_METHOD(mysqlnd_result_buffered, initialize_result_set_rest)(MYSQLND_RES_ /* }}} */ +/* {{{ mysqlnd_result_buffered_c::initialize_result_set_rest */ +static enum_func_status +MYSQLND_METHOD(mysqlnd_result_buffered_c, initialize_result_set_rest)(MYSQLND_RES_BUFFERED * const result, MYSQLND_RES_METADATA * const meta, + MYSQLND_STATS * stats, zend_bool int_and_float_native TSRMLS_DC) +{ + unsigned int i; + enum_func_status ret = PASS; + const unsigned int field_count = meta->field_count; + const uint64_t row_count = result->row_count; + enum_func_status rc; + DBG_ENTER("mysqlnd_result_buffered_c::initialize_result_set_rest"); + + if (result->initialized_rows < row_count) { + zend_uchar * initialized = ((MYSQLND_RES_BUFFERED_C *) result)->initialized; + zval ** current_row = mnd_emalloc(field_count * sizeof(zval *)); + + if (!current_row) { + DBG_RETURN(FAIL); + } + + for (i = 0; i < result->row_count; i++) { + /* (i / 8) & the_bit_for_i*/ + if (initialized[i >> 3] & (1 << (i & 7))) { + continue; + } + + rc = result->m.row_decoder(result->row_buffers[i], current_row, field_count, meta->fields, int_and_float_native, stats TSRMLS_CC); + + if (rc != PASS) { + ret = FAIL; + break; + } + result->initialized_rows++; + initialized[i >> 3] |= (1 << (i & 7)); + for (i = 0; i < field_count; i++) { + /* + NULL fields are 0 length, 0 is not more than 0 + 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 (meta->fields[i].max_length < len) { + meta->fields[i].max_length = len; + } + } + zval_ptr_dtor(¤t_row[i]); + } + } + mnd_efree(current_row); + } + DBG_RETURN(ret); +} +/* }}} */ + + /* {{{ 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) @@ -205,25 +262,23 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, free_result)(MYSQLND_RES_UNBUFFERED * /* }}} */ -/* {{{ mysqlnd_result_buffered::free_result */ +/* {{{ mysqlnd_result_buffered_zval::free_result */ static void -MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * const set TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_result_buffered_zval, free_result)(MYSQLND_RES_BUFFERED_ZVAL * const set TSRMLS_DC) { - unsigned int field_count = set->field_count; - int64_t row; + zval ** data = set->data; - DBG_ENTER("mysqlnd_res::free_buffered_data"); - DBG_INF_FMT("Freeing "MYSQLND_LLU_SPEC" row(s)", set->row_count); + DBG_ENTER("mysqlnd_result_buffered_zval::free_result"); - if (set->data) { + 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; - zval **data = set->data; - set->data = NULL; /* prevent double free if following loop is interrupted */ - + 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; - MYSQLND_MEMORY_POOL_CHUNK *current_buffer = set->row_buffers[row]; int64_t col; if (current_row != NULL) { @@ -239,13 +294,48 @@ MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * cons } } } - current_buffer->free_chunk(current_buffer TSRMLS_CC); } - MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_COPY_ON_WRITE_PERFORMED, copy_on_write_performed, STAT_COPY_ON_WRITE_SAVED, copy_on_write_saved); mnd_efree(data); } + set->data_cursor = NULL; + DBG_VOID_RETURN; +} +/* }}} */ + + +/* {{{ mysqlnd_result_buffered_c::free_result */ +static void +MYSQLND_METHOD(mysqlnd_result_buffered_c, free_result)(MYSQLND_RES_BUFFERED_C * const set TSRMLS_DC) +{ + DBG_ENTER("mysqlnd_result_buffered_c::free_result"); + mnd_pefree(set->initialized, set->persistent); + set->initialized = NULL; + DBG_VOID_RETURN; +} +/* }}} */ + + +/* {{{ mysqlnd_result_buffered::free_result */ +static void +MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * const set TSRMLS_DC) +{ + int64_t row; + + DBG_ENTER("mysqlnd_result_buffered::free_result"); + DBG_INF_FMT("Freeing "MYSQLND_LLU_SPEC" row(s)", set->row_count); + + if (set->type == MYSQLND_BUFFERED_TYPE_ZVAL) { + MYSQLND_METHOD(mysqlnd_result_buffered_zval, free_result)((MYSQLND_RES_BUFFERED_ZVAL *) set TSRMLS_CC); + } if (set->type == MYSQLND_BUFFERED_TYPE_C) { + MYSQLND_METHOD(mysqlnd_result_buffered_c, free_result)((MYSQLND_RES_BUFFERED_C *) set TSRMLS_CC); + } + + for (row = set->row_count - 1; row >= 0; row--) { + MYSQLND_MEMORY_POOL_CHUNK *current_buffer = set->row_buffers[row]; + current_buffer->free_chunk(current_buffer TSRMLS_CC); + } if (set->lengths) { mnd_pefree(set->lengths, set->persistent); @@ -253,8 +343,8 @@ MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * cons } if (set->row_buffers) { - mnd_efree(set->row_buffers); - set->row_buffers = NULL; + mnd_pefree(set->row_buffers, 0); + set->row_buffers = NULL; } if (set->result_set_memory_pool) { @@ -263,7 +353,6 @@ MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * cons } - set->data_cursor = NULL; set->row_count = 0; mnd_pefree(set, set->persistent); @@ -590,31 +679,49 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s completeness. */ static unsigned long * -MYSQLND_METHOD(mysqlnd_result_buffered, fetch_lengths)(MYSQLND_RES_BUFFERED * const result TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_lengths)(MYSQLND_RES_BUFFERED * const result TSRMLS_DC) { - unsigned int i; - zval **previous_row; - MYSQLND_RES_BUFFERED *set = result; - + const MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result; /* If: - unbuffered result - first row has not been read - last_row has been read */ + DBG_ENTER("mysqlnd_result_buffered_zval::fetch_lengths"); + if (set->data_cursor == NULL || set->data_cursor == set->data || - ((set->data_cursor - set->data) > (set->row_count * result->field_count) )) + ((set->data_cursor - set->data) > (result->row_count * result->field_count) )) { - return NULL;/* No rows or no more rows */ + DBG_INF("EOF"); + DBG_RETURN(NULL);/* No rows or no more rows */ } + DBG_INF("non NULL"); + DBG_RETURN(result->lengths); +} +/* }}} */ - previous_row = set->data_cursor - result->field_count; - for (i = 0; i < result->field_count; i++) { - result->lengths[i] = (Z_TYPE_P(previous_row[i]) == IS_NULL)? 0:Z_STRLEN_P(previous_row[i]); - } - return result->lengths; +/* {{{ mysqlnd_result_buffered_c::fetch_lengths */ +/* + Do lazy initialization for buffered results. As PHP strings have + length inside, this function makes not much sense in the context + of PHP, to be called as separate function. But let's have it for + completeness. +*/ +static unsigned long * +MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_lengths)(MYSQLND_RES_BUFFERED * const result TSRMLS_DC) +{ + const MYSQLND_RES_BUFFERED_C * set = (MYSQLND_RES_BUFFERED_C *) result; + DBG_ENTER("mysqlnd_result_buffered_c::fetch_lengths"); + + if (set->current_row > set->row_count || set->current_row == 0) { + DBG_INF("EOF"); + DBG_RETURN(NULL); /* No more rows, or no fetched row */ + } + DBG_INF("non NULL"); + DBG_RETURN(result->lengths); } /* }}} */ @@ -767,7 +874,7 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi /* {{{ mysqlnd_result_unbuffered::fetch_row */ static enum_func_status -MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void * param, const unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) { enum_func_status ret; zval *row = (zval *) param; @@ -944,20 +1051,111 @@ static enum_func_status MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) { MYSQLND_ROW_C * row = (MYSQLND_ROW_C *) param; - MYSQLND_RES_BUFFERED * set = result->stored_data; const MYSQLND_RES_METADATA * const meta = result->meta; unsigned int field_count = meta->field_count; enum_func_status ret = FAIL; - DBG_ENTER("mysqlnd_result_buffered::fetch_row_c"); + if (result->stored_data->type == MYSQLND_BUFFERED_TYPE_ZVAL) { + MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result->stored_data; + + /* If we haven't read everything */ + if (set->data_cursor && + (set->data_cursor - set->data) < (result->stored_data->row_count * field_count)) + { + zval **current_row = set->data_cursor; + unsigned int i; + + if (NULL == 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, + field_count, + meta->fields, + result->conn->options->int_and_float_native, + result->conn->stats TSRMLS_CC); + if (rc != PASS) { + DBG_RETURN(FAIL); + } + set->initialized_rows++; + for (i = 0; i < field_count; i++) { + /* + NULL fields are 0 length, 0 is not more than 0 + 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 (meta->fields[i].max_length < len) { + meta->fields[i].max_length = len; + } + } + } + } + +/* BEGIN difference between normal normal fetch and _c */ + /* there is no conn handle in this function thus we can't set OOM in error_info */ + *row = mnd_malloc(field_count * sizeof(char *)); + if (*row) { + for (i = 0; i < field_count; i++) { + zval * data = current_row[i]; + + set->lengths[i] = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data); + + if (Z_TYPE_P(data) != IS_NULL) { + convert_to_string(data); + (*row)[i] = Z_STRVAL_P(data); + } else { + (*row)[i] = NULL; + } + } + set->data_cursor += field_count; + MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF); + } else { + SET_OOM_ERROR(*result->conn->error_info); + } +/* END difference between normal normal fetch and _c */ + + *fetched_anything = *row? TRUE:FALSE; + ret = *row? PASS:FAIL; + } else { + set->data_cursor = NULL; + DBG_INF("EOF reached"); + *fetched_anything = FALSE; + ret = PASS; + } + } else if (result->stored_data->type == MYSQLND_BUFFERED_TYPE_C) { + /* + We don't support _C with pdo because it uses the data in a different way - just references it. + We will either leak or give nirvana pointers + */ + *fetched_anything = FALSE; + DBG_RETURN(FAIL); + } + DBG_INF_FMT("ret=PASS fetched=%u", *fetched_anything); + DBG_RETURN(ret); +} +/* }}} */ + + +/* {{{ mysqlnd_result_buffered_zval::fetch_row */ +static enum_func_status +MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, void * param, const unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) +{ + zval * row = (zval *) param; + const MYSQLND_RES_METADATA * const meta = result->meta; + unsigned int field_count = meta->field_count; + enum_func_status ret = FAIL; + MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result->stored_data; + + DBG_ENTER("mysqlnd_result_buffered_zval::fetch_row"); + /* If we haven't read everything */ if (set->data_cursor && (set->data_cursor - set->data) < (set->row_count * field_count)) { - zval **current_row = set->data_cursor; - MYSQLND_FIELD * field = meta->fields; unsigned int i; + zval **current_row = set->data_cursor; if (NULL == current_row[0]) { uint64_t row_num = (set->data_cursor - set->data) / field_count; @@ -979,30 +1177,44 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void */ if (Z_TYPE_P(current_row[i]) >= IS_STRING) { unsigned long len = Z_STRLEN_P(current_row[i]); - if (field->max_length < len) { - field->max_length = len; + if (meta->fields[i].max_length < len) { + meta->fields[i].max_length = len; } } } } -/* BEGIN difference between normal normal fetch and _c */ - /* there is no conn handle in this function thus we can't set OOM in error_info */ - *row = mnd_malloc(field_count * sizeof(char *)); - if (ret) { - for (i = 0; i < field_count; i++) { - zval * data = current_row[i]; + for (i = 0; i < field_count; i++) { + zval * data = current_row[i]; - if (Z_TYPE_P(data) != IS_NULL) { - convert_to_string(data); - (*row)[i] = Z_STRVAL_P(data); + 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); + } + if (flags & MYSQLND_FETCH_ASSOC) { + /* zend_hash_quick_update needs length + trailing zero */ + /* QQ: Error handling ? */ + /* + zend_hash_quick_update does not check, as add_assoc_zval_ex do, whether + 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); + 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); } else { - (*row)[i] = NULL; + zend_hash_index_update(Z_ARRVAL_P(row), + meta->zend_hash_keys[i].key, + (void *) &data, sizeof(zval *), NULL); } } } -/* END difference between normal normal fetch and _c */ - set->data_cursor += field_count; MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF); *fetched_anything = TRUE; @@ -1019,38 +1231,45 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void /* }}} */ -/* {{{ mysqlnd_result_buffered::fetch_row */ +/* {{{ mysqlnd_result_buffered_c::fetch_row */ static enum_func_status -MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void * param, const unsigned int flags, zend_bool * fetched_anything TSRMLS_DC) { zval * row = (zval *) param; - MYSQLND_RES_BUFFERED * set = result->stored_data; const MYSQLND_RES_METADATA * const meta = result->meta; unsigned int field_count = meta->field_count; enum_func_status ret = FAIL; - DBG_ENTER("mysqlnd_result_buffered::fetch_row"); + MYSQLND_RES_BUFFERED_C * set = (MYSQLND_RES_BUFFERED_C *) result->stored_data; + + DBG_ENTER("mysqlnd_result_buffered_c::fetch_row"); /* If we haven't read everything */ - if (set->data_cursor && - (set->data_cursor - set->data) < (set->row_count * field_count)) - { - zval **current_row = set->data_cursor; - MYSQLND_FIELD * field = meta->fields; + if (set->current_row < set->row_count) { + zval **current_row; + enum_func_status rc; unsigned int i; - if (NULL == 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, - field_count, - meta->fields, - result->conn->options->int_and_float_native, - result->conn->stats TSRMLS_CC); - if (rc != PASS) { - DBG_RETURN(FAIL); - } + current_row = mnd_emalloc(field_count * sizeof(zval *)); + if (!current_row) { + SET_OOM_ERROR(*result->conn->error_info); + DBG_RETURN(FAIL); + } + + rc = result->stored_data->m.row_decoder(result->stored_data->row_buffers[set->current_row], + current_row, + field_count, + meta->fields, + result->conn->options->int_and_float_native, + result->conn->stats TSRMLS_CC); + if (rc != PASS) { + DBG_RETURN(FAIL); + } + if (!(set->initialized[set->current_row >> 3] & (1 << (set->current_row & 7)))) { + set->initialized[set->current_row >> 3] |= (1 << (set->current_row & 7)); /* mark initialized */ + set->initialized_rows++; + for (i = 0; i < field_count; i++) { /* NULL fields are 0 length, 0 is not more than 0 @@ -1059,16 +1278,18 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row)(MYSQLND_RES * result, void * */ if (Z_TYPE_P(current_row[i]) >= IS_STRING) { unsigned long len = Z_STRLEN_P(current_row[i]); - if (field->max_length < len) { - field->max_length = len; + if (meta->fields[i].max_length < len) { + meta->fields[i].max_length = len; } } } } - for (i = 0; i < field_count; i++, field++) { + for (i = 0; i < field_count; i++) { zval * data = current_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); @@ -1084,8 +1305,8 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row)(MYSQLND_RES * result, void * Z_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->fields[i].name, + meta->fields[i].name_length + 1, meta->zend_hash_keys[i].key, (void *) &data, sizeof(zval *), NULL); } else { @@ -1094,17 +1315,28 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row)(MYSQLND_RES * result, void * (void *) &data, sizeof(zval *), NULL); } } + /* + This will usually not destroy anything but decref. + However, if neither NUM nor ASSOC is set we will free memory cleanly and won't leak. + 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); } - set->data_cursor += field_count; + mnd_efree(current_row); + set->current_row++; MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF); *fetched_anything = TRUE; ret = PASS; } else { - set->data_cursor = NULL; - DBG_INF("EOF reached"); + if (set->current_row == set->row_count) { + set->current_row = set->row_count + 1; + } + DBG_INF_FMT("EOF reached. current_row=%llu", (unsigned long long) set->current_row); *fetched_anything = FALSE; ret = PASS; } + DBG_INF_FMT("ret=PASS fetched=%u", *fetched_anything); DBG_RETURN(ret); } @@ -1113,7 +1345,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row)(MYSQLND_RES * result, void * /* {{{ mysqlnd_res::fetch_row */ static enum_func_status -MYSQLND_METHOD(mysqlnd_res, fetch_row)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool *fetched_anything TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_res, fetch_row)(MYSQLND_RES * result, void * param, const unsigned int flags, zend_bool *fetched_anything TSRMLS_DC) { const mysqlnd_fetch_row_func f = result->stored_data? result->stored_data->m.fetch_row:(result->unbuf? result->unbuf->m.fetch_row:NULL); if (f) { @@ -1131,6 +1363,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_row)(MYSQLND_RES * result, void * param, unsig enum_func_status MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const conn, MYSQLND_RES * result, MYSQLND_RES_METADATA * meta, + MYSQLND_MEMORY_POOL_CHUNK ***row_buffers, zend_bool binary_protocol TSRMLS_DC) { enum_func_status ret; @@ -1142,13 +1375,13 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c set = result->stored_data; - if (!set) { + if (!set || !row_buffers) { ret = FAIL; goto end; } if (free_rows) { - set->row_buffers = mnd_emalloc((size_t)(free_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *))); - if (!set->row_buffers) { + *row_buffers = mnd_pemalloc((size_t)(free_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)), 0); + if (!*row_buffers) { SET_OOM_ERROR(*conn->error_info); ret = FAIL; goto end; @@ -1184,16 +1417,16 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c ret = FAIL; goto end; } - new_row_buffers = mnd_erealloc(set->row_buffers, (size_t)(total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *))); + new_row_buffers = mnd_perealloc(*row_buffers, (size_t)(total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)), 0); if (!new_row_buffers) { SET_OOM_ERROR(*conn->error_info); ret = FAIL; goto end; } - set->row_buffers = new_row_buffers; + *row_buffers = new_row_buffers; } free_rows--; - set->row_buffers[set->row_count] = row_packet->row_buffer; + (*row_buffers)[set->row_count] = row_packet->row_buffer; set->row_count++; @@ -1228,7 +1461,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c ret = FAIL; goto end; } - set->row_buffers = mnd_erealloc(set->row_buffers, (size_t) (set->row_count * sizeof(MYSQLND_MEMORY_POOL_CHUNK *))); + *row_buffers = mnd_perealloc(*row_buffers, (size_t) (set->row_count * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)), 0); } if (conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) { @@ -1247,7 +1480,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c ret == PASS? "PASS":"FAIL", (uint) set->row_count, conn->upsert_status->warning_count, conn->upsert_status->server_status); end: PACKET_FREE(row_packet); - + DBG_INF_FMT("rows=%llu", (unsigned long long)result->stored_data->row_count); DBG_RETURN(ret); } /* }}} */ @@ -1260,6 +1493,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result, const unsigned int flags TSRMLS_DC) { enum_func_status ret; + MYSQLND_MEMORY_POOL_CHUNK ***row_buffers = NULL; DBG_ENTER("mysqlnd_res::store_result"); @@ -1270,13 +1504,23 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result, CONN_SET_STATE(conn, CONN_FETCHING_DATA); - result->stored_data = mysqlnd_result_buffered_init(result->field_count, flags & MYSQLND_STORE_PS, result->persistent TSRMLS_CC); - if (!result->stored_data) { - SET_OOM_ERROR(*conn->error_info); - DBG_RETURN(NULL); + if (flags & MYSQLND_STORE_NO_COPY) { + result->stored_data = (MYSQLND_RES_BUFFERED *) mysqlnd_result_buffered_zval_init(result->field_count, flags & MYSQLND_STORE_PS, result->persistent TSRMLS_CC); + if (!result->stored_data) { + SET_OOM_ERROR(*conn->error_info); + DBG_RETURN(NULL); + } + row_buffers = &result->stored_data->row_buffers; + } else if (flags & MYSQLND_STORE_COPY) { + result->stored_data = (MYSQLND_RES_BUFFERED *) mysqlnd_result_buffered_c_init(result->field_count, flags & MYSQLND_STORE_PS, result->persistent TSRMLS_CC); + if (!result->stored_data) { + SET_OOM_ERROR(*conn->error_info); + DBG_RETURN(NULL); + } + row_buffers = &result->stored_data->row_buffers; } + ret = result->m.store_result_fetch_data(conn, result, result->meta, row_buffers, flags & MYSQLND_STORE_PS TSRMLS_CC); - ret = result->m.store_result_fetch_data(conn, result, result->meta, flags & MYSQLND_STORE_PS TSRMLS_CC); if (FAIL == ret) { if (result->stored_data) { COPY_CLIENT_ERROR(*conn->error_info, result->stored_data->error_info); @@ -1286,24 +1530,30 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result, DBG_RETURN(NULL); } else { /* Overflow ? */ - MYSQLND_RES_METADATA * meta = result->meta; - MYSQLND_RES_BUFFERED * set = result->stored_data; - if (set->row_count) { - /* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */ - if (set->row_count * meta->field_count * sizeof(zval *) > SIZE_MAX) { - SET_OOM_ERROR(*conn->error_info); - 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 *))); - if (!set->data) { - SET_OOM_ERROR(*conn->error_info); - DBG_RETURN(NULL); + if (flags & MYSQLND_STORE_NO_COPY) { + MYSQLND_RES_METADATA * meta = result->meta; + MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result->stored_data; + if (set->row_count) { + /* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */ + if (set->row_count * meta->field_count * sizeof(zval *) > SIZE_MAX) { + SET_OOM_ERROR(*conn->error_info); + 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 *))); + 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; + } else if (flags & MYSQLND_STORE_COPY) { + MYSQLND_RES_BUFFERED_C * set = (MYSQLND_RES_BUFFERED_C *) result->stored_data; + set->current_row = 0; + set->initialized = mnd_pecalloc((set->row_count / 8) + 1, sizeof(zend_uchar), set->persistent); /* +1 for safety */ } - /* Position at the first row */ - set->data_cursor = set->data; } /* libmysql's documentation says it should be so for SELECT statements */ @@ -1370,19 +1620,37 @@ MYSQLND_METHOD(mysqlnd_res, data_seek)(MYSQLND_RES * const result, const uint64_ /* }}} */ -/* {{{ mysqlnd_result_buffered::data_seek */ +/* {{{ mysqlnd_result_buffered_zval::data_seek */ static enum_func_status -MYSQLND_METHOD(mysqlnd_result_buffered, data_seek)(MYSQLND_RES_BUFFERED * const result, const uint64_t row TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_result_buffered_zval, data_seek)(MYSQLND_RES_BUFFERED * const result, const uint64_t row TSRMLS_DC) { - DBG_ENTER("mysqlnd_result_buffered::data_seek"); + MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result; + DBG_ENTER("mysqlnd_result_buffered_zval::data_seek"); /* libmysql just moves to the end, it does traversing of a linked list */ - if (row >= result->row_count) { - result->data_cursor = NULL; + if (row >= set->row_count) { + set->data_cursor = NULL; } else { - result->data_cursor = result->data + row * result->field_count; + set->data_cursor = set->data + row * result->field_count; } + DBG_RETURN(PASS); +} +/* }}} */ + +/* {{{ mysqlnd_result_buffered_c::data_seek */ +static enum_func_status +MYSQLND_METHOD(mysqlnd_result_buffered_c, data_seek)(MYSQLND_RES_BUFFERED * const result, const uint64_t row TSRMLS_DC) +{ + MYSQLND_RES_BUFFERED_C * set = (MYSQLND_RES_BUFFERED_C *) result; + DBG_ENTER("mysqlnd_result_buffered_c::data_seek"); + + /* libmysql just moves to the end, it does traversing of a linked list */ + if (row >= set->row_count) { + set->current_row = set->row_count; + } else { + set->current_row = row; + } DBG_RETURN(PASS); } /* }}} */ @@ -1539,7 +1807,7 @@ MYSQLND_METHOD(mysqlnd_res, field_tell)(const MYSQLND_RES * const result TSRMLS_ /* {{{ mysqlnd_res::fetch_into */ static void -MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, unsigned int flags, +MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, const unsigned int flags, zval *return_value, enum_mysqlnd_extension extension TSRMLS_DC ZEND_FILE_LINE_DC) { @@ -1585,7 +1853,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_row_c)(MYSQLND_RES * result TSRMLS_DC) MYSQLND_ROW_C ret = NULL; DBG_ENTER("mysqlnd_res::fetch_row_c"); - if (result->stored_data && result->stored_data->m.fetch_row == MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row)) { + if (result->stored_data && result->stored_data->m.fetch_row == MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)) { MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(result, (void *) &ret, 0, &fetched_anything TSRMLS_CC); } else if (result->unbuf && result->unbuf->m.fetch_row == MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)) { MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(result, (void *) &ret, 0, &fetched_anything TSRMLS_CC); @@ -1600,7 +1868,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_row_c)(MYSQLND_RES * result TSRMLS_DC) /* {{{ mysqlnd_res::fetch_all */ static void -MYSQLND_METHOD(mysqlnd_res, fetch_all)(MYSQLND_RES * result, unsigned int flags, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC) +MYSQLND_METHOD(mysqlnd_res, fetch_all)(MYSQLND_RES * result, const unsigned int flags, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC) { zval *row; ulong i = 0; @@ -1713,12 +1981,12 @@ MYSQLND_CLASS_METHODS_END; MYSQLND_CLASS_METHODS_START(mysqlnd_result_buffered) - MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row), + NULL, /* fetch_row */ NULL, /* row_decoder */ MYSQLND_METHOD(mysqlnd_result_buffered, num_rows), - MYSQLND_METHOD(mysqlnd_result_buffered, fetch_lengths), - MYSQLND_METHOD(mysqlnd_result_buffered, data_seek), - MYSQLND_METHOD(mysqlnd_result_buffered, initialize_result_set_rest), + NULL, /* fetch_lengths */ + NULL, /* data_seek */ + NULL, /* initialize_result_set_rest */ MYSQLND_METHOD(mysqlnd_result_buffered, free_result) MYSQLND_CLASS_METHODS_END; @@ -1778,7 +2046,7 @@ mysqlnd_result_unbuffered_init(unsigned int field_count, zend_bool ps, zend_bool ret->m.fetch_lengths = NULL; /* makes no sense */ ret->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol; } else { - ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol; + ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol_zval; } DBG_RETURN(ret); @@ -1786,14 +2054,57 @@ mysqlnd_result_unbuffered_init(unsigned int field_count, zend_bool ps, zend_bool /* }}} */ -/* {{{ mysqlnd_result_buffered_init */ -PHPAPI MYSQLND_RES_BUFFERED * -mysqlnd_result_buffered_init(unsigned int field_count, zend_bool ps, zend_bool persistent TSRMLS_DC) +/* {{{ mysqlnd_result_buffered_zval_init */ +PHPAPI MYSQLND_RES_BUFFERED_ZVAL * +mysqlnd_result_buffered_zval_init(unsigned int field_count, zend_bool ps, zend_bool persistent TSRMLS_DC) +{ + size_t alloc_size = sizeof(MYSQLND_RES_BUFFERED_ZVAL) + mysqlnd_plugin_count() * sizeof(void *); + MYSQLND_RES_BUFFERED_ZVAL * ret = mnd_pecalloc(1, alloc_size, persistent); + + DBG_ENTER("mysqlnd_result_buffered_zval_init"); + + if (!ret) { + DBG_RETURN(NULL); + } + if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(unsigned long), persistent))) { + mnd_pefree(ret, persistent); + DBG_RETURN(NULL); + } + if (!(ret->result_set_memory_pool = mysqlnd_mempool_create(MYSQLND_G(mempool_default_size) TSRMLS_CC))) { + mnd_efree(ret->lengths); + mnd_pefree(ret, persistent); + DBG_RETURN(NULL); + } + + ret->persistent = persistent; + ret->field_count= field_count; + ret->ps = ps; + ret->m = *mysqlnd_result_buffered_get_methods(); + ret->type = MYSQLND_BUFFERED_TYPE_ZVAL; + + if (ps) { + ret->m.fetch_lengths = NULL; /* makes no sense */ + ret->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol; + } else { + ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol_zval; + } + ret->m.fetch_row = MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row); + ret->m.fetch_lengths = MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_lengths); + ret->m.data_seek = MYSQLND_METHOD(mysqlnd_result_buffered_zval, data_seek); + ret->m.initialize_result_set_rest = MYSQLND_METHOD(mysqlnd_result_buffered_zval, initialize_result_set_rest); + DBG_RETURN(ret); +} +/* }}} */ + + +/* {{{ mysqlnd_result_buffered_c_init */ +PHPAPI MYSQLND_RES_BUFFERED_C * +mysqlnd_result_buffered_c_init(unsigned int field_count, zend_bool ps, zend_bool persistent TSRMLS_DC) { - size_t alloc_size = sizeof(MYSQLND_RES_BUFFERED) + mysqlnd_plugin_count() * sizeof(void *); - MYSQLND_RES_BUFFERED * ret = mnd_pecalloc(1, alloc_size, persistent); + size_t alloc_size = sizeof(MYSQLND_RES_BUFFERED_C) + mysqlnd_plugin_count() * sizeof(void *); + MYSQLND_RES_BUFFERED_C * ret = mnd_pecalloc(1, alloc_size, persistent); - DBG_ENTER("mysqlnd_result_buffered_init"); + DBG_ENTER("mysqlnd_result_buffered_c_init"); if (!ret) { DBG_RETURN(NULL); @@ -1812,13 +2123,18 @@ mysqlnd_result_buffered_init(unsigned int field_count, zend_bool ps, zend_bool p ret->field_count= field_count; ret->ps = ps; ret->m = *mysqlnd_result_buffered_get_methods(); + ret->type = MYSQLND_BUFFERED_TYPE_C; if (ps) { ret->m.fetch_lengths = NULL; /* makes no sense */ ret->m.row_decoder = php_mysqlnd_rowp_read_binary_protocol; } else { - ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol; + ret->m.row_decoder = php_mysqlnd_rowp_read_text_protocol_c; } + ret->m.fetch_row = MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row); + ret->m.fetch_lengths = MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_lengths); + ret->m.data_seek = MYSQLND_METHOD(mysqlnd_result_buffered_c, data_seek); + ret->m.initialize_result_set_rest = MYSQLND_METHOD(mysqlnd_result_buffered_c, initialize_result_set_rest); DBG_RETURN(ret); } -- cgit v1.2.1 From e6e5d3535dc767cadd9d962e41dd837bd58a2ad3 Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Mon, 19 May 2014 20:32:41 +0300 Subject: remove mysqlnd_bt.c as it a long dead code --- ext/mysqlnd/mysqlnd_result.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 0112a1394d..68eabf7368 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -630,8 +630,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 +647,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); -- cgit v1.2.1 From 6288bb8ffefe9cf9648b8d2190729c087b5c2586 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Tue, 17 Jun 2014 17:50:54 +0800 Subject: Refactoring mysqlnd (incompleted, only mysqlnd ext compilable) --- ext/mysqlnd/mysqlnd_result.c | 157 ++++++++++++++++++++----------------------- 1 file changed, 73 insertions(+), 84 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') 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; -- cgit v1.2.1 From 83d450c78de128da32048ef369d9769fa73be9da Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 18 Jun 2014 14:42:46 +0800 Subject: Fixed segfault of stream handling --- ext/mysqlnd/mysqlnd_result.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index a8ae8be92b..26551ecd69 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -1800,7 +1800,6 @@ 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. */ - 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"); @@ -1868,7 +1867,6 @@ 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 :) */ - ZVAL_NEW_ARR(return_value); array_init_size(return_value, set? (unsigned int) set->row_count : 4); do { -- cgit v1.2.1 From d5c6816e865329e9baedca12eaf0427d6812e2fa Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 18 Jun 2014 16:10:51 +0800 Subject: Fixed memory leak while doing fetch --- ext/mysqlnd/mysqlnd_result.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 26551ecd69..6eaeb063e4 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -1182,8 +1182,8 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, vo set->lengths[i] = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data); if (flags & MYSQLND_FETCH_NUM) { - Z_TRY_ADDREF_P(data); zend_hash_next_index_insert(Z_ARRVAL_P(row), data); + ZVAL_NULL(data); } if (flags & MYSQLND_FETCH_ASSOC) { /* zend_hash_quick_update needs length + trailing zero */ @@ -1193,13 +1193,14 @@ 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_TRY_ADDREF_P(data); if (meta->zend_hash_keys[i].is_numeric == FALSE) { 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, data); } + ZVAL_NULL(data); } + zval_ptr_dtor(data); } set->data_cursor += field_count; MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF); -- cgit v1.2.1 From b38f6f3de96990163d36c82c248fb29e6f0815c4 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 18 Jun 2014 23:13:30 +0800 Subject: Fixed various bugs (ext/mysql with mysqlnd tests pass) --- ext/mysqlnd/mysqlnd_result.c | 36 +++++++----------------------------- 1 file changed, 7 insertions(+), 29 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 6eaeb063e4..fb8bc4b3d2 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -143,6 +143,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, initialize_result_set_rest)(MYSQLND_RE /* }}} */ +#if 0 /* {{{ 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) @@ -188,6 +189,7 @@ mysqlnd_rset_zval_ptr_dtor(zval *zv, enum_mysqlnd_res_type type, zend_bool * cop DBG_VOID_RETURN; } /* }}} */ +#endif /* {{{ mysqlnd_result_unbuffered::free_last_data */ @@ -203,22 +205,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; - 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, ©_ctor_called TSRMLS_CC); - if (copy_ctor_called) { - ++ctor_called_count; - } + //???mysqlnd_rset_zval_ptr_dtor(&(unbuf->last_row_data[i]), unbuf->ps ? MYSQLND_RES_PS_UNBUF : MYSQLND_RES_NORMAL, ©_ctor_called TSRMLS_CC); + 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; @@ -275,8 +266,6 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, free_result)(MYSQLND_RES_BUFFERED_Z 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; @@ -286,20 +275,10 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, free_result)(MYSQLND_RES_BUFFERED_Z if (current_row != NULL) { for (col = field_count - 1; col >= 0; --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) { - ++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; @@ -1182,8 +1161,8 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, vo set->lengths[i] = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data); if (flags & MYSQLND_FETCH_NUM) { + Z_TRY_ADDREF_P(data); zend_hash_next_index_insert(Z_ARRVAL_P(row), data); - ZVAL_NULL(data); } if (flags & MYSQLND_FETCH_ASSOC) { /* zend_hash_quick_update needs length + trailing zero */ @@ -1193,14 +1172,13 @@ 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_TRY_ADDREF_P(data); if (meta->zend_hash_keys[i].is_numeric == FALSE) { 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, data); } - ZVAL_NULL(data); } - zval_ptr_dtor(data); } set->data_cursor += field_count; MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF); -- cgit v1.2.1 From 27e8e11ff97e9932957b8fd47ddc059f7f08acde Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Thu, 19 Jun 2014 10:46:23 +0800 Subject: unused variables --- ext/mysqlnd/mysqlnd_result.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index fb8bc4b3d2..20b4514199 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -204,7 +204,7 @@ 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; + 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, ©_ctor_called TSRMLS_CC); zval_ptr_dtor(&(unbuf->last_row_data[i])); -- cgit v1.2.1 From ffaf8beda769f5353e3991947884aac0cfd64f43 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Thu, 19 Jun 2014 14:43:14 +0800 Subject: Fixed segfault --- ext/mysqlnd/mysqlnd_result.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 20b4514199..8720b6a496 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -787,7 +787,7 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi 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); + 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) { @@ -905,7 +905,7 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void 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); + unsigned int len = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0; if (flags & MYSQLND_FETCH_NUM) { Z_TRY_ADDREF_P(data); @@ -1070,7 +1070,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void for (i = 0; i < field_count; i++) { zval * data = ¤t_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); @@ -1158,7 +1158,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, vo for (i = 0; i < field_count; i++) { zval * data = ¤t_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_TRY_ADDREF_P(data); @@ -1254,7 +1254,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void for (i = 0; i < field_count; i++) { zval * data = ¤t_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_TRY_ADDREF_P(data); -- cgit v1.2.1 From 92a708989380bfb5d5da00665895025398bdbc91 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 23 Jun 2014 19:12:15 +0800 Subject: Use zend_string in mysqlnd --- ext/mysqlnd/mysqlnd_result.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 8720b6a496..c8313712ba 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -921,7 +921,7 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void */ Z_TRY_ADDREF_P(data); if (meta->zend_hash_keys[i].is_numeric == FALSE) { - zend_hash_str_update(Z_ARRVAL_P(row), meta->fields[i].name, meta->fields[i].name_length, data); + zend_hash_update(Z_ARRVAL_P(row), meta->fields[i].name, data); } else { zend_hash_index_update(Z_ARRVAL_P(row), meta->zend_hash_keys[i].key, data); } @@ -1174,7 +1174,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, vo */ Z_TRY_ADDREF_P(data); if (meta->zend_hash_keys[i].is_numeric == FALSE) { - zend_hash_str_update(Z_ARRVAL_P(row), meta->fields[i].name, meta->fields[i].name_length, data); + zend_hash_update(Z_ARRVAL_P(row), meta->fields[i].name, data); } else { zend_hash_index_update(Z_ARRVAL_P(row), meta->zend_hash_keys[i].key, data); } @@ -1270,7 +1270,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void */ Z_TRY_ADDREF_P(data); if (meta->zend_hash_keys[i].is_numeric == FALSE) { - zend_hash_str_update(Z_ARRVAL_P(row), meta->fields[i].name, meta->fields[i].name_length, data); + zend_hash_update(Z_ARRVAL_P(row), meta->fields[i].name, data); } else { zend_hash_index_update(Z_ARRVAL_P(row), meta->zend_hash_keys[i].key, data); } -- cgit v1.2.1 From 587923ccc837fc22901f3114631bcc3b1b384fcd Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Mon, 23 Jun 2014 23:01:35 +0800 Subject: Cleanup (refactoring is finish) --- ext/mysqlnd/mysqlnd_result.c | 56 -------------------------------------------- 1 file changed, 56 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index c8313712ba..bc2bbd5df9 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -70,7 +70,6 @@ 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) { if (Z_TYPE(data_cursor[i]) == IS_STRING) { unsigned long len = Z_STRLEN(data_cursor[i]); if (meta->fields[i].max_length < len) { @@ -126,7 +125,6 @@ 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(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) { @@ -143,55 +141,6 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, initialize_result_set_rest)(MYSQLND_RE /* }}} */ -#if 0 -/* {{{ 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) { - *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_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_P(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_P(zv) == IS_STRING) { - ZVAL_NULL(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; -} -/* }}} */ -#endif - - /* {{{ 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) @@ -206,7 +155,6 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, free_last_data)(MYSQLND_RES_UNBUFFERED if (unbuf->last_row_data) { 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, ©_ctor_called TSRMLS_CC); zval_ptr_dtor(&(unbuf->last_row_data[i])); } @@ -1053,7 +1001,6 @@ 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(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) { @@ -1145,7 +1092,6 @@ 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) { if (Z_TYPE(current_row[i]) == IS_STRING) { unsigned long len = Z_STRLEN(current_row[i]); if (meta->fields[i].max_length < len) { @@ -1241,7 +1187,6 @@ 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(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) { @@ -1886,7 +1831,6 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field_data)(MYSQLND_RES * result, unsigned int zend_hash_internal_pointer_reset(Z_ARRVAL(row)); while (i++ < offset) { zend_hash_move_forward(Z_ARRVAL(row)); - //???entry = zend_hash_get_current_data(Z_ARRVAL(row)); } entry = zend_hash_get_current_data(Z_ARRVAL(row)); -- cgit v1.2.1 From 8ce23d8f4fc5df0daec05642df8ead016f00fc32 Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 25 Jun 2014 00:42:20 +0800 Subject: Don't use zend_string for other fields (only name here is enough) --- ext/mysqlnd/mysqlnd_result.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index bc2bbd5df9..a8d1a56530 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -869,7 +869,7 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void */ Z_TRY_ADDREF_P(data); if (meta->zend_hash_keys[i].is_numeric == FALSE) { - zend_hash_update(Z_ARRVAL_P(row), meta->fields[i].name, data); + 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, data); } @@ -1120,7 +1120,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, vo */ Z_TRY_ADDREF_P(data); if (meta->zend_hash_keys[i].is_numeric == FALSE) { - zend_hash_update(Z_ARRVAL_P(row), meta->fields[i].name, data); + 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, data); } @@ -1215,7 +1215,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void */ Z_TRY_ADDREF_P(data); if (meta->zend_hash_keys[i].is_numeric == FALSE) { - zend_hash_update(Z_ARRVAL_P(row), meta->fields[i].name, data); + 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, data); } -- cgit v1.2.1 From 3f42f2f5d1c8026b6e1d21b91857a08d918c28c8 Mon Sep 17 00:00:00 2001 From: Veres Lajos Date: Tue, 12 Aug 2014 22:00:23 +0100 Subject: typofixes --- ext/mysqlnd/mysqlnd_result.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 0814926483..bb4dc09c7b 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -1182,7 +1182,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c No need to FREE_ALLOCA as we can reuse the 'lengths' and 'fields' arrays. For lengths its absolutely safe. 'fields' is reused because the ownership of the strings has been - transfered above. + transferred above. */ } /* Overflow ? */ -- cgit v1.2.1 From 63d3f0b844b3a5f1c94be3c97bca29235dc2b3fc Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 19 Aug 2014 08:07:31 +0200 Subject: basic macro replacements, all at once --- ext/mysqlnd/mysqlnd_result.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 0641d504c6..8fb89fddf8 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -71,7 +71,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, initialize_result_set_rest)(MYSQLND Thus for NULL and zero-length we are quite efficient. */ if (Z_TYPE(data_cursor[i]) == IS_STRING) { - unsigned long len = Z_STRLEN(data_cursor[i]); + unsigned long len = Z_STRSIZE(data_cursor[i]); if (meta->fields[i].max_length < len) { meta->fields[i].max_length = len; } @@ -126,7 +126,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, initialize_result_set_rest)(MYSQLND_RE Thus for NULL and zero-length we are quite efficient. */ if (Z_TYPE(current_row[i]) == IS_STRING) { - unsigned long len = Z_STRLEN(current_row[i]); + unsigned long len = Z_STRSIZE(current_row[i]); if (meta->fields[i].max_length < len) { meta->fields[i].max_length = len; } @@ -735,7 +735,7 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi for (i = 0; i < field_count; i++, field++) { zval * data = &result->unbuf->last_row_data[i]; - unsigned int len = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0; + unsigned int len = (Z_TYPE_P(data) == IS_STRING)? Z_STRSIZE_P(data) : 0; /* BEGIN difference between normal normal fetch and _c */ if (Z_TYPE_P(data) != IS_NULL) { @@ -853,7 +853,7 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void for (i = 0; i < field_count; i++, field++) { zval * data = &result->unbuf->last_row_data[i]; - unsigned int len = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0; + unsigned int len = (Z_TYPE_P(data) == IS_STRING)? Z_STRSIZE_P(data) : 0; if (flags & MYSQLND_FETCH_NUM) { Z_TRY_ADDREF_P(data); @@ -1002,7 +1002,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void Thus for NULL and zero-length we are quite efficient. */ if (Z_TYPE(current_row[i]) == IS_STRING) { - unsigned long len = Z_STRLEN(current_row[i]); + unsigned long len = Z_STRSIZE(current_row[i]); if (meta->fields[i].max_length < len) { meta->fields[i].max_length = len; } @@ -1017,7 +1017,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void for (i = 0; i < field_count; i++) { zval * data = ¤t_row[i]; - set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0; + set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRSIZE_P(data) : 0; if (Z_TYPE_P(data) != IS_NULL) { convert_to_string(data); @@ -1093,7 +1093,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, vo Thus for NULL and zero-length we are quite efficient. */ if (Z_TYPE(current_row[i]) == IS_STRING) { - unsigned long len = Z_STRLEN(current_row[i]); + unsigned long len = Z_STRSIZE(current_row[i]); if (meta->fields[i].max_length < len) { meta->fields[i].max_length = len; } @@ -1104,7 +1104,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, vo for (i = 0; i < field_count; i++) { zval * data = ¤t_row[i]; - set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0; + set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRSIZE_P(data) : 0; if (flags & MYSQLND_FETCH_NUM) { Z_TRY_ADDREF_P(data); @@ -1188,7 +1188,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void Thus for NULL and zero-length we are quite efficient. */ if (Z_TYPE(current_row[i]) == IS_STRING) { - unsigned long len = Z_STRLEN(current_row[i]); + unsigned long len = Z_STRSIZE(current_row[i]); if (meta->fields[i].max_length < len) { meta->fields[i].max_length = len; } @@ -1199,7 +1199,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void for (i = 0; i < field_count; i++) { zval * data = ¤t_row[i]; - set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0; + set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRSIZE_P(data) : 0; if (flags & MYSQLND_FETCH_NUM) { Z_TRY_ADDREF_P(data); -- cgit v1.2.1 From bdbf47df181bdafc1b2bc2df1d23815f01510b88 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 19 Aug 2014 16:51:06 +0200 Subject: ported mysql and mysqlnd --- ext/mysqlnd/mysqlnd_result.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 8fb89fddf8..00611079c1 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -71,7 +71,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, initialize_result_set_rest)(MYSQLND Thus for NULL and zero-length we are quite efficient. */ if (Z_TYPE(data_cursor[i]) == IS_STRING) { - unsigned long len = Z_STRSIZE(data_cursor[i]); + php_uint_t len = Z_STRSIZE(data_cursor[i]); if (meta->fields[i].max_length < len) { meta->fields[i].max_length = len; } @@ -126,7 +126,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, initialize_result_set_rest)(MYSQLND_RE Thus for NULL and zero-length we are quite efficient. */ if (Z_TYPE(current_row[i]) == IS_STRING) { - unsigned long len = Z_STRSIZE(current_row[i]); + php_uint_t len = Z_STRSIZE(current_row[i]); if (meta->fields[i].max_length < len) { meta->fields[i].max_length = len; } @@ -599,7 +599,7 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s of PHP, to be called as separate function. But let's have it for completeness. */ -static unsigned long * +static php_uint_t * MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_lengths)(MYSQLND_RES_BUFFERED * const result TSRMLS_DC) { const MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result; @@ -631,7 +631,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_lengths)(MYSQLND_RES_BUFFERED of PHP, to be called as separate function. But let's have it for completeness. */ -static unsigned long * +static php_uint_t * MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_lengths)(MYSQLND_RES_BUFFERED * const result TSRMLS_DC) { const MYSQLND_RES_BUFFERED_C * set = (MYSQLND_RES_BUFFERED_C *) result; @@ -648,7 +648,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_lengths)(MYSQLND_RES_BUFFERED * /* {{{ mysqlnd_result_unbuffered::fetch_lengths */ -static unsigned long * +static php_uint_t * MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_lengths)(MYSQLND_RES_UNBUFFERED * const result TSRMLS_DC) { /* simulate output of libmysql */ @@ -658,10 +658,10 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_lengths)(MYSQLND_RES_UNBUFFERED /* {{{ mysqlnd_res::fetch_lengths */ -static unsigned long * +static php_uint_t * MYSQLND_METHOD(mysqlnd_res, fetch_lengths)(MYSQLND_RES * const result TSRMLS_DC) { - unsigned long * ret; + php_uint_t * ret; DBG_ENTER("mysqlnd_res::fetch_lengths"); ret = result->stored_data && result->stored_data->m.fetch_lengths ? result->stored_data->m.fetch_lengths(result->stored_data TSRMLS_CC) : @@ -731,7 +731,7 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi *row = mnd_malloc(field_count * sizeof(char *)); if (*row) { MYSQLND_FIELD * field = meta->fields; - unsigned long * lengths = result->unbuf->lengths; + php_uint_t * lengths = result->unbuf->lengths; for (i = 0; i < field_count; i++, field++) { zval * data = &result->unbuf->last_row_data[i]; @@ -849,7 +849,7 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void { HashTable * row_ht = Z_ARRVAL_P(row); MYSQLND_FIELD * field = meta->fields; - unsigned long * lengths = result->unbuf->lengths; + php_uint_t * lengths = result->unbuf->lengths; for (i = 0; i < field_count; i++, field++) { zval * data = &result->unbuf->last_row_data[i]; @@ -1002,7 +1002,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void Thus for NULL and zero-length we are quite efficient. */ if (Z_TYPE(current_row[i]) == IS_STRING) { - unsigned long len = Z_STRSIZE(current_row[i]); + php_uint_t len = Z_STRSIZE(current_row[i]); if (meta->fields[i].max_length < len) { meta->fields[i].max_length = len; } @@ -1093,7 +1093,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, vo Thus for NULL and zero-length we are quite efficient. */ if (Z_TYPE(current_row[i]) == IS_STRING) { - unsigned long len = Z_STRSIZE(current_row[i]); + php_uint_t len = Z_STRSIZE(current_row[i]); if (meta->fields[i].max_length < len) { meta->fields[i].max_length = len; } @@ -1188,7 +1188,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void Thus for NULL and zero-length we are quite efficient. */ if (Z_TYPE(current_row[i]) == IS_STRING) { - unsigned long len = Z_STRSIZE(current_row[i]); + php_uint_t len = Z_STRSIZE(current_row[i]); if (meta->fields[i].max_length < len) { meta->fields[i].max_length = len; } @@ -1776,7 +1776,7 @@ 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; - ulong i = 0; + php_uint_t i = 0; MYSQLND_RES_BUFFERED *set = result->stored_data; DBG_ENTER("mysqlnd_res::fetch_all"); @@ -1927,7 +1927,7 @@ mysqlnd_result_unbuffered_init(unsigned int field_count, zend_bool ps, zend_bool DBG_RETURN(NULL); } - if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(unsigned long), persistent))) { + if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(php_uint_t), persistent))) { mnd_pefree(ret, persistent); DBG_RETURN(NULL); } @@ -2010,7 +2010,7 @@ mysqlnd_result_buffered_c_init(unsigned int field_count, zend_bool ps, zend_bool if (!ret) { DBG_RETURN(NULL); } - if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(unsigned long), persistent))) { + if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(php_uint_t), persistent))) { mnd_pefree(ret, persistent); DBG_RETURN(NULL); } -- cgit v1.2.1 From eb1871b3fb63f48216f20663f0cc479d322e3970 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Thu, 21 Aug 2014 09:54:40 +0200 Subject: yet trivial fixes to mysql exts --- ext/mysqlnd/mysqlnd_result.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 00611079c1..65ad1099b6 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -1967,7 +1967,7 @@ mysqlnd_result_buffered_zval_init(unsigned int field_count, zend_bool ps, zend_b if (!ret) { DBG_RETURN(NULL); } - if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(unsigned long), persistent))) { + if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(php_uint_t), persistent))) { mnd_pefree(ret, persistent); DBG_RETURN(NULL); } -- cgit v1.2.1 From c3e3c98ec666812daaaca896cf5ef758a8a6df14 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Mon, 25 Aug 2014 19:24:55 +0200 Subject: master renames phase 1 --- ext/mysqlnd/mysqlnd_result.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 65ad1099b6..ea275be192 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -71,7 +71,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, initialize_result_set_rest)(MYSQLND Thus for NULL and zero-length we are quite efficient. */ if (Z_TYPE(data_cursor[i]) == IS_STRING) { - php_uint_t len = Z_STRSIZE(data_cursor[i]); + zend_ulong len = Z_STRLEN(data_cursor[i]); if (meta->fields[i].max_length < len) { meta->fields[i].max_length = len; } @@ -126,7 +126,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, initialize_result_set_rest)(MYSQLND_RE Thus for NULL and zero-length we are quite efficient. */ if (Z_TYPE(current_row[i]) == IS_STRING) { - php_uint_t len = Z_STRSIZE(current_row[i]); + zend_ulong len = Z_STRLEN(current_row[i]); if (meta->fields[i].max_length < len) { meta->fields[i].max_length = len; } @@ -599,7 +599,7 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s of PHP, to be called as separate function. But let's have it for completeness. */ -static php_uint_t * +static zend_ulong * MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_lengths)(MYSQLND_RES_BUFFERED * const result TSRMLS_DC) { const MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result; @@ -631,7 +631,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_lengths)(MYSQLND_RES_BUFFERED of PHP, to be called as separate function. But let's have it for completeness. */ -static php_uint_t * +static zend_ulong * MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_lengths)(MYSQLND_RES_BUFFERED * const result TSRMLS_DC) { const MYSQLND_RES_BUFFERED_C * set = (MYSQLND_RES_BUFFERED_C *) result; @@ -648,7 +648,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_lengths)(MYSQLND_RES_BUFFERED * /* {{{ mysqlnd_result_unbuffered::fetch_lengths */ -static php_uint_t * +static zend_ulong * MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_lengths)(MYSQLND_RES_UNBUFFERED * const result TSRMLS_DC) { /* simulate output of libmysql */ @@ -658,10 +658,10 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_lengths)(MYSQLND_RES_UNBUFFERED /* {{{ mysqlnd_res::fetch_lengths */ -static php_uint_t * +static zend_ulong * MYSQLND_METHOD(mysqlnd_res, fetch_lengths)(MYSQLND_RES * const result TSRMLS_DC) { - php_uint_t * ret; + zend_ulong * ret; DBG_ENTER("mysqlnd_res::fetch_lengths"); ret = result->stored_data && result->stored_data->m.fetch_lengths ? result->stored_data->m.fetch_lengths(result->stored_data TSRMLS_CC) : @@ -731,11 +731,11 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi *row = mnd_malloc(field_count * sizeof(char *)); if (*row) { MYSQLND_FIELD * field = meta->fields; - php_uint_t * lengths = result->unbuf->lengths; + zend_ulong * 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_STRING)? Z_STRSIZE_P(data) : 0; + 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) { @@ -849,11 +849,11 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void { HashTable * row_ht = Z_ARRVAL_P(row); MYSQLND_FIELD * field = meta->fields; - php_uint_t * lengths = result->unbuf->lengths; + zend_ulong * 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_STRING)? Z_STRSIZE_P(data) : 0; + unsigned int len = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0; if (flags & MYSQLND_FETCH_NUM) { Z_TRY_ADDREF_P(data); @@ -1002,7 +1002,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void Thus for NULL and zero-length we are quite efficient. */ if (Z_TYPE(current_row[i]) == IS_STRING) { - php_uint_t len = Z_STRSIZE(current_row[i]); + zend_ulong len = Z_STRLEN(current_row[i]); if (meta->fields[i].max_length < len) { meta->fields[i].max_length = len; } @@ -1017,7 +1017,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void for (i = 0; i < field_count; i++) { zval * data = ¤t_row[i]; - set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRSIZE_P(data) : 0; + 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); @@ -1093,7 +1093,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, vo Thus for NULL and zero-length we are quite efficient. */ if (Z_TYPE(current_row[i]) == IS_STRING) { - php_uint_t len = Z_STRSIZE(current_row[i]); + zend_ulong len = Z_STRLEN(current_row[i]); if (meta->fields[i].max_length < len) { meta->fields[i].max_length = len; } @@ -1104,7 +1104,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, vo for (i = 0; i < field_count; i++) { zval * data = ¤t_row[i]; - set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRSIZE_P(data) : 0; + set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0; if (flags & MYSQLND_FETCH_NUM) { Z_TRY_ADDREF_P(data); @@ -1188,7 +1188,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void Thus for NULL and zero-length we are quite efficient. */ if (Z_TYPE(current_row[i]) == IS_STRING) { - php_uint_t len = Z_STRSIZE(current_row[i]); + zend_ulong len = Z_STRLEN(current_row[i]); if (meta->fields[i].max_length < len) { meta->fields[i].max_length = len; } @@ -1199,7 +1199,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void for (i = 0; i < field_count; i++) { zval * data = ¤t_row[i]; - set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRSIZE_P(data) : 0; + set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0; if (flags & MYSQLND_FETCH_NUM) { Z_TRY_ADDREF_P(data); @@ -1776,7 +1776,7 @@ 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; - php_uint_t i = 0; + zend_ulong i = 0; MYSQLND_RES_BUFFERED *set = result->stored_data; DBG_ENTER("mysqlnd_res::fetch_all"); @@ -1927,7 +1927,7 @@ mysqlnd_result_unbuffered_init(unsigned int field_count, zend_bool ps, zend_bool DBG_RETURN(NULL); } - if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(php_uint_t), persistent))) { + if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(zend_ulong), persistent))) { mnd_pefree(ret, persistent); DBG_RETURN(NULL); } @@ -1967,7 +1967,7 @@ mysqlnd_result_buffered_zval_init(unsigned int field_count, zend_bool ps, zend_b if (!ret) { DBG_RETURN(NULL); } - if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(php_uint_t), persistent))) { + if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(zend_ulong), persistent))) { mnd_pefree(ret, persistent); DBG_RETURN(NULL); } @@ -2010,7 +2010,7 @@ mysqlnd_result_buffered_c_init(unsigned int field_count, zend_bool ps, zend_bool if (!ret) { DBG_RETURN(NULL); } - if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(php_uint_t), persistent))) { + if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(zend_ulong), persistent))) { mnd_pefree(ret, persistent); DBG_RETURN(NULL); } -- cgit v1.2.1 From d0cb715373c3fbe9dc095378ec5ed8c71f799f67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Schl=C3=BCter?= Date: Fri, 19 Sep 2014 18:33:14 +0200 Subject: s/PHP 5/PHP 7/ --- ext/mysqlnd/mysqlnd_result.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/mysqlnd/mysqlnd_result.c') diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index ea275be192..610642d8de 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -1,6 +1,6 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ | Copyright (c) 2006-2014 The PHP Group | +----------------------------------------------------------------------+ -- cgit v1.2.1