MDEV-20331 Add class Type_numeric_attributes

This commit is contained in:
Alexander Barkov 2019-08-12 21:46:20 +04:00
parent e7525beac8
commit 0e0d57141e
7 changed files with 177 additions and 144 deletions

View File

@ -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

View File

@ -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),

View File

@ -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()

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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<uint32>(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() {}