From 0e0d57141edebee7506d5d21c9347b5aa1b083d0 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 12 Aug 2019 21:46:20 +0400 Subject: [PATCH] MDEV-20331 Add class Type_numeric_attributes --- sql/field.h | 24 +++---- sql/item.cc | 2 +- sql/item_func.h | 2 +- sql/item_timefunc.cc | 5 +- sql/item_timefunc.h | 16 +++-- sql/sql_type.cc | 110 ++++++++++++++++------------- sql/sql_type.h | 162 ++++++++++++++++++++++++------------------- 7 files changed, 177 insertions(+), 144 deletions(-) diff --git a/sql/field.h b/sql/field.h index 634063fe774..cf115cceeae 100644 --- a/sql/field.h +++ b/sql/field.h @@ -781,11 +781,13 @@ public: const LEX_CSTRING *field_name_arg); virtual ~Field() {} - virtual Type_std_attributes type_std_attributes() const + virtual Type_numeric_attributes type_numeric_attributes() const { - return Type_std_attributes(field_length, decimals(), - MY_TEST(flags & UNSIGNED_FLAG), - dtcollation()); + return Type_numeric_attributes(field_length, decimals(), is_unsigned()); + } + Type_std_attributes type_std_attributes() const + { + return Type_std_attributes(type_numeric_attributes(), dtcollation()); } bool is_unsigned() const { return flags & UNSIGNED_FLAG; } @@ -2238,7 +2240,7 @@ public: { return type_limits_int()->char_length(); } - Type_std_attributes type_std_attributes() const + Type_numeric_attributes type_numeric_attributes() const { /* For integer data types, the user-specified length does not constrain the @@ -2252,9 +2254,8 @@ public: */ uint32 length1= max_display_length(); uint32 length2= field_length; - return Type_std_attributes(MY_MAX(length1, length2), decimals(), - MY_TEST(flags & UNSIGNED_FLAG), - dtcollation()); + return Type_numeric_attributes(MY_MAX(length1, length2), + decimals(), is_unsigned()); } Information_schema_numeric_attributes information_schema_numeric_attributes() const @@ -3991,11 +3992,10 @@ public: { return FIELD_BLOB; } - Type_std_attributes type_std_attributes() const + Type_numeric_attributes type_numeric_attributes() const { - return Type_std_attributes(Field_blob::max_display_length(), decimals(), - MY_TEST(flags & UNSIGNED_FLAG), - dtcollation()); + return Type_numeric_attributes(Field_blob::max_display_length(), + decimals(), is_unsigned()); } Information_schema_character_attributes information_schema_character_attributes() const diff --git a/sql/item.cc b/sql/item.cc index 0c598fbab9e..0ad394c61eb 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -449,7 +449,7 @@ const TABLE_SHARE *Item::field_table_or_null() tables. */ Item::Item(THD *thd, Item *item): - Type_all_attributes(item), + Type_all_attributes(*item), join_tab_idx(item->join_tab_idx), is_expensive_cache(-1), rsize(0), diff --git a/sql/item_func.h b/sql/item_func.h index 2e97611699c..d59ba73b37d 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -950,7 +950,7 @@ public: bool fix_type_handler(const Type_aggregator *aggregator); void fix_length_and_dec_double() { - count_real_length(args, arg_count); + aggregate_numeric_attributes_real(args, arg_count); max_length= float_length(decimals); } void fix_length_and_dec_decimal() diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 82446cdd0da..97961a5e378 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1920,7 +1920,10 @@ bool Item_func_from_unixtime::fix_length_and_dec() THD *thd= current_thd; thd->time_zone_used= 1; tz= thd->variables.time_zone; - fix_attributes_datetime_not_fixed_dec(args[0]->decimals); + Type_std_attributes::set( + Type_temporal_attributes_not_fixed_dec(MAX_DATETIME_WIDTH, + args[0]->decimals, false), + DTCollation_numeric()); maybe_null= true; return FALSE; } diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 65fd223d6d4..de00c39acde 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -1556,9 +1556,11 @@ public: { uint dec= MY_MAX(item->arguments()[0]->datetime_precision(current_thd), interval_dec(item->arguments()[1], int_type(item))); - item->collation.set(item->default_charset(), - DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); - item->fix_char_length_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec); + item->Type_std_attributes::set( + Type_temporal_attributes_not_fixed_dec(MAX_DATETIME_WIDTH, dec, false), + DTCollation(item->default_charset(), + DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII)); + item->fix_char_length(item->max_length); return false; } bool get_date(THD *thd, Item_handled_func *item, @@ -1663,9 +1665,11 @@ public: uint dec0= item->arguments()[0]->decimals; uint dec1= Interval_DDhhmmssff::fsp(current_thd, item->arguments()[1]); uint dec= MY_MAX(dec0, dec1); - item->collation.set(item->default_charset(), - DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); - item->fix_char_length_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec); + item->Type_std_attributes::set( + Type_temporal_attributes_not_fixed_dec(MAX_DATETIME_WIDTH, dec, false), + DTCollation(item->default_charset(), + DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII)); + item->fix_char_length(item->max_length); return false; } bool get_date(THD *thd, Item_handled_func *item, diff --git a/sql/sql_type.cc b/sql/sql_type.cc index b618622b531..7265bdd2cee 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -1078,7 +1078,7 @@ Datetime_truncation_not_needed::Datetime_truncation_not_needed(THD *thd, Item *i /********************************************************************/ -uint Type_std_attributes::count_max_decimals(Item **item, uint nitems) +uint Type_numeric_attributes::find_max_decimals(Item **item, uint nitems) { uint res= 0; for (uint i= 0; i < nitems; i++) @@ -1087,55 +1087,61 @@ uint Type_std_attributes::count_max_decimals(Item **item, uint nitems) } +uint Type_numeric_attributes::count_unsigned(Item **item, uint nitems) +{ + uint res= 0; + for (uint i= 0 ; i < nitems ; i++) + { + if (item[i]->unsigned_flag) + res++; + } + return res; +} + + +uint32 Type_numeric_attributes::find_max_char_length(Item **item, uint nitems) +{ + uint32 char_length= 0; + for (uint i= 0; i < nitems ; i++) + set_if_bigger(char_length, item[i]->max_char_length()); + return char_length; +} + + +uint32 Type_numeric_attributes::find_max_octet_length(Item **item, uint nitems) +{ + uint32 octet_length= 0; + for (uint i= 0; i < nitems ; i++) + set_if_bigger(octet_length, item[i]->max_length); + return octet_length; +} + + +int Type_numeric_attributes::find_max_decimal_int_part(Item **item, uint nitems) +{ + int max_int_part= 0; + for (uint i=0 ; i < nitems ; i++) + set_if_bigger(max_int_part, item[i]->decimal_int_part()); + return max_int_part; +} + + /** Set max_length/decimals of function if function is fixed point and result length/precision depends on argument ones. */ -void Type_std_attributes::count_decimal_length(Item **item, uint nitems) +void +Type_numeric_attributes::aggregate_numeric_attributes_decimal(Item **item, + uint nitems, + bool unsigned_arg) { - int max_int_part= 0; - decimals= 0; - unsigned_flag= 1; - for (uint i=0 ; i < nitems ; i++) - { - set_if_bigger(decimals, item[i]->decimals); - set_if_bigger(max_int_part, item[i]->decimal_int_part()); - set_if_smaller(unsigned_flag, item[i]->unsigned_flag); - } + int max_int_part= find_max_decimal_int_part(item, nitems); + decimals= find_max_decimals(item, nitems); int precision= MY_MIN(max_int_part + decimals, DECIMAL_MAX_PRECISION); - fix_char_length(my_decimal_precision_to_length_no_truncation(precision, - (uint8) decimals, - unsigned_flag)); -} - - -/** - Set max_length of if it is maximum length of its arguments. -*/ - -void Type_std_attributes::count_only_length(Item **item, uint nitems) -{ - uint32 char_length= 0; - unsigned_flag= 0; - for (uint i= 0; i < nitems ; i++) - { - set_if_bigger(char_length, item[i]->max_char_length()); - set_if_bigger(unsigned_flag, item[i]->unsigned_flag); - } - fix_char_length(char_length); -} - - -void Type_std_attributes::count_octet_length(Item **item, uint nitems) -{ - max_length= 0; - unsigned_flag= 0; - for (uint i= 0; i < nitems ; i++) - { - set_if_bigger(max_length, item[i]->max_length); - set_if_bigger(unsigned_flag, item[i]->unsigned_flag); - } + max_length= my_decimal_precision_to_length_no_truncation(precision, + (uint8) decimals, + unsigned_flag); } @@ -1144,7 +1150,9 @@ void Type_std_attributes::count_octet_length(Item **item, uint nitems) result length/precision depends on argument ones. */ -void Type_std_attributes::count_real_length(Item **items, uint nitems) +void +Type_numeric_attributes::aggregate_numeric_attributes_real(Item **items, + uint nitems) { uint32 length= 0; decimals= 0; @@ -1183,16 +1191,17 @@ void Type_std_attributes::count_real_length(Item **items, uint nitems) @retval False on success, true on error. */ -bool Type_std_attributes::count_string_length(const char *func_name, - Item **items, uint nitems) +bool Type_std_attributes::aggregate_attributes_string(const char *func_name, + Item **items, uint nitems) { if (agg_arg_charsets_for_string_result(collation, func_name, items, nitems, 1)) return true; if (collation.collation == &my_charset_bin) - count_octet_length(items, nitems); + max_length= find_max_octet_length(items, nitems); else - count_only_length(items, nitems); + fix_char_length(find_max_char_length(items, nitems)); + unsigned_flag= count_unsigned(items, nitems) > 0; decimals= max_length ? NOT_FIXED_DEC : 0; return false; } @@ -4170,7 +4179,7 @@ bool Type_handler_int_result:: { // Convert a mixture of signed and unsigned int to decimal handler->set_handler(&type_handler_newdecimal); - func->aggregate_attributes_decimal(items, nitems); + func->aggregate_attributes_decimal(items, nitems, false); return false; } } @@ -4198,7 +4207,8 @@ bool Type_handler_decimal_result:: Type_all_attributes *func, Item **items, uint nitems) const { - func->aggregate_attributes_decimal(items, nitems); + uint unsigned_count= func->count_unsigned(items, nitems); + func->aggregate_attributes_decimal(items, nitems, unsigned_count == nitems); return false; } diff --git a/sql/sql_type.h b/sql/sql_type.h index 8f1d51b1aab..677fac75bc8 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -2773,38 +2773,87 @@ char_to_byte_length_safe(size_t char_length_arg, uint32 mbmaxlen_arg) return tmp > UINT_MAX32 ? (uint32) UINT_MAX32 : static_cast(tmp); } -/** - A class to store type attributes for the standard data types. - Does not include attributes for the extended data types - such as ENUM, SET, GEOMETRY. -*/ -class Type_std_attributes + +class Type_numeric_attributes { public: - DTCollation collation; - uint decimals; + static uint count_unsigned(Item **item, uint nitems); + static uint32 find_max_char_length(Item **item, uint nitems); + static uint32 find_max_octet_length(Item **item, uint nitems); + static int find_max_decimal_int_part(Item **item, uint nitems); + static uint find_max_decimals(Item **item, uint nitems); +public: /* The maximum value length in characters multiplied by collation->mbmaxlen. Almost always it's the maximum value length in bytes. */ uint32 max_length; + uint decimals; bool unsigned_flag; +public: + Type_numeric_attributes() + :max_length(0), decimals(0), unsigned_flag(false) + { } + Type_numeric_attributes(uint32 max_length_arg, uint decimals_arg, + bool unsigned_flag_arg) + :max_length(max_length_arg), + decimals(decimals_arg), + unsigned_flag(unsigned_flag_arg) + { } +protected: + void aggregate_numeric_attributes_real(Item **item, uint nitems); + void aggregate_numeric_attributes_decimal(Item **item, uint nitems, + bool unsigned_arg); +}; + + + +class Type_temporal_attributes: public Type_numeric_attributes +{ +public: + Type_temporal_attributes(uint int_part_length, uint dec, bool unsigned_arg) + :Type_numeric_attributes(int_part_length + (dec ? 1 : 0), + MY_MIN(dec, TIME_SECOND_PART_DIGITS), + unsigned_arg) + { + max_length+= decimals; + } +}; + + +class Type_temporal_attributes_not_fixed_dec: public Type_numeric_attributes +{ +public: + Type_temporal_attributes_not_fixed_dec(uint32 int_part_length, uint dec, + bool unsigned_flag) + :Type_numeric_attributes(int_part_length, dec, unsigned_flag) + { + if (decimals == NOT_FIXED_DEC) + max_length+= TIME_SECOND_PART_DIGITS + 1; + else if (decimals) + { + set_if_smaller(decimals, TIME_SECOND_PART_DIGITS); + max_length+= decimals + 1; + } + } +}; + + +/** + A class to store type attributes for the standard data types. + Does not include attributes for the extended data types + such as ENUM, SET, GEOMETRY. +*/ +class Type_std_attributes: public Type_numeric_attributes +{ +public: + DTCollation collation; Type_std_attributes() - :collation(&my_charset_bin, DERIVATION_COERCIBLE), - decimals(0), max_length(0), unsigned_flag(false) + :collation(&my_charset_bin, DERIVATION_COERCIBLE) { } - Type_std_attributes(const Type_std_attributes *other) - :collation(other->collation), - decimals(other->decimals), - max_length(other->max_length), - unsigned_flag(other->unsigned_flag) - { } - Type_std_attributes(uint32 max_length_arg, uint decimals_arg, - bool unsigned_flag_arg, const DTCollation &dtc) - :collation(dtc), - decimals(decimals_arg), - max_length(max_length_arg), - unsigned_flag(unsigned_flag_arg) + Type_std_attributes(const Type_numeric_attributes &nattr, + const DTCollation &dtc) + :Type_numeric_attributes(nattr), collation(dtc) { } void set(const Type_std_attributes *other) { @@ -2814,6 +2863,10 @@ public: { *this= other; } + void set(const Type_numeric_attributes &nattr, const DTCollation &dtc) + { + *this= Type_std_attributes(nattr, dtc); + } uint32 max_char_length() const { return max_length / collation.collation->mbmaxlen; } void fix_length_and_charset(uint32 max_char_length_arg, CHARSET_INFO *cs) @@ -2826,41 +2879,11 @@ public: max_length= char_to_byte_length_safe(max_char_length_arg, collation.collation->mbmaxlen); } - void fix_char_length_temporal_not_fixed_dec(uint int_part_length, uint dec) + void fix_attributes_temporal(uint32 int_part_length, uint dec) { - uint char_length= int_part_length; - if ((decimals= dec)) - { - if (decimals == NOT_FIXED_DEC) - char_length+= TIME_SECOND_PART_DIGITS + 1; - else - { - set_if_smaller(decimals, TIME_SECOND_PART_DIGITS); - char_length+= decimals + 1; - } - } - fix_char_length(char_length); - } - void fix_attributes_temporal_not_fixed_dec(uint int_part_length, uint dec) - { - collation= DTCollation_numeric(); - unsigned_flag= 0; - fix_char_length_temporal_not_fixed_dec(int_part_length, dec); - } - void fix_attributes_time_not_fixed_dec(uint dec) - { - fix_attributes_temporal_not_fixed_dec(MIN_TIME_WIDTH, dec); - } - void fix_attributes_datetime_not_fixed_dec(uint dec) - { - fix_attributes_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec); - } - void fix_attributes_temporal(uint int_part_length, uint dec) - { - collation= DTCollation_numeric(); - unsigned_flag= 0; - decimals= MY_MIN(dec, TIME_SECOND_PART_DIGITS); - max_length= decimals + int_part_length + (dec ? 1 : 0); + *this= Type_std_attributes( + Type_temporal_attributes(int_part_length, dec, false), + DTCollation_numeric()); } void fix_attributes_date() { @@ -2875,38 +2898,31 @@ public: fix_attributes_temporal(MAX_DATETIME_WIDTH, dec); } - void count_only_length(Item **item, uint nitems); - void count_octet_length(Item **item, uint nitems); - void count_real_length(Item **item, uint nitems); - void count_decimal_length(Item **item, uint nitems); - bool count_string_length(const char *func_name, Item **item, uint nitems); - uint count_max_decimals(Item **item, uint nitems); - void aggregate_attributes_int(Item **items, uint nitems) { collation= DTCollation_numeric(); - count_only_length(items, nitems); + fix_char_length(find_max_char_length(items, nitems)); + unsigned_flag= count_unsigned(items, nitems) > 0; decimals= 0; } void aggregate_attributes_real(Item **items, uint nitems) { collation= DTCollation_numeric(); - count_real_length(items, nitems); + aggregate_numeric_attributes_real(items, nitems); } - void aggregate_attributes_decimal(Item **items, uint nitems) + void aggregate_attributes_decimal(Item **items, uint nitems, + bool unsigned_arg) { collation= DTCollation_numeric(); - count_decimal_length(items, nitems); + aggregate_numeric_attributes_decimal(items, nitems, + (unsigned_flag= unsigned_arg)); } bool aggregate_attributes_string(const char *func_name, - Item **item, uint nitems) - { - return count_string_length(func_name, item, nitems); - } + Item **item, uint nitems); void aggregate_attributes_temporal(uint int_part_length, Item **item, uint nitems) { - fix_attributes_temporal(int_part_length, count_max_decimals(item, nitems)); + fix_attributes_temporal(int_part_length, find_max_decimals(item, nitems)); } bool agg_item_collations(DTCollation &c, const char *name, @@ -3010,7 +3026,7 @@ public: Type_all_attributes() :Type_std_attributes() { } - Type_all_attributes(const Type_all_attributes *other) + Type_all_attributes(const Type_all_attributes &other) :Type_std_attributes(other) { } virtual ~Type_all_attributes() {}