diff options
author | unknown <bell@sanja.is.com.ua> | 2003-07-22 11:18:51 +0300 |
---|---|---|
committer | unknown <bell@sanja.is.com.ua> | 2003-07-22 11:18:51 +0300 |
commit | ca6c74b7ee8f9a1a94521083215601ef635f1db3 (patch) | |
tree | 809bf6c0d03158e877f1213952247b53143326d1 /sql/item_cmpfunc.cc | |
parent | eba0a3aaadc3c82a87c60d6c58957ad776fba2ff (diff) | |
parent | 491cdf396fe45d1246e5ab664e0d4192244f89fd (diff) | |
download | mariadb-git-ca6c74b7ee8f9a1a94521083215601ef635f1db3.tar.gz |
merge
sql/item.h:
Auto merged
sql/item_func.cc:
Auto merged
sql/item_func.h:
Auto merged
sql/sql_lex.cc:
Auto merged
sql/sql_select.h:
Auto merged
sql/sql_yacc.yy:
Auto merged
Diffstat (limited to 'sql/item_cmpfunc.cc')
-rw-r--r-- | sql/item_cmpfunc.cc | 283 |
1 files changed, 121 insertions, 162 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 08ae7e2063a..e8d3cba3ddb 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -24,6 +24,32 @@ #include "mysql_priv.h" #include <m_ctype.h> +static Item_result item_store_type(Item_result a,Item_result b) +{ + if (a == STRING_RESULT || b == STRING_RESULT) + return STRING_RESULT; + else if (a == REAL_RESULT || b == REAL_RESULT) + return REAL_RESULT; + else + return INT_RESULT; +} + +static void agg_result_type(Item_result *type, Item **items, uint nitems) +{ + 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()); +} + +static void agg_cmp_type(Item_result *type, Item **items, uint nitems) +{ + 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()); +} + static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname) { my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0), @@ -561,10 +587,7 @@ void Item_func_between::fix_length_and_dec() */ if (!args[0] || !args[1] || !args[2]) return; - cmp_type=item_cmp_type(args[0]->result_type(), - item_cmp_type(args[1]->result_type(), - args[2]->result_type())); - + agg_cmp_type(&cmp_type, args, 3); if (cmp_type == STRING_RESULT && agg_arg_collations_for_comparison(cmp_collation, args, 3)) return; @@ -655,28 +678,17 @@ longlong Item_func_between::val_int() return 0; } -static Item_result item_store_type(Item_result a,Item_result b) -{ - if (a == STRING_RESULT || b == STRING_RESULT) - return STRING_RESULT; - else if (a == REAL_RESULT || b == REAL_RESULT) - return REAL_RESULT; - else - return INT_RESULT; -} - void Item_func_ifnull::fix_length_and_dec() { maybe_null=args[1]->maybe_null; max_length=max(args[0]->max_length,args[1]->max_length); decimals=max(args[0]->decimals,args[1]->decimals); - if ((cached_result_type=item_store_type(args[0]->result_type(), - args[1]->result_type())) != - REAL_RESULT) - decimals= 0; + agg_result_type(&cached_result_type, args, 2); if (cached_result_type == STRING_RESULT) agg_arg_collations(collation, args, arg_count); + else if (cached_result_type != REAL_RESULT) + decimals= 0; } @@ -749,19 +761,18 @@ Item_func_if::fix_length_and_dec() cached_result_type= arg1_type; set_charset(args[1]->charset()); } - else if (arg1_type == STRING_RESULT || arg2_type == STRING_RESULT) - { - cached_result_type = STRING_RESULT; - if (agg_arg_collations(collation, args+1, 2)) - return; - } else { - set_charset(&my_charset_bin); // Number - if (arg1_type == REAL_RESULT || arg2_type == REAL_RESULT) - cached_result_type = REAL_RESULT; + agg_result_type(&cached_result_type, args+1, 2); + if (cached_result_type == STRING_RESULT) + { + if (agg_arg_collations(collation, args+1, 2)) + return; + } else - cached_result_type=arg1_type; // Should be INT_RESULT + { + set_charset(&my_charset_bin); // Number + } } } @@ -805,7 +816,7 @@ Item_func_nullif::fix_length_and_dec() { max_length=args[0]->max_length; decimals=args[0]->decimals; - cached_result_type=args[0]->result_type(); + agg_result_type(&cached_result_type, args, 2); } } @@ -868,64 +879,60 @@ Item *Item_func_case::find_item(String *str) String *first_expr_str,*tmp; longlong first_expr_int; double first_expr_real; - bool int_used, real_used,str_used; - int_used=real_used=str_used=0; - + /* These will be initialized later */ LINT_INIT(first_expr_str); LINT_INIT(first_expr_int); LINT_INIT(first_expr_real); + if (first_expr_num != -1) + { + switch (cmp_type) + { + case STRING_RESULT: + // We can't use 'str' here as this may be overwritten + if (!(first_expr_str= args[first_expr_num]->val_str(&str_value))) + return else_expr_num != -1 ? args[else_expr_num] : 0; // Impossible + break; + case INT_RESULT: + 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; + break; + case REAL_RESULT: + 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; + break; + case ROW_RESULT: + default: + // This case should never be choosen + DBUG_ASSERT(0); + break; + } + } + // 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 + // No expression between CASE and the first WHEN if (args[i]->val_int()) return args[i+1]; continue; } - switch (args[i]->result_type()) { + switch (cmp_type) { case STRING_RESULT: - if (!str_used) - { - 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 ((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,cmp_collation.collation)==0) return args[i+1]; - } break; case INT_RESULT: - if (!int_used) - { - int_used=1; - first_expr_int= first_expr->val_int(); - if (first_expr->null_value) - return else_expr; - } if (args[i]->val_int()==first_expr_int && !args[i]->null_value) return args[i+1]; break; case REAL_RESULT: - if (!real_used) - { - real_used=1; - first_expr_real= first_expr->val(); - if (first_expr->null_value) - return else_expr; - } if (args[i]->val()==first_expr_real && !args[i]->null_value) return args[i+1]; break; @@ -937,7 +944,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; } @@ -993,104 +1000,57 @@ double Item_func_case::val() return res; } - -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); -} - - -bool Item_func_case::walk (Item_processor processor, byte *arg) -{ - return first_expr->walk(processor, arg) || - else_expr->walk(processor, arg) || - Item_func::walk(processor, arg); -} - -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*2]; + 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); } } @@ -1149,13 +1109,11 @@ void Item_func_coalesce::fix_length_and_dec() { max_length= 0; decimals= 0; - cached_result_type = args[0]->result_type(); + agg_result_type(&cached_result_type, args, arg_count); for (uint i=0 ; i < arg_count ; i++) { set_if_bigger(max_length,args[i]->max_length); set_if_bigger(decimals,args[i]->decimals); - cached_result_type=item_store_type(cached_result_type, - args[i]->result_type()); } if (cached_result_type == STRING_RESULT) agg_arg_collations(collation, args, arg_count); @@ -1445,7 +1403,8 @@ void Item_func_in::fix_length_and_dec() Item **arg, **arg_end; uint const_itm= 1; - if ((args[0]->result_type() == STRING_RESULT) && + agg_cmp_type(&cmp_type, args, arg_count); + if ((cmp_type == STRING_RESULT) && (agg_arg_collations_for_comparison(cmp_collation, args, arg_count))) return; @@ -1458,7 +1417,7 @@ void Item_func_in::fix_length_and_dec() */ if (const_itm && !nulls_in_row()) { - switch (args[0]->result_type()) { + switch (cmp_type) { case STRING_RESULT: uint i; array=new in_string(arg_count-1,(qsort2_cmp) srtcmp_in, @@ -1492,7 +1451,7 @@ void Item_func_in::fix_length_and_dec() else { in_item= cmp_item::get_comparator(args[0]); - if (args[0]->result_type() == STRING_RESULT) + if (cmp_type == STRING_RESULT) in_item->cmp_charset= cmp_collation.collation; } maybe_null= args[0]->maybe_null; |