mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
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). The patch removes support for Decimal floating point numbers and now defaults to using similar logic as what libmysqlclient does: convert a 4 byte floating point number into a string, and then the string into a double. The quirks of MySQL are maintained as seen in Field_Float::val_str()
This commit is contained in:
parent
3f1d1892c9
commit
f2eadb93b9
9 changed files with 140 additions and 90 deletions
|
@ -24,6 +24,7 @@
|
|||
#include "mysqlnd_wireprotocol.h"
|
||||
#include "mysqlnd_priv.h"
|
||||
#include "mysqlnd_debug.h"
|
||||
#include "ext/standard/float_to_double.h"
|
||||
|
||||
#define MYSQLND_SILENT
|
||||
|
||||
|
@ -181,55 +182,11 @@ 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
|
||||
#ifndef NOT_FIXED_DEC
|
||||
# define NOT_FIXED_DEC 31
|
||||
#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);
|
||||
}
|
||||
#endif
|
||||
dval = float_to_double(fval, (field->decimals >= NOT_FIXED_DEC) ? -1 : field->decimals);
|
||||
|
||||
ZVAL_DOUBLE(zv, dval);
|
||||
DBG_VOID_RETURN;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue