Commit 39521244 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-16408 Remove tests for Item::type() in Item_basic_value::eq()

parent f4dfc609
......@@ -1655,3 +1655,104 @@ Note 1105 DBUG: [1] arg=2 handler=0 (time)
Note 1105 DBUG: [2] arg=3 handler=2 (datetime)
SET SESSION debug_dbug="-d,Predicant_to_list_comparator";
SET SESSION debug_dbug="-d,Item_func_in";
#
# MDEV-16408 Remove tests for Item::type() in Item_basic_value::eq()
#
SET SESSION debug_dbug="+d,Item_basic_value";
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2),(3);
SELECT * FROM t1 WHERE a BETWEEN 1 AND 1.0;
a
1
Warnings:
Note 1105 bin_eq=0 a=int'1' b=decimal'1.0'
SELECT * FROM t1 WHERE a BETWEEN 1 AND 1;
a
1
Warnings:
Note 1105 bin_eq=1 a=int'1' b=int'1'
SELECT * FROM t1 WHERE a BETWEEN 0 AND 1;
a
1
Warnings:
Note 1105 bin_eq=0 a=int'0' b=int'1'
SELECT * FROM t1 WHERE a BETWEEN 0 AND -1;
a
Warnings:
Note 1105 bin_eq=0 a=int'0' b=int''
SELECT * FROM t1 WHERE a BETWEEN -1 AND -1;
a
Warnings:
Note 1105 bin_eq=1 a=int'' b=int''
SELECT * FROM t1 WHERE a BETWEEN -0000000000000001 AND -1;
a
Warnings:
Note 1105 bin_eq=1 a=bigint'' b=int''
SELECT * FROM t1 WHERE a BETWEEN -1 AND 18446744073709551615;
a
1
2
3
Warnings:
Note 1105 bin_eq=0 a=int'' b=bigint'18446744073709551615'
SELECT * FROM t1 WHERE a BETWEEN -1 AND 18446744073709551616;
a
1
2
3
Warnings:
Note 1105 bin_eq=0 a=int'' b=decimal'18446744073709551616'
SELECT * FROM t1 WHERE a BETWEEN 1e2 AND 100e0;
a
Warnings:
Note 1105 bin_eq=1 a=double'1e2' b=double'100e0'
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN 1 AND ?' USING 1;
a
1
Warnings:
Note 1105 bin_eq=1 a=int'1' b=int'?'
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN -1 AND ?' USING 18446744073709551615;
a
1
2
3
Warnings:
Note 1105 bin_eq=0 a=int'' b=bigint'?'
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN -1 AND ?' USING 18446744073709551616;
a
1
2
3
Warnings:
Note 1105 bin_eq=0 a=int'' b=decimal'?'
DROP TABLE t1;
CREATE TABLE t1 (a DECIMAL(10,3));
INSERT INTO t1 VALUES (1),(2),(3);
SELECT * FROM t1 WHERE a BETWEEN 1.0 AND 1.0;
a
1.000
DROP TABLE t1;
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES ('00:00:00'),('00:00:01');
SELECT * FROM t1 WHERE a BETWEEN TIME'00:00:00' AND TIME'00:00:00';
a
00:00:00
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(10));
INSERT INTO t1 VALUES ('0'),('1'),('2');
SELECT * FROM t1 WHERE a BETWEEN '0' AND '0';
a
0
Warnings:
Note 1105 eq=1 a=varchar'0' b=varchar'0'
SELECT * FROM t1 WHERE a BETWEEN '0' AND ' 0';
a
Warnings:
Note 1105 eq=0 a=varchar'0' b=varchar'0'
SELECT * FROM t1 WHERE a BETWEEN '0' AND '0 ';
a
0
Warnings:
Note 1105 eq=1 a=varchar'0' b=varchar'0 '
DROP TABLE t1;
SET SESSION debug_dbug="-d,Item_basic_value";
......@@ -475,3 +475,48 @@ SELECT
SET SESSION debug_dbug="-d,Predicant_to_list_comparator";
SET SESSION debug_dbug="-d,Item_func_in";
--echo #
--echo # MDEV-16408 Remove tests for Item::type() in Item_basic_value::eq()
--echo #
SET SESSION debug_dbug="+d,Item_basic_value";
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2),(3);
SELECT * FROM t1 WHERE a BETWEEN 1 AND 1.0;
SELECT * FROM t1 WHERE a BETWEEN 1 AND 1;
SELECT * FROM t1 WHERE a BETWEEN 0 AND 1;
SELECT * FROM t1 WHERE a BETWEEN 0 AND -1;
SELECT * FROM t1 WHERE a BETWEEN -1 AND -1;
SELECT * FROM t1 WHERE a BETWEEN -0000000000000001 AND -1;
SELECT * FROM t1 WHERE a BETWEEN -1 AND 18446744073709551615;
SELECT * FROM t1 WHERE a BETWEEN -1 AND 18446744073709551616;
SELECT * FROM t1 WHERE a BETWEEN 1e2 AND 100e0;
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN 1 AND ?' USING 1;
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN -1 AND ?' USING 18446744073709551615;
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN -1 AND ?' USING 18446744073709551616;
DROP TABLE t1;
# DECIMAL does not work yet
CREATE TABLE t1 (a DECIMAL(10,3));
INSERT INTO t1 VALUES (1),(2),(3);
SELECT * FROM t1 WHERE a BETWEEN 1.0 AND 1.0;
DROP TABLE t1;
# Temporal types do not work yet
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES ('00:00:00'),('00:00:01');
SELECT * FROM t1 WHERE a BETWEEN TIME'00:00:00' AND TIME'00:00:00';
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(10));
INSERT INTO t1 VALUES ('0'),('1'),('2');
SELECT * FROM t1 WHERE a BETWEEN '0' AND '0';
SELECT * FROM t1 WHERE a BETWEEN '0' AND ' 0';
SELECT * FROM t1 WHERE a BETWEEN '0' AND '0 ';
DROP TABLE t1;
SET SESSION debug_dbug="-d,Item_basic_value";
......@@ -3631,6 +3631,35 @@ longlong Item_field::val_int_endpoint(bool left_endp, bool *incl_endp)
return null_value? LONGLONG_MIN : res;
}
bool Item_basic_value::eq(const Item *item, bool binary_cmp) const
{
const Item_basic_value *other= item->get_item_basic_value();
Type other_type;
// Exclude CACHE_OTEM and VARBIN_ITEM
if (!other ||
(other_type= other->type()) == CACHE_ITEM ||
other_type == VARBIN_ITEM)
return false;
const Type_handler *h= type_handler()->type_handler_for_comparison();
bool res= (h == other->type_handler()->type_handler_for_comparison()) &&
(binary_cmp ? h->Item_basic_value_bin_eq(this, other) :
h->Item_basic_value_eq(this, other));
DBUG_EXECUTE_IF("Item_basic_value",
push_warning_printf(current_thd,
Sql_condition::WARN_LEVEL_NOTE,
ER_UNKNOWN_ERROR, "%seq=%d a=%s'%.*s' b=%s'%.*s'",
binary_cmp ? "bin_" : "",
(int) res,
type_handler()->name().ptr(),
(int) name.length, name.str,
other->type_handler()->name().ptr(),
(int) other->name.length, other->name.str
););
return res;
}
/**
Create an item from a string we KNOW points to a valid longlong
end \\0 terminated number string.
......@@ -4697,10 +4726,20 @@ bool Item_param::convert_str_value(THD *thd)
bool Item_param::basic_const_item() const
{
DBUG_ASSERT(has_valid_state());
if (state == NO_VALUE ||
(state == SHORT_DATA_VALUE && type_handler()->cmp_type() == TIME_RESULT))
return FALSE;
return TRUE;
switch (state) {
case LONG_DATA_VALUE:
case NULL_VALUE:
return true;
case SHORT_DATA_VALUE:
return type_handler()->cmp_type() != TIME_RESULT;
case DEFAULT_VALUE:
case IGNORE_VALUE:
invalid_default_param();
return false;
case NO_VALUE:
break;
}
return false;
}
......@@ -4761,48 +4800,6 @@ Item_param::clone_item(THD *thd)
}
bool Item_param::value_eq(const Item *item, bool binary_cmp) const
{
switch (value.type_handler()->cmp_type()) {
case INT_RESULT:
return int_eq(value.integer, item);
case REAL_RESULT:
return real_eq(value.real, item);
case STRING_RESULT:
return str_eq(&value.m_string, item, binary_cmp);
case DECIMAL_RESULT:
case TIME_RESULT:
case ROW_RESULT:
break;
}
return false;
}
bool
Item_param::eq(const Item *item, bool binary_cmp) const
{
if (!basic_const_item())
return FALSE;
// There's no "default". See comments in Item_param::save_in_field().
switch (state) {
case IGNORE_VALUE:
case DEFAULT_VALUE:
invalid_default_param();
return false;
case NULL_VALUE:
return null_eq(item);
case SHORT_DATA_VALUE:
case LONG_DATA_VALUE:
return value_eq(item, binary_cmp);
case NO_VALUE:
return false;
}
DBUG_ASSERT(0); // Garbage
return FALSE;
}
/* End of Item_param related */
void Item_param::print(String *str, enum_query_type query_type)
......
......@@ -99,6 +99,7 @@ class sp_head;
class Protocol;
struct TABLE_LIST;
void item_init(void); /* Init item functions */
class Item_basic_value;
class Item_result_field;
class Item_field;
class Item_ref;
......@@ -2077,6 +2078,7 @@ class Item: public Value_source,
delete this;
}
virtual const Item_basic_value *get_item_basic_value() const { return NULL; }
virtual Item_splocal *get_item_splocal() { return 0; }
virtual Rewritable_query_parameter *get_rewritable_query_parameter()
{ return 0; }
......@@ -2503,22 +2505,6 @@ class Item_fixed_hybrid: public Item
*/
class Item_basic_value :public Item
{
bool is_basic_value(const Item *item, Type type_arg) const
{
return item->basic_const_item() && item->type() == type_arg;
}
bool is_basic_value(Type type_arg) const
{
return basic_const_item() && type() == type_arg;
}
bool str_eq(const String *value,
const String *other, CHARSET_INFO *cs, bool binary_cmp) const
{
return binary_cmp ?
value->bin_eq(other) :
collation.collation == cs && value->eq(other, collation.collation);
}
protected:
// Value metadata, e.g. to make string processing easier
class Metadata: private MY_STRING_METADATA
......@@ -2555,37 +2541,11 @@ class Item_basic_value :public Item
fix_charset_and_length(str.charset(), dv, Metadata(&str));
}
Item_basic_value(THD *thd): Item(thd) {}
/*
In the xxx_eq() methods below we need to cast off "const" to
call val_xxx(). This is OK for Item_basic_constant and Item_param.
*/
bool null_eq(const Item *item) const
{
DBUG_ASSERT(is_basic_value(NULL_ITEM));
return item->type() == NULL_ITEM;
}
bool str_eq(const String *value, const Item *item, bool binary_cmp) const
{
DBUG_ASSERT(is_basic_value(STRING_ITEM));
return is_basic_value(item, STRING_ITEM) &&
str_eq(value, ((Item_basic_value*)item)->val_str(NULL),
item->collation.collation, binary_cmp);
}
bool real_eq(double value, const Item *item) const
{
DBUG_ASSERT(is_basic_value(REAL_ITEM));
return is_basic_value(item, REAL_ITEM) &&
value == ((Item_basic_value*)item)->val_real();
}
bool int_eq(longlong value, const Item *item) const
{
DBUG_ASSERT(is_basic_value(INT_ITEM));
return is_basic_value(item, INT_ITEM) &&
value == ((Item_basic_value*)item)->val_int() &&
(value >= 0 || item->unsigned_flag == unsigned_flag);
}
public:
Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
const Tmp_field_param *param);
const Item_basic_value *get_item_basic_value() const { return this; }
bool eq(const Item *item, bool binary_cmp) const;
};
......@@ -2983,6 +2943,7 @@ class Item_literal: public Item_basic_constant
bool check_partition_func_processor(void *int_arg) { return false;}
bool const_item() const { return true; }
bool basic_const_item() const { return true; }
const Item_basic_value *get_item_basic_value() const { return this; }
};
......@@ -3448,7 +3409,6 @@ class Item_null :public Item_basic_constant
collation.set(cs, DERIVATION_IGNORABLE, MY_REPERTOIRE_ASCII);
}
enum Type type() const { return NULL_ITEM; }
bool eq(const Item *item, bool binary_cmp) const { return null_eq(item); }
double val_real();
longlong val_int();
String *val_str(String *str);
......@@ -3694,7 +3654,6 @@ class Item_param :public Item_basic_value,
PValue value;
const String *value_query_val_str(THD *thd, String* str) const;
bool value_eq(const Item *item, bool binary_cmp) const;
Item *value_clone_item(THD *thd);
bool can_return_value() const;
......@@ -3861,12 +3820,6 @@ class Item_param :public Item_basic_value,
*/
Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs);
Item *clone_item(THD *thd);
/*
Implement by-value equality evaluation if parameter value
is set and is a basic constant (integer, real or string).
Otherwise return FALSE.
*/
bool eq(const Item *item, bool binary_cmp) const;
void set_param_type_and_swap_value(Item_param *from);
Rewritable_query_parameter *get_rewritable_query_parameter()
......@@ -3942,8 +3895,6 @@ class Item_int :public Item_num
Item *neg(THD *thd);
uint decimal_precision() const
{ return (uint) (max_length - MY_TEST(value < 0)); }
bool eq(const Item *item, bool binary_cmp) const
{ return int_eq(value, item); }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_int>(thd, this); }
};
......@@ -4084,8 +4035,6 @@ class Item_float :public Item_num
Item *clone_item(THD *thd);
Item *neg(THD *thd);
virtual void print(String *str, enum_query_type query_type);
bool eq(const Item *item, bool binary_cmp) const
{ return real_eq(value, item); }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_float>(thd, this); }
};
......@@ -4204,10 +4153,6 @@ class Item_string :public Item_literal
}
int save_in_field(Field *field, bool no_conversions);
const Type_handler *type_handler() const { return &type_handler_varchar; }
bool eq(const Item *item, bool binary_cmp) const
{
return str_eq(&str_value, item, binary_cmp);
}
Item *clone_item(THD *thd);
Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs)
{
......
......@@ -6356,3 +6356,65 @@ bool Type_handler_general_purpose_string::
}
/***************************************************************************/
bool Type_handler_null::Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b)
const
{
return a->basic_const_item() &&
b->basic_const_item();
}
bool Type_handler_real_result::Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b)
const
{
return a->basic_const_item() &&
b->basic_const_item() &&
const_cast<Item_basic_value*>(a)->val_real() ==
const_cast<Item_basic_value*>(b)->val_real();
}
bool Type_handler_int_result::Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b)
const
{
longlong value;
return a->basic_const_item() &&
b->basic_const_item() &&
(value= const_cast<Item_basic_value*>(a)->val_int()) ==
const_cast<Item_basic_value*>(b)->val_int() &&
(value >= 0 || a->unsigned_flag == b->unsigned_flag);
}
bool Type_handler_string_result::Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b)
const
{
if (!a->basic_const_item() ||
!b->basic_const_item() ||
a->collation.collation != b->collation.collation)
return false;
String *sa= const_cast<Item_basic_value*>(a)->val_str(NULL);
String *sb= const_cast<Item_basic_value*>(b)->val_str(NULL);
return sa->eq(sb, a->collation.collation);
}
bool
Type_handler_string_result::Item_basic_value_bin_eq(const Item_basic_value *a,
const Item_basic_value *b)
const
{
if (!a->basic_const_item() ||
!b->basic_const_item())
return false;
String *sa= const_cast<Item_basic_value*>(a)->val_str(NULL);
String *sb= const_cast<Item_basic_value*>(b)->val_str(NULL);
return sa->bin_eq(sb);
}
/***************************************************************************/
......@@ -30,6 +30,7 @@ class Field;
class Column_definition;
class Column_definition_attributes;
class Item;
class Item_basic_value;
class Item_param;
class Item_cache;
class Item_func_or_sum;
......@@ -1390,6 +1391,16 @@ class Type_handler
return NULL;
}
virtual bool set_comparator_func(Arg_comparator *cmp) const= 0;
virtual bool Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b) const
{
return false;
}
virtual bool Item_basic_value_bin_eq(const Item_basic_value *a,
const Item_basic_value *b) const
{
return Item_basic_value_eq(a, b);
}
virtual bool Item_hybrid_func_fix_attributes(THD *thd,
const char *name,
Type_handler_hybrid_field_type *,
......@@ -1866,6 +1877,8 @@ class Type_handler_real_result: public Type_handler_numeric
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
bool Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b) const;
uint Item_decimal_precision(const Item *item) const;
bool Item_save_in_value(Item *item, st_value *value) const;
bool Item_param_set_from_value(THD *thd,
......@@ -2145,6 +2158,8 @@ class Type_handler_int_result: public Type_handler_numeric
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
bool Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b) const;
uint Item_decimal_precision(const Item *item) const;
bool Item_save_in_value(Item *item, st_value *value) const;
bool Item_param_set_from_value(THD *thd,
......@@ -2308,6 +2323,10 @@ class Type_handler_string_result: public Type_handler
const Schema_specification_st *schema)
const;
uint32 max_display_length(const Item *item) const;
bool Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b) const;
bool Item_basic_value_bin_eq(const Item_basic_value *a,
const Item_basic_value *b) const;
uint Item_time_precision(Item *item) const
{
return Item_temporal_precision(item, true);
......@@ -3296,6 +3315,13 @@ class Type_handler_null: public Type_handler_general_purpose_string
const Type_handler *type_handler_for_union(const Item *) const;
uint32 max_display_length(const Item *item) const { return 0; }
uint32 calc_pack_length(uint32 length) const { return 0; }
bool Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b) const;
bool Item_basic_value_bin_eq(const Item_basic_value *a,
const Item_basic_value *b) const
{
return Type_handler_null::Item_basic_value_eq(a, b);
}
bool Item_save_in_value(Item *item, st_value *value) const;
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
......
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