Skip to content

Commit 5ed6fc6

Browse files
author
Dag Wanvik
committed
Bug#26359109 REFACTOR ITEM_FUNC::FIX_NUM_TYPE_SHARED_FOR_CASE FOR REUSE BY LEAD/LAG
[ was: Settled a TODO FIXME item: reuse fix_num_type_shared_for_case for LEAD/LAG ] [ Revision 2: after Roy's 2. review - Renamed fix_*from_args -> aggregate_* (after first rename in revision 1) - Fixed bug in set_data_type_datetime: used wrong MAX_*_WIDTH constant - Removed Docygen reference to max_chars for methods that don't see that level of detail. - Unfolded logic into separate switch branches for readability in Item::aggregate_temporal_properties ] [ Revision 1: after Roy's review - All review items except: "I also wonder if we should skip max_length calculation here and thus ignore decimals in that calculation. Calculation of decimals might still be needed to avoid regressions in results, but max_length should be strictly derived from the float type, IMHO." and one changed that caused a crash: "I do not think we should set decimals here, we should accept the constructor default." which, if done, breaks func_time.test ] Settled a windowing TODO FIXME item: reuse fix_num_type_shared_for_case for LEAD/LAG - Added the method header file and made it non-static, so we can use it in Item_lead_lag. - Changed its signature to accept Item instead of Item_func, since Item_sum (parent class of Item_lead_lag) is not an Item_func. - In the process lifted auxiliary type resolving functions up from Item_result_field/Item_func up to Item (at Roy's request: we felt they belong more naturally there than in Item_result_field even though that is the closes common ancestor of Item_func and Item_sum).
1 parent b4186b2 commit 5ed6fc6

File tree

6 files changed

+212
-232
lines changed

6 files changed

+212
-232
lines changed

sql/item.cc

Lines changed: 182 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -7829,6 +7829,188 @@ bool Item::cache_const_expr_analyzer(uchar **arg)
78297829
}
78307830

78317831

