Commit 3cd7690a authored by Alexander Barkov's avatar Alexander Barkov

MDEV-12568 Add Type_handler::subquery_type_allows_materialization()

parent 5a759d31
...@@ -9711,9 +9711,8 @@ Item_cache_temporal::Item_cache_temporal(THD *thd, ...@@ -9711,9 +9711,8 @@ Item_cache_temporal::Item_cache_temporal(THD *thd,
enum_field_types field_type_arg): enum_field_types field_type_arg):
Item_cache_int(thd, field_type_arg) Item_cache_int(thd, field_type_arg)
{ {
if (mysql_type_to_time_type(Item_cache_temporal::field_type()) == if (mysql_timestamp_type() == MYSQL_TIMESTAMP_ERROR)
MYSQL_TIMESTAMP_ERROR) set_handler(&type_handler_datetime2);
set_handler_by_field_type(MYSQL_TYPE_DATETIME);
} }
...@@ -9821,7 +9820,7 @@ bool Item_cache_temporal::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) ...@@ -9821,7 +9820,7 @@ bool Item_cache_temporal::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
} }
unpack_time(value, ltime); unpack_time(value, ltime);
ltime->time_type= mysql_type_to_time_type(field_type()); ltime->time_type= mysql_timestamp_type();
if (ltime->time_type == MYSQL_TIMESTAMP_TIME) if (ltime->time_type == MYSQL_TIMESTAMP_TIME)
{ {
ltime->hour+= (ltime->month*32+ltime->day)*24; ltime->hour+= (ltime->month*32+ltime->day)*24;
......
...@@ -890,7 +890,7 @@ String *Item_func_hybrid_field_type::val_str_from_date_op(String *str) ...@@ -890,7 +890,7 @@ String *Item_func_hybrid_field_type::val_str_from_date_op(String *str)
if (date_op_with_null_check(&ltime) || if (date_op_with_null_check(&ltime) ||
(null_value= str->alloc(MAX_DATE_STRING_REP_LENGTH))) (null_value= str->alloc(MAX_DATE_STRING_REP_LENGTH)))
return (String *) 0; return (String *) 0;
ltime.time_type= mysql_type_to_time_type(field_type()); ltime.time_type= mysql_timestamp_type();
str->length(my_TIME_to_str(&ltime, const_cast<char*>(str->ptr()), decimals)); str->length(my_TIME_to_str(&ltime, const_cast<char*>(str->ptr()), decimals));
str->set_charset(&my_charset_bin); str->set_charset(&my_charset_bin);
DBUG_ASSERT(!null_value); DBUG_ASSERT(!null_value);
...@@ -902,7 +902,7 @@ double Item_func_hybrid_field_type::val_real_from_date_op() ...@@ -902,7 +902,7 @@ double Item_func_hybrid_field_type::val_real_from_date_op()
MYSQL_TIME ltime; MYSQL_TIME ltime;
if (date_op_with_null_check(&ltime)) if (date_op_with_null_check(&ltime))
return 0; return 0;
ltime.time_type= mysql_type_to_time_type(field_type()); ltime.time_type= mysql_timestamp_type();
return TIME_to_double(&ltime); return TIME_to_double(&ltime);
} }
longlong Item_func_hybrid_field_type::val_int_from_date_op() longlong Item_func_hybrid_field_type::val_int_from_date_op()
...@@ -910,7 +910,7 @@ longlong Item_func_hybrid_field_type::val_int_from_date_op() ...@@ -910,7 +910,7 @@ longlong Item_func_hybrid_field_type::val_int_from_date_op()
MYSQL_TIME ltime; MYSQL_TIME ltime;
if (date_op_with_null_check(&ltime)) if (date_op_with_null_check(&ltime))
return 0; return 0;
ltime.time_type= mysql_type_to_time_type(field_type()); ltime.time_type= mysql_timestamp_type();
return TIME_to_ulonglong(&ltime); return TIME_to_ulonglong(&ltime);
} }
...@@ -923,7 +923,7 @@ Item_func_hybrid_field_type::val_decimal_from_date_op(my_decimal *dec) ...@@ -923,7 +923,7 @@ Item_func_hybrid_field_type::val_decimal_from_date_op(my_decimal *dec)
my_decimal_set_zero(dec); my_decimal_set_zero(dec);
return 0; return 0;
} }
ltime.time_type= mysql_type_to_time_type(field_type()); ltime.time_type= mysql_timestamp_type();
return date2my_decimal(&ltime, dec); return date2my_decimal(&ltime, dec);
} }
......
...@@ -1532,7 +1532,7 @@ String *Item_temporal_hybrid_func::val_str_ascii(String *str) ...@@ -1532,7 +1532,7 @@ String *Item_temporal_hybrid_func::val_str_ascii(String *str)
/* Check that the returned timestamp type matches to the function type */ /* Check that the returned timestamp type matches to the function type */
DBUG_ASSERT(field_type() == MYSQL_TYPE_STRING || DBUG_ASSERT(field_type() == MYSQL_TYPE_STRING ||
ltime.time_type == MYSQL_TIMESTAMP_NONE || ltime.time_type == MYSQL_TIMESTAMP_NONE ||
mysql_type_to_time_type(field_type()) == ltime.time_type); ltime.time_type == mysql_timestamp_type());
return str; return str;
} }
...@@ -3226,7 +3226,7 @@ void Item_func_str_to_date::fix_length_and_dec() ...@@ -3226,7 +3226,7 @@ void Item_func_str_to_date::fix_length_and_dec()
} }
} }
} }
cached_timestamp_type= mysql_type_to_time_type(field_type()); cached_timestamp_type= mysql_timestamp_type();
} }
......
...@@ -843,34 +843,9 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs) ...@@ -843,34 +843,9 @@ bool subquery_types_allow_materialization(Item_in_subselect *in_subs)
all_are_fields &= (outer->real_item()->type() == Item::FIELD_ITEM && all_are_fields &= (outer->real_item()->type() == Item::FIELD_ITEM &&
inner->real_item()->type() == Item::FIELD_ITEM); inner->real_item()->type() == Item::FIELD_ITEM);
total_key_length += inner->max_length; total_key_length += inner->max_length;
if (outer->cmp_type() != inner->cmp_type()) if (!inner->type_handler()->subquery_type_allows_materialization(inner,
outer))
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
switch (outer->cmp_type()) {
case STRING_RESULT:
if (!(outer->collation.collation == inner->collation.collation))
DBUG_RETURN(FALSE);
// Materialization does not work with BLOB columns
if (inner->field_type() == MYSQL_TYPE_BLOB ||
inner->field_type() == MYSQL_TYPE_GEOMETRY)
DBUG_RETURN(FALSE);
/*
Materialization also is unable to work when create_tmp_table() will
create a blob column because item->max_length is too big.
The following check is copied from Item::make_string_field():
*/
if (inner->too_big_for_varchar())
{
DBUG_RETURN(FALSE);
}
break;
case TIME_RESULT:
if (mysql_type_to_time_type(outer->field_type()) !=
mysql_type_to_time_type(inner->field_type()))
DBUG_RETURN(FALSE);
default:
/* suitable for materialization */
break;
}
} }
/* /*
......
...@@ -3187,3 +3187,57 @@ uint Type_handler_string_result::Item_temporal_precision(Item *item, ...@@ -3187,3 +3187,57 @@ uint Type_handler_string_result::Item_temporal_precision(Item *item,
} }
/***************************************************************************/ /***************************************************************************/
bool Type_handler_real_result::
subquery_type_allows_materialization(const Item *inner,
const Item *outer) const
{
DBUG_ASSERT(inner->cmp_type() == REAL_RESULT);
return outer->cmp_type() == REAL_RESULT;
}
bool Type_handler_int_result::
subquery_type_allows_materialization(const Item *inner,
const Item *outer) const
{
DBUG_ASSERT(inner->cmp_type() == INT_RESULT);
return outer->cmp_type() == INT_RESULT;
}
bool Type_handler_decimal_result::
subquery_type_allows_materialization(const Item *inner,
const Item *outer) const
{
DBUG_ASSERT(inner->cmp_type() == DECIMAL_RESULT);
return outer->cmp_type() == DECIMAL_RESULT;
}
bool Type_handler_string_result::
subquery_type_allows_materialization(const Item *inner,
const Item *outer) const
{
DBUG_ASSERT(inner->cmp_type() == STRING_RESULT);
return outer->cmp_type() == STRING_RESULT &&
outer->collation.collation == inner->collation.collation &&
/*
Materialization also is unable to work when create_tmp_table() will
create a blob column because item->max_length is too big.
The following test is copied from Item::make_string_field():
*/
!inner->too_big_for_varchar();
}
bool Type_handler_temporal_result::
subquery_type_allows_materialization(const Item *inner,
const Item *outer) const
{
DBUG_ASSERT(inner->cmp_type() == TIME_RESULT);
return mysql_timestamp_type() ==
outer->type_handler()->mysql_timestamp_type();
}
/***************************************************************************/
...@@ -367,6 +367,10 @@ class Type_handler ...@@ -367,6 +367,10 @@ class Type_handler
virtual enum_field_types real_field_type() const { return field_type(); } virtual enum_field_types real_field_type() const { return field_type(); }
virtual Item_result result_type() const= 0; virtual Item_result result_type() const= 0;
virtual Item_result cmp_type() const= 0; virtual Item_result cmp_type() const= 0;
virtual enum_mysql_timestamp_type mysql_timestamp_type() const
{
return MYSQL_TIMESTAMP_ERROR;
}
/** /**
Prepared statement long data: Prepared statement long data:
Check whether this parameter data type is compatible with long data. Check whether this parameter data type is compatible with long data.
...@@ -480,6 +484,9 @@ class Type_handler ...@@ -480,6 +484,9 @@ class Type_handler
Item *target_expr, Item *target_value, Item *target_expr, Item *target_value,
Item_bool_func2 *source, Item_bool_func2 *source,
Item *source_expr, Item *source_const) const= 0; Item *source_expr, Item *source_const) const= 0;
virtual bool
subquery_type_allows_materialization(const Item *inner,
const Item *outer) const= 0;
virtual Item_cache *Item_get_cache(THD *thd, const Item *item) 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 set_comparator_func(Arg_comparator *cmp) const= 0;
virtual bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, virtual bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
...@@ -605,6 +612,12 @@ class Type_handler_row: public Type_handler ...@@ -605,6 +612,12 @@ class Type_handler_row: public Type_handler
return ROW_RESULT; return ROW_RESULT;
} }
const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_comparison() const;
bool subquery_type_allows_materialization(const Item *inner,
const Item *outer) const
{
DBUG_ASSERT(0);
return false;
}
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const
{ {
DBUG_ASSERT(0); DBUG_ASSERT(0);
...@@ -834,6 +847,8 @@ class Type_handler_real_result: public Type_handler_numeric ...@@ -834,6 +847,8 @@ class Type_handler_real_result: public Type_handler_numeric
Item_result cmp_type() const { return REAL_RESULT; } Item_result cmp_type() const { return REAL_RESULT; }
virtual ~Type_handler_real_result() {} virtual ~Type_handler_real_result() {}
const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_comparison() const;
bool subquery_type_allows_materialization(const Item *inner,
const Item *outer) const;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const; Sort_param *param) const;
void sortlength(THD *thd, void sortlength(THD *thd,
...@@ -889,6 +904,8 @@ class Type_handler_decimal_result: public Type_handler_numeric ...@@ -889,6 +904,8 @@ class Type_handler_decimal_result: public Type_handler_numeric
Item_result cmp_type() const { return DECIMAL_RESULT; } Item_result cmp_type() const { return DECIMAL_RESULT; }
virtual ~Type_handler_decimal_result() {}; virtual ~Type_handler_decimal_result() {};
const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_comparison() const;
bool subquery_type_allows_materialization(const Item *inner,
const Item *outer) const;
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const; Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const; Sort_param *param) const;
...@@ -943,6 +960,8 @@ class Type_handler_int_result: public Type_handler_numeric ...@@ -943,6 +960,8 @@ class Type_handler_int_result: public Type_handler_numeric
Item_result cmp_type() const { return INT_RESULT; } Item_result cmp_type() const { return INT_RESULT; }
virtual ~Type_handler_int_result() {} virtual ~Type_handler_int_result() {}
const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_comparison() const;
bool subquery_type_allows_materialization(const Item *inner,
const Item *outer) const;
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const; Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field, void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const; Sort_param *param) const;
...@@ -1005,6 +1024,8 @@ class Type_handler_temporal_result: public Type_handler ...@@ -1005,6 +1024,8 @@ class Type_handler_temporal_result: public Type_handler
Item *target_expr, Item *target_value, Item *target_expr, Item *target_value,
Item_bool_func2 *source, Item_bool_func2 *source,
Item *source_expr, Item *source_const) const; Item *source_expr, Item *source_const) const;
bool subquery_type_allows_materialization(const Item *inner,
const Item *outer) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) 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_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
...@@ -1081,6 +1102,8 @@ class Type_handler_string_result: public Type_handler ...@@ -1081,6 +1102,8 @@ class Type_handler_string_result: public Type_handler
Item *target_expr, Item *target_value, Item *target_expr, Item *target_value,
Item_bool_func2 *source, Item_bool_func2 *source,
Item *source_expr, Item *source_const) const; Item *source_expr, Item *source_const) const;
bool subquery_type_allows_materialization(const Item *inner,
const Item *outer) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const; Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const; bool set_comparator_func(Arg_comparator *cmp) const;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
...@@ -1278,6 +1301,10 @@ class Type_handler_time_common: public Type_handler_temporal_result ...@@ -1278,6 +1301,10 @@ class Type_handler_time_common: public Type_handler_temporal_result
virtual ~Type_handler_time_common() { } virtual ~Type_handler_time_common() { }
const Name name() const { return m_name_time; } const Name name() const { return m_name_time; }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; } enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
enum_mysql_timestamp_type mysql_timestamp_type() const
{
return MYSQL_TIMESTAMP_TIME;
}
const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_comparison() const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
String *print_item_value(THD *thd, Item *item, String *str) const; String *print_item_value(THD *thd, Item *item, String *str) const;
...@@ -1325,6 +1352,10 @@ class Type_handler_date_common: public Type_handler_temporal_with_date ...@@ -1325,6 +1352,10 @@ class Type_handler_date_common: public Type_handler_temporal_with_date
virtual ~Type_handler_date_common() {} virtual ~Type_handler_date_common() {}
const Name name() const { return m_name_date; } const Name name() const { return m_name_date; }
enum_field_types field_type() const { return MYSQL_TYPE_DATE; } enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
enum_mysql_timestamp_type mysql_timestamp_type() const
{
return MYSQL_TIMESTAMP_DATE;
}
String *print_item_value(THD *thd, Item *item, String *str) const; String *print_item_value(THD *thd, Item *item, String *str) const;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const; Item **items, uint nitems) const;
...@@ -1355,6 +1386,10 @@ class Type_handler_datetime_common: public Type_handler_temporal_with_date ...@@ -1355,6 +1386,10 @@ class Type_handler_datetime_common: public Type_handler_temporal_with_date
virtual ~Type_handler_datetime_common() {} virtual ~Type_handler_datetime_common() {}
const Name name() const { return m_name_datetime; } const Name name() const { return m_name_datetime; }
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
enum_mysql_timestamp_type mysql_timestamp_type() const
{
return MYSQL_TIMESTAMP_DATETIME;
}
String *print_item_value(THD *thd, Item *item, String *str) const; String *print_item_value(THD *thd, Item *item, String *str) const;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const; Item **items, uint nitems) const;
...@@ -1387,6 +1422,10 @@ class Type_handler_timestamp_common: public Type_handler_temporal_with_date ...@@ -1387,6 +1422,10 @@ class Type_handler_timestamp_common: public Type_handler_temporal_with_date
virtual ~Type_handler_timestamp_common() {} virtual ~Type_handler_timestamp_common() {}
const Name name() const { return m_name_timestamp; } const Name name() const { return m_name_timestamp; }
enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; } enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
enum_mysql_timestamp_type mysql_timestamp_type() const
{
return MYSQL_TIMESTAMP_DATETIME;
}
String *print_item_value(THD *thd, Item *item, String *str) const; String *print_item_value(THD *thd, Item *item, String *str) const;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func, bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const; Item **items, uint nitems) const;
...@@ -1480,6 +1519,11 @@ class Type_handler_blob_common: public Type_handler_string_result ...@@ -1480,6 +1519,11 @@ class Type_handler_blob_common: public Type_handler_string_result
{ {
public: public:
virtual ~Type_handler_blob_common() { } virtual ~Type_handler_blob_common() { }
bool subquery_type_allows_materialization(const Item *inner,
const Item *outer) const
{
return false; // Materialization does not work with BLOB columns
}
bool is_param_long_data_type() const { return true; } bool is_param_long_data_type() const { return true; }
}; };
...@@ -1542,6 +1586,11 @@ class Type_handler_geometry: public Type_handler_string_result ...@@ -1542,6 +1586,11 @@ class Type_handler_geometry: public Type_handler_string_result
enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; } enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; }
bool is_param_long_data_type() const { return true; } bool is_param_long_data_type() const { return true; }
const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_comparison() const;
bool subquery_type_allows_materialization(const Item *inner,
const Item *outer) const
{
return false; // Materialization does not work with GEOMETRY columns
}
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool is_traditional_type() const bool is_traditional_type() const
...@@ -1628,6 +1677,10 @@ class Type_handler_hybrid_field_type ...@@ -1628,6 +1677,10 @@ class Type_handler_hybrid_field_type
} }
Item_result result_type() const { return m_type_handler->result_type(); } Item_result result_type() const { return m_type_handler->result_type(); }
Item_result cmp_type() const { return m_type_handler->cmp_type(); } Item_result cmp_type() const { return m_type_handler->cmp_type(); }
enum_mysql_timestamp_type mysql_timestamp_type() const
{
return m_type_handler->mysql_timestamp_type();
}
void set_handler(const Type_handler *other) void set_handler(const Type_handler *other)
{ {
m_type_handler= other; m_type_handler= other;
......
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