mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-12775 Reuse data type aggregation code for hybrid functions and UNION
Introducing a new class Type_holder (used internally in sql_union.cc), to reuse exactly the same data type attribute aggregation Type_handler API for hybrid functions and UNION. This fixes a number of bugs in UNION: - MDEV-9495 Wrong field type for a UNION of a signed and an unsigned INT expression - MDEV-9497 UNION and COALESCE produce different field types for DECIMAL+INT - MDEV-12594 UNION between fixed length double columns does not always preserve scale - MDEV-12595 UNION converts INT to BIGINT - MDEV-12599 UNION is not symmetric when mixing INT and CHAR Details: - sql_union.cc: Reusing attribute aggregation for UNION. Adding new methods: * st_select_lex_unit::join_union_type_handlers() * st_select_lex_unit::join_union_type_attributes() * st_select_lex_unit::join_union_item_types() Removing the old join_types()-based code. - Changing Type_handler::Item_hybrid_func_fix_attributes() to accept "name", Type_handler_hybrid_field_type, Type_all_attributes as three separate parameters instead of a single Item_hybrid_func parameter, to make it possible to pass both Item_hybrid_func and Type_holder. - Moving the former special GEOMETRY and ENUM/SET attribute aggregation code from Item_type_holder::join_types() to * Type_handler_typelib::Item_hybrid_func_fix_attributes(). * Type_handler_geometry::Item_hybrid_func_fix_attrubutes(). This makes GEOMETRY/ENUM/SET symmetric with all other data types (from the UNION point of view). Removing Item_type_holder::join_types() and Item_type_holder::get_full_info(). - Adding new methods into Type_all_attributes: * Type_all_attributes::set_geometry_type() and Item_hybrid_func::set_geometry_type(). * Adding Type_all_attributes::get_typelib(). * Adding Type_all_attributes::set_typelib(). - Adding Type_handler_typelib as a common parent for Type_handler_enum and Type_handler_set, to avoid code duplication: they have already had two common methods, and we're adding one more shared method. - Adding Type_all_attributes::set_maybe_null(), as some type handlers may want to set maybe_null (e.g. Type_handler_geometry) during data type attribute aggregation. - Changing Type_geometry_attributes() to accept Type_handler and Type_all_attributes as two separate parameters, instead of a single Item parameter, to make it possible to pass Type_holder. - Adding Item_args::add_argument(). - Moving Item_args::alloc_arguments() from "protected" to "public". - Moving Item_type_holder::Item_type_holder() from item.cc to item.h, as now it's very simple. Btw, this constructor should probably be eventually removed. It's now used only in sql_show.cc, which could be modified to use Item_return_decimal (for symmetry with Item_return_xxx created for all other data types). Or, another option: remove all Item_return_xxx and use Item_type_holder for all data types instead. - storage/tokudb/mysql-test/tokudb/r/type_float.result Recording new results (MDEV-12594). - mysql-test/r/cte_recursive.result Recording new results (MDEV-9497) - mysql-test/r/subselect*.result Recording new results (MDEV-12595) - mysql-test/r/metadata.result Recording new results (MDEV-9495) - mysql-test/r/temp_table.result Recording new results (MDEV-12594) - mysql-test/r/type_float.result Recording new results (MDEV-12594)
This commit is contained in:
104
sql/sql_type.cc
104
sql/sql_type.cc
@ -482,29 +482,18 @@ const Type_handler *Type_handler_row::type_handler_for_comparison() const
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
const Type_handler *Type_handler_enum::type_handler_for_item_field() const
|
||||
const Type_handler *Type_handler_typelib::type_handler_for_item_field() const
|
||||
{
|
||||
return &type_handler_string;
|
||||
}
|
||||
|
||||
|
||||
const Type_handler *Type_handler_enum::cast_to_int_type_handler() const
|
||||
const Type_handler *Type_handler_typelib::cast_to_int_type_handler() const
|
||||
{
|
||||
return &type_handler_longlong;
|
||||
}
|
||||
|
||||
|
||||
const Type_handler *Type_handler_set::type_handler_for_item_field() const
|
||||
{
|
||||
return &type_handler_string;
|
||||
}
|
||||
|
||||
|
||||
const Type_handler *Type_handler_set::cast_to_int_type_handler() const
|
||||
{
|
||||
return &type_handler_longlong;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
bool
|
||||
@ -2080,7 +2069,10 @@ Type_handler_temporal_result::Item_get_cache(THD *thd, const Item *item) const
|
||||
/*************************************************************************/
|
||||
|
||||
bool Type_handler_int_result::
|
||||
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
Item_hybrid_func_fix_attributes(THD *thd,
|
||||
const char *func_name,
|
||||
Type_handler_hybrid_field_type *handler,
|
||||
Type_all_attributes *func,
|
||||
Item **items, uint nitems) const
|
||||
{
|
||||
uint unsigned_flag= items[0]->unsigned_flag;
|
||||
@ -2089,7 +2081,7 @@ bool Type_handler_int_result::
|
||||
if (unsigned_flag != items[i]->unsigned_flag)
|
||||
{
|
||||
// Convert a mixture of signed and unsigned int to decimal
|
||||
func->set_handler(&type_handler_newdecimal);
|
||||
handler->set_handler(&type_handler_newdecimal);
|
||||
func->aggregate_attributes_decimal(items, nitems);
|
||||
return false;
|
||||
}
|
||||
@ -2100,7 +2092,10 @@ bool Type_handler_int_result::
|
||||
|
||||
|
||||
bool Type_handler_real_result::
|
||||
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
Item_hybrid_func_fix_attributes(THD *thd,
|
||||
const char *func_name,
|
||||
Type_handler_hybrid_field_type *handler,
|
||||
Type_all_attributes *func,
|
||||
Item **items, uint nitems) const
|
||||
{
|
||||
func->aggregate_attributes_real(items, nitems);
|
||||
@ -2109,7 +2104,10 @@ bool Type_handler_real_result::
|
||||
|
||||
|
||||
bool Type_handler_decimal_result::
|
||||
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
Item_hybrid_func_fix_attributes(THD *thd,
|
||||
const char *func_name,
|
||||
Type_handler_hybrid_field_type *handler,
|
||||
Type_all_attributes *func,
|
||||
Item **items, uint nitems) const
|
||||
{
|
||||
func->aggregate_attributes_decimal(items, nitems);
|
||||
@ -2118,26 +2116,59 @@ bool Type_handler_decimal_result::
|
||||
|
||||
|
||||
bool Type_handler_string_result::
|
||||
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
Item_hybrid_func_fix_attributes(THD *thd,
|
||||
const char *func_name,
|
||||
Type_handler_hybrid_field_type *handler,
|
||||
Type_all_attributes *func,
|
||||
Item **items, uint nitems) const
|
||||
{
|
||||
return func->aggregate_attributes_string(func->func_name(), items, nitems);
|
||||
return func->aggregate_attributes_string(func_name, items, nitems);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
We can have enum/set type after merging only if we have one enum|set
|
||||
field (or MIN|MAX(enum|set field)) and number of NULL fields
|
||||
*/
|
||||
bool Type_handler_typelib::
|
||||
Item_hybrid_func_fix_attributes(THD *thd,
|
||||
const char *func_name,
|
||||
Type_handler_hybrid_field_type *handler,
|
||||
Type_all_attributes *func,
|
||||
Item **items, uint nitems) const
|
||||
{
|
||||
TYPELIB *typelib= NULL;
|
||||
for (uint i= 0; i < nitems; i++)
|
||||
{
|
||||
if ((typelib= items[i]->get_typelib()))
|
||||
break;
|
||||
}
|
||||
DBUG_ASSERT(typelib); // There must be at least one typelib
|
||||
func->set_typelib(typelib);
|
||||
return func->aggregate_attributes_string(func_name, items, nitems);
|
||||
}
|
||||
|
||||
|
||||
bool Type_handler_blob_common::
|
||||
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
Item_hybrid_func_fix_attributes(THD *thd,
|
||||
const char *func_name,
|
||||
Type_handler_hybrid_field_type *handler,
|
||||
Type_all_attributes *func,
|
||||
Item **items, uint nitems) const
|
||||
{
|
||||
if (func->aggregate_attributes_string(func->func_name(), items, nitems))
|
||||
if (func->aggregate_attributes_string(func_name, items, nitems))
|
||||
return true;
|
||||
func->set_handler(blob_type_handler(func->max_length));
|
||||
handler->set_handler(blob_type_handler(func->max_length));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Type_handler_date_common::
|
||||
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
Item_hybrid_func_fix_attributes(THD *thd,
|
||||
const char *func_name,
|
||||
Type_handler_hybrid_field_type *handler,
|
||||
Type_all_attributes *func,
|
||||
Item **items, uint nitems) const
|
||||
{
|
||||
func->fix_attributes_date();
|
||||
@ -2146,7 +2177,10 @@ bool Type_handler_date_common::
|
||||
|
||||
|
||||
bool Type_handler_time_common::
|
||||
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
Item_hybrid_func_fix_attributes(THD *thd,
|
||||
const char *func_name,
|
||||
Type_handler_hybrid_field_type *handler,
|
||||
Type_all_attributes *func,
|
||||
Item **items, uint nitems) const
|
||||
{
|
||||
func->aggregate_attributes_temporal(MIN_TIME_WIDTH, items, nitems);
|
||||
@ -2155,7 +2189,10 @@ bool Type_handler_time_common::
|
||||
|
||||
|
||||
bool Type_handler_datetime_common::
|
||||
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
Item_hybrid_func_fix_attributes(THD *thd,
|
||||
const char *func_name,
|
||||
Type_handler_hybrid_field_type *handler,
|
||||
Type_all_attributes *func,
|
||||
Item **items, uint nitems) const
|
||||
{
|
||||
func->aggregate_attributes_temporal(MAX_DATETIME_WIDTH, items, nitems);
|
||||
@ -2164,7 +2201,10 @@ bool Type_handler_datetime_common::
|
||||
|
||||
|
||||
bool Type_handler_timestamp_common::
|
||||
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
Item_hybrid_func_fix_attributes(THD *thd,
|
||||
const char *func_name,
|
||||
Type_handler_hybrid_field_type *handler,
|
||||
Type_all_attributes *func,
|
||||
Item **items, uint nitems) const
|
||||
{
|
||||
func->aggregate_attributes_temporal(MAX_DATETIME_WIDTH, items, nitems);
|
||||
@ -2173,11 +2213,14 @@ bool Type_handler_timestamp_common::
|
||||
|
||||
#ifdef HAVE_SPATIAL
|
||||
bool Type_handler_geometry::
|
||||
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
Item_hybrid_func_fix_attributes(THD *thd,
|
||||
const char *func_name,
|
||||
Type_handler_hybrid_field_type *handler,
|
||||
Type_all_attributes *func,
|
||||
Item **items, uint nitems) const
|
||||
{
|
||||
DBUG_ASSERT(nitems > 0);
|
||||
Type_geometry_attributes gattr(items[0]);
|
||||
Type_geometry_attributes gattr(items[0]->type_handler(), items[0]);
|
||||
for (uint i= 1; i < nitems; i++)
|
||||
gattr.join(items[i]);
|
||||
func->set_geometry_type(gattr.get_geometry_type());
|
||||
@ -2185,7 +2228,7 @@ bool Type_handler_geometry::
|
||||
func->unsigned_flag= false;
|
||||
func->decimals= 0;
|
||||
func->max_length= (uint32) UINT_MAX32;
|
||||
func->maybe_null= true;
|
||||
func->set_maybe_null(true);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@ -2202,7 +2245,8 @@ bool Type_handler::
|
||||
with aggregating for CASE-alike functions (e.g. COALESCE)
|
||||
for the majority of data type handlers.
|
||||
*/
|
||||
return Item_hybrid_func_fix_attributes(thd, func, items, nitems);
|
||||
return Item_hybrid_func_fix_attributes(thd, func->func_name(),
|
||||
func, func, items, nitems);
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user