maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #10215
Please review MDEV-11615 Split Item_hybrid_func::fix_attributes into virtual methods in Type_handler
Hello Sanja,
Please review a patch for MDEV-11615.
Thanks!
commit 0fc326434740e8beb411ef5c71ee615581b91c77
Author: Alexander Barkov <bar@xxxxxxxxxxx>
Date: Tue Dec 20 18:19:47 2016 +0400
MDEV-11615 Split Item_hybrid_func::fix_attributes into virtual methods in Type_handler
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index a81dd46..f4bd211 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -3108,25 +3108,19 @@ void Item_func_case::fix_length_and_dec()
set_handler_by_field_type(agg_field_type(agg, nagg, true));
- if (Item_func_case::result_type() == STRING_RESULT)
- {
- if (count_string_result_length(Item_func_case::field_type(), agg, nagg))
- return;
- /*
- Copy all THEN and ELSE items back to args[] array.
- Some of the items might have been changed to Item_func_conv_charset.
- */
- for (nagg= 0 ; nagg < ncases / 2 ; nagg++)
- change_item_tree_if_needed(thd, &args[nagg * 2 + 1], agg[nagg]);
+ if (fix_attributes(agg, nagg))
+ return;
+
+ /*
+ Copy all modified THEN and ELSE items back to args[] array.
+ Some of the items might have been changed to Item_func_conv_charset.
+ */
+ for (nagg= 0 ; nagg < ncases / 2 ; nagg++)
+ change_item_tree_if_needed(thd, &args[nagg * 2 + 1], agg[nagg]);
+
+ if (else_expr_num != -1)
+ change_item_tree_if_needed(thd, &args[else_expr_num], agg[nagg++]);
- if (else_expr_num != -1)
- change_item_tree_if_needed(thd, &args[else_expr_num], agg[nagg++]);
- }
- else
- {
- fix_attributes(agg, nagg);
- }
-
/*
Aggregate first expression and all WHEN expression types
and collations when string comparison
@@ -3405,31 +3399,12 @@ my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value)
}
-void Item_hybrid_func::fix_attributes(Item **items, uint nitems)
+bool Item_hybrid_func::fix_attributes(Item **items, uint nitems)
{
- switch (Item_hybrid_func::result_type()) {
- case STRING_RESULT:
- if (count_string_result_length(Item_hybrid_func::field_type(),
- items, nitems))
- return;
- break;
- case DECIMAL_RESULT:
- collation.set_numeric();
- count_decimal_length(items, nitems);
- break;
- case REAL_RESULT:
- collation.set_numeric();
- count_real_length(items, nitems);
- break;
- case INT_RESULT:
- collation.set_numeric();
- count_only_length(items, nitems);
- decimals= 0;
- break;
- case ROW_RESULT:
- case TIME_RESULT:
- DBUG_ASSERT(0);
- }
+ bool rc= Item_hybrid_func::type_handler()->
+ Item_hybrid_func_fix_attributes(current_thd, this, items, nitems);
+ DBUG_ASSERT(!rc || current_thd->is_error());
+ return rc;
}
/****************************************************************************
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 716c47e..d1c3737 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -568,30 +568,6 @@ void Item_udf_func::fix_num_length_and_dec()
/**
- Count max_length and decimals for temporal functions.
-
- @param item Argument array
- @param nitems Number of arguments in the array.
-
- @retval False on success, true on error.
-*/
-void Item_func::count_datetime_length(enum_field_types field_type_arg,
- Item **item, uint nitems)
-{
- unsigned_flag= 0;
- decimals= 0;
- if (field_type_arg != MYSQL_TYPE_DATE)
- {
- for (uint i= 0; i < nitems; i++)
- set_if_bigger(decimals, item[i]->decimals);
- }
- set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
- uint len= decimals ? (decimals + 1) : 0;
- len+= mysql_temporal_int_part_length(field_type_arg);
- fix_char_length(len);
-}
-
-/**
Set max_length/decimals of function if function is fixed point and
result length/precision depends on argument ones.
*/
@@ -665,7 +641,7 @@ void Item_func::count_real_length(Item **items, uint nitems)
/**
- Calculate max_length and decimals for STRING_RESULT functions.
+ Calculate max_length and decimals for string functions.
@param field_type Field type.
@param items Argument array.
@@ -673,18 +649,13 @@ void Item_func::count_real_length(Item **items, uint nitems)
@retval False on success, true on error.
*/
-bool Item_func::count_string_result_length(enum_field_types field_type_arg,
- Item **items, uint nitems)
+bool Item_func::count_string_length(Item **items, uint nitems)
{
+ DBUG_ASSERT(!is_temporal_type(field_type()));
if (agg_arg_charsets_for_string_result(collation, items, nitems, 1))
return true;
- if (is_temporal_type(field_type_arg))
- count_datetime_length(field_type_arg, items, nitems);
- else
- {
- count_only_length(items, nitems);
- decimals= max_length ? NOT_FIXED_DEC : 0;
- }
+ count_only_length(items, nitems);
+ decimals= max_length ? NOT_FIXED_DEC : 0;
return false;
}
diff --git a/sql/item_func.h b/sql/item_func.h
index dbe23e3..458be99 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -45,11 +45,49 @@ class Item_func :public Item_func_or_sum
void count_only_length(Item **item, uint nitems);
void count_real_length(Item **item, uint nitems);
void count_decimal_length(Item **item, uint nitems);
- void count_datetime_length(enum_field_types field_type,
- Item **item, uint nitems);
- bool count_string_result_length(enum_field_types field_type,
- Item **item, uint nitems);
+ bool count_string_length(Item **item, uint nitems);
+ uint count_max_decimals(Item **item, uint nitems)
+ {
+ uint res= 0;
+ for (uint i= 0; i < nitems; i++)
+ set_if_bigger(res, item[i]->decimals);
+ return res;
+ }
public:
+ void aggregate_attributes_int(Item **items, uint nitems)
+ {
+ collation.set_numeric();
+ count_only_length(items, nitems);
+ decimals= 0;
+ }
+ void aggregate_attributes_real(Item **items, uint nitems)
+ {
+ collation.set_numeric();
+ count_real_length(items, nitems);
+ }
+ void aggregate_attributes_decimal(Item **items, uint nitems)
+ {
+ collation.set_numeric();
+ count_decimal_length(items, nitems);
+ }
+ bool aggregate_attributes_string(Item **item, uint nitems)
+ {
+ return count_string_length(item, nitems);
+ }
+ void set_attributes_temporal(uint int_part_length, uint dec)
+ {
+ collation.set_numeric();
+ unsigned_flag= 0;
+ decimals= MY_MIN(dec, TIME_SECOND_PART_DIGITS);
+ uint length= decimals + int_part_length + (dec ? 1 : 0);
+ fix_char_length(length);
+ }
+ void aggregate_attributes_temporal(uint int_part_length,
+ Item **item, uint nitems)
+ {
+ set_attributes_temporal(int_part_length, count_max_decimals(item, nitems));
+ }
+
table_map not_null_tables_cache;
enum Functype { UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC,
@@ -389,7 +427,7 @@ class Item_hybrid_func: public Item_func,
public Type_handler_hybrid_field_type
{
protected:
- void fix_attributes(Item **item, uint nitems);
+ bool fix_attributes(Item **item, uint nitems);
public:
Item_hybrid_func(THD *thd): Item_func(thd) { }
Item_hybrid_func(THD *thd, Item *a): Item_func(thd, a) { }
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index b7dd4c2..0f6424e 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -890,6 +890,79 @@ 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 **items, uint nitems) const
+{
+ func->aggregate_attributes_int(items, nitems);
+ return false;
+}
+
+
+bool Type_handler_real_result::
+ Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
+ Item **items, uint nitems) const
+{
+ func->aggregate_attributes_real(items, nitems);
+ return false;
+}
+
+
+bool Type_handler_decimal_result::
+ Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
+ Item **items, uint nitems) const
+{
+ func->aggregate_attributes_decimal(items, nitems);
+ return false;
+}
+
+
+bool Type_handler_string_result::
+ Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
+ Item **items, uint nitems) const
+{
+ return func->aggregate_attributes_string(items, nitems);
+}
+
+
+bool Type_handler_date_common::
+ Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
+ Item **items, uint nitems) const
+{
+ func->set_attributes_temporal(MAX_DATE_WIDTH, 0);
+ return false;
+}
+
+
+bool Type_handler_time_common::
+ Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
+ Item **items, uint nitems) const
+{
+ func->aggregate_attributes_temporal(MIN_TIME_WIDTH, items, nitems);
+ return false;
+}
+
+
+bool Type_handler_datetime_common::
+ Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
+ Item **items, uint nitems) const
+{
+ func->aggregate_attributes_temporal(MAX_DATETIME_WIDTH, items, nitems);
+ return false;
+}
+
+
+bool Type_handler_timestamp_common::
+ Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
+ Item **items, uint nitems) const
+{
+ func->aggregate_attributes_temporal(MAX_DATETIME_WIDTH, items, nitems);
+ return false;
+}
+
+
+/*************************************************************************/
+
/**
MAX/MIN for the traditional numeric types preserve the exact data type
from Fields, but do not preserve the exact type from Items:
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 1f82f5b..e1a5883 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -28,6 +28,7 @@ class Item;
class Item_cache;
class Item_sum_hybrid;
class Item_func_hex;
+class Item_hybrid_func;
class Item_func_hybrid_field_type;
class Item_func_between;
class Item_func_in;
@@ -298,6 +299,9 @@ class Type_handler
bool no_conversions) 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,
+ Item **items,
+ uint nitems) const= 0;
virtual bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *) const= 0;
virtual String *Item_func_hex_val_str_ascii(Item_func_hex *item,
String *str) const= 0;
@@ -391,6 +395,12 @@ class Type_handler_row: public Type_handler
}
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,
+ Item **items, uint nitems) const
+ {
+ DBUG_ASSERT(0);
+ return true;
+ }
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const
{
DBUG_ASSERT(0);
@@ -473,6 +483,8 @@ class Type_handler_real_result: public Type_handler_numeric
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;
+ bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
+ Item **items, uint nitems) const;
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
@@ -513,6 +525,8 @@ class Type_handler_decimal_result: public Type_handler_numeric
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;
+ bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
+ Item **items, uint nitems) const;
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
@@ -551,6 +565,8 @@ class Type_handler_int_result: public Type_handler_numeric
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;
+ bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
+ Item **items, uint nitems) const;
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
@@ -626,6 +642,8 @@ class Type_handler_string_result: public Type_handler
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;
+ bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
+ Item **items, uint nitems) const;
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
@@ -778,6 +796,8 @@ class Type_handler_time_common: public Type_handler_temporal_result
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
const Type_handler *type_handler_for_comparison() const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
+ bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
+ Item **items, uint nitems) const;
cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
};
@@ -813,62 +833,85 @@ class Type_handler_temporal_with_date: public Type_handler_temporal_result
};
-class Type_handler_date: public Type_handler_temporal_with_date
+class Type_handler_date_common: public Type_handler_temporal_with_date
{
public:
- virtual ~Type_handler_date() {}
+ virtual ~Type_handler_date_common() {}
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
+ bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
+ Item **items, uint nitems) const;
+};
+
+class Type_handler_date: public Type_handler_date_common
+{
+public:
+ virtual ~Type_handler_date() {}
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
};
-class Type_handler_newdate: public Type_handler_temporal_with_date
+class Type_handler_newdate: public Type_handler_date_common
{
public:
virtual ~Type_handler_newdate() {}
- enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
};
-class Type_handler_datetime: public Type_handler_temporal_with_date
+class Type_handler_datetime_common: public Type_handler_temporal_with_date
{
public:
- virtual ~Type_handler_datetime() {}
+ virtual ~Type_handler_datetime_common() {}
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
+ bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
+ Item **items, uint nitems) const;
+};
+
+
+class Type_handler_datetime: public Type_handler_datetime_common
+{
+public:
+ virtual ~Type_handler_datetime() {}
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
};
-class Type_handler_datetime2: public Type_handler_temporal_with_date
+class Type_handler_datetime2: public Type_handler_datetime_common
{
public:
virtual ~Type_handler_datetime2() {}
- enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
enum_field_types real_field_type() const { return MYSQL_TYPE_DATETIME2; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
};
-class Type_handler_timestamp: public Type_handler_temporal_with_date
+class Type_handler_timestamp_common: public Type_handler_temporal_with_date
{
public:
- virtual ~Type_handler_timestamp() {}
+ virtual ~Type_handler_timestamp_common() {}
enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
+ bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
+ Item **items, uint nitems) const;
+};
+
+
+class Type_handler_timestamp: public Type_handler_timestamp_common
+{
+public:
+ virtual ~Type_handler_timestamp() {}
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
};
-class Type_handler_timestamp2: public Type_handler_temporal_with_date
+class Type_handler_timestamp2: public Type_handler_timestamp_common
{
public:
virtual ~Type_handler_timestamp2() {}
- enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
enum_field_types real_field_type() const { return MYSQL_TYPE_TIMESTAMP2; }
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;