mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-12707 Split resolve_const_item() into virtual methods in Type_handler
This commit is contained in:
@ -173,29 +173,29 @@ SELECT DATE'2001-01-01' IN ('2001-01-01','2001-02-02');
|
||||
DATE'2001-01-01' IN ('2001-01-01','2001-02-02')
|
||||
1
|
||||
Warnings:
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (date)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (date)
|
||||
Note 1105 DBUG: types_compatible=yes bisect=yes
|
||||
SELECT DATE'2001-01-01' IN ('2001-01-01','2001-02-02',NULL);
|
||||
DATE'2001-01-01' IN ('2001-01-01','2001-02-02',NULL)
|
||||
1
|
||||
Warnings:
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (date)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (date)
|
||||
Note 1105 DBUG: types_compatible=yes bisect=yes
|
||||
SELECT DATE'2001-01-01' NOT IN ('2001-01-01','2001-02-02');
|
||||
DATE'2001-01-01' NOT IN ('2001-01-01','2001-02-02')
|
||||
0
|
||||
Warnings:
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (date)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (date)
|
||||
Note 1105 DBUG: types_compatible=yes bisect=yes
|
||||
SELECT DATE'2001-01-01' NOT IN ('2001-01-01','2001-02-02',NULL);
|
||||
DATE'2001-01-01' NOT IN ('2001-01-01','2001-02-02',NULL)
|
||||
0
|
||||
Warnings:
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (date)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (date)
|
||||
Note 1105 DBUG: types_compatible=yes bisect=yes
|
||||
# Column predicant, compatible types, bisect
|
||||
CREATE TABLE t1 (a INT UNSIGNED);
|
||||
@ -354,38 +354,38 @@ CREATE TABLE t1 (a DATE);
|
||||
SELECT a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0) FROM t1;
|
||||
a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0)
|
||||
Warnings:
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
|
||||
Note 1105 DBUG: [2] arg=3 handler=0 (datetime)
|
||||
Note 1105 DBUG: [3] arg=4 handler=0 (datetime)
|
||||
Note 1105 DBUG: [4] arg=5 handler=0 (datetime)
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (date)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (date)
|
||||
Note 1105 DBUG: [2] arg=3 handler=0 (date)
|
||||
Note 1105 DBUG: [3] arg=4 handler=0 (date)
|
||||
Note 1105 DBUG: [4] arg=5 handler=0 (date)
|
||||
Note 1105 DBUG: types_compatible=yes bisect=yes
|
||||
SELECT a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL) FROM t1;
|
||||
a IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL)
|
||||
Warnings:
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
|
||||
Note 1105 DBUG: [2] arg=3 handler=0 (datetime)
|
||||
Note 1105 DBUG: [3] arg=4 handler=0 (datetime)
|
||||
Note 1105 DBUG: [4] arg=5 handler=0 (datetime)
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (date)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (date)
|
||||
Note 1105 DBUG: [2] arg=3 handler=0 (date)
|
||||
Note 1105 DBUG: [3] arg=4 handler=0 (date)
|
||||
Note 1105 DBUG: [4] arg=5 handler=0 (date)
|
||||
Note 1105 DBUG: types_compatible=yes bisect=yes
|
||||
SELECT a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0) FROM t1;
|
||||
a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0)
|
||||
Warnings:
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
|
||||
Note 1105 DBUG: [2] arg=3 handler=0 (datetime)
|
||||
Note 1105 DBUG: [3] arg=4 handler=0 (datetime)
|
||||
Note 1105 DBUG: [4] arg=5 handler=0 (datetime)
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (date)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (date)
|
||||
Note 1105 DBUG: [2] arg=3 handler=0 (date)
|
||||
Note 1105 DBUG: [3] arg=4 handler=0 (date)
|
||||
Note 1105 DBUG: [4] arg=5 handler=0 (date)
|
||||
Note 1105 DBUG: types_compatible=yes bisect=yes
|
||||
SELECT a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL) FROM t1;
|
||||
a NOT IN ('2001-01-01',DATE'2001-01-02',20010102,20010102.0,20010102e0,NULL)
|
||||
Warnings:
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
|
||||
Note 1105 DBUG: [2] arg=3 handler=0 (datetime)
|
||||
Note 1105 DBUG: [3] arg=4 handler=0 (datetime)
|
||||
Note 1105 DBUG: [4] arg=5 handler=0 (datetime)
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (date)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (date)
|
||||
Note 1105 DBUG: [2] arg=3 handler=0 (date)
|
||||
Note 1105 DBUG: [3] arg=4 handler=0 (date)
|
||||
Note 1105 DBUG: [4] arg=5 handler=0 (date)
|
||||
Note 1105 DBUG: types_compatible=yes bisect=yes
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a TIME);
|
||||
@ -610,26 +610,26 @@ CREATE TABLE t1 (a DATE);
|
||||
SELECT DATE'2001-01-01' IN (a,'2001-01-01') FROM t1;
|
||||
DATE'2001-01-01' IN (a,'2001-01-01')
|
||||
Warnings:
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (date)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (date)
|
||||
Note 1105 DBUG: types_compatible=yes bisect=no
|
||||
SELECT DATE'2001-01-01' IN (a,'2001-01-01',NULL) FROM t1;
|
||||
DATE'2001-01-01' IN (a,'2001-01-01',NULL)
|
||||
Warnings:
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (date)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (date)
|
||||
Note 1105 DBUG: types_compatible=yes bisect=no
|
||||
SELECT DATE'2001-01-01' NOT IN (a,'2001-01-01') FROM t1;
|
||||
DATE'2001-01-01' NOT IN (a,'2001-01-01')
|
||||
Warnings:
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (date)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (date)
|
||||
Note 1105 DBUG: types_compatible=yes bisect=no
|
||||
SELECT DATE'2001-01-01' NOT IN (a,'2001-01-01',NULL) FROM t1;
|
||||
DATE'2001-01-01' NOT IN (a,'2001-01-01',NULL)
|
||||
Warnings:
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (datetime)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (datetime)
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (date)
|
||||
Note 1105 DBUG: [1] arg=2 handler=0 (date)
|
||||
Note 1105 DBUG: types_compatible=yes bisect=no
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (a TIME);
|
||||
@ -1147,25 +1147,25 @@ SELECT a IN (1,DATE'2001-01-01') FROM t1;
|
||||
a IN (1,DATE'2001-01-01')
|
||||
Warnings:
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (double)
|
||||
Note 1105 DBUG: [1] arg=2 handler=1 (datetime)
|
||||
Note 1105 DBUG: [1] arg=2 handler=1 (date)
|
||||
Note 1105 DBUG: types_compatible=no bisect=no
|
||||
SELECT a IN (1,DATE'2001-01-01',NULL) FROM t1;
|
||||
a IN (1,DATE'2001-01-01',NULL)
|
||||
Warnings:
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (double)
|
||||
Note 1105 DBUG: [1] arg=2 handler=1 (datetime)
|
||||
Note 1105 DBUG: [1] arg=2 handler=1 (date)
|
||||
Note 1105 DBUG: types_compatible=no bisect=no
|
||||
SELECT a NOT IN (1,DATE'2001-01-01') FROM t1;
|
||||
a NOT IN (1,DATE'2001-01-01')
|
||||
Warnings:
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (double)
|
||||
Note 1105 DBUG: [1] arg=2 handler=1 (datetime)
|
||||
Note 1105 DBUG: [1] arg=2 handler=1 (date)
|
||||
Note 1105 DBUG: types_compatible=no bisect=no
|
||||
SELECT a NOT IN (1,DATE'2001-01-01',NULL) FROM t1;
|
||||
a NOT IN (1,DATE'2001-01-01',NULL)
|
||||
Warnings:
|
||||
Note 1105 DBUG: [0] arg=1 handler=0 (double)
|
||||
Note 1105 DBUG: [1] arg=2 handler=1 (datetime)
|
||||
Note 1105 DBUG: [1] arg=2 handler=1 (date)
|
||||
Note 1105 DBUG: types_compatible=no bisect=no
|
||||
SELECT a IN (1,TIMESTAMP'2001-01-01 10:20:30') FROM t1;
|
||||
a IN (1,TIMESTAMP'2001-01-01 10:20:30')
|
||||
|
99
sql/item.cc
99
sql/item.cc
@ -9101,101 +9101,14 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
|
||||
Item *item= *ref;
|
||||
if (item->basic_const_item())
|
||||
return; // Can't be better
|
||||
|
||||
Item *new_item= NULL;
|
||||
Item_result res_type= item_cmp_type(comp_item, item);
|
||||
const char *name= item->name.str; // Alloced on THD::mem_root
|
||||
MEM_ROOT *mem_root= thd->mem_root;
|
||||
|
||||
switch (res_type) {
|
||||
case TIME_RESULT:
|
||||
Type_handler_hybrid_field_type cmp(comp_item->type_handler_for_comparison());
|
||||
if (!cmp.aggregate_for_comparison(item->type_handler_for_comparison()))
|
||||
{
|
||||
bool is_null;
|
||||
Item **ref_copy= ref;
|
||||
/* the following call creates a constant and puts it in new_item */
|
||||
enum_field_types type= item->field_type_for_temporal_comparison(comp_item);
|
||||
get_datetime_value(thd, &ref_copy, &new_item, type, &is_null);
|
||||
if (is_null)
|
||||
new_item= new (mem_root) Item_null(thd, name);
|
||||
break;
|
||||
Item *new_item= cmp.type_handler()->
|
||||
make_const_item_for_comparison(thd, item, comp_item);
|
||||
if (new_item)
|
||||
thd->change_item_tree(ref, new_item);
|
||||
}
|
||||
case STRING_RESULT:
|
||||
{
|
||||
char buff[MAX_FIELD_WIDTH];
|
||||
String tmp(buff,sizeof(buff),&my_charset_bin),*result;
|
||||
result=item->val_str(&tmp);
|
||||
if (item->null_value)
|
||||
new_item= new (mem_root) Item_null(thd, name);
|
||||
else
|
||||
{
|
||||
uint length= result->length();
|
||||
char *tmp_str= thd->strmake(result->ptr(), length);
|
||||
new_item= new (mem_root) Item_string(thd, name, tmp_str, length, result->charset());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case INT_RESULT:
|
||||
{
|
||||
longlong result=item->val_int();
|
||||
uint length=item->max_length;
|
||||
bool null_value=item->null_value;
|
||||
new_item= (null_value ? (Item*) new (mem_root) Item_null(thd, name) :
|
||||
(Item*) new (mem_root) Item_int(thd, name, result, length));
|
||||
break;
|
||||
}
|
||||
case ROW_RESULT:
|
||||
if (item->type() == Item::ROW_ITEM && comp_item->type() == Item::ROW_ITEM)
|
||||
{
|
||||
/*
|
||||
Substitute constants only in Item_row's. Don't affect other Items
|
||||
with ROW_RESULT (eg Item_singlerow_subselect).
|
||||
|
||||
For such Items more optimal is to detect if it is constant and replace
|
||||
it with Item_row. This would optimize queries like this:
|
||||
SELECT * FROM t1 WHERE (a,b) = (SELECT a,b FROM t2 LIMIT 1);
|
||||
*/
|
||||
Item_row *item_row= (Item_row*) item;
|
||||
Item_row *comp_item_row= (Item_row*) comp_item;
|
||||
uint col;
|
||||
new_item= 0;
|
||||
/*
|
||||
If item and comp_item are both Item_row's and have same number of cols
|
||||
then process items in Item_row one by one.
|
||||
We can't ignore NULL values here as this item may be used with <=>, in
|
||||
which case NULL's are significant.
|
||||
*/
|
||||
DBUG_ASSERT(item->result_type() == comp_item->result_type());
|
||||
DBUG_ASSERT(item_row->cols() == comp_item_row->cols());
|
||||
col= item_row->cols();
|
||||
while (col-- > 0)
|
||||
resolve_const_item(thd, item_row->addr(col),
|
||||
comp_item_row->element_index(col));
|
||||
break;
|
||||
}
|
||||
/* Fallthrough */
|
||||
case REAL_RESULT:
|
||||
{ // It must REAL_RESULT
|
||||
double result= item->val_real();
|
||||
uint length=item->max_length,decimals=item->decimals;
|
||||
bool null_value=item->null_value;
|
||||
new_item= (null_value ? (Item*) new (mem_root) Item_null(thd, name) : (Item*)
|
||||
new (mem_root) Item_float(thd, name, result, decimals, length));
|
||||
break;
|
||||
}
|
||||
case DECIMAL_RESULT:
|
||||
{
|
||||
my_decimal decimal_value;
|
||||
my_decimal *result= item->val_decimal(&decimal_value);
|
||||
uint length= item->max_length, decimals= item->decimals;
|
||||
bool null_value= item->null_value;
|
||||
new_item= (null_value ?
|
||||
(Item*) new (mem_root) Item_null(thd, name) :
|
||||
(Item*) new (mem_root) Item_decimal(thd, name, result, length, decimals));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (new_item)
|
||||
thd->change_item_tree(ref, new_item);
|
||||
}
|
||||
|
||||
/**
|
||||
|
21
sql/item.h
21
sql/item.h
@ -733,6 +733,10 @@ public:
|
||||
{
|
||||
return Type_handler::get_handler_by_field_type(field_type());
|
||||
}
|
||||
const Type_handler *type_handler_for_comparison() const
|
||||
{
|
||||
return type_handler()->type_handler_for_comparison();
|
||||
}
|
||||
virtual const Type_handler *real_type_handler() const
|
||||
{
|
||||
return type_handler();
|
||||
@ -1317,23 +1321,6 @@ public:
|
||||
return f_type == MYSQL_TYPE_TIME ? val_time_packed() :
|
||||
val_datetime_packed();
|
||||
}
|
||||
enum_field_types field_type_for_temporal_comparison(const Item *other) const
|
||||
{
|
||||
if (cmp_type() == TIME_RESULT)
|
||||
{
|
||||
if (other->cmp_type() == TIME_RESULT)
|
||||
return Field::field_type_merge(field_type(), other->field_type());
|
||||
else
|
||||
return field_type();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (other->cmp_type() == TIME_RESULT)
|
||||
return other->field_type();
|
||||
DBUG_ASSERT(0); // Two non-temporal data types, we should not get to here
|
||||
return MYSQL_TYPE_DATETIME;
|
||||
}
|
||||
}
|
||||
bool get_seconds(ulonglong *sec, ulong *sec_part);
|
||||
virtual bool get_date_result(MYSQL_TIME *ltime, ulonglong fuzzydate)
|
||||
{ return get_date(ltime,fuzzydate); }
|
||||
|
@ -552,20 +552,20 @@ bool Arg_comparator::set_cmp_func_string()
|
||||
}
|
||||
|
||||
|
||||
bool Arg_comparator::set_cmp_func_temporal()
|
||||
bool Arg_comparator::set_cmp_func_time()
|
||||
{
|
||||
enum_field_types f_type= a[0]->field_type_for_temporal_comparison(b[0]);
|
||||
m_compare_collation= &my_charset_numeric;
|
||||
if (f_type == MYSQL_TYPE_TIME)
|
||||
{
|
||||
func= is_owner_equal_func() ? &Arg_comparator::compare_e_time :
|
||||
&Arg_comparator::compare_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
func= is_owner_equal_func() ? &Arg_comparator::compare_e_datetime :
|
||||
&Arg_comparator::compare_datetime;
|
||||
}
|
||||
func= is_owner_equal_func() ? &Arg_comparator::compare_e_time :
|
||||
&Arg_comparator::compare_time;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Arg_comparator::set_cmp_func_datetime()
|
||||
{
|
||||
m_compare_collation= &my_charset_numeric;
|
||||
func= is_owner_equal_func() ? &Arg_comparator::compare_e_datetime :
|
||||
&Arg_comparator::compare_datetime;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,8 @@ public:
|
||||
bool set_cmp_func_for_row_arguments();
|
||||
bool set_cmp_func_row();
|
||||
bool set_cmp_func_string();
|
||||
bool set_cmp_func_temporal();
|
||||
bool set_cmp_func_time();
|
||||
bool set_cmp_func_datetime();
|
||||
bool set_cmp_func_int();
|
||||
bool set_cmp_func_real();
|
||||
bool set_cmp_func_decimal();
|
||||
|
143
sql/sql_type.cc
143
sql/sql_type.cc
@ -457,7 +457,19 @@ const Type_handler *Type_handler_time_common::type_handler_for_comparison() cons
|
||||
return &type_handler_time;
|
||||
}
|
||||
|
||||
const Type_handler *Type_handler_temporal_with_date::type_handler_for_comparison() const
|
||||
const Type_handler *Type_handler_date_common::type_handler_for_comparison() const
|
||||
{
|
||||
return &type_handler_newdate;
|
||||
}
|
||||
|
||||
|
||||
const Type_handler *Type_handler_datetime_common::type_handler_for_comparison() const
|
||||
{
|
||||
return &type_handler_datetime;
|
||||
}
|
||||
|
||||
|
||||
const Type_handler *Type_handler_timestamp_common::type_handler_for_comparison() const
|
||||
{
|
||||
return &type_handler_datetime;
|
||||
}
|
||||
@ -652,9 +664,14 @@ Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h)
|
||||
{
|
||||
/*
|
||||
We're here if both m_type_handler and h are temporal data types.
|
||||
- If both data types are TIME, we preserve TIME.
|
||||
- If both data types are DATE, we preserve DATE.
|
||||
Preserving DATE is needed for EXPLAIN FORMAT=JSON,
|
||||
to print DATE constants using proper format:
|
||||
'YYYY-MM-DD' rather than 'YYYY-MM-DD 00:00:00'.
|
||||
*/
|
||||
if (field_type() != MYSQL_TYPE_TIME || h->field_type() != MYSQL_TYPE_TIME)
|
||||
m_type_handler= &type_handler_datetime; // DATETIME bits TIME
|
||||
if (field_type() != h->field_type())
|
||||
m_type_handler= &type_handler_datetime;
|
||||
}
|
||||
}
|
||||
else if ((a == INT_RESULT || a == DECIMAL_RESULT) &&
|
||||
@ -1917,9 +1934,15 @@ bool Type_handler_string_result::set_comparator_func(Arg_comparator *cmp) const
|
||||
return cmp->set_cmp_func_string();
|
||||
}
|
||||
|
||||
bool Type_handler_temporal_result::set_comparator_func(Arg_comparator *cmp) const
|
||||
bool Type_handler_time_common::set_comparator_func(Arg_comparator *cmp) const
|
||||
{
|
||||
return cmp->set_cmp_func_temporal();
|
||||
return cmp->set_cmp_func_time();
|
||||
}
|
||||
|
||||
bool
|
||||
Type_handler_temporal_with_date::set_comparator_func(Arg_comparator *cmp) const
|
||||
{
|
||||
return cmp->set_cmp_func_datetime();
|
||||
}
|
||||
|
||||
|
||||
@ -4211,3 +4234,113 @@ bool Type_handler::
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
Item *Type_handler_int_result::
|
||||
make_const_item_for_comparison(THD *thd, Item *item, Item *cmp) const
|
||||
{
|
||||
longlong result= item->val_int();
|
||||
if (item->null_value)
|
||||
return new (thd->mem_root) Item_null(thd, item->name.str);
|
||||
return new (thd->mem_root) Item_int(thd, item->name.str, result,
|
||||
item->max_length);
|
||||
}
|
||||
|
||||
|
||||
Item *Type_handler_real_result::
|
||||
make_const_item_for_comparison(THD *thd, Item *item, Item *cmp) const
|
||||
{
|
||||
double result= item->val_real();
|
||||
if (item->null_value)
|
||||
return new (thd->mem_root) Item_null(thd, item->name.str);
|
||||
return new (thd->mem_root) Item_float(thd, item->name.str, result,
|
||||
item->decimals, item->max_length);
|
||||
}
|
||||
|
||||
|
||||
Item *Type_handler_decimal_result::
|
||||
make_const_item_for_comparison(THD *thd, Item *item, Item *cmp) const
|
||||
{
|
||||
my_decimal decimal_value;
|
||||
my_decimal *result= item->val_decimal(&decimal_value);
|
||||
if (item->null_value)
|
||||
return new (thd->mem_root) Item_null(thd, item->name.str);
|
||||
return new (thd->mem_root) Item_decimal(thd, item->name.str, result,
|
||||
item->max_length, item->decimals);
|
||||
}
|
||||
|
||||
|
||||
Item *Type_handler_string_result::
|
||||
make_const_item_for_comparison(THD *thd, Item *item, Item *cmp) const
|
||||
{
|
||||
StringBuffer<MAX_FIELD_WIDTH> tmp;
|
||||
String *result= item->val_str(&tmp);
|
||||
if (item->null_value)
|
||||
return new (thd->mem_root) Item_null(thd, item->name.str);
|
||||
uint length= result->length();
|
||||
char *tmp_str= thd->strmake(result->ptr(), length);
|
||||
return new (thd->mem_root) Item_string(thd, item->name.str,
|
||||
tmp_str, length, result->charset());
|
||||
}
|
||||
|
||||
|
||||
Item *Type_handler_time_common::
|
||||
make_const_item_for_comparison(THD *thd, Item *item, Item *cmp) const
|
||||
{
|
||||
Item_cache_temporal *cache;
|
||||
longlong value= item->val_time_packed();
|
||||
if (item->null_value)
|
||||
return new (thd->mem_root) Item_null(thd, item->name.str);
|
||||
cache= new (thd->mem_root) Item_cache_temporal(thd, field_type());
|
||||
if (cache)
|
||||
cache->store_packed(value, item);
|
||||
return cache;
|
||||
}
|
||||
|
||||
|
||||
Item *Type_handler_temporal_with_date::
|
||||
make_const_item_for_comparison(THD *thd, Item *item, Item *cmp) const
|
||||
{
|
||||
Item_cache_temporal *cache;
|
||||
longlong value= item->val_datetime_packed();
|
||||
if (item->null_value)
|
||||
return new (thd->mem_root) Item_null(thd, item->name.str);
|
||||
cache= new (thd->mem_root) Item_cache_temporal(thd, field_type());
|
||||
if (cache)
|
||||
cache->store_packed(value, item);
|
||||
return cache;
|
||||
}
|
||||
|
||||
|
||||
Item *Type_handler_row::
|
||||
make_const_item_for_comparison(THD *thd, Item *item, Item *cmp) const
|
||||
{
|
||||
if (item->type() == Item::ROW_ITEM && cmp->type() == Item::ROW_ITEM)
|
||||
{
|
||||
/*
|
||||
Substitute constants only in Item_row's. Don't affect other Items
|
||||
with ROW_RESULT (eg Item_singlerow_subselect).
|
||||
|
||||
For such Items more optimal is to detect if it is constant and replace
|
||||
it with Item_row. This would optimize queries like this:
|
||||
SELECT * FROM t1 WHERE (a,b) = (SELECT a,b FROM t2 LIMIT 1);
|
||||
*/
|
||||
Item_row *item_row= (Item_row*) item;
|
||||
Item_row *comp_item_row= (Item_row*) cmp;
|
||||
uint col;
|
||||
/*
|
||||
If item and comp_item are both Item_row's and have same number of cols
|
||||
then process items in Item_row one by one.
|
||||
We can't ignore NULL values here as this item may be used with <=>, in
|
||||
which case NULL's are significant.
|
||||
*/
|
||||
DBUG_ASSERT(item->result_type() == cmp->result_type());
|
||||
DBUG_ASSERT(item_row->cols() == comp_item_row->cols());
|
||||
col= item_row->cols();
|
||||
while (col-- > 0)
|
||||
resolve_const_item(thd, item_row->addr(col),
|
||||
comp_item_row->element_index(col));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -746,6 +746,26 @@ public:
|
||||
virtual bool
|
||||
subquery_type_allows_materialization(const Item *inner,
|
||||
const Item *outer) const= 0;
|
||||
/**
|
||||
Make a simple constant replacement item for a constant "src",
|
||||
so the new item can futher be used for comparison with "cmp", e.g.:
|
||||
src = cmp -> replacement = cmp
|
||||
|
||||
"this" is the type handler that is used to compare "src" and "cmp".
|
||||
|
||||
@param thd - current thread, for mem_root
|
||||
@param src - The item that we want to replace. It's a const item,
|
||||
but it can be complex enough to calculate on every row.
|
||||
@param cmp - The src's comparand.
|
||||
@retval - a pointer to the created replacement Item
|
||||
@retval - NULL, if could not create a replacement (e.g. on EOM).
|
||||
NULL is also returned for ROWs, because instead of replacing
|
||||
a Item_row to a new Item_row, Type_handler_row just replaces
|
||||
its elements.
|
||||
*/
|
||||
virtual Item *make_const_item_for_comparison(THD *thd,
|
||||
Item *src,
|
||||
Item *cmp) const= 0;
|
||||
virtual Item_cache *Item_get_cache(THD *thd, const Item *item) const= 0;
|
||||
virtual bool set_comparator_func(Arg_comparator *cmp) const= 0;
|
||||
virtual bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
@ -935,6 +955,7 @@ public:
|
||||
DBUG_ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
Item *make_const_item_for_comparison(THD *thd, Item *src, Item *cmp) const;
|
||||
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
|
||||
bool set_comparator_func(Arg_comparator *cmp) const;
|
||||
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
@ -1137,6 +1158,7 @@ public:
|
||||
SORT_FIELD_ATTR *attr) const;
|
||||
bool Item_save_in_value(Item *item, st_value *value) const;
|
||||
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
|
||||
Item *make_const_item_for_comparison(THD *thd, Item *src, Item *cmp) const;
|
||||
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
|
||||
bool set_comparator_func(Arg_comparator *cmp) const;
|
||||
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
@ -1201,6 +1223,7 @@ public:
|
||||
return Item_send_str(item, protocol, buf);
|
||||
}
|
||||
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
|
||||
Item *make_const_item_for_comparison(THD *thd, Item *src, Item *cmp) const;
|
||||
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
|
||||
bool set_comparator_func(Arg_comparator *cmp) const;
|
||||
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
@ -1257,6 +1280,7 @@ public:
|
||||
SORT_FIELD_ATTR *attr) const;
|
||||
bool Item_save_in_value(Item *item, st_value *value) const;
|
||||
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
|
||||
Item *make_const_item_for_comparison(THD *thd, Item *src, Item *cmp) const;
|
||||
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
|
||||
bool set_comparator_func(Arg_comparator *cmp) const;
|
||||
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
@ -1318,7 +1342,6 @@ public:
|
||||
bool subquery_type_allows_materialization(const Item *inner,
|
||||
const Item *outer) const;
|
||||
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
|
||||
bool set_comparator_func(Arg_comparator *cmp) const;
|
||||
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
|
||||
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
|
||||
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
|
||||
@ -1401,6 +1424,7 @@ public:
|
||||
Item *source_expr, Item *source_const) const;
|
||||
bool subquery_type_allows_materialization(const Item *inner,
|
||||
const Item *outer) const;
|
||||
Item *make_const_item_for_comparison(THD *thd, Item *src, Item *cmp) const;
|
||||
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
|
||||
bool set_comparator_func(Arg_comparator *cmp) const;
|
||||
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
@ -1693,6 +1717,8 @@ public:
|
||||
String *print_item_value(THD *thd, Item *item, String *str) const;
|
||||
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
Item **items, uint nitems) const;
|
||||
Item *make_const_item_for_comparison(THD *thd, Item *src, Item *cmp) const;
|
||||
bool set_comparator_func(Arg_comparator *cmp) const;
|
||||
cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
|
||||
in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
|
||||
};
|
||||
@ -1729,13 +1755,14 @@ class Type_handler_temporal_with_date: public Type_handler_temporal_result
|
||||
{
|
||||
public:
|
||||
virtual ~Type_handler_temporal_with_date() {}
|
||||
const Type_handler *type_handler_for_comparison() const;
|
||||
bool Item_save_in_value(Item *item, st_value *value) const;
|
||||
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
|
||||
{
|
||||
return Item_send_date(item, protocol, buf);
|
||||
}
|
||||
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
|
||||
Item *make_const_item_for_comparison(THD *thd, Item *src, Item *cmp) const;
|
||||
bool set_comparator_func(Arg_comparator *cmp) const;
|
||||
cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
|
||||
in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
|
||||
};
|
||||
@ -1747,6 +1774,7 @@ class Type_handler_date_common: public Type_handler_temporal_with_date
|
||||
public:
|
||||
virtual ~Type_handler_date_common() {}
|
||||
const Name name() const { return m_name_date; }
|
||||
const Type_handler *type_handler_for_comparison() const;
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
|
||||
enum_mysql_timestamp_type mysql_timestamp_type() const
|
||||
{
|
||||
@ -1790,6 +1818,7 @@ class Type_handler_datetime_common: public Type_handler_temporal_with_date
|
||||
public:
|
||||
virtual ~Type_handler_datetime_common() {}
|
||||
const Name name() const { return m_name_datetime; }
|
||||
const Type_handler *type_handler_for_comparison() const;
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
|
||||
enum_mysql_timestamp_type mysql_timestamp_type() const
|
||||
{
|
||||
@ -1846,6 +1875,7 @@ class Type_handler_timestamp_common: public Type_handler_temporal_with_date
|
||||
public:
|
||||
virtual ~Type_handler_timestamp_common() {}
|
||||
const Name name() const { return m_name_timestamp; }
|
||||
const Type_handler *type_handler_for_comparison() const;
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
|
||||
enum_mysql_timestamp_type mysql_timestamp_type() const
|
||||
{
|
||||
|
Reference in New Issue
Block a user