7832+
/**
7833+
Set the maximum number of characters required by any of the items in args.
7834+
*/
7835+
void Item::aggregate_char_length(Item **args, uint nitems)
7836+
{
7837+
uint32 char_length= 0;
7838+
for (uint i= 0; i < nitems; i++)
7839+
set_if_bigger(char_length, args[i]->max_char_length());
7840+
fix_char_length(char_length);
7841+
}
7842+
7843+
7844+
/**
7845+
Set ::max_length and ::decimals of function if function is floating point and
7846+
result length/precision depends on argument ones.
7847+
7848+
@param item Argument array.
7849+
@param nitems Number of arguments in the array.
7850+
*/
7851+
void Item::aggregate_float_properties(Item **item, uint nitems)
7852+
{
7853+
DBUG_ASSERT(result_type() == REAL_RESULT);
7854+
uint32 length= 0;
7855+
uint8 decimals_cnt= 0;
7856+
uint32 maxl= 0;
7857+
for (uint i=0 ; i < nitems; i++)
7858+
{
7859+
if (decimals_cnt != NOT_FIXED_DEC)
7860+
{
7861+
set_if_bigger(decimals_cnt, item[i]->decimals);
7862+
set_if_bigger(length, (item[i]->max_length - item[i]->decimals));
7863+
}
7864+
set_if_bigger(maxl, item[i]->max_length);
7865+
}
7866+
if (decimals_cnt != NOT_FIXED_DEC)
7867+
{
7868+
maxl= length;
7869+
length+= decimals_cnt;
7870+
if (length < maxl) // If previous operation gave overflow
7871+
maxl= UINT_MAX32;
7872+
else
7873+
maxl= length;
7874+
}
7875+
7876+
this->max_length= maxl;
7877+
this->decimals= decimals_cnt;
7878+
}
7879+
7880+
/**
7881+
Set precision and decimals of function when this depends on arguments'
7882+
values for these quantities.
7883+
7884+
@param item Argument array.
7885+
@param nitems Number of arguments in the array.
7886+
*/
7887+
void Item::aggregate_decimal_properties(Item **item, uint nitems)
7888+
{
7889+
DBUG_ASSERT(result_type() == DECIMAL_RESULT);
7890+
int max_int_part= 0;
7891+
uint8 decimal_cnt= 0;
7892+
for (uint i=0 ; i < nitems ; i++)
7893+
{
7894+
set_if_bigger(decimal_cnt, item[i]->decimals);
7895+
set_if_bigger(max_int_part, item[i]->decimal_int_part());
7896+
}
7897+
int precision= min(max_int_part + decimal_cnt, DECIMAL_MAX_PRECISION);
7898+
set_data_type_decimal(precision, decimal_cnt);
7899+
}
7900+
7901+
7902+
/**
7903+
Set fractional seconds precision for temporal functions.
7904+
7905+
@param item Argument array
7906+
@param nitems Number of arguments in the array.
7907+
*/
7908+
void Item::aggregate_temporal_properties(Item **item, uint nitems)
7909+
{
7910+
DBUG_ASSERT(result_type() == STRING_RESULT);
7911+
uint8 decimal_cnt= 0;
7912+
7913+
switch (data_type())
7914+
{
7915+
case MYSQL_TYPE_DATETIME:
7916+
for (uint i= 0; i < nitems; i++)
7917+
set_if_bigger(decimal_cnt, item[i]->datetime_precision());
7918+
set_if_smaller(decimal_cnt, DATETIME_MAX_DECIMALS);
7919+
set_data_type_datetime(decimal_cnt);
7920+
break;
7921+
7922+
case MYSQL_TYPE_TIMESTAMP:
7923+
for (uint i= 0; i < nitems; i++)
7924+
set_if_bigger(decimal_cnt, item[i]->datetime_precision());
7925+
set_if_smaller(decimal_cnt, DATETIME_MAX_DECIMALS);
7926+
set_data_type_timestamp(decimal_cnt);
7927+
break;
7928+
7929+
case MYSQL_TYPE_NEWDATE:
7930+
DBUG_ASSERT(false);
7931+
set_data_type_date();
7932+
set_data_type(MYSQL_TYPE_NEWDATE);
7933+
break;
7934+
7935+
case MYSQL_TYPE_DATE:
7936+
set_data_type_date();
7937+
break;
7938+
7939+
case MYSQL_TYPE_TIME:
7940+
for (uint i= 0; i < nitems; i++)
7941+
set_if_bigger(decimal_cnt, item[i]->time_precision());
7942+
set_if_smaller(decimal_cnt, DATETIME_MAX_DECIMALS);
7943+
set_data_type_time(decimal_cnt);
7944+
break;
7945+
7946+
default:
7947+
DBUG_ASSERT(false); /* purecov: inspected */
7948+
}
7949+
}
7950+
7951+
7952+
/**
7953+
Aggregate string properties (character set, collation and maximum length) for
7954+
string function.q
7955+
7956+
@param field_type Field type.
7957+
@param name Name of function
7958+
@param items Argument array.
7959+
@param nitems Number of arguments.
7960+
7961+
@retval False on success, true on error.
7962+
*/
7963+
bool Item::aggregate_string_properties(enum_field_types field_type,
7964+
const char *name,
7965+
Item **items, uint nitems)
7966+
{
7967+
DBUG_ASSERT(result_type() == STRING_RESULT);
7968+
if (agg_item_charsets_for_string_result(collation, name, items, nitems, 1))
7969+
return true;
7970+
if (is_temporal_type(field_type))
7971+
aggregate_temporal_properties(items, nitems);
7972+
else
7973+
{
7974+
decimals= NOT_FIXED_DEC;
7975+
aggregate_char_length(items, nitems);
7976+
}
7977+
return false;
7978+
}
7979+
7980+
7981+
/**
7982+
This function is used to resolve type for numeric result type of CASE,
7983+
COALESCE, IF and LEAD/LAG. COALESCE is a CASE abbreviation according to the
7984+
standard.
7985+
7986+
@param result_type The desired result type
7987+
@param item The arguments of func
7988+
@param nitems The number of arguments
7989+
*/
7990+
void Item::aggregate_num_type(Item_result result_type,
7991+
Item **item,
7992+
uint nitems)
7993+
{
7994+
switch (result_type)
7995+
{
7996+
case DECIMAL_RESULT:
7997+
aggregate_decimal_properties(item, nitems);
7998+
break;
7999+
case REAL_RESULT:
8000+
aggregate_float_properties(item, nitems);
8001+
break;
8002+
case INT_RESULT:
8003+
case STRING_RESULT:
8004+
aggregate_char_length(item, nitems);
8005+
decimals= 0;
8006+
break;
8007+
case ROW_RESULT:
8008+
default:
8009+
DBUG_ASSERT(0);
8010+
}
8011+
}
8012+
8013+
78328014
/**
78338015
Cache item if needed.
78348016
@@ -10898,87 +11080,6 @@ void Item_result_field::cleanup()
1089811080
}
1089911081

1090011082

10901-
/**
10902-
Set char_length to the maximum number of characters required by any
10903-
of this function's or window function's arguments.
10904-
10905-
This function doesn't set unsigned_flag. Call agg_result_type()
10906-
first to do that.
10907-
*/
10908-
void Item_result_field::count_only_length(Item **item, uint nitems)
10909-
{
10910-
uint32 char_length= 0;
10911-
for (uint i= 0; i < nitems; i++)
10912-
set_if_bigger(char_length, item[i]->max_char_length());
10913-
fix_char_length(char_length);
10914-
}
10915-
10916-
10917-
/**
10918-
Count max_length and decimals for temporal functions or window functions.
10919-
10920-
@param item Argument array
10921-
@param nitems Number of arguments in the array.
10922-
*/
10923-
void Item_result_field::count_datetime_length(Item **item, uint nitems)
10924-
{
10925-
unsigned_flag= false;
10926-
decimals= 0;
10927-
if (data_type() != MYSQL_TYPE_DATE)
10928-
{
10929-
for (uint i= 0; i < nitems; i++)
10930-
set_if_bigger(decimals,
10931-
data_type() == MYSQL_TYPE_TIME ?
10932-
item[i]->time_precision() : item[i]->datetime_precision());
10933-
}
10934-
set_if_smaller(decimals, DATETIME_MAX_DECIMALS);
10935-
uint len= decimals ? (decimals + 1) : 0;
10936-
switch (data_type())
10937-
{
10938-
case MYSQL_TYPE_DATETIME:
10939-
case MYSQL_TYPE_TIMESTAMP:
10940-
len+= MAX_DATETIME_WIDTH;
10941-
break;
10942-
case MYSQL_TYPE_DATE:
10943-
case MYSQL_TYPE_NEWDATE:
10944-
len+= MAX_DATE_WIDTH;
10945-
break;
10946-
case MYSQL_TYPE_TIME:
10947-
len+= MAX_TIME_WIDTH;
10948-
break;
10949-
default:
10950-
DBUG_ASSERT(0); /* purecov: inspected */
10951-
}
10952-
fix_char_length(len);
10953-
}
10954-
10955-
10956-
/**
10957-
Calculate max_length and decimals for STRING_RESULT functions or window
10958-
functions.
10959-
10960-
@param field_type Field type.
10961-
@param items Argument array.
10962-
@param nitems Number of arguments.
10963-
10964-
@retval False on success, true on error.
10965-
*/
10966-
bool Item_result_field::count_string_result_length(enum_field_types field_type,
10967-
Item **items, uint nitems)
10968-
{
10969-
if (agg_item_charsets_for_string_result(collation, func_name(), items, nitems, 1))
10970-
return true;
10971-
if (is_temporal_type(field_type))
10972-
count_datetime_length(items, nitems);
10973-
else
10974-
{
10975-
decimals= NOT_FIXED_DEC;
10976-
count_only_length(items, nitems);
10977-
}
10978-
return false;
10979-
}
10980-
10981-
1098211083
double Item_result_field::val_real_result()
1098311084
{
1098411085
double res;
@@ -11112,7 +11213,6 @@ bool Item_result_field::is_null_result()
1111211213
return res;
1111311214
}
1111411215

