Commit e7dcec54 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-8703 Wrong result for SELECT..WHERE LENGTH(decimal_10_1_column)!=3 AND...

MDEV-8703 Wrong result for SELECT..WHERE LENGTH(decimal_10_1_column)!=3 AND decimal_10_1_column=1.10
parent 0736cddb
...@@ -2078,3 +2078,72 @@ DROP TABLE t1,t2; ...@@ -2078,3 +2078,72 @@ DROP TABLE t1,t2;
# #
# End of 10.0 tests # End of 10.0 tests
# #
#
# Start of 10.1 tests
#
#
# MDEV-8703 Wrong result for SELECT..WHERE LENGTH(decimal_10_1_column)!=3 AND decimal_10_1_column=1.10
#
CREATE TABLE t1 (a DECIMAL(10,1));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
SELECT * FROM t1 WHERE LENGTH(a)!=3;
a
SELECT * FROM t1 WHERE LENGTH(a)!=3 AND a=1.10;
a
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=3 AND a=1.10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
# Notice 1.1 instead of 1.10 in the final WHERE condition
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = 1.10) and (<cache>(length(1.1)) <> rand()))
DROP TABLE t1;
CREATE TABLE t1 (a DECIMAL(10,2));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
SELECT * FROM t1 WHERE LENGTH(a)!=4;
a
SELECT * FROM t1 WHERE LENGTH(a)!=4 AND a=1.10;
a
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=4 AND a=1.10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
# Notice 1.10 in the final WHERE condition
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = 1.10) and (<cache>(length(1.10)) <> rand()))
DROP TABLE t1;
CREATE TABLE t1 (a DECIMAL(10,3));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
SELECT * FROM t1 WHERE LENGTH(a)!=5;
a
SELECT * FROM t1 WHERE LENGTH(a)!=5 AND a=1.10;
a
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=5 AND a=1.10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
# Notice 1.100 rather than 1.10 in the final WHERE condition
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = 1.10) and (<cache>(length(1.100)) <> rand()))
DROP TABLE t1;
#
# End of 10.1 tests
#
...@@ -1622,3 +1622,52 @@ DROP TABLE t1,t2; ...@@ -1622,3 +1622,52 @@ DROP TABLE t1,t2;
--echo # --echo #
--echo # End of 10.0 tests --echo # End of 10.0 tests
--echo # --echo #
--echo #
--echo # Start of 10.1 tests
--echo #
--echo #
--echo # MDEV-8703 Wrong result for SELECT..WHERE LENGTH(decimal_10_1_column)!=3 AND decimal_10_1_column=1.10
--echo #
# The constant scale is bigger than the field scale
CREATE TABLE t1 (a DECIMAL(10,1));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
SELECT * FROM t1 WHERE LENGTH(a)!=3;
SELECT * FROM t1 WHERE LENGTH(a)!=3 AND a=1.10;
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=3 AND a=1.10;
--echo # Notice 1.1 instead of 1.10 in the final WHERE condition
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
DROP TABLE t1;
# The constant scale is equal to the field scale
CREATE TABLE t1 (a DECIMAL(10,2));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
SELECT * FROM t1 WHERE LENGTH(a)!=4;
SELECT * FROM t1 WHERE LENGTH(a)!=4 AND a=1.10;
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=4 AND a=1.10;
--echo # Notice 1.10 in the final WHERE condition
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
DROP TABLE t1;
# The constant scale is smaller than the field scale
CREATE TABLE t1 (a DECIMAL(10,3));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
SELECT * FROM t1 WHERE LENGTH(a)!=5;
SELECT * FROM t1 WHERE LENGTH(a)!=5 AND a=1.10;
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=5 AND a=1.10;
--echo # Notice 1.100 rather than 1.10 in the final WHERE condition
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
DROP TABLE t1;
--echo #
--echo # End of 10.1 tests
--echo #
...@@ -1402,22 +1402,19 @@ Item *Field_num::convert_zerofill_number_to_string(THD *thd, Item *item) const ...@@ -1402,22 +1402,19 @@ Item *Field_num::convert_zerofill_number_to_string(THD *thd, Item *item) const
} }
Item *Field_num::get_equal_const_item(THD *thd, const Context &ctx, Item *Field_num::get_equal_zerofill_const_item(THD *thd, const Context &ctx,
Item_field *field_item, Item_field *field_item,
Item *const_item) Item *const_item)
{ {
DBUG_ASSERT(const_item->const_item()); switch (ctx.subst_constraint()) {
if ((flags & ZEROFILL_FLAG) && IS_NUM(type())) case IDENTITY_SUBST:
{
if (ctx.subst_constraint() == IDENTITY_SUBST)
return convert_zerofill_number_to_string(thd, const_item); return convert_zerofill_number_to_string(thd, const_item);
else case ANY_SUBST:
{ break;
}
DBUG_ASSERT(const_item->const_item());
DBUG_ASSERT(ctx.compare_type() != STRING_RESULT); DBUG_ASSERT(ctx.compare_type() != STRING_RESULT);
return field_item; return field_item;
}
}
return const_item;
} }
...@@ -3293,6 +3290,38 @@ Field_new_decimal::unpack(uchar* to, const uchar *from, const uchar *from_end, ...@@ -3293,6 +3290,38 @@ Field_new_decimal::unpack(uchar* to, const uchar *from, const uchar *from_end,
return from+len; return from+len;
} }
Item *Field_new_decimal::get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item,
Item *const_item)
{
if (flags & ZEROFILL_FLAG)
return Field_num::get_equal_zerofill_const_item(thd, ctx,
field_item, const_item);
switch (ctx.subst_constraint()) {
case IDENTITY_SUBST:
if (const_item->field_type() != MYSQL_TYPE_NEWDECIMAL ||
const_item->decimal_scale() != decimals())
{
my_decimal *val, val_buffer, val_buffer2;
if (!(val= const_item->val_decimal(&val_buffer)))
{
DBUG_ASSERT(0);
return const_item;
}
/* Truncate or extend the decimal value to the scale of the field */
my_decimal_round(E_DEC_FATAL_ERROR, val, decimals(), true, &val_buffer2);
return new (thd->mem_root) Item_decimal(thd, field_name, &val_buffer2,
decimals(), field_length);
}
break;
case ANY_SUBST:
break;
}
return const_item;
}
int Field_num::store_time_dec(MYSQL_TIME *ltime, uint dec_arg) int Field_num::store_time_dec(MYSQL_TIME *ltime, uint dec_arg)
{ {
longlong v= TIME_to_ulonglong(ltime); longlong v= TIME_to_ulonglong(ltime);
......
...@@ -365,13 +365,6 @@ class Field: public Value_source ...@@ -365,13 +365,6 @@ class Field: public Value_source
Field(const Item &); /* Prevent use of these */ Field(const Item &); /* Prevent use of these */
void operator=(Field &); void operator=(Field &);
public: public:
virtual bool can_be_substituted_to_equal_item(const Context &ctx,
const Item_equal *item);
virtual Item *get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item, Item *const_item)
{
return const_item;
}
static void *operator new(size_t size, MEM_ROOT *mem_root) throw () static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
{ return alloc_root(mem_root, size); } { return alloc_root(mem_root, size); }
static void *operator new(size_t size) throw () static void *operator new(size_t size) throw ()
...@@ -1107,6 +1100,13 @@ public: ...@@ -1107,6 +1100,13 @@ public:
*/ */
virtual bool test_if_equality_guarantees_uniqueness(const Item *const_item) virtual bool test_if_equality_guarantees_uniqueness(const Item *const_item)
const; const;
virtual bool can_be_substituted_to_equal_item(const Context &ctx,
const Item_equal *item);
virtual Item *get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item, Item *const_item)
{
return const_item;
}
virtual bool can_optimize_keypart_ref(const Item_bool_func *cond, virtual bool can_optimize_keypart_ref(const Item_bool_func *cond,
const Item *item) const; const Item *item) const;
virtual bool can_optimize_hash_join(const Item_bool_func *cond, virtual bool can_optimize_hash_join(const Item_bool_func *cond,
...@@ -1208,9 +1208,10 @@ protected: ...@@ -1208,9 +1208,10 @@ protected:
class Field_num :public Field { class Field_num :public Field {
protected: protected:
Item *convert_zerofill_number_to_string(THD *thd, Item *item) const; Item *convert_zerofill_number_to_string(THD *thd, Item *item) const;
Item *get_equal_zerofill_const_item(THD *thd, const Context &ctx,
Item_field *field_item,
Item *const_item);
public: public:
Item *get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item, Item *const_item);
const uint8 dec; const uint8 dec;
bool zerofill,unsigned_flag; // Purify cannot handle bit fields bool zerofill,unsigned_flag; // Purify cannot handle bit fields
Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
...@@ -1222,6 +1223,13 @@ public: ...@@ -1222,6 +1223,13 @@ public:
uint repertoire(void) const { return MY_REPERTOIRE_NUMERIC; } uint repertoire(void) const { return MY_REPERTOIRE_NUMERIC; }
CHARSET_INFO *charset(void) const { return &my_charset_numeric; } CHARSET_INFO *charset(void) const { return &my_charset_numeric; }
void prepend_zeros(String *value) const; void prepend_zeros(String *value) const;
Item *get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item, Item *const_item)
{
return (flags & ZEROFILL_FLAG) ?
get_equal_zerofill_const_item(thd, ctx, field_item, const_item) :
const_item;
}
void add_zerofill_and_unsigned(String &res) const; void add_zerofill_and_unsigned(String &res) const;
friend class Create_field; friend class Create_field;
void make_field(Send_field *); void make_field(Send_field *);
...@@ -1440,6 +1448,8 @@ public: ...@@ -1440,6 +1448,8 @@ public:
uint is_equal(Create_field *new_field); uint is_equal(Create_field *new_field);
virtual const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data); virtual const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data);
static Field *create_from_item(MEM_ROOT *root, Item *); static Field *create_from_item(MEM_ROOT *root, Item *);
Item *get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item, Item *const_item);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment