From d5a6d17707bfda6015b60b589d38e5ad5d3ab52c Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 17 Jul 2003 16:07:56 +0500 Subject: [PATCH] CASE stores first_expr and else_expr in args[] array now. This allowed to reuse a lot of code. --- sql/item_cmpfunc.cc | 118 ++++++++------------------------------------ sql/item_cmpfunc.h | 24 ++++++--- sql/item_func.cc | 11 +++-- sql/item_func.h | 1 + 4 files changed, 46 insertions(+), 108 deletions(-) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 758733aaa2c..df02dc5fe32 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -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 &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); } } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 9de222aafaf..9953e3d87a4 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -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 &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 &fields); Item *find_item(String *str); - void set_outer_resolving(); }; diff --git a/sql/item_func.cc b/sql/item_func.cc index 7e236225067..ea3c3980a50 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -102,10 +102,9 @@ eval_const_cond(COND *cond) return ((Item_func*) cond)->val_int() ? TRUE : FALSE; } - -Item_func::Item_func(List &list) - :allowed_arg_cols(1) +void Item_func::set_arguments(List &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 &list) list.empty(); // Fields are used } +Item_func::Item_func(List &list) + :allowed_arg_cols(1) +{ + set_arguments(list); +} + /* Resolve references to table column for a function and it's argument diff --git a/sql/item_func.h b/sql/item_func.h index a0969fc6b9a..7002f885c50 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -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 &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 &fields);