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;
#
# 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;
--echo #
--echo # End of 10.0 tests
--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
}
Item *Field_num::get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item,
Item *const_item)
Item *Field_num::get_equal_zerofill_const_item(THD *thd, const Context &ctx,
Item_field *field_item,
Item *const_item)
{
DBUG_ASSERT(const_item->const_item());
if ((flags & ZEROFILL_FLAG) && IS_NUM(type()))
{
if (ctx.subst_constraint() == IDENTITY_SUBST)
return convert_zerofill_number_to_string(thd, const_item);
else
{
DBUG_ASSERT(ctx.compare_type() != STRING_RESULT);
return field_item;
}
switch (ctx.subst_constraint()) {
case IDENTITY_SUBST:
return convert_zerofill_number_to_string(thd, const_item);
case ANY_SUBST:
break;
}
return const_item;
DBUG_ASSERT(const_item->const_item());
DBUG_ASSERT(ctx.compare_type() != STRING_RESULT);
return field_item;
}
......@@ -3293,6 +3290,38 @@ Field_new_decimal::unpack(uchar* to, const uchar *from, const uchar *from_end,
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)
{
longlong v= TIME_to_ulonglong(ltime);
......
......@@ -365,13 +365,6 @@ class Field: public Value_source
Field(const Item &); /* Prevent use of these */
void operator=(Field &);
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 ()
{ return alloc_root(mem_root, size); }
static void *operator new(size_t size) throw ()
......@@ -1107,6 +1100,13 @@ class Field: public Value_source
*/
virtual bool test_if_equality_guarantees_uniqueness(const Item *const_item)
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,
const Item *item) const;
virtual bool can_optimize_hash_join(const Item_bool_func *cond,
......@@ -1208,9 +1208,10 @@ class Field: public Value_source
class Field_num :public Field {
protected:
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:
Item *get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item, Item *const_item);
const uint8 dec;
bool zerofill,unsigned_flag; // Purify cannot handle bit fields
Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
......@@ -1222,6 +1223,13 @@ class Field_num :public Field {
uint repertoire(void) const { return MY_REPERTOIRE_NUMERIC; }
CHARSET_INFO *charset(void) const { return &my_charset_numeric; }
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;
friend class Create_field;
void make_field(Send_field *);
......@@ -1440,6 +1448,8 @@ class Field_new_decimal :public Field_num {
uint is_equal(Create_field *new_field);
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 *);
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