summaryrefslogtreecommitdiff
path: root/ext/mysqlnd
diff options
context:
space:
mode:
authorXinchen Hui <laruence@php.net>2015-03-25 13:05:08 +0800
committerXinchen Hui <laruence@php.net>2015-03-25 13:05:08 +0800
commitfe0ca2745f00940a27bfc8e87db534541a19af70 (patch)
tree9f6ecb6d7dd517f46f71bfc12cdeebd17f8fc904 /ext/mysqlnd
parentef2db26c60537e84b502608ff404263d5f4dc5d2 (diff)
parent968fbc6acf0bc27be17c0209be7f966e89a55943 (diff)
downloadphp-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.m426
-rw-r--r--ext/mysqlnd/mysqlnd_ps.c51
-rw-r--r--ext/mysqlnd/mysqlnd_ps_codec.c49
-rw-r--r--ext/mysqlnd/mysqlnd_result.c4
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 ? */