maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #10186
MDEV-11558 Split Item_type_holder::display_length into virtual methods in Type_handler
Hello Nirbhay,
Can you please review a patch for MDEV-11558?
Thanks!
diff --git a/sql/item.cc b/sql/item.cc
index a1c3f13..831e9b4 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -9958,12 +9958,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:
@@ -10000,7 +10000,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);
@@ -10012,64 +10012,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
diff --git a/sql/item.h b/sql/item.h
index 6651fee..724356d 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -697,6 +697,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);
@@ -2498,7 +2526,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);
@@ -5575,7 +5603,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; }
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index fc34c7c..cc87c8e 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -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
{
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 6a694df..d9bc0eb 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -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;
};
Follow ups