Commit e12390a3 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-13864 (partial) Change Item_func_case to store the predicant in args[0]

This is a preparatory step for MDEV-13864.
It does not change behavior in any ways. It simply splits methods into smaller peaces.
The intent of this separate patch is to make more readable the main patch for
MDEV-13864 (which will actually move the predicant to args[0]).

1. Splitting fix_length_and_dec() into smaller pieces, adding:
  - bool aggregate_then_and_else_arguments(THD *thd);
  - bool aggregate_switch_and_when_arguments(THD *thd);

2. Splitting find_item() into smaller pieces, adding:
  - Item *find_item_searched();
  - Item *find_item_simple();

3. Splitting print() into smaller pieces, adding:

  - void print_when_then_arguments(String *str, enum_query_type query_type,
                                   Item **items, uint count);
  - void print_else_argument(String *str, enum_query_type query_type, Item *item)

4. Moving the maybe_null handling part related to ELSE from fix_length_and_dec()
   to fix_fields(), as in all other Item_func's.

5. Removing the unused String* argument from find_item().

6. Moving find_item() from public to private, as it's not needed outside.
parent c027717a
...@@ -2856,26 +2856,25 @@ Item_func_case::Item_func_case(THD *thd, List<Item> &list, ...@@ -2856,26 +2856,25 @@ Item_func_case::Item_func_case(THD *thd, List<Item> &list,
failed failed
*/ */
Item *Item_func_case::find_item(String *str)
Item *Item_func_case::find_item_searched()
{ {
if (first_expr_num == -1) uint count= arg_count / 2;
{ for (uint i= 0 ; i < count ; i++)
for (uint i=0 ; i < ncases ; i+=2)
{ {
// No expression between CASE and the first WHEN if (args[2 * i]->val_bool())
if (args[i]->val_bool()) return args[2 * i + 1];
return args[i+1];
continue;
}
} }
else return else_expr_num != -1 ? args[else_expr_num] : 0;
{ }
Item *Item_func_case::find_item_simple()
{
/* Compare every WHEN argument with it and return the first match */ /* Compare every WHEN argument with it and return the first match */
uint idx; uint idx;
if (!Predicant_to_list_comparator::cmp(this, &idx, NULL)) if (!Predicant_to_list_comparator::cmp(this, &idx, NULL))
return args[idx + 1]; return args[idx + 1];
}
// No, WHEN clauses all missed, return ELSE expression
return else_expr_num != -1 ? args[else_expr_num] : 0; return else_expr_num != -1 ? args[else_expr_num] : 0;
} }
...@@ -2884,7 +2883,7 @@ String *Item_func_case::str_op(String *str) ...@@ -2884,7 +2883,7 @@ String *Item_func_case::str_op(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
String *res; String *res;
Item *item=find_item(str); Item *item= find_item();
if (!item) if (!item)
{ {
...@@ -2901,9 +2900,7 @@ String *Item_func_case::str_op(String *str) ...@@ -2901,9 +2900,7 @@ String *Item_func_case::str_op(String *str)
longlong Item_func_case::int_op() longlong Item_func_case::int_op()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH]; Item *item= find_item();
String dummy_str(buff,sizeof(buff),default_charset());
Item *item=find_item(&dummy_str);
longlong res; longlong res;
if (!item) if (!item)
...@@ -2919,9 +2916,7 @@ longlong Item_func_case::int_op() ...@@ -2919,9 +2916,7 @@ longlong Item_func_case::int_op()
double Item_func_case::real_op() double Item_func_case::real_op()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH]; Item *item= find_item();
String dummy_str(buff,sizeof(buff),default_charset());
Item *item=find_item(&dummy_str);
double res; double res;
if (!item) if (!item)
...@@ -2938,9 +2933,7 @@ double Item_func_case::real_op() ...@@ -2938,9 +2933,7 @@ double Item_func_case::real_op()
my_decimal *Item_func_case::decimal_op(my_decimal *decimal_value) my_decimal *Item_func_case::decimal_op(my_decimal *decimal_value)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH]; Item *item= find_item();
String dummy_str(buff, sizeof(buff), default_charset());
Item *item= find_item(&dummy_str);
my_decimal *res; my_decimal *res;
if (!item) if (!item)
...@@ -2958,9 +2951,7 @@ my_decimal *Item_func_case::decimal_op(my_decimal *decimal_value) ...@@ -2958,9 +2951,7 @@ my_decimal *Item_func_case::decimal_op(my_decimal *decimal_value)
bool Item_func_case::date_op(MYSQL_TIME *ltime, uint fuzzydate) bool Item_func_case::date_op(MYSQL_TIME *ltime, uint fuzzydate)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH]; Item *item= find_item();
String dummy_str(buff, sizeof(buff), default_charset());
Item *item= find_item(&dummy_str);
if (!item) if (!item)
return (null_value= true); return (null_value= true);
return (null_value= item->get_date_with_conversion(ltime, fuzzydate)); return (null_value= item->get_date_with_conversion(ltime, fuzzydate));
...@@ -2979,6 +2970,10 @@ bool Item_func_case::fix_fields(THD *thd, Item **ref) ...@@ -2979,6 +2970,10 @@ bool Item_func_case::fix_fields(THD *thd, Item **ref)
return TRUE; return TRUE;
bool res= Item_func::fix_fields(thd, ref); bool res= Item_func::fix_fields(thd, ref);
if (else_expr_num == -1 || args[else_expr_num]->maybe_null)
maybe_null= 1;
/* /*
Call check_stack_overrun after fix_fields to be sure that stack variable Call check_stack_overrun after fix_fields to be sure that stack variable
is not optimized away is not optimized away
...@@ -3032,18 +3027,26 @@ bool Item_func_case::prepare_predicant_and_values(THD *thd, uint *found_types) ...@@ -3032,18 +3027,26 @@ bool Item_func_case::prepare_predicant_and_values(THD *thd, uint *found_types)
void Item_func_case::fix_length_and_dec() void Item_func_case::fix_length_and_dec()
{ {
Item **agg= arg_buffer;
uint nagg;
THD *thd= current_thd; THD *thd= current_thd;
m_found_types= 0; m_found_types= 0;
if (else_expr_num == -1 || args[else_expr_num]->maybe_null) if (!aggregate_then_and_else_arguments(thd) &&
maybe_null= 1; first_expr_num != -1)
aggregate_switch_and_when_arguments(thd);
}
/*
/*
Aggregate all THEN and ELSE expression types Aggregate all THEN and ELSE expression types
and collations when string result and collations when string result
*/
@param THD - current thd
@param offs - the offset of the leftmost THEN argument
@paran count - the number or THEN..ELSE pairs
*/
bool Item_func_case::aggregate_then_and_else_arguments(THD *thd)
{
Item **agg= arg_buffer;
uint nagg;
for (nagg= 0 ; nagg < ncases/2 ; nagg++) for (nagg= 0 ; nagg < ncases/2 ; nagg++)
agg[nagg]= args[nagg*2+1]; agg[nagg]= args[nagg*2+1];
...@@ -3052,10 +3055,10 @@ void Item_func_case::fix_length_and_dec() ...@@ -3052,10 +3055,10 @@ void Item_func_case::fix_length_and_dec()
agg[nagg++]= args[else_expr_num]; agg[nagg++]= args[else_expr_num];
if (aggregate_for_result(func_name(), agg, nagg, true)) if (aggregate_for_result(func_name(), agg, nagg, true))
return; return true;
if (fix_attributes(agg, nagg)) if (fix_attributes(agg, nagg))
return; return true;
/* /*
Copy all modified THEN and ELSE items back to args[] array. Copy all modified THEN and ELSE items back to args[] array.
...@@ -3066,13 +3069,18 @@ void Item_func_case::fix_length_and_dec() ...@@ -3066,13 +3069,18 @@ void Item_func_case::fix_length_and_dec()
if (else_expr_num != -1) if (else_expr_num != -1)
change_item_tree_if_needed(thd, &args[else_expr_num], agg[nagg++]); change_item_tree_if_needed(thd, &args[else_expr_num], agg[nagg++]);
return false;
}
/*
Aggregate first expression and all WHEN expression types /*
Aggregate the predicant expression and all WHEN expression types
and collations when string comparison and collations when string comparison
*/ */
if (first_expr_num != -1) bool Item_func_case::aggregate_switch_and_when_arguments(THD *thd)
{ {
Item **agg= arg_buffer;
uint nagg;
if (prepare_predicant_and_values(thd, &m_found_types)) if (prepare_predicant_and_values(thd, &m_found_types))
{ {
/* /*
...@@ -3081,22 +3089,21 @@ void Item_func_case::fix_length_and_dec() ...@@ -3081,22 +3089,21 @@ void Item_func_case::fix_length_and_dec()
to make fix_fields() catches such errors. to make fix_fields() catches such errors.
*/ */
DBUG_ASSERT(thd->is_error()); DBUG_ASSERT(thd->is_error());
return; return true;
} }
agg[0]= args[first_expr_num];
/* /*
As the first expression and WHEN expressions As the predicant expression and WHEN expressions
are intermixed in args[] array THEN and ELSE items, are intermixed in args[] array THEN and ELSE items,
extract the first expression and all WHEN expressions into extract the first expression and all WHEN expressions into
a temporary array, to process them easier. a temporary array, to process them easier.
*/ */
agg[0]= args[first_expr_num]; // The predicant
for (nagg= 0; nagg < ncases/2 ; nagg++) for (nagg= 0; nagg < ncases/2 ; nagg++)
agg[nagg+1]= args[nagg*2]; agg[nagg+1]= args[nagg*2];
nagg++; nagg++;
if (!(m_found_types= collect_cmp_types(agg, nagg))) if (!(m_found_types= collect_cmp_types(agg, nagg)))
return; return true;
if (m_found_types & (1U << STRING_RESULT)) if (m_found_types & (1U << STRING_RESULT))
{ {
...@@ -3125,7 +3132,7 @@ void Item_func_case::fix_length_and_dec() ...@@ -3125,7 +3132,7 @@ void Item_func_case::fix_length_and_dec()
CASE utf16_item WHEN CONVERT(latin1_item USING utf16) THEN ... END CASE utf16_item WHEN CONVERT(latin1_item USING utf16) THEN ... END
*/ */
if (agg_arg_charsets_for_comparison(cmp_collation, agg, nagg)) if (agg_arg_charsets_for_comparison(cmp_collation, agg, nagg))
return; return true;
/* /*
Now copy first expression and all WHEN expressions back to args[] Now copy first expression and all WHEN expressions back to args[]
arrray, because some of the items might have been changed to converters arrray, because some of the items might have been changed to converters
...@@ -3135,12 +3142,12 @@ void Item_func_case::fix_length_and_dec() ...@@ -3135,12 +3142,12 @@ void Item_func_case::fix_length_and_dec()
for (nagg= 0; nagg < ncases / 2; nagg++) for (nagg= 0; nagg < ncases / 2; nagg++)
change_item_tree_if_needed(thd, &args[nagg * 2], agg[nagg + 1]); change_item_tree_if_needed(thd, &args[nagg * 2], agg[nagg + 1]);
} }
if (make_unique_cmp_items(thd, cmp_collation.collation)) if (make_unique_cmp_items(thd, cmp_collation.collation))
return; return true;
}
return false;
} }
...@@ -3230,10 +3237,30 @@ Item* Item_func_case::propagate_equal_fields(THD *thd, const Context &ctx, COND_ ...@@ -3230,10 +3237,30 @@ Item* Item_func_case::propagate_equal_fields(THD *thd, const Context &ctx, COND_
} }
/** void Item_func_case::print_when_then_arguments(String *str,
@todo enum_query_type query_type,
Fix this so that it prints the whole CASE expression Item **items, uint count)
*/ {
for (uint i=0 ; i < count ; i++)
{
str->append(STRING_WITH_LEN("when "));
items[i * 2]->print_parenthesised(str, query_type, precedence());
str->append(STRING_WITH_LEN(" then "));
items[i * 2 + 1]->print_parenthesised(str, query_type, precedence());
str->append(' ');
}
}
void Item_func_case::print_else_argument(String *str,
enum_query_type query_type,
Item *item)
{
str->append(STRING_WITH_LEN("else "));
item->print_parenthesised(str, query_type, precedence());
str->append(' ');
}
void Item_func_case::print(String *str, enum_query_type query_type) void Item_func_case::print(String *str, enum_query_type query_type)
{ {
...@@ -3243,20 +3270,9 @@ void Item_func_case::print(String *str, enum_query_type query_type) ...@@ -3243,20 +3270,9 @@ void Item_func_case::print(String *str, enum_query_type query_type)
args[first_expr_num]->print_parenthesised(str, query_type, precedence()); args[first_expr_num]->print_parenthesised(str, query_type, precedence());
str->append(' '); str->append(' ');
} }
for (uint i=0 ; i < ncases ; i+=2) print_when_then_arguments(str, query_type, &args[0], ncases / 2);
{
str->append(STRING_WITH_LEN("when "));
args[i]->print_parenthesised(str, query_type, precedence());
str->append(STRING_WITH_LEN(" then "));
args[i+1]->print_parenthesised(str, query_type, precedence());
str->append(' ');
}
if (else_expr_num != -1) if (else_expr_num != -1)
{ print_else_argument(str, query_type, args[else_expr_num]);
str->append(STRING_WITH_LEN("else "));
args[else_expr_num]->print_parenthesised(str, query_type, precedence());
str->append(' ');
}
str->append(STRING_WITH_LEN("end")); str->append(STRING_WITH_LEN("end"));
} }
......
...@@ -2041,6 +2041,17 @@ class Item_func_case :public Item_func_case_expression, ...@@ -2041,6 +2041,17 @@ class Item_func_case :public Item_func_case_expression,
Item **arg_buffer; Item **arg_buffer;
uint m_found_types; uint m_found_types;
bool prepare_predicant_and_values(THD *thd, uint *found_types); bool prepare_predicant_and_values(THD *thd, uint *found_types);
bool aggregate_then_and_else_arguments(THD *thd);
bool aggregate_switch_and_when_arguments(THD *thd);
Item *find_item_searched();
Item *find_item_simple();
Item *find_item()
{
return first_expr_num == -1 ? find_item_searched() : find_item_simple();
}
void print_when_then_arguments(String *str, enum_query_type query_type,
Item **items, uint count);
void print_else_argument(String *str, enum_query_type query_type, Item *item);
public: public:
Item_func_case(THD *thd, List<Item> &list, Item *first_expr_arg, Item_func_case(THD *thd, List<Item> &list, Item *first_expr_arg,
Item *else_expr_arg); Item *else_expr_arg);
...@@ -2055,7 +2066,6 @@ class Item_func_case :public Item_func_case_expression, ...@@ -2055,7 +2066,6 @@ class Item_func_case :public Item_func_case_expression,
const char *func_name() const { return "case"; } const char *func_name() const { return "case"; }
enum precedence precedence() const { return BETWEEN_PRECEDENCE; } enum precedence precedence() const { return BETWEEN_PRECEDENCE; }
virtual void print(String *str, enum_query_type query_type); virtual void print(String *str, enum_query_type query_type);
Item *find_item(String *str);
CHARSET_INFO *compare_collation() const { return cmp_collation.collation; } CHARSET_INFO *compare_collation() const { return cmp_collation.collation; }
void cleanup() void cleanup()
{ {
...@@ -2081,6 +2091,7 @@ class Item_func_case :public Item_func_case_expression, ...@@ -2081,6 +2091,7 @@ class Item_func_case :public Item_func_case_expression,
} }
}; };
/* /*
The Item_func_in class implements The Item_func_in class implements
in_expr IN (<in value list>) in_expr IN (<in value list>)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment