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,
enum_field_types field_type_arg):
Item_cache_int(thd, field_type_arg)
{
if (mysql_type_to_time_type(Item_cache_temporal::field_type()) ==
MYSQL_TIMESTAMP_ERROR)
set_handler_by_field_type(MYSQL_TYPE_DATETIME);
if (mysql_timestamp_type() == MYSQL_TIMESTAMP_ERROR)
set_handler(&type_handler_datetime2);
}
......@@ -9821,7 +9820,7 @@ bool Item_cache_temporal::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
}
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)
{
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)
if (date_op_with_null_check(&ltime) ||
(null_value= str->alloc(MAX_DATE_STRING_REP_LENGTH)))
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->set_charset(&my_charset_bin);
DBUG_ASSERT(!null_value);
......@@ -902,7 +902,7 @@ double Item_func_hybrid_field_type::val_real_from_date_op()
MYSQL_TIME ltime;
if (date_op_with_null_check(&ltime))
return 0;
ltime.time_type= mysql_type_to_time_type(field_type());
ltime.time_type= mysql_timestamp_type();
return TIME_to_double(&ltime);
}
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;
if (date_op_with_null_check(&ltime))
return 0;
ltime.time_type= mysql_type_to_time_type(field_type());
ltime.time_type= mysql_timestamp_type();
return TIME_to_ulonglong(&ltime);
}
......@@ -923,7 +923,7 @@ Item_func_hybrid_field_type::val_decimal_from_date_op(my_decimal *dec)
my_decimal_set_zero(dec);
return 0;
}
ltime.time_type= mysql_type_to_time_type(field_type());
ltime.time_type= mysql_timestamp_type();
return date2my_decimal(&ltime, dec);
}
......
......@@ -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 */
DBUG_ASSERT(field_type() == MYSQL_TYPE_STRING ||
ltime.time_type == MYSQL_TIMESTAMP_NONE ||
mysql_type_to_time_type(field_type()) == ltime.time_type);
ltime.time_type == mysql_timestamp_type());
return str;
}
......@@ -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)
all_are_fields &= (outer->real_item()->type() == Item::FIELD_ITEM &&
inner->real_item()->type() == Item::FIELD_ITEM);
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);
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,
}
/***************************************************************************/
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
virtual enum_field_types real_field_type() const { return field_type(); }
virtual Item_result result_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:
Check whether this parameter data type is compatible with long data.
......@@ -480,6 +484,9 @@ class Type_handler
Item *target_expr, Item *target_value,
Item_bool_func2 *source,
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 bool set_comparator_func(Arg_comparator *cmp) const= 0;
virtual bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
......@@ -605,6 +612,12 @@ class Type_handler_row: public Type_handler
return ROW_RESULT;
}
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
{
DBUG_ASSERT(0);
......@@ -834,6 +847,8 @@ class Type_handler_real_result: public Type_handler_numeric
Item_result cmp_type() const { return REAL_RESULT; }
virtual ~Type_handler_real_result() {}
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,
Sort_param *param) const;
void sortlength(THD *thd,
......@@ -889,6 +904,8 @@ class Type_handler_decimal_result: public Type_handler_numeric
Item_result cmp_type() const { return DECIMAL_RESULT; }
virtual ~Type_handler_decimal_result() {};
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;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const;
......@@ -943,6 +960,8 @@ class Type_handler_int_result: public Type_handler_numeric
Item_result cmp_type() const { return INT_RESULT; }
virtual ~Type_handler_int_result() {}
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;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const;
......@@ -1005,6 +1024,8 @@ class Type_handler_temporal_result: public Type_handler
Item *target_expr, Item *target_value,
Item_bool_func2 *source,
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;
bool set_comparator_func(Arg_comparator *cmp) 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
Item *target_expr, Item *target_value,
Item_bool_func2 *source,
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;
bool set_comparator_func(Arg_comparator *cmp) const;
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
virtual ~Type_handler_time_common() { }
const Name name() const { return m_name_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;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) 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
virtual ~Type_handler_date_common() {}
const Name name() const { return m_name_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;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const;
......@@ -1355,6 +1386,10 @@ class Type_handler_datetime_common: public Type_handler_temporal_with_date
virtual ~Type_handler_datetime_common() {}
const Name name() const { return m_name_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;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const;
......@@ -1387,6 +1422,10 @@ class Type_handler_timestamp_common: public Type_handler_temporal_with_date
virtual ~Type_handler_timestamp_common() {}
const Name name() const { return m_name_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;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const;
......@@ -1480,6 +1519,11 @@ class Type_handler_blob_common: public Type_handler_string_result
{
public:
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; }
};
......@@ -1542,6 +1586,11 @@ class Type_handler_geometry: public Type_handler_string_result
enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; }
bool is_param_long_data_type() const { return true; }
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,
const Field *target) const;
bool is_traditional_type() const
......@@ -1628,6 +1677,10 @@ class Type_handler_hybrid_field_type
}
Item_result result_type() const { return m_type_handler->result_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)
{
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