Fix a bug with mysqlnd_fetch_field(_direct()). With mysqlnd the optimised

function was called, which however, doesn't respect that during store the
raw data is not unpacked, to be lazy. The data is unpacked to zvals later,
during every row fetch. However, this way max_length won't be calculated
correctly. So, if a mysqlnd_fetch_field(_direct) call comes we need to
unpack everything and then calculate max_length...and that is expensive,
defies our lazy unpacking optimisation.
This commit is contained in:
Andrey Hristov 2009-05-28 11:47:15 +00:00
parent 7d2383061c
commit c90b10a290
3 changed files with 23 additions and 3 deletions

View File

@ -158,8 +158,8 @@ PHPAPI enum_func_status _mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQ
#define mysqlnd_field_seek(result, ofs) (result)->m.seek_field((result), (ofs))
#define mysqlnd_field_tell(result) ((result)->meta? (result)->meta->current_field:0)
#define mysqlnd_fetch_field(result) (result)->m.fetch_field((result) TSRMLS_CC)
#define mysqlnd_fetch_field_direct(result,fnr) ((result)->meta? &((result)->meta->fields[(fnr)]):NULL)
#define mysqlnd_fetch_fields(result) ((result)->meta? (result)->meta->fields: NULL)
#define mysqlnd_fetch_field_direct(result,fnr) (result)->m.fetch_field_direct((result), (fnr) TSRMLS_CC)
#define mysqlnd_fetch_fields(result) (result)->m.fetch_fields((result) TSRMLS_CC)
/* mysqlnd metadata */
#define mysqlnd_get_client_info() MYSQLND_VERSION

View File

@ -815,7 +815,7 @@ void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQL
if (persistent == FALSE) {
DBG_INF_FMT("after : %lu", zend_memory_usage(persistent TSRMLS_CC));
}
MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_EREALLOC_COUNT:STAT_MEM_REALLOC_COUNT);
MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_REALLOC_COUNT:STAT_MEM_EREALLOC_COUNT);
if (MYSQLND_G(collect_memory_statistics)) {
enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_REALLOC_COUNT:STAT_MEM_EREALLOC_COUNT;
enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_REALLOC_AMMOUNT:STAT_MEM_EREALLOC_AMMOUNT;

View File

@ -1736,6 +1736,16 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field)(MYSQLND_RES * const result TSRMLS_DC)
{
DBG_ENTER("mysqlnd_res::fetch_field");
if (result->meta) {
/*
We optimize the result set, so we don't convert all the data from raw buffer format to
zval arrays during store. In the case someone doesn't read all the lines this will
save time. However, when a metadata call is done, we need to calculate max_length.
We don't have control whether max_length will be used, unfortunately. Otherwise we
could have been able to skip that step.
Well, if the mysqli API switches from returning stdClass to class like mysqli_field_metadata,
then we can have max_length as dynamic property, which will be calculated during runtime and
not during mysqli_fetch_field() time.
*/
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 */
mysqlnd_res_initialize_result_set_rest(result TSRMLS_CC);
@ -1754,6 +1764,16 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field_direct)(MYSQLND_RES * const result,
{
DBG_ENTER("mysqlnd_res::fetch_field_direct");
if (result->meta) {
/*
We optimize the result set, so we don't convert all the data from raw buffer format to
zval arrays during store. In the case someone doesn't read all the lines this will
save time. However, when a metadata call is done, we need to calculate max_length.
We don't have control whether max_length will be used, unfortunately. Otherwise we
could have been able to skip that step.
Well, if the mysqli API switches from returning stdClass to class like mysqli_field_metadata,
then we can have max_length as dynamic property, which will be calculated during runtime and
not during mysqli_fetch_field_direct() time.
*/
if (result->stored_data && (result->stored_data->initialized_rows < result->stored_data->row_count)) {
/* we have to initialized the rest to get the updated max length */
mysqlnd_res_initialize_result_set_rest(result TSRMLS_CC);