summaryrefslogtreecommitdiff
path: root/ext/mysqlnd
diff options
context:
space:
mode:
authorKeyur Govande <keyur@php.net>2014-08-15 23:13:36 +0000
committerKeyur Govande <keyur@php.net>2014-08-15 23:13:36 +0000
commit7c4b5d91874ea0a69f5b65c05494056aaae81e71 (patch)
treeeb121b86478dbfc7f6741e553bbf6032bc093704 /ext/mysqlnd
parent59c2477bc331370105e917db27e82d4e483ab7f0 (diff)
parent0407bdf252004cce08e383bc0f4aa0bbc69c9a25 (diff)
downloadphp-git-7c4b5d91874ea0a69f5b65c05494056aaae81e71.tar.gz
Merge branch 'PHP-5.4' into PHP-5.5
* PHP-5.4: Add NEWS Fix failing tests Patch for bug #67839 (mysqli does not handle 4-byte floats correctly) Conflicts: ext/mysqli/tests/table.inc
Diffstat (limited to 'ext/mysqlnd')
-rw-r--r--ext/mysqlnd/config9.m426
-rw-r--r--ext/mysqlnd/mysqlnd_ps_codec.c49
2 files changed, 71 insertions, 4 deletions
diff --git a/ext/mysqlnd/config9.m4 b/ext/mysqlnd/config9.m4
index 09aca5af8a..deda4414c4 100644
--- a/ext/mysqlnd/config9.m4
+++ b/ext/mysqlnd/config9.m4
@@ -61,3 +61,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_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c
index d0e44fa275..fa4ed9da6f 100644
--- a/ext/mysqlnd/mysqlnd_ps_codec.c
+++ b/ext/mysqlnd/mysqlnd_ps_codec.c
@@ -174,12 +174,53 @@ ps_fetch_int64(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_l
static void
ps_fetch_float(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row 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;
}
/* }}} */