mirror of
https://github.com/php/php-src.git
synced 2024-09-22 02:17:32 +00:00
Merge branch 'PHP-5.5' into PHP-5.6
* PHP-5.5:
Add NEWS
Patch commit d9f85373e3
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
This commit is contained in:
commit
90144c0d08
@ -33,6 +33,7 @@
|
||||
#include "ext/standard/php_smart_str.h"
|
||||
#include "php_mysqli_structs.h"
|
||||
#include "mysqli_priv.h"
|
||||
#include "ext/mysqlnd/mysql_float_to_double.h"
|
||||
|
||||
|
||||
#if !defined(MYSQLI_USE_MYSQLND)
|
||||
@ -413,8 +414,18 @@ mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval ***args, unsigned int argc,
|
||||
col_type = (stmt->stmt->fields) ? stmt->stmt->fields[ofs].type : MYSQL_TYPE_STRING;
|
||||
|
||||
switch (col_type) {
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
case MYSQL_TYPE_FLOAT:
|
||||
convert_to_double_ex(args[i]);
|
||||
stmt->result.buf[ofs].type = IS_DOUBLE;
|
||||
stmt->result.buf[ofs].buflen = sizeof(float);
|
||||
|
||||
stmt->result.buf[ofs].val = (char *)emalloc(sizeof(float));
|
||||
bind[ofs].buffer_type = MYSQL_TYPE_FLOAT;
|
||||
bind[ofs].buffer = stmt->result.buf[ofs].val;
|
||||
bind[ofs].is_null = &stmt->result.is_null[ofs];
|
||||
break;
|
||||
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
convert_to_double_ex(args[i]);
|
||||
stmt->result.buf[ofs].type = IS_DOUBLE;
|
||||
stmt->result.buf[ofs].buflen = sizeof(double);
|
||||
@ -1053,8 +1064,22 @@ void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS)
|
||||
}
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
ZVAL_DOUBLE(stmt->result.vars[i], *(double *)stmt->result.buf[i].val);
|
||||
{
|
||||
double dval;
|
||||
if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_FLOAT) {
|
||||
#ifndef NOT_FIXED_DEC
|
||||
# define NOT_FIXED_DEC 31
|
||||
#endif
|
||||
dval = mysql_float_to_double(*(float *)stmt->result.buf[i].val,
|
||||
(stmt->stmt->fields[i].decimals >= NOT_FIXED_DEC) ? -1 :
|
||||
stmt->stmt->fields[i].decimals);
|
||||
} else {
|
||||
dval = *((double *)stmt->result.buf[i].val);
|
||||
}
|
||||
|
||||
ZVAL_DOUBLE(stmt->result.vars[i], dval);
|
||||
break;
|
||||
}
|
||||
case IS_STRING:
|
||||
if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_LONGLONG
|
||||
#if MYSQL_VERSION_ID > 50002
|
||||
|
@ -62,7 +62,7 @@ mysqli_close($link);
|
||||
--EXPECT--
|
||||
array(7) {
|
||||
[0]=>
|
||||
float(3.141593)
|
||||
float(3.14159)
|
||||
[1]=>
|
||||
float(-1.0E-6)
|
||||
[2]=>
|
||||
@ -70,10 +70,10 @@ array(7) {
|
||||
[3]=>
|
||||
float(1.0E+12)
|
||||
[4]=>
|
||||
float(0.5646425)
|
||||
float(0.564642)
|
||||
[5]=>
|
||||
float(1)
|
||||
[6]=>
|
||||
float(8.888889E+14)
|
||||
float(8.88889E+14)
|
||||
}
|
||||
done!
|
||||
|
@ -36,19 +36,27 @@ mysqli_float_handling - ensure 4 byte float is handled correctly
|
||||
die();
|
||||
}
|
||||
|
||||
if (!mysqli_stmt_execute($stmt)) {
|
||||
$id = null;
|
||||
$fp4 = null;
|
||||
$fp8 = null;
|
||||
|
||||
if (!mysqli_stmt_bind_result($stmt, $id, $fp4, $fp8)) {
|
||||
printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
|
||||
die();
|
||||
}
|
||||
|
||||
|
||||
if (!($result = mysqli_stmt_get_result($stmt))) {
|
||||
if (!mysqli_stmt_execute($stmt)) {
|
||||
printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
|
||||
die();
|
||||
}
|
||||
|
||||
$data = mysqli_fetch_assoc($result);
|
||||
print $data['id'] . ": " . $data['fp4'] . ": " . $data['fp8'] . "\n";
|
||||
|
||||
if (!(mysqli_stmt_fetch($stmt))) {
|
||||
printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
|
||||
die();
|
||||
}
|
||||
|
||||
print $id . ": " . $fp4 . ": " . $fp8 . "\n";
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
|
@ -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
|
||||
|
60
ext/mysqlnd/mysql_float_to_double.h
Normal file
60
ext/mysqlnd/mysql_float_to_double.h
Normal file
@ -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 */
|
@ -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,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 = mysql_float_to_double(fval, (field->decimals >= NOT_FIXED_DEC) ? -1 : field->decimals);
|
||||
|
||||
ZVAL_DOUBLE(zv, dval);
|
||||
DBG_VOID_RETURN;
|
||||
|
Loading…
Reference in New Issue
Block a user