11115-
1111611216
/**
1111711217
Helper method: Convert string to the given charset, then print.
1111811218

sql/item.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,7 +1185,7 @@ class Item : public Parse_tree_node
11851185
set_data_type(MYSQL_TYPE_TIMESTAMP);
11861186
collation.set_numeric();
11871187
decimals= fsp;
1188-
max_length= MAX_DATE_WIDTH + fsp + (fsp > 0 ? 1 : 0);
1188+
max_length= MAX_DATETIME_WIDTH + fsp + (fsp > 0 ? 1 : 0);
11891189
}
11901190

11911191
/**
@@ -2531,6 +2531,16 @@ class Item : public Parse_tree_node
25312531
return t == FUNC_ITEM || t == COND_ITEM;
25322532
}
25332533

2534+
void aggregate_decimal_properties(Item **item, uint nitems);
2535+
void aggregate_float_properties(Item **item, uint nitems);
2536+
void aggregate_char_length(Item **args, uint nitems);
2537+
void aggregate_temporal_properties(Item **item, uint nitems);
2538+
bool aggregate_string_properties(enum_field_types field_type,
2539+
const char *name, Item **item,
2540+
uint nitems);
2541+
void aggregate_num_type(Item_result result_type, Item **item,
2542+
uint nitems);
2543+
25342544
/**
25352545
This function applies only to Item_field objects referred to by an Item_ref
25362546
object that has been marked as a const_item.
@@ -4479,10 +4489,6 @@ class Item_result_field :public Item /* Item with result field */
44794489
*/
44804490
virtual const char *func_name() const= 0;
44814491
bool check_gcol_func_processor(uchar *) override { return false; }
4482-
void count_only_length(Item **item, uint nitems);
4483-
void count_datetime_length(Item **item, uint nitems);
4484-
bool count_string_result_length(enum_field_types field_type,
4485-
Item **item, uint nitems);
44864492
bool mark_field_in_map(uchar *arg) override
44874493
{
44884494
bool rc= Item::mark_field_in_map(arg);

0 commit comments

Comments
 (0)