summaryrefslogtreecommitdiff
path: root/sql/item_cmpfunc.cc
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2003-07-22 11:18:51 +0300
committerunknown <bell@sanja.is.com.ua>2003-07-22 11:18:51 +0300
commitca6c74b7ee8f9a1a94521083215601ef635f1db3 (patch)
tree809bf6c0d03158e877f1213952247b53143326d1 /sql/item_cmpfunc.cc
parenteba0a3aaadc3c82a87c60d6c58957ad776fba2ff (diff)
parent491cdf396fe45d1246e5ab664e0d4192244f89fd (diff)
downloadmariadb-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.cc283
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;