Commit 7d0a8832 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-11558 Split Item_type_holder::display_length into virtual methods in Type_handler

parent 93bc7283
......@@ -10085,12 +10085,12 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
if (collation.collation != &my_charset_bin)
{
max_length= MY_MAX(old_max_chars * collation.collation->mbmaxlen,
display_length(item) /
item->max_display_length() /
item->collation.collation->mbmaxlen *
collation.collation->mbmaxlen);
}
else
set_if_bigger(max_length, display_length(item));
set_if_bigger(max_length, item->max_display_length());
break;
}
case REAL_RESULT:
......@@ -10127,7 +10127,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
break;
}
default:
max_length= MY_MAX(max_length, display_length(item));
max_length= MY_MAX(max_length, item->max_display_length());
};
maybe_null|= item->maybe_null;
get_full_info(item);
......@@ -10139,64 +10139,6 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
DBUG_RETURN(FALSE);
}
/**
Calculate lenth for merging result for given Item type.
@param item Item for length detection
@return
length
*/
uint32 Item_type_holder::display_length(Item *item)
{
if (item->type() == Item::FIELD_ITEM)
return ((Item_field *)item)->max_disp_length();
switch (item->field_type())
{
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_YEAR:
case MYSQL_TYPE_NEWDATE:
case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_BIT:
case MYSQL_TYPE_NEWDECIMAL:
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_GEOMETRY:
return item->max_length;
case MYSQL_TYPE_TINY:
return 4;
case MYSQL_TYPE_SHORT:
return 6;
case MYSQL_TYPE_LONG:
return MY_INT32_NUM_DECIMAL_DIGITS;
case MYSQL_TYPE_FLOAT:
return 25;
case MYSQL_TYPE_DOUBLE:
return 53;
case MYSQL_TYPE_NULL:
return 0;
case MYSQL_TYPE_LONGLONG:
return 20;
case MYSQL_TYPE_INT24:
return 8;
default:
DBUG_ASSERT(0); // we should never go there
return 0;
}
}
/**
Make temporary table field according collected information about type
......
......@@ -721,6 +721,34 @@ class Item: public Value_source,
{
return Type_handler::string_type_handler(max_length)->field_type();
}
/*
Calculate the maximum length of an expression.
This method is used in data type aggregation for UNION, e.g.:
SELECT 'b' UNION SELECT COALESCE(double_10_3_field) FROM t1;
The result is usually equal to max_length, except for some numeric types.
In case of the INT, FLOAT, DOUBLE data types Item::max_length and
Item::decimals are ignored, so the returned value depends only on the
data type itself. E.g. for an expression of the DOUBLE(10,3) data type,
the result is always 53 (length 10 and precision 3 do not matter).
max_length is ignored for these numeric data types because the length limit
means only "expected maximum length", it is not a hard limit, so it does
not impose any data truncation. E.g. a column of the type INT(4) can
normally store big values up to 2147483647 without truncation. When we're
aggregating such column for UNION it's important to create a long enough
result column, not to lose any data.
For detailed behaviour of various data types see implementations of
the corresponding Type_handler_xxx::max_display_length().
Note, Item_field::max_display_length() overrides this to get
max_display_length() from the underlying field.
*/
virtual uint32 max_display_length() const
{
return type_handler()->max_display_length(this);
}
Item_cache* get_cache(THD *thd) const
{
return type_handler()->Item_get_cache(thd, this);
......@@ -2459,7 +2487,7 @@ class Item_field :public Item_ident
Item_equal *find_item_equal(COND_EQUAL *cond_equal);
Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *);
Item *replace_equal_field(THD *thd, uchar *arg);
inline uint32 max_disp_length() { return field->max_display_length(); }
uint32 max_display_length() const { return field->max_display_length(); }
Item_field *field_for_view_update() { return this; }
int fix_outer_field(THD *thd, Field **field, Item **reference);
virtual Item *update_value_transformer(THD *thd, uchar *select_arg);
......@@ -5545,7 +5573,6 @@ class Item_type_holder: public Item,
String *val_str(String*);
bool join_types(THD *thd, Item *);
Field *make_field_by_type(TABLE *table);
static uint32 display_length(Item *item);
static enum_field_types get_real_type(Item *);
Field::geometry_type get_geometry_type() const { return geometry_type; };
Item* get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
......
......@@ -695,6 +695,37 @@ Field *Type_handler_set::make_conversion_table_field(TABLE *table,
/*************************************************************************/
uint32 Type_handler_decimal_result::max_display_length(const Item *item) const
{
return item->max_length;
}
uint32 Type_handler_temporal_result::max_display_length(const Item *item) const
{
return item->max_length;
}
uint32 Type_handler_string_result::max_display_length(const Item *item) const
{
return item->max_length;
}
uint32 Type_handler_year::max_display_length(const Item *item) const
{
return item->max_length;
}
uint32 Type_handler_bit::max_display_length(const Item *item) const
{
return item->max_length;
}
/*************************************************************************/
int Type_handler_time_common::Item_save_in_field(Item *item, Field *field,
bool no_conversions) const
{
......
......@@ -291,6 +291,7 @@ class Type_handler
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const= 0;
virtual uint32 max_display_length(const Item *item) const= 0;
virtual int Item_save_in_field(Item *item, Field *field,
bool no_conversions) const= 0;
virtual Item_cache *Item_get_cache(THD *thd, const Item *item) const= 0;
......@@ -372,6 +373,11 @@ class Type_handler_row: public Type_handler
{
DBUG_ASSERT(0);
}
uint32 max_display_length(const Item *item) const
{
DBUG_ASSERT(0);
return 0;
}
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const
{
DBUG_ASSERT(0);
......@@ -493,6 +499,7 @@ class Type_handler_decimal_result: public Type_handler_numeric
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
uint32 max_display_length(const Item *item) const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const;
......@@ -564,6 +571,7 @@ class Type_handler_temporal_result: public Type_handler
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
uint32 max_display_length(const Item *item) 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;
......@@ -600,6 +608,7 @@ class Type_handler_string_result: public Type_handler
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
uint32 max_display_length(const Item *item) const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const;
......@@ -649,6 +658,7 @@ class Type_handler_tiny: public Type_handler_int_result
public:
virtual ~Type_handler_tiny() {}
enum_field_types field_type() const { return MYSQL_TYPE_TINY; }
uint32 max_display_length(const Item *item) const { return 4; }
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const;
};
......@@ -659,6 +669,7 @@ class Type_handler_short: public Type_handler_int_result
public:
virtual ~Type_handler_short() {}
enum_field_types field_type() const { return MYSQL_TYPE_SHORT; }
uint32 max_display_length(const Item *item) const { return 6; }
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const;
};
......@@ -669,6 +680,10 @@ class Type_handler_long: public Type_handler_int_result
public:
virtual ~Type_handler_long() {}
enum_field_types field_type() const { return MYSQL_TYPE_LONG; }
uint32 max_display_length(const Item *item) const
{
return MY_INT32_NUM_DECIMAL_DIGITS;
}
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const;
};
......@@ -679,6 +694,7 @@ class Type_handler_longlong: public Type_handler_int_result
public:
virtual ~Type_handler_longlong() {}
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
uint32 max_display_length(const Item *item) const { return 20; }
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const;
};
......@@ -689,6 +705,7 @@ class Type_handler_int24: public Type_handler_int_result
public:
virtual ~Type_handler_int24() {}
enum_field_types field_type() const { return MYSQL_TYPE_INT24; }
uint32 max_display_length(const Item *item) const { return 8; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
};
......@@ -699,6 +716,7 @@ class Type_handler_year: public Type_handler_int_result
public:
virtual ~Type_handler_year() {}
enum_field_types field_type() const { return MYSQL_TYPE_YEAR; }
uint32 max_display_length(const Item *item) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
};
......@@ -709,6 +727,7 @@ class Type_handler_bit: public Type_handler_int_result
public:
virtual ~Type_handler_bit() {}
enum_field_types field_type() const { return MYSQL_TYPE_BIT; }
uint32 max_display_length(const Item *item) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
};
......@@ -719,6 +738,7 @@ class Type_handler_float: public Type_handler_real_result
public:
virtual ~Type_handler_float() {}
enum_field_types field_type() const { return MYSQL_TYPE_FLOAT; }
uint32 max_display_length(const Item *item) const { return 25; }
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
......@@ -730,6 +750,7 @@ class Type_handler_double: public Type_handler_real_result
public:
virtual ~Type_handler_double() {}
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
uint32 max_display_length(const Item *item) const { return 53; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
};
......@@ -860,6 +881,7 @@ class Type_handler_null: public Type_handler_string_result
public:
virtual ~Type_handler_null() {}
enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
uint32 max_display_length(const Item *item) const { return 0; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
};
......
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