Skip to content

Commit

Permalink
MDEV-12655 Move Item_func::count_xxx_length() to Type_std_attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Barkov committed May 2, 2017
1 parent c67971a commit 50b70e7
Show file tree
Hide file tree
Showing 6 changed files with 268 additions and 221 deletions.
14 changes: 7 additions & 7 deletions sql/item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2355,9 +2355,9 @@ void my_coll_agg_error(Item** args, uint count, const char *fname,
}


bool Item_func_or_sum::agg_item_collations(DTCollation &c, const char *fname,
Item **av, uint count,
uint flags, int item_sep)
bool Type_std_attributes::agg_item_collations(DTCollation &c, const char *fname,
Item **av, uint count,
uint flags, int item_sep)
{
uint i;
Item **arg;
Expand Down Expand Up @@ -2402,10 +2402,10 @@ bool Item_func_or_sum::agg_item_collations(DTCollation &c, const char *fname,
}


bool Item_func_or_sum::agg_item_set_converter(const DTCollation &coll,
const char *fname,
Item **args, uint nargs,
uint flags, int item_sep)
bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll,
const char *fname,
Item **args, uint nargs,
uint flags, int item_sep)
{
Item **arg, *safe_args[2]= {NULL, NULL};

Expand Down
76 changes: 12 additions & 64 deletions sql/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -4059,80 +4059,31 @@ class Item_func_or_sum: public Item_result_field,
public Item_args,
public Used_tables_and_const_cache
{
bool agg_item_collations(DTCollation &c, const char *name,
Item **items, uint nitems,
uint flags, int item_sep);
bool agg_item_set_converter(const DTCollation &coll, const char *fname,
Item **args, uint nargs,
uint flags, int item_sep);
protected:
/*
Collect arguments' character sets together.
We allow to apply automatic character set conversion in some cases.
The conditions when conversion is possible are:
- arguments A and B have different charsets
- A wins according to coercibility rules
(i.e. a column is stronger than a string constant,
an explicit COLLATE clause is stronger than a column)
- character set of A is either superset for character set of B,
or B is a string constant which can be converted into the
character set of A without data loss.
If all of the above is true, then it's possible to convert
B into the character set of A, and then compare according
to the collation of A.
For functions with more than two arguments:
collect(A,B,C) ::= collect(collect(A,B),C)
Since this function calls THD::change_item_tree() on the passed Item **
pointers, it is necessary to pass the original Item **'s, not copies.
Otherwise their values will not be properly restored (see BUG#20769).
If the items are not consecutive (eg. args[2] and args[5]), use the
item_sep argument, ie.
agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
*/
bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems,
uint flags, int item_sep)
{
if (agg_item_collations(c, func_name(), items, nitems, flags, item_sep))
return true;

return agg_item_set_converter(c, func_name(), items, nitems,
flags, item_sep);
return Type_std_attributes::agg_arg_charsets(c, func_name(),
items, nitems,
flags, item_sep);
}
/*
Aggregate arguments for string result, e.g: CONCAT(a,b)
- convert to @@character_set_connection if all arguments are numbers
- allow DERIVATION_NONE
*/
bool agg_arg_charsets_for_string_result(DTCollation &c,
Item **items, uint nitems,
int item_sep= 1)
{
uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
MY_COLL_ALLOW_COERCIBLE_CONV |
MY_COLL_ALLOW_NUMERIC_CONV;
return agg_arg_charsets(c, items, nitems, flags, item_sep);
return Type_std_attributes::
agg_arg_charsets_for_string_result(c, func_name(),
items, nitems, item_sep);
}
/*
Aggregate arguments for string result, when some comparison
is involved internally, e.g: REPLACE(a,b,c)
- convert to @@character_set_connection if all arguments are numbers
- disallow DERIVATION_NONE
*/
bool agg_arg_charsets_for_string_result_with_comparison(DTCollation &c,
Item **items,
uint nitems,
int item_sep= 1)
{
uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
MY_COLL_ALLOW_COERCIBLE_CONV |
MY_COLL_ALLOW_NUMERIC_CONV |
MY_COLL_DISALLOW_NONE;
return agg_arg_charsets(c, items, nitems, flags, item_sep);
return Type_std_attributes::
agg_arg_charsets_for_string_result_with_comparison(c, func_name(),
items, nitems,
item_sep);
}

/*
Expand All @@ -4144,13 +4095,10 @@ class Item_func_or_sum: public Item_result_field,
Item **items, uint nitems,
int item_sep= 1)
{
uint flags= MY_COLL_ALLOW_SUPERSET_CONV |
MY_COLL_ALLOW_COERCIBLE_CONV |
MY_COLL_DISALLOW_NONE;
return agg_arg_charsets(c, items, nitems, flags, item_sep);
return Type_std_attributes::
agg_arg_charsets_for_comparison(c, func_name(), items, nitems, item_sep);
}


public:
// This method is used by Arg_comparator
bool agg_arg_charsets_for_comparison(CHARSET_INFO **cs, Item **a, Item **b)
Expand Down
110 changes: 0 additions & 110 deletions sql/item_func.cc
Original file line number Diff line number Diff line change
Expand Up @@ -592,116 +592,6 @@ void Item_udf_func::fix_num_length_and_dec()
}


/**
Set max_length/decimals of function if function is fixed point and
result length/precision depends on argument ones.
*/

void Item_func::count_decimal_length(Item **item, uint nitems)
{
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 precision= MY_MIN(max_int_part + decimals, DECIMAL_MAX_PRECISION);
fix_char_length(my_decimal_precision_to_length_no_truncation(precision,
decimals,
unsigned_flag));
}


/**
Set max_length of if it is maximum length of its arguments.
*/

void Item_func::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 Item_func::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);
}
}


/**
Set max_length/decimals of function if function is floating point and
result length/precision depends on argument ones.
*/

void Item_func::count_real_length(Item **items, uint nitems)
{
uint32 length= 0;
decimals= 0;
max_length= 0;
unsigned_flag= false;
for (uint i=0 ; i < nitems ; i++)
{
if (decimals < FLOATING_POINT_DECIMALS)
{
set_if_bigger(decimals, items[i]->decimals);
/* Will be ignored if items[i]->decimals >= FLOATING_POINT_DECIMALS */
set_if_bigger(length, (items[i]->max_length - items[i]->decimals));
}
set_if_bigger(max_length, items[i]->max_length);
}
if (decimals < FLOATING_POINT_DECIMALS)
{
max_length= length;
length+= decimals;
if (length < max_length) // If previous operation gave overflow
max_length= UINT_MAX32;
else
max_length= length;
}
// Corner case: COALESCE(DOUBLE(255,4), DOUBLE(255,3)) -> FLOAT(255, 4)
set_if_smaller(max_length, MAX_FIELD_CHARLENGTH);
}


/**
Calculate max_length and decimals for string functions.
@param field_type Field type.
@param items Argument array.
@param nitems Number of arguments.
@retval False on success, true on error.
*/
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 (collation.collation == &my_charset_bin)
count_octet_length(items, nitems);
else
count_only_length(items, nitems);
decimals= max_length ? NOT_FIXED_DEC : 0;
return false;
}


void Item_func::signal_divide_by_null()
{
THD *thd= current_thd;
Expand Down
37 changes: 0 additions & 37 deletions sql/item_func.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,45 +42,8 @@ class Item_func :public Item_func_or_sum
uint allowed_arg_cols;
String *val_str_from_val_str_ascii(String *str, String *str2);

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(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;
}
virtual bool check_allowed_arg_cols(uint argno);
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 aggregate_attributes_temporal(uint int_part_length,
Item **item, uint nitems)
{
fix_attributes_temporal(int_part_length, count_max_decimals(item, nitems));
}

table_map not_null_tables_cache;

Expand Down
Loading

0 comments on commit 50b70e7

Please sign in to comment.