diff options
author | Keyur Govande <keyur@php.net> | 2014-08-15 23:47:06 +0000 |
---|---|---|
committer | Keyur Govande <keyur@php.net> | 2014-08-15 23:47:06 +0000 |
commit | 032dee4982f16363e648a52fa79073cb4519efa1 (patch) | |
tree | 3ca2fe6d8e934a05d5aa79405edb1eba7ea2e0f8 /ext/mysqlnd/mysqlnd_ps_codec.c | |
parent | 3e6cfeed8f4c3410bbb67c45585510654e0c7425 (diff) | |
parent | 6279246d2c60437c583f9c273075579bf17be654 (diff) | |
download | php-git-032dee4982f16363e648a52fa79073cb4519efa1.tar.gz |
Merge branch 'PHP-5.5' into PHP-5.6
* PHP-5.5:
Update NEWS
Fix another failing test
Add NEWS
Fix failing tests
Patch for bug #67839 (mysqli does not handle 4-byte floats correctly)
Conflicts:
ext/mysqli/tests/mysqli_change_user.phpt
Diffstat (limited to 'ext/mysqlnd/mysqlnd_ps_codec.c')
-rw-r--r-- | ext/mysqlnd/mysqlnd_ps_codec.c | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index d96a57721c..3ff0019c00 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; } /* }}} */ |