Skip to content

Commit e7dcec5

Browse files
author
Alexander Barkov
committed
MDEV-8703 Wrong result for SELECT..WHERE LENGTH(decimal_10_1_column)!=3 AND decimal_10_1_column=1.10
1 parent 0736cdd commit e7dcec5

File tree

4 files changed

+180
-23
lines changed

4 files changed

+180
-23
lines changed

mysql-test/r/type_newdecimal.result

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2078,3 +2078,72 @@ DROP TABLE t1,t2;
20782078
#
20792079
# End of 10.0 tests
20802080
#
2081+
#
2082+
# Start of 10.1 tests
2083+
#
2084+
#
2085+
# MDEV-8703 Wrong result for SELECT..WHERE LENGTH(decimal_10_1_column)!=3 AND decimal_10_1_column=1.10
2086+
#
2087+
CREATE TABLE t1 (a DECIMAL(10,1));
2088+
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
2089+
SELECT * FROM t1 WHERE LENGTH(a)!=3;
2090+
a
2091+
SELECT * FROM t1 WHERE LENGTH(a)!=3 AND a=1.10;
2092+
a
2093+
EXPLAIN EXTENDED
2094+
SELECT * FROM t1 WHERE LENGTH(a)!=3 AND a=1.10;
2095+
id select_type table type possible_keys key key_len ref rows filtered Extra
2096+
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2097+
Warnings:
2098+
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
2099+
# Notice 1.1 instead of 1.10 in the final WHERE condition
2100+
EXPLAIN EXTENDED
2101+
SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
2102+
id select_type table type possible_keys key key_len ref rows filtered Extra
2103+
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2104+
Warnings:
2105+
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = 1.10) and (<cache>(length(1.1)) <> rand()))
2106+
DROP TABLE t1;
2107+
CREATE TABLE t1 (a DECIMAL(10,2));
2108+
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
2109+
SELECT * FROM t1 WHERE LENGTH(a)!=4;
2110+
a
2111+
SELECT * FROM t1 WHERE LENGTH(a)!=4 AND a=1.10;
2112+
a
2113+
EXPLAIN EXTENDED
2114+
SELECT * FROM t1 WHERE LENGTH(a)!=4 AND a=1.10;
2115+
id select_type table type possible_keys key key_len ref rows filtered Extra
2116+
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2117+
Warnings:
2118+
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
2119+
# Notice 1.10 in the final WHERE condition
2120+
EXPLAIN EXTENDED
2121+
SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
2122+
id select_type table type possible_keys key key_len ref rows filtered Extra
2123+
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2124+
Warnings:
2125+
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = 1.10) and (<cache>(length(1.10)) <> rand()))
2126+
DROP TABLE t1;
2127+
CREATE TABLE t1 (a DECIMAL(10,3));
2128+
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
2129+
SELECT * FROM t1 WHERE LENGTH(a)!=5;
2130+
a
2131+
SELECT * FROM t1 WHERE LENGTH(a)!=5 AND a=1.10;
2132+
a
2133+
EXPLAIN EXTENDED
2134+
SELECT * FROM t1 WHERE LENGTH(a)!=5 AND a=1.10;
2135+
id select_type table type possible_keys key key_len ref rows filtered Extra
2136+
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2137+
Warnings:
2138+
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
2139+
# Notice 1.100 rather than 1.10 in the final WHERE condition
2140+
EXPLAIN EXTENDED
2141+
SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
2142+
id select_type table type possible_keys key key_len ref rows filtered Extra
2143+
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
2144+
Warnings:
2145+
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = 1.10) and (<cache>(length(1.100)) <> rand()))
2146+
DROP TABLE t1;
2147+
#
2148+
# End of 10.1 tests
2149+
#

