diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 9e4f35dd5e1..a69995e51a0 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -191,7 +191,7 @@ then echo "Installing all prepared tables" fi if ( - $pkgdatadir/mysql_create_system_tables $create_option $mdata $hostname $windows + $bindir/mysql_create_system_tables $create_option $mdata $hostname $windows if test -n "$fill_help_tables" then cat $fill_help_tables diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 758733aaa2c..1f1b449e9a7 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,18 +887,12 @@ 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 { - /* QQ: COERCIBILITY */ - if (first_expr_is_binary || (args[i]->charset()->state & MY_CS_BINSORT)) - { - if (sortcmp(tmp,first_expr_str,&my_charset_bin)==0) - return args[i+1]; - } - else if (sortcmp(tmp,first_expr_str,tmp->charset())==0) + if (sortcmp(tmp,first_expr_str,&my_charset_bin)==0) return args[i+1]; } break; @@ -906,9 +900,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 +911,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 +926,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; } @@ -988,104 +982,74 @@ double Item_func_case::val() return res; } - -bool -Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) +static void agg_result_type(Item_result *type, Item **items, uint nitems) { - 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; + uint i; + type[0]= items[0]->result_type(); + for (i=1 ; i < nitems ; i++) + type[0]= item_store_type(type[0], items[i]->result_type()); } - -void Item_func_case::split_sum_func(Item **ref_pointer_array, - List &fields) +static void agg_cmp_type(Item_result *type, Item **items, uint nitems) { - 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); + uint i; + type[0]= items[0]->result_type(); + for (i=1 ; i < nitems ; i++) + type[0]= item_cmp_type(type[0], items[i]->result_type()); } - -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() { + Item **agg; + uint nagg; + + if (!(agg= (Item**) sql_alloc(sizeof(Item*)*(ncases+1)))) + return; + + // Aggregate all THEN and ELSE expression types + // and collations when string result + + for (nagg= 0 ; nagg < ncases/2 ; nagg++) + agg[nagg]= args[nagg*2+1]; + + if (else_expr_num != -1) + agg[nagg++]= args[else_expr_num]; + + agg_result_type(&cached_result_type, agg, nagg); + if ((cached_result_type == STRING_RESULT) && + agg_arg_collations(collation, agg, nagg)) + return; + + + // Aggregate first expression and all THEN expression types + // and collations when string comparison + if (first_expr_num != -1) + { + agg[0]= args[first_expr_num]; + for (nagg= 0; nagg < ncases/2 ; nagg++) + agg[nagg+1]= args[nagg]; + nagg++; + agg_cmp_type(&cmp_type, agg, nagg); + if ((cmp_type == STRING_RESULT) && + agg_arg_collations_for_comparison(cmp_collation, agg, nagg)) + return; + } + + 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..a9fba76a7b8 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -348,27 +348,38 @@ 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; + Item_result cmp_type; + DTCollation cmp_collation; 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); diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index f5da95571c4..1982b9e3ba8 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -2030,7 +2030,7 @@ CHARSET_INFO my_charset_utf8_bin= 3, /* mbmaxlen */ 0, &my_charset_handler, - &my_collation_ci_handler + &my_collation_bin_handler };