Skip to content

Commit 3944a50

Browse files
author
Dag Wanvik
committed
Bug#31110614 INCORRECT RESULT WHEN COMPARING A FLOATING-POINT NUMBER WITH AN INTEGER
A logical error in the constant folding code for the case when a decimal (or float) constant is the left operand and the field is the right operand caused wrong result. Reviewed-by: catalin.besleage@oracle.com Change-Id: Iee10da5290f575b8f1eb089c76b29ea363b06e59
1 parent 80d57cd commit 3944a50

File tree

3 files changed

+35
-14
lines changed

3 files changed

+35
-14
lines changed

mysql-test/r/const_folding.result

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49848,3 +49848,9 @@ NULL
4984849848
SELECT * FROM t0 WHERE t0.c0 <=> 2035382037;
4984949849
c0
4985049850
DROP TABLE t0;
49851+
CREATE TABLE t0(c0 INT);
49852+
INSERT INTO t0(c0) VALUES (0);
49853+
SELECT * FROM t0 WHERE 0.9 > t0.c0;
49854+
c0
49855+
0
49856+
DROP TABLE t0;

mysql-test/t/const_folding.test

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,3 +1108,11 @@ INSERT INTO t0(c0) VALUES(NULL);
11081108
SELECT * FROM t0 WHERE NOT(t0.c0 <=> 2035382037);
11091109
SELECT * FROM t0 WHERE t0.c0 <=> 2035382037;
11101110
DROP TABLE t0;
1111+
1112+
#
1113+
# Bug#31110614 INCORRECT RESULT WHEN COMPARING A FLOATING-POINT NUMBER WITH AN INTEGER
1114+
#
1115+
CREATE TABLE t0(c0 INT);
1116+
INSERT INTO t0(c0) VALUES (0);
1117+
SELECT * FROM t0 WHERE 0.9 > t0.c0;
1118+
DROP TABLE t0;

sql/sql_const_folding.cc

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License, version 2.0,
@@ -213,6 +213,8 @@ static bool fold_or_convert_dec(THD *thd, Item **const_val,
213213
constant (at execution time). May be modified if
214214
we replace or fold the constant.
215215
@param ft the function type of the comparison
216+
@param left_has_field
217+
the field is the left operand
216218
@param[out] place the placement of the const_val relative to
217219
the range of f
218220
@param[out] discount_equal
@@ -222,6 +224,7 @@ static bool fold_or_convert_dec(THD *thd, Item **const_val,
222224
*/
223225
static bool analyze_int_field_constant(THD *thd, Item_field *f,
224226
Item **const_val, Item_func::Functype ft,
227+
bool left_has_field,
225228
Range_placement *place,
226229
bool *discount_equal) {
227230
const bool field_unsigned = f->unsigned_flag;
@@ -300,20 +303,21 @@ static bool analyze_int_field_constant(THD *thd, Item_field *f,
300303
if (d == nullptr) d = (*const_val)->val_decimal(&d_buff);
301304
if (ft == Item_func::LT_FUNC || ft == Item_func::LE_FUNC) {
302305
/*
303-
Round up the decimal to next integral value, then try to convert
304-
that to a longlong, or short circuit
306+
Round up (or down if field is the right operand) the decimal to next
307+
integral value, then try to convert that to a longlong, or short
308+
circuit
305309
*/
306-
if (round_fold_or_convert_dec(thd, const_val, place, f, d, true,
307-
discount_equal))
310+
if (round_fold_or_convert_dec(thd, const_val, place, f, d,
311+
left_has_field, discount_equal))
308312
return true;
309313
if (*place != RP_INSIDE) return false;
310314
} else if (ft == Item_func::GT_FUNC || ft == Item_func::GE_FUNC) {
311315
/*
312-
Round down the decimal to next integral value, then try to convert
313-
that to a longlong
316+
Round down (or up) the decimal to next integral value, then try to
317+
convert that to a longlong
314318
*/
315-
if (round_fold_or_convert_dec(thd, const_val, place, f, d, false,
316-
discount_equal))
319+
if (round_fold_or_convert_dec(thd, const_val, place, f, d,
320+
!left_has_field, discount_equal))
317321
return true;
318322
if (*place != RP_INSIDE) return false;
319323
} else { // for =, <>
@@ -972,6 +976,8 @@ static bool analyze_time_field_constant(THD *thd, Item **const_val) {
972976
constant (at execution time). May be modified if
973977
we replace or fold the constant.
974978
@param func the function of the comparison
979+
@param left_has_field
980+
the field is the left operand
975981
@param[out] place the placement of the const_val relative to
976982
the range of f
977983
@param[out] discount_equal
@@ -981,8 +987,9 @@ static bool analyze_time_field_constant(THD *thd, Item **const_val) {
981987
@returns true on error
982988
*/
983989
static bool analyze_field_constant(THD *thd, Item_field *f, Item **const_val,
984-
Item_func *func, Range_placement *place,
985-
bool *discount_equal, bool *negative) {
990+
Item_func *func, bool left_has_field,
991+
Range_placement *place, bool *discount_equal,
992+
bool *negative) {
986993
*place = RP_INSIDE; // a priori
987994

988995
if ((*const_val)->is_null()) return false;
@@ -995,8 +1002,8 @@ static bool analyze_field_constant(THD *thd, Item_field *f, Item **const_val,
9951002
case MYSQL_TYPE_INT24:
9961003
case MYSQL_TYPE_LONG:
9971004
case MYSQL_TYPE_LONGLONG:
998-
return analyze_int_field_constant(thd, f, const_val, ft, place,
999-
discount_equal);
1005+
return analyze_int_field_constant(thd, f, const_val, ft, left_has_field,
1006+
place, discount_equal);
10001007
case MYSQL_TYPE_NEWDECIMAL:
10011008
return analyze_decimal_field_constant(thd, f, const_val, ft, place,
10021009
negative);
@@ -1369,7 +1376,7 @@ bool fold_condition(THD *thd, Item *cond, Item **retcond,
13691376

13701377
if (analyze_field_constant(
13711378
thd, down_cast<Item_field *>(args[!left_has_field]->real_item()), c,
1372-
func, &place, &discount_eq, &negative))
1379+
func, left_has_field, &place, &discount_eq, &negative))
13731380
return true; /* purecov: inspected */
13741381

13751382
if (discount_eq &&

0 commit comments

Comments
 (0)