mysql-test/t/type_newdecimal.test

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,3 +1622,52 @@ DROP TABLE t1,t2;
16221622
--echo #
16231623
--echo # End of 10.0 tests
16241624
--echo #
1625+
1626+
--echo #
1627+
--echo # Start of 10.1 tests
1628+
--echo #
1629+
1630+
--echo #
1631+
--echo # MDEV-8703 Wrong result for SELECT..WHERE LENGTH(decimal_10_1_column)!=3 AND decimal_10_1_column=1.10
1632+
--echo #
1633+
1634+
# The constant scale is bigger than the field scale
1635+
CREATE TABLE t1 (a DECIMAL(10,1));
1636+
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
1637+
SELECT * FROM t1 WHERE LENGTH(a)!=3;
1638+
SELECT * FROM t1 WHERE LENGTH(a)!=3 AND a=1.10;
1639+
EXPLAIN EXTENDED
1640+
SELECT * FROM t1 WHERE LENGTH(a)!=3 AND a=1.10;
1641+
--echo # Notice 1.1 instead of 1.10 in the final WHERE condition
1642+
EXPLAIN EXTENDED
1643+
SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
1644+
DROP TABLE t1;
1645+
1646+
# The constant scale is equal to the field scale
1647+
CREATE TABLE t1 (a DECIMAL(10,2));
1648+
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
1649+
SELECT * FROM t1 WHERE LENGTH(a)!=4;
1650+
SELECT * FROM t1 WHERE LENGTH(a)!=4 AND a=1.10;
1651+
EXPLAIN EXTENDED
1652+
SELECT * FROM t1 WHERE LENGTH(a)!=4 AND a=1.10;
1653+
--echo # Notice 1.10 in the final WHERE condition
1654+
EXPLAIN EXTENDED
1655+
SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
1656+
DROP TABLE t1;
1657+
1658+
# The constant scale is smaller than the field scale
1659+
CREATE TABLE t1 (a DECIMAL(10,3));
1660+
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
1661+
SELECT * FROM t1 WHERE LENGTH(a)!=5;
1662+
SELECT * FROM t1 WHERE LENGTH(a)!=5 AND a=1.10;
1663+
EXPLAIN EXTENDED
1664+
SELECT * FROM t1 WHERE LENGTH(a)!=5 AND a=1.10;
1665+
--echo # Notice 1.100 rather than 1.10 in the final WHERE condition
1666+
EXPLAIN EXTENDED
1667+
SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
1668+
DROP TABLE t1;
1669+
1670+
1671+
--echo #
1672+
--echo # End of 10.1 tests
1673+
--echo #

sql/field.cc

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,22 +1402,19 @@ Item *Field_num::convert_zerofill_number_to_string(THD *thd, Item *item) const
14021402
}
14031403

14041404

