mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
CASE stores first_expr and else_expr in args[] array now.
This allowed to reuse a lot of code.
This commit is contained in:
parent
85cc122794
commit
d5a6d17707
4 changed files with 46 additions and 108 deletions
|
@ -872,9 +872,9 @@ Item *Item_func_case::find_item(String *str)
|
|||
LINT_INIT(first_expr_real);
|
||||
|
||||
// Compare every WHEN argument with it and return the first match
|
||||
for (uint i=0 ; i < arg_count ; i+=2)
|
||||
for (uint i=0 ; i < ncases ; i+=2)
|
||||
{
|
||||
if (!first_expr)
|
||||
if (first_expr_num == -1)
|
||||
{
|
||||
// No expression between CASE and first WHEN
|
||||
if (args[i]->val_int())
|
||||
|
@ -887,8 +887,8 @@ Item *Item_func_case::find_item(String *str)
|
|||
{
|
||||
str_used=1;
|
||||
// We can't use 'str' here as this may be overwritten
|
||||
if (!(first_expr_str= first_expr->val_str(&str_value)))
|
||||
return else_expr; // Impossible
|
||||
if (!(first_expr_str= args[first_expr_num]->val_str(&str_value)))
|
||||
return else_expr_num != -1 ? args[else_expr_num] : 0; // Impossible
|
||||
}
|
||||
if ((tmp=args[i]->val_str(str))) // If not null
|
||||
{
|
||||
|
@ -906,9 +906,9 @@ Item *Item_func_case::find_item(String *str)
|
|||
if (!int_used)
|
||||
{
|
||||
int_used=1;
|
||||
first_expr_int= first_expr->val_int();
|
||||
if (first_expr->null_value)
|
||||
return else_expr;
|
||||
first_expr_int= args[first_expr_num]->val_int();
|
||||
if (args[first_expr_num]->null_value)
|
||||
return else_expr_num != -1 ? args[else_expr_num] : 0;
|
||||
}
|
||||
if (args[i]->val_int()==first_expr_int && !args[i]->null_value)
|
||||
return args[i+1];
|
||||
|
@ -917,9 +917,9 @@ Item *Item_func_case::find_item(String *str)
|
|||
if (!real_used)
|
||||
{
|
||||
real_used=1;
|
||||
first_expr_real= first_expr->val();
|
||||
if (first_expr->null_value)
|
||||
return else_expr;
|
||||
first_expr_real= args[first_expr_num]->val();
|
||||
if (args[first_expr_num]->null_value)
|
||||
return else_expr_num != -1 ? args[else_expr_num] : 0;
|
||||
}
|
||||
if (args[i]->val()==first_expr_real && !args[i]->null_value)
|
||||
return args[i+1];
|
||||
|
@ -932,7 +932,7 @@ Item *Item_func_case::find_item(String *str)
|
|||
}
|
||||
}
|
||||
// No, WHEN clauses all missed, return ELSE expression
|
||||
return else_expr;
|
||||
return else_expr_num != -1 ? args[else_expr_num] : 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -989,103 +989,25 @@ double Item_func_case::val()
|
|||
}
|
||||
|
||||
|
||||
bool
|
||||
Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
{
|
||||
if (first_expr && (first_expr->fix_fields(thd, tables, &first_expr) ||
|
||||
first_expr->check_cols(1)) ||
|
||||
else_expr && (else_expr->fix_fields(thd, tables, &else_expr) ||
|
||||
else_expr->check_cols(1)))
|
||||
return 1;
|
||||
if (Item_func::fix_fields(thd, tables, ref))
|
||||
return 1;
|
||||
if (first_expr)
|
||||
{
|
||||
used_tables_cache|=(first_expr)->used_tables();
|
||||
const_item_cache&= (first_expr)->const_item();
|
||||
with_sum_func= with_sum_func || (first_expr)->with_sum_func;
|
||||
first_expr_is_binary= first_expr->charset()->state & MY_CS_BINSORT;
|
||||
}
|
||||
if (else_expr)
|
||||
{
|
||||
used_tables_cache|=(else_expr)->used_tables();
|
||||
const_item_cache&= (else_expr)->const_item();
|
||||
with_sum_func= with_sum_func || (else_expr)->with_sum_func;
|
||||
}
|
||||
if (!else_expr || else_expr->maybe_null)
|
||||
maybe_null=1; // The result may be NULL
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Item_func_case::split_sum_func(Item **ref_pointer_array,
|
||||
List<Item> &fields)
|
||||
{
|
||||
if (first_expr)
|
||||
{
|
||||
if (first_expr->with_sum_func && first_expr->type() != SUM_FUNC_ITEM)
|
||||
first_expr->split_sum_func(ref_pointer_array, fields);
|
||||
else if (first_expr->used_tables() || first_expr->type() == SUM_FUNC_ITEM)
|
||||
{
|
||||
uint el= fields.elements;
|
||||
fields.push_front(first_expr);
|
||||
ref_pointer_array[el]= first_expr;
|
||||
first_expr= new Item_ref(ref_pointer_array + el, 0, first_expr->name);
|
||||
}
|
||||
}
|
||||
if (else_expr)
|
||||
{
|
||||
if (else_expr->with_sum_func && else_expr->type() != SUM_FUNC_ITEM)
|
||||
else_expr->split_sum_func(ref_pointer_array, fields);
|
||||
else if (else_expr->used_tables() || else_expr->type() == SUM_FUNC_ITEM)
|
||||
{
|
||||
uint el= fields.elements;
|
||||
fields.push_front(else_expr);
|
||||
ref_pointer_array[el]= else_expr;
|
||||
else_expr= new Item_ref(ref_pointer_array + el, 0, else_expr->name);
|
||||
}
|
||||
}
|
||||
Item_func::split_sum_func(ref_pointer_array, fields);
|
||||
}
|
||||
|
||||
|
||||
void Item_func_case::set_outer_resolving()
|
||||
{
|
||||
first_expr->set_outer_resolving();
|
||||
else_expr->set_outer_resolving();
|
||||
Item_func::set_outer_resolving();
|
||||
}
|
||||
|
||||
void Item_func_case::update_used_tables()
|
||||
{
|
||||
Item_func::update_used_tables();
|
||||
if (first_expr)
|
||||
{
|
||||
used_tables_cache|=(first_expr)->used_tables();
|
||||
const_item_cache&= (first_expr)->const_item();
|
||||
}
|
||||
if (else_expr)
|
||||
{
|
||||
used_tables_cache|=(else_expr)->used_tables();
|
||||
const_item_cache&= (else_expr)->const_item();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Item_func_case::fix_length_and_dec()
|
||||
{
|
||||
if (first_expr_num != -1)
|
||||
first_expr_is_binary= args[first_expr_num]->charset()->state & MY_CS_BINSORT;
|
||||
if (!else_expr_num != -1 || args[else_expr_num]->maybe_null)
|
||||
maybe_null=1;
|
||||
|
||||
max_length=0;
|
||||
decimals=0;
|
||||
cached_result_type = args[1]->result_type();
|
||||
for (uint i=0 ; i < arg_count ; i+=2)
|
||||
for (uint i=0 ; i < ncases ; i+=2)
|
||||
{
|
||||
set_if_bigger(max_length,args[i+1]->max_length);
|
||||
set_if_bigger(decimals,args[i+1]->decimals);
|
||||
}
|
||||
if (else_expr != NULL)
|
||||
if (else_expr_num != -1)
|
||||
{
|
||||
set_if_bigger(max_length,else_expr->max_length);
|
||||
set_if_bigger(decimals,else_expr->decimals);
|
||||
set_if_bigger(max_length,args[else_expr_num]->max_length);
|
||||
set_if_bigger(decimals,args[else_expr_num]->decimals);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -348,27 +348,37 @@ public:
|
|||
|
||||
class Item_func_case :public Item_func
|
||||
{
|
||||
Item * first_expr, *else_expr;
|
||||
int first_expr_num, else_expr_num;
|
||||
enum Item_result cached_result_type;
|
||||
String tmp_value;
|
||||
bool first_expr_is_binary;
|
||||
uint ncases;
|
||||
public:
|
||||
Item_func_case(List<Item> &list, Item *first_expr_arg, Item *else_expr_arg)
|
||||
:Item_func(list), first_expr(first_expr_arg), else_expr(else_expr_arg),
|
||||
:Item_func(), first_expr_num(-1), else_expr_num(-1),
|
||||
cached_result_type(INT_RESULT)
|
||||
{}
|
||||
{
|
||||
ncases= list.elements;
|
||||
if (first_expr_arg)
|
||||
{
|
||||
first_expr_num= list.elements;
|
||||
list.push_back(first_expr_arg);
|
||||
}
|
||||
if (else_expr_arg)
|
||||
{
|
||||
else_expr_num= list.elements;
|
||||
list.push_back(else_expr_arg);
|
||||
}
|
||||
set_arguments(list);
|
||||
}
|
||||
double val();
|
||||
longlong val_int();
|
||||
String *val_str(String *);
|
||||
void fix_length_and_dec();
|
||||
void update_used_tables();
|
||||
enum Item_result result_type () const { return cached_result_type; }
|
||||
const char *func_name() const { return "case"; }
|
||||
void print(String *str);
|
||||
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
|
||||
void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
|
||||
Item *find_item(String *str);
|
||||
void set_outer_resolving();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -102,10 +102,9 @@ eval_const_cond(COND *cond)
|
|||
return ((Item_func*) cond)->val_int() ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
|
||||
Item_func::Item_func(List<Item> &list)
|
||||
:allowed_arg_cols(1)
|
||||
void Item_func::set_arguments(List<Item> &list)
|
||||
{
|
||||
allowed_arg_cols= 1;
|
||||
arg_count=list.elements;
|
||||
if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
|
||||
{
|
||||
|
@ -122,6 +121,12 @@ Item_func::Item_func(List<Item> &list)
|
|||
list.empty(); // Fields are used
|
||||
}
|
||||
|
||||
Item_func::Item_func(List<Item> &list)
|
||||
:allowed_arg_cols(1)
|
||||
{
|
||||
set_arguments(list);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Resolve references to table column for a function and it's argument
|
||||
|
|
|
@ -115,6 +115,7 @@ public:
|
|||
virtual const char *func_name() const { return "?"; }
|
||||
virtual bool const_item() const { return const_item_cache; }
|
||||
inline Item **arguments() const { return args; }
|
||||
void set_arguments(List<Item> &list);
|
||||
inline uint argument_count() const { return arg_count; }
|
||||
inline void remove_arguments() { arg_count=0; }
|
||||
virtual void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
|
||||
|
|
Loading…
Reference in a new issue