Commit bdeb6fe2 authored by paul@ice.snake.net's avatar paul@ice.snake.net

Merge paul@bk-internal.mysql.com:/home/bk/mysql-4.1

into ice.snake.net:/Users/paul/mysql-4.1
parents 7fb37ad8 a2f7ef9c
......@@ -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
......
......@@ -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)
{
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)
static void agg_result_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);
}
void Item_func_case::set_outer_resolving()
{
first_expr->set_outer_resolving();
else_expr->set_outer_resolving();
Item_func::set_outer_resolving();
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::update_used_tables()
static void agg_cmp_type(Item_result *type, Item **items, uint nitems)
{
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();
}
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::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);
}
}
......
......@@ -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<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);
......
......@@ -2030,7 +2030,7 @@ CHARSET_INFO my_charset_utf8_bin=
3, /* mbmaxlen */
0,
&my_charset_handler,
&my_collation_ci_handler
&my_collation_bin_handler
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment