summaryrefslogtreecommitdiff
path: root/ext/mysqlnd
diff options
context:
space:
mode:
authorKeyur Govande <keyur@php.net>2015-01-07 22:50:55 +0000
committerKeyur Govande <keyur@php.net>2015-01-07 22:50:55 +0000
commit90144c0d083e9ecf390fc2a08ccb3c450d14ffab (patch)
tree8c81d140f3eeaf994cf94205e8566117e810efd1 /ext/mysqlnd
parentb0a26ab8f840ed1b48011caab3411c599f4451c5 (diff)
parent9bbd55ddc7742b74152fd9339268c3340e6a08e5 (diff)
downloadphp-git-90144c0d083e9ecf390fc2a08ccb3c450d14ffab.tar.gz
Merge branch 'PHP-5.5' into PHP-5.6
* PHP-5.5: Add NEWS Patch commit d9f85373e32 by moving the float_to_double function to a header file. Fix for bugs #68114 (Build fails on OS X due to undefined symbols) and #68657 (Reading 4 byte floats with Mysqli and libmysqlclient has rounding errors). 5.5.22 now Conflicts: configure.in main/php_version.h
Diffstat (limited to 'ext/mysqlnd')
-rw-r--r--ext/mysqlnd/config9.m431
-rw-r--r--ext/mysqlnd/mysql_float_to_double.h60
-rw-r--r--ext/mysqlnd/mysqlnd_ps_codec.c53
3 files changed, 65 insertions, 79 deletions
diff --git a/ext/mysqlnd/config9.m4 b/ext/mysqlnd/config9.m4
index 8f749cf273..0e08b977af 100644
--- a/ext/mysqlnd/config9.m4
+++ b/ext/mysqlnd/config9.m4
@@ -49,34 +49,3 @@ fi
if test "$PHP_MYSQLND" != "no" || test "$PHP_MYSQLND_ENABLED" = "yes" || test "$PHP_MYSQLI" != "no"; then
PHP_ADD_BUILD_DIR([ext/mysqlnd], 1)
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>
-#include <string.h>
-
-int main(int argc, char **argv) {
- typedef float dec32 __attribute__((mode(SD)));
- dec32 k = 99.49f;
- double d2 = (double)k;
- const char *check_str = "99.49";
- char print_str[32];
-
- snprintf(print_str, 32, "%f", d2);
- return memcmp(print_str, check_str, 5);
-}
-],[
- 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/mysql_float_to_double.h b/ext/mysqlnd/mysql_float_to_double.h
new file mode 100644
index 0000000000..2ccce7d14d
--- /dev/null
+++ b/ext/mysqlnd/mysql_float_to_double.h
@@ -0,0 +1,60 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | 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 |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Keyur Govande <kgovande@gmail.com> |
+ +----------------------------------------------------------------------+
+*/
+
+#ifndef MYSQL_FLOAT_TO_DOUBLE_H
+#define MYSQL_FLOAT_TO_DOUBLE_H
+
+#include "main/php.h"
+#include <float.h>
+#include "main/snprintf.h"
+
+#define MAX_CHAR_BUF_LEN 255
+
+#ifndef FLT_DIG
+# define FLT_DIG 6
+#endif
+
+/*
+ * Convert from a 4-byte float to a 8-byte decimal by first converting
+ * the float to a string, and then the string to a double.
+ * The decimals argument specifies the precision of the output. If decimals
+ * is less than zero, then a gcvt(3) like logic is used with the significant
+ * digits set to FLT_DIG i.e. 6.
+ */
+static inline double mysql_float_to_double(float fp4, int decimals) {
+ char num_buf[MAX_CHAR_BUF_LEN]; /* Over allocated */
+
+ if (decimals < 0) {
+ php_gcvt(fp4, FLT_DIG, '.', 'e', num_buf);
+ } else {
+ php_sprintf(num_buf, "%.*f", decimals, fp4);
+ }
+
+ return zend_strtod(num_buf, NULL);
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
+
+#endif /* MYSQL_FLOAT_TO_DOUBLE_H */
diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c
index 20334dfc72..2ddf81c211 100644
--- a/ext/mysqlnd/mysqlnd_ps_codec.c
+++ b/ext/mysqlnd/mysqlnd_ps_codec.c
@@ -24,6 +24,7 @@
#include "mysqlnd_wireprotocol.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_debug.h"
+#include "ext/mysqlnd/mysql_float_to_double.h"
#define MYSQLND_SILENT
@@ -181,56 +182,12 @@ ps_fetch_float(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_l
(*row)+= 4;
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)));
- /* volatile so the compiler will not optimize away the conversion */
- volatile dec32 d32val = fval;
-
- /* The following cast is guaranteed to do the right thing */
- dval = (double) d32val;
- }
-#elif defined(PHP_WIN32)
- {
- /* float datatype on Winows is already 4 byte but has a precision of 7 digits */
- char num_buf[2048];
- (void)_gcvt_s(num_buf, 2048, fval, field->decimals >= 31 ? 7 : field->decimals);
- dval = zend_strtod(num_buf, NULL);
- }
-#else
- {
- char num_buf[2048]; /* Over allocated */
- char *s;
-
-#ifndef FLT_DIG
-# define FLT_DIG 6
-#endif
- /* 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 ? FLT_DIG : field->decimals,
- '.',
- 'e',
- num_buf);
-
- /* And now convert back to double */
- dval = zend_strtod(s, NULL);
- }
+#ifndef NOT_FIXED_DEC
+# define NOT_FIXED_DEC 31
#endif
+ dval = mysql_float_to_double(fval, (field->decimals >= NOT_FIXED_DEC) ? -1 : field->decimals);
+
ZVAL_DOUBLE(zv, dval);
DBG_VOID_RETURN;
}