diff options
author | Xinchen Hui <laruence@php.net> | 2015-03-25 13:05:08 +0800 |
---|---|---|
committer | Xinchen Hui <laruence@php.net> | 2015-03-25 13:05:08 +0800 |
commit | fe0ca2745f00940a27bfc8e87db534541a19af70 (patch) | |
tree | 9f6ecb6d7dd517f46f71bfc12cdeebd17f8fc904 /ext/mysqlnd | |
parent | ef2db26c60537e84b502608ff404263d5f4dc5d2 (diff) | |
parent | 968fbc6acf0bc27be17c0209be7f966e89a55943 (diff) | |
download | php-git-fe0ca2745f00940a27bfc8e87db534541a19af70.tar.gz |
Merge branch 'PHP-5.4' of https://git.php.net/repository/php-src into PHP-5.4
Diffstat (limited to 'ext/mysqlnd')
-rw-r--r-- | ext/mysqlnd/config9.m4 | 26 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_ps.c | 51 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_ps_codec.c | 49 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_result.c | 4 |
4 files changed, 107 insertions, 23 deletions
diff --git a/ext/mysqlnd/config9.m4 b/ext/mysqlnd/config9.m4 index 2c15c34e8d..d730ba7e71 100644 --- a/ext/mysqlnd/config9.m4 +++ b/ext/mysqlnd/config9.m4 @@ -51,3 +51,29 @@ if test "$PHP_MYSQLND" != "no" || test "$PHP_MYSQLND_ENABLED" = "yes" || test "$ #endif ]) fi + +dnl +dnl Check if the compiler supports Decimal32/64/128 types from the IEEE-754 2008 version +dnl References: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1657.pdf +dnl http://speleotrove.com/decimal/ +dnl +AC_CACHE_CHECK([whether whether compiler supports Decimal32/64/128 types], ac_cv_decimal_fp_supported,[ +AC_TRY_RUN( [ +#include <stdio.h> + +int main(int argc, char **argv) { + typedef float dec32 __attribute__((mode(SD))); + dec32 k = 99.49f; + double d2 = (double)k; + return 0; +} +],[ + ac_cv_decimal_fp_supported=yes +],[ + ac_cv_decimal_fp_supported=no +],[ + ac_cv_decimal_fp_supported=no +])]) +if test "$ac_cv_decimal_fp_supported" = "yes"; then + AC_DEFINE(HAVE_DECIMAL_FP_SUPPORT, 1, [Define if the compiler supports Decimal32/64/128 types.]) +fi diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c index 23a0f8a687..bdc46bdb06 100644 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@ -50,6 +50,7 @@ enum_func_status mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, static void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const stmt TSRMLS_DC); static void mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const stmt, unsigned int param_no TSRMLS_DC); +static void MYSQLND_METHOD(mysqlnd_stmt, free_stmt_result)(MYSQLND_STMT * const s TSRMLS_DC); /* {{{ mysqlnd_stmt::store_result */ static MYSQLND_RES * @@ -226,7 +227,7 @@ MYSQLND_METHOD(mysqlnd_stmt, next_result)(MYSQLND_STMT * s TSRMLS_DC) DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status->server_status, stmt->upsert_status->server_status & SERVER_STATUS_CURSOR_EXISTS); /* Free space for next result */ - s->m->free_stmt_content(s TSRMLS_CC); + MYSQLND_METHOD(mysqlnd_stmt, free_stmt_result)(s TSRMLS_CC); { enum_func_status ret = s->m->parse_execute_response(s TSRMLS_CC); DBG_RETURN(ret); @@ -2076,6 +2077,37 @@ mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const s, unsigned int param /* }}} */ +/* {{{ mysqlnd_stmt::free_stmt_result */ +static void +MYSQLND_METHOD(mysqlnd_stmt, free_stmt_result)(MYSQLND_STMT * const s TSRMLS_DC) +{ + MYSQLND_STMT_DATA * stmt = s? s->data:NULL; + DBG_ENTER("mysqlnd_stmt::free_stmt_result"); + if (!stmt) { + DBG_VOID_RETURN; + } + + /* + First separate the bound variables, which point to the result set, then + destroy the set. + */ + mysqlnd_stmt_separate_result_bind(s TSRMLS_CC); + /* Not every statement has a result set attached */ + if (stmt->result) { + stmt->result->m.free_result_internal(stmt->result TSRMLS_CC); + stmt->result = NULL; + } + if (stmt->error_info->error_list) { + zend_llist_clean(stmt->error_info->error_list); + mnd_pefree(stmt->error_info->error_list, s->persistent); + stmt->error_info->error_list = NULL; + } + + DBG_VOID_RETURN; +} +/* }}} */ + + /* {{{ mysqlnd_stmt::free_stmt_content */ static void MYSQLND_METHOD(mysqlnd_stmt, free_stmt_content)(MYSQLND_STMT * const s TSRMLS_DC) @@ -2108,22 +2140,7 @@ MYSQLND_METHOD(mysqlnd_stmt, free_stmt_content)(MYSQLND_STMT * const s TSRMLS_DC stmt->param_bind = NULL; } - /* - First separate the bound variables, which point to the result set, then - destroy the set. - */ - mysqlnd_stmt_separate_result_bind(s TSRMLS_CC); - /* Not every statement has a result set attached */ - if (stmt->result) { - stmt->result->m.free_result_internal(stmt->result TSRMLS_CC); - stmt->result = NULL; - } - if (stmt->error_info->error_list) { - zend_llist_clean(stmt->error_info->error_list); - mnd_pefree(stmt->error_info->error_list, s->persistent); - stmt->error_info->error_list = NULL; - } - + MYSQLND_METHOD(mysqlnd_stmt, free_stmt_result)(s TSRMLS_CC); DBG_VOID_RETURN; } /* }}} */ diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index e2640c775b..3f7d31002f 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -195,12 +195,53 @@ void ps_fetch_float(zval *zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar **row, zend_bool as_unicode TSRMLS_DC) { - float value; + float fval; + double dval; DBG_ENTER("ps_fetch_float"); - float4get(value, *row); - ZVAL_DOUBLE(zv, value); + float4get(fval, *row); (*row)+= 4; - DBG_INF_FMT("value=%f", value); + DBG_INF_FMT("value=%f", fval); + + /* + * The following is needed to correctly support 4-byte floats. + * Otherwise, a value of 9.99 in a FLOAT column comes out of mysqli + * as 9.9998998641968. + * + * For GCC, we use the built-in decimal support to "up-convert" a + * 4-byte float to a 8-byte double. + * When that is not available, we fall back to converting the float + * to a string and then converting the string to a double. This mimics + * what MySQL does. + */ +#ifdef HAVE_DECIMAL_FP_SUPPORT + { + typedef float dec32 __attribute__((mode(SD))); + dec32 d32val = fval; + + /* The following cast is guaranteed to do the right thing */ + dval = (double) d32val; + } +#else + { + char num_buf[2048]; /* Over allocated */ + char *s; + + /* Convert to string. Ignoring localization, etc. + * Following MySQL's rules. If precision is undefined (NOT_FIXED_DEC i.e. 31) + * or larger than 31, the value is limited to 6 (FLT_DIG). + */ + s = php_gcvt(fval, + field->decimals >= 31 ? 6 : field->decimals, + '.', + 'e', + num_buf); + + /* And now convert back to double */ + dval = zend_strtod(s, NULL); + } +#endif + + ZVAL_DOUBLE(zv, dval); DBG_VOID_RETURN; } /* }}} */ diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 0814926483..2b5b892102 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -518,7 +518,7 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s conn->current_result = NULL; } else { stmt->result = NULL; - memset(stmt, 0, sizeof(MYSQLND_STMT)); + memset(stmt, 0, sizeof(*stmt)); stmt->state = MYSQLND_STMT_INITTED; } } else { @@ -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 ? */ |