mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 20:12:31 +01:00
Bug #48537: difference of index selection between rpm binary
and .tar.gz, windows vs linux.. On Intel x86 machines index selection by the MySQL query optimizer could sometimes depend on the compiler version and optimization flags used to build the server binary. The problem was a result of a known issue with floating point calculations on x86: since internal FPU precision (80 bit) differs from precision used by programs (32-bit float or 64-bit double), the result of calculating a complex expression may depend on how FPU registers are allocated by the compiler and whether intermediate values are spilled from FPU to memory. In this particular case compiler versions and optimization flags had an effect on cost calculation when choosing the best index in best_access_path(). A possible solution to this problem which has already been implemented in mysql-trunk is to limit FPU internal precision to 64 bits. So the fix is a backport of the relevant code to 5.1 from mysql-trunk. configure.in: Configure check for fpu_control.h mysql-test/r/explain.result: Test case for bug #48537. mysql-test/t/explain.test: Test case for bug #48537. sql/mysqld.cc: Backport of the code to switch FPU on x86 to 64-bit precision.
This commit is contained in:
parent
d72a4710aa
commit
f3a8307397
4 changed files with 65 additions and 3 deletions
|
@ -838,8 +838,8 @@ AC_TYPE_SIZE_T
|
|||
AC_HEADER_DIRENT
|
||||
AC_HEADER_STDC
|
||||
AC_HEADER_SYS_WAIT
|
||||
AC_CHECK_HEADERS(fcntl.h fenv.h float.h floatingpoint.h ieeefp.h limits.h \
|
||||
memory.h pwd.h select.h \
|
||||
AC_CHECK_HEADERS(fcntl.h fenv.h float.h floatingpoint.h fpu_control.h \
|
||||
ieeefp.h limits.h memory.h pwd.h select.h \
|
||||
stdlib.h stddef.h \
|
||||
strings.h string.h synch.h sys/mman.h sys/socket.h netinet/in.h arpa/inet.h \
|
||||
sys/timeb.h sys/types.h sys/un.h sys/vadvise.h sys/wait.h term.h \
|
||||
|
|
|
@ -238,4 +238,17 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||
DROP TABLE t1, t2;
|
||||
#
|
||||
# Bug #48573: difference of index selection between rpm binary and
|
||||
# .tar.gz, windows vs linux..
|
||||
#
|
||||
CREATE TABLE t1(c1 INT, c2 INT, c4 INT, c5 INT, KEY(c2, c5), KEY(c2, c4, c5));
|
||||
INSERT INTO t1 VALUES(4, 1, 1, 1);
|
||||
INSERT INTO t1 VALUES(3, 1, 1, 1);
|
||||
INSERT INTO t1 VALUES(2, 1, 1, 1);
|
||||
INSERT INTO t1 VALUES(1, 1, 1, 1);
|
||||
EXPLAIN SELECT c1 FROM t1 WHERE c2 = 1 AND c4 = 1 AND c5 = 1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ref c2,c2_2 c2 10 const,const 3 Using where
|
||||
DROP TABLE t1;
|
||||
End of 5.1 tests.
|
||||
|
|
|
@ -213,4 +213,19 @@ EXPLAIN SELECT 1 FROM t1 WHERE a = (SELECT 1 FROM t1 t JOIN t2 WHERE b <= 1 AND
|
|||
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
--echo #
|
||||
--echo # Bug #48573: difference of index selection between rpm binary and
|
||||
--echo # .tar.gz, windows vs linux..
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1(c1 INT, c2 INT, c4 INT, c5 INT, KEY(c2, c5), KEY(c2, c4, c5));
|
||||
INSERT INTO t1 VALUES(4, 1, 1, 1);
|
||||
INSERT INTO t1 VALUES(3, 1, 1, 1);
|
||||
INSERT INTO t1 VALUES(2, 1, 1, 1);
|
||||
INSERT INTO t1 VALUES(1, 1, 1, 1);
|
||||
|
||||
EXPLAIN SELECT c1 FROM t1 WHERE c2 = 1 AND c4 = 1 AND c5 = 1;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo End of 5.1 tests.
|
||||
|
|
|
@ -183,6 +183,21 @@ typedef fp_except fp_except_t;
|
|||
/* for IRIX to use set_fpc_csr() */
|
||||
#include <sys/fpu.h>
|
||||
#endif
|
||||
#ifdef HAVE_FPU_CONTROL_H
|
||||
#include <fpu_control.h>
|
||||
#endif
|
||||
#if defined(__i386__) && !defined(HAVE_FPU_CONTROL_H)
|
||||
# define fpu_control_t unsigned int
|
||||
# define _FPU_EXTENDED 0x300
|
||||
# define _FPU_DOUBLE 0x200
|
||||
# ifdef __GNUC__
|
||||
# define _FPU_GETCW(cw) __asm__ __volatile__("fnstcw %0" : "=m" (*&cw))
|
||||
# define _FPU_SETCW(cw) __asm__ __volatile__("fldcw %0" : : "m" (*&cw))
|
||||
# else
|
||||
# define _FPU_GETCW(cw) (cw= 0)
|
||||
# define _FPU_SETCW(cw)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
inline void setup_fpu()
|
||||
{
|
||||
|
@ -204,7 +219,26 @@ inline void setup_fpu()
|
|||
/* Set FPU rounding mode to "round-to-nearest" */
|
||||
fesetround(FE_TONEAREST);
|
||||
#endif /* HAVE_FESETROUND */
|
||||
|
||||
|
||||
/*
|
||||
x86 (32-bit) requires FPU precision to be explicitly set to 64 bit
|
||||
(double precision) for portable results of floating point operations.
|
||||
However, there is no need to do so if compiler is using SSE2 for floating
|
||||
point, double values will be stored and processed in 64 bits anyway.
|
||||
*/
|
||||
#if defined(__i386__) && !defined(__SSE2_MATH__)
|
||||
#if defined(_WIN32)
|
||||
#if !defined(_WIN64)
|
||||
_control87(_PC_53, MCW_PC);
|
||||
#endif /* !_WIN64 */
|
||||
#else /* !_WIN32 */
|
||||
fpu_control_t cw;
|
||||
_FPU_GETCW(cw);
|
||||
cw= (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
|
||||
_FPU_SETCW(cw);
|
||||
#endif /* _WIN32 && */
|
||||
#endif /* __i386__ */
|
||||
|
||||
#if defined(__sgi) && defined(HAVE_SYS_FPU_H)
|
||||
/* Enable denormalized DOUBLE values support for IRIX */
|
||||
union fpc_csr n;
|
||||
|
|
Loading…
Reference in a new issue