1405-
Item *Field_num::get_equal_const_item(THD *thd, const Context &ctx,
1406-
Item_field *field_item,
1407-
Item *const_item)
1405+
Item *Field_num::get_equal_zerofill_const_item(THD *thd, const Context &ctx,
1406+
Item_field *field_item,
1407+
Item *const_item)
14081408
{
1409-
DBUG_ASSERT(const_item->const_item());
1410-
if ((flags & ZEROFILL_FLAG) && IS_NUM(type()))
1411-
{
1412-
if (ctx.subst_constraint() == IDENTITY_SUBST)
1413-
return convert_zerofill_number_to_string(thd, const_item);
1414-
else
1415-
{
1416-
DBUG_ASSERT(ctx.compare_type() != STRING_RESULT);
1417-
return field_item;
1418-
}
1409+
switch (ctx.subst_constraint()) {
1410+
case IDENTITY_SUBST:
1411+
return convert_zerofill_number_to_string(thd, const_item);
1412+
case ANY_SUBST:
1413+
break;
14191414
}
1420-
return const_item;
1415+
DBUG_ASSERT(const_item->const_item());
1416+
DBUG_ASSERT(ctx.compare_type() != STRING_RESULT);
1417+
return field_item;
14211418
}
14221419

14231420

@@ -3293,6 +3290,38 @@ Field_new_decimal::unpack(uchar* to, const uchar *from, const uchar *from_end,
32933290
return from+len;
32943291
}
32953292

3293+
3294+
Item *Field_new_decimal::get_equal_const_item(THD *thd, const Context &ctx,
3295+
Item_field *field_item,
3296+
Item *const_item)
3297+
{
3298+
if (flags & ZEROFILL_FLAG)
3299+
return Field_num::get_equal_zerofill_const_item(thd, ctx,
3300+
field_item, const_item);
3301+
switch (ctx.subst_constraint()) {
3302+
case IDENTITY_SUBST:
3303+
if (const_item->field_type() != MYSQL_TYPE_NEWDECIMAL ||
3304+
const_item->decimal_scale() != decimals())
3305+
{
3306+
my_decimal *val, val_buffer, val_buffer2;
3307+
if (!(val= const_item->val_decimal(&val_buffer)))
3308+
{
3309+
DBUG_ASSERT(0);
3310+
return const_item;
3311+
}
3312+
/* Truncate or extend the decimal value to the scale of the field */
3313+
my_decimal_round(E_DEC_FATAL_ERROR, val, decimals(), true, &val_buffer2);
3314+
return new (thd->mem_root) Item_decimal(thd, field_name, &val_buffer2,
3315+
decimals(), field_length);
3316+
}
3317+
break;
3318+
case ANY_SUBST:
3319+
break;
3320+
}
3321+
return const_item;
3322+
}
3323+
3324+
32963325
int Field_num::store_time_dec(MYSQL_TIME *ltime, uint dec_arg)
32973326
{
32983327
longlong v= TIME_to_ulonglong(ltime);

sql/field.h

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -365,13 +365,6 @@ class Field: public Value_source
365365
Field(const Item &); /* Prevent use of these */
366366
void operator=(Field &);
367367
public:
368-
virtual bool can_be_substituted_to_equal_item(const Context &ctx,
369-
const Item_equal *item);
370-
virtual Item *get_equal_const_item(THD *thd, const Context &ctx,
371-
Item_field *field_item, Item *const_item)
372-
{
373-
return const_item;
374-
}
375368
static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
376369
{ return alloc_root(mem_root, size); }
377370
static void *operator new(size_t size) throw ()
@@ -1107,6 +1100,13 @@ class Field: public Value_source
11071100
*/
11081101
virtual bool test_if_equality_guarantees_uniqueness(const Item *const_item)
11091102
const;
1103+
virtual bool can_be_substituted_to_equal_item(const Context &ctx,
1104+
const Item_equal *item);
1105+
virtual Item *get_equal_const_item(THD *thd, const Context &ctx,
1106+
Item_field *field_item, Item *const_item)
1107+
{
1108+
return const_item;
1109+
}
11101110
virtual bool can_optimize_keypart_ref(const Item_bool_func *cond,
11111111
const Item *item) const;
11121112
virtual bool can_optimize_hash_join(const Item_bool_func *cond,
@@ -1208,9 +1208,10 @@ class Field: public Value_source
12081208
class Field_num :public Field {
12091209
protected:
12101210
Item *convert_zerofill_number_to_string(THD *thd, Item *item) const;
1211+
Item *get_equal_zerofill_const_item(THD *thd, const Context &ctx,
1212+
Item_field *field_item,
1213+
Item *const_item);
12111214
public:
1212-
Item *get_equal_const_item(THD *thd, const Context &ctx,
1213-
Item_field *field_item, Item *const_item);
12141215
const uint8 dec;
12151216
bool zerofill,unsigned_flag; // Purify cannot handle bit fields
12161217
Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
@@ -1222,6 +1223,13 @@ class Field_num :public Field {
12221223
uint repertoire(void) const { return MY_REPERTOIRE_NUMERIC; }
12231224
CHARSET_INFO *charset(void) const { return &my_charset_numeric; }
12241225
void prepend_zeros(String *value) const;
1226+
Item *get_equal_const_item(THD *thd, const Context &ctx,
1227+
Item_field *field_item, Item *const_item)
1228+
{
1229+
return (flags & ZEROFILL_FLAG) ?
1230+
get_equal_zerofill_const_item(thd, ctx, field_item, const_item) :
1231+
const_item;
1232+
}
12251233
void add_zerofill_and_unsigned(String &res) const;
12261234
friend class Create_field;
12271235
void make_field(Send_field *);
@@ -1440,6 +1448,8 @@ class Field_new_decimal :public Field_num {
14401448
uint is_equal(Create_field *new_field);
14411449
virtual const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data);
14421450
static Field *create_from_item(MEM_ROOT *root, Item *);
1451+
Item *get_equal_const_item(THD *thd, const Context &ctx,
1452+
Item_field *field_item, Item *const_item);
14431453
};
14441454

14451455

0 commit comments

Comments
 (0)