summaryrefslogtreecommitdiff
path: root/sql/item_cmpfunc.cc
diff options
context:
space:
mode:
authorunknown <malff/marcsql@weblab.(none)>2007-02-15 14:04:03 -0700
committerunknown <malff/marcsql@weblab.(none)>2007-02-15 14:04:03 -0700
commit25bf1eae6ae033253ea305bd0ea8e1ffac535835 (patch)
tree2cc557ce1ce0982d41e97b4574a4db6d03ad0301 /sql/item_cmpfunc.cc
parentae6cc963a7a177fd54c8c55b6b1189d32dd0c324 (diff)
parent4f12094fdd942423efb612fff24d0f62e48201d8 (diff)
downloadmariadb-git-25bf1eae6ae033253ea305bd0ea8e1ffac535835.tar.gz
Merge weblab.(none):/home/marcsql/TREE/mysql-5.1-base
into weblab.(none):/home/marcsql/TREE/mysql-5.1-rt-merge mysql-test/r/subselect.result: Auto merged mysql-test/t/ps_1general.test: Auto merged mysql-test/t/subselect.test: Auto merged sql/event_data_objects.cc: Auto merged sql/event_queue.cc: Auto merged sql/item_cmpfunc.cc: Auto merged sql/item_cmpfunc.h: Auto merged sql/item_subselect.cc: Auto merged sql/item_subselect.h: Auto merged sql/set_var.cc: Auto merged sql/sp_head.cc: Auto merged sql/sql_lex.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_yacc.yy: Auto merged
Diffstat (limited to 'sql/item_cmpfunc.cc')
-rw-r--r--sql/item_cmpfunc.cc197
1 files changed, 147 insertions, 50 deletions
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 3e074d1c8f1..529b596e65f 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -26,13 +26,17 @@
static bool convert_constant_item(THD *thd, Field *field, Item **item);
-static Item_result item_store_type(Item_result a,Item_result b)
+static Item_result item_store_type(Item_result a, Item *item,
+ my_bool unsigned_flag)
{
+ Item_result b= item->result_type();
+
if (a == STRING_RESULT || b == STRING_RESULT)
return STRING_RESULT;
else if (a == REAL_RESULT || b == REAL_RESULT)
return REAL_RESULT;
- else if (a == DECIMAL_RESULT || b == DECIMAL_RESULT)
+ else if (a == DECIMAL_RESULT || b == DECIMAL_RESULT ||
+ unsigned_flag != item->unsigned_flag)
return DECIMAL_RESULT;
else
return INT_RESULT;
@@ -41,6 +45,7 @@ static Item_result item_store_type(Item_result a,Item_result b)
static void agg_result_type(Item_result *type, Item **items, uint nitems)
{
Item **item, **item_end;
+ my_bool unsigned_flag= 0;
*type= STRING_RESULT;
/* Skip beginning NULL items */
@@ -49,6 +54,7 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems)
if ((*item)->type() != Item::NULL_ITEM)
{
*type= (*item)->result_type();
+ unsigned_flag= (*item)->unsigned_flag;
item++;
break;
}
@@ -57,7 +63,7 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems)
for (; item < item_end; item++)
{
if ((*item)->type() != Item::NULL_ITEM)
- *type= item_store_type(type[0], (*item)->result_type());
+ *type= item_store_type(*type, *item, unsigned_flag);
}
}
@@ -176,6 +182,22 @@ longlong Item_func_not::val_int()
}
/*
+ We put any NOT expression into parenthesis to avoid
+ possible problems with internal view representations where
+ any '!' is converted to NOT. It may cause a problem if
+ '!' is used in an expression together with other operators
+ whose precedence is lower than the precedence of '!' yet
+ higher than the precedence of NOT.
+*/
+
+void Item_func_not::print(String *str)
+{
+ str->append('(');
+ Item_func::print(str);
+ str->append(')');
+}
+
+/*
special NOT for ALL subquery
*/
@@ -306,7 +328,7 @@ static bool convert_constant_item(THD *thd, Field *field, Item **item)
void Item_bool_func2::fix_length_and_dec()
{
max_length= 1; // Function returns 0 or 1
- THD *thd= current_thd;
+ THD *thd;
/*
As some compare functions are generated after sql_yacc,
@@ -344,12 +366,13 @@ void Item_bool_func2::fix_length_and_dec()
return;
}
+ thd= current_thd;
if (!thd->is_context_analysis_only())
{
- Item *real_item= args[0]->real_item();
- if (real_item->type() == FIELD_ITEM)
+ Item *arg_real_item= args[0]->real_item();
+ if (arg_real_item->type() == FIELD_ITEM)
{
- Field *field=((Item_field*) real_item)->field;
+ Field *field=((Item_field*) arg_real_item)->field;
if (field->can_be_compared_as_longlong())
{
if (convert_constant_item(thd, field,&args[1]))
@@ -361,10 +384,10 @@ void Item_bool_func2::fix_length_and_dec()
}
}
}
- real_item= args[1]->real_item();
- if (real_item->type() == FIELD_ITEM /* && !real_item->const_item() */)
+ arg_real_item= args[1]->real_item();
+ if (arg_real_item->type() == FIELD_ITEM)
{
- Field *field=((Item_field*) real_item)->field;
+ Field *field=((Item_field*) arg_real_item)->field;
if (field->can_be_compared_as_longlong())
{
if (convert_constant_item(thd, field,&args[0]))
@@ -400,9 +423,9 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
return 1;
for (uint i=0; i < n; i++)
{
- if ((*a)->el(i)->cols() != (*b)->el(i)->cols())
+ if ((*a)->element_index(i)->cols() != (*b)->element_index(i)->cols())
{
- my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->el(i)->cols());
+ my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->element_index(i)->cols());
return 1;
}
comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i));
@@ -464,8 +487,19 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
break;
}
case DECIMAL_RESULT:
+ break;
case REAL_RESULT:
+ {
+ if ((*a)->decimals < NOT_FIXED_DEC && (*b)->decimals < NOT_FIXED_DEC)
+ {
+ precision= 5 * log_01[max((*a)->decimals, (*b)->decimals)];
+ if (func == &Arg_comparator::compare_real)
+ func= &Arg_comparator::compare_real_fixed;
+ else if (func == &Arg_comparator::compare_e_real)
+ func= &Arg_comparator::compare_e_real_fixed;
+ }
break;
+ }
default:
DBUG_ASSERT(0);
}
@@ -604,6 +638,44 @@ int Arg_comparator::compare_e_decimal()
return test(my_decimal_cmp(val1, val2) == 0);
}
+
+int Arg_comparator::compare_real_fixed()
+{
+ /*
+ Fix yet another manifestation of Bug#2338. 'Volatile' will instruct
+ gcc to flush double values out of 80-bit Intel FPU registers before
+ performing the comparison.
+ */
+ volatile double val1, val2;
+ val1= (*a)->val_real();
+ if (!(*a)->null_value)
+ {
+ val2= (*b)->val_real();
+ if (!(*b)->null_value)
+ {
+ owner->null_value= 0;
+ if (val1 == val2 || fabs(val1 - val2) < precision)
+ return 0;
+ if (val1 < val2)
+ return -1;
+ return 1;
+ }
+ }
+ owner->null_value= 1;
+ return -1;
+}
+
+
+int Arg_comparator::compare_e_real_fixed()
+{
+ double val1= (*a)->val_real();
+ double val2= (*b)->val_real();
+ if ((*a)->null_value || (*b)->null_value)
+ return test((*a)->null_value && (*b)->null_value);
+ return test(val1 == val2 || fabs(val1 - val2) < precision);
+}
+
+
int Arg_comparator::compare_int_signed()
{
longlong val1= (*a)->val_int();
@@ -840,10 +912,10 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
uint n= cache->cols();
for (uint i= 0; i < n; i++)
{
- if (args[0]->el(i)->used_tables())
- ((Item_cache *)cache->el(i))->set_used_tables(OUTER_REF_TABLE_BIT);
+ if (args[0]->element_index(i)->used_tables())
+ ((Item_cache *)cache->element_index(i))->set_used_tables(OUTER_REF_TABLE_BIT);
else
- ((Item_cache *)cache->el(i))->set_used_tables(0);
+ ((Item_cache *)cache->element_index(i))->set_used_tables(0);
}
used_tables_cache= args[0]->used_tables();
}
@@ -914,11 +986,35 @@ longlong Item_in_optimizer::val_int()
We disable the predicates we've pushed down into subselect, run the
subselect and see if it has produced any rows.
*/
- ((Item_in_subselect*)args[1])->enable_pushed_conds= FALSE;
- longlong tmp= args[1]->val_bool_result();
- result_for_null_param= null_value=
- !((Item_in_subselect*)args[1])->engine->no_rows();
- ((Item_in_subselect*)args[1])->enable_pushed_conds= TRUE;
+ Item_in_subselect *item_subs=(Item_in_subselect*)args[1];
+ if (cache->cols() == 1)
+ {
+ item_subs->set_cond_guard_var(0, FALSE);
+ (void) args[1]->val_bool_result();
+ result_for_null_param= null_value= !item_subs->engine->no_rows();
+ item_subs->set_cond_guard_var(0, TRUE);
+ }
+ else
+ {
+ uint i;
+ uint ncols= cache->cols();
+ /*
+ Turn off the predicates that are based on column compares for
+ which the left part is currently NULL
+ */
+ for (i= 0; i < ncols; i++)
+ {
+ if (cache->element_index(i)->null_value)
+ item_subs->set_cond_guard_var(i, FALSE);
+ }
+
+ (void) args[1]->val_bool_result();
+ result_for_null_param= null_value= !item_subs->engine->no_rows();
+
+ /* Turn all predicates back on */
+ for (i= 0; i < ncols; i++)
+ item_subs->set_cond_guard_var(i, TRUE);
+ }
}
}
return 0;
@@ -1032,15 +1128,17 @@ longlong Item_func_strcmp::val_int()
void Item_func_interval::fix_length_and_dec()
{
- use_decimal_comparison= (row->el(0)->result_type() == DECIMAL_RESULT) ||
- (row->el(0)->result_type() == INT_RESULT);
+ use_decimal_comparison= ((row->element_index(0)->result_type() ==
+ DECIMAL_RESULT) ||
+ (row->element_index(0)->result_type() ==
+ INT_RESULT));
if (row->cols() > 8)
{
bool consts=1;
for (uint i=1 ; consts && i < row->cols() ; i++)
{
- consts&= row->el(i)->const_item();
+ consts&= row->element_index(i)->const_item();
}
if (consts &&
@@ -1051,7 +1149,7 @@ void Item_func_interval::fix_length_and_dec()
{
for (uint i=1 ; i < row->cols(); i++)
{
- Item *el= row->el(i);
+ Item *el= row->element_index(i);
interval_range *range= intervals + (i-1);
if ((el->result_type() == DECIMAL_RESULT) ||
(el->result_type() == INT_RESULT))
@@ -1076,7 +1174,7 @@ void Item_func_interval::fix_length_and_dec()
{
for (uint i=1 ; i < row->cols(); i++)
{
- intervals[i-1].dbl= row->el(i)->val_real();
+ intervals[i-1].dbl= row->element_index(i)->val_real();
}
}
}
@@ -1116,15 +1214,15 @@ longlong Item_func_interval::val_int()
if (use_decimal_comparison)
{
- dec= row->el(0)->val_decimal(&dec_buf);
- if (row->el(0)->null_value)
+ dec= row->element_index(0)->val_decimal(&dec_buf);
+ if (row->element_index(0)->null_value)
return -1;
my_decimal2double(E_DEC_FATAL_ERROR, dec, &value);
}
else
{
- value= row->el(0)->val_real();
- if (row->el(0)->null_value)
+ value= row->element_index(0)->val_real();
+ if (row->element_index(0)->null_value)
return -1;
}
@@ -1160,16 +1258,16 @@ longlong Item_func_interval::val_int()
for (i=1 ; i < row->cols() ; i++)
{
- Item *el= row->el(i);
+ Item *el= row->element_index(i);
if (use_decimal_comparison &&
((el->result_type() == DECIMAL_RESULT) ||
(el->result_type() == INT_RESULT)))
{
- my_decimal e_dec_buf, *e_dec= row->el(i)->val_decimal(&e_dec_buf);
+ my_decimal e_dec_buf, *e_dec= row->element_index(i)->val_decimal(&e_dec_buf);
if (my_decimal_cmp(e_dec, dec) > 0)
return i-1;
}
- else if (row->el(i)->val_real() > value)
+ else if (row->element_index(i)->val_real() > value)
return i-1;
}
return i-1;
@@ -1246,11 +1344,11 @@ void Item_func_between::fix_length_and_dec()
They are compared as integers, so for const item this time-consuming
conversion can be done only once, not for every single comparison
*/
- if (args[0]->type() == FIELD_ITEM &&
+ if (args[0]->real_item()->type() == FIELD_ITEM &&
thd->lex->sql_command != SQLCOM_CREATE_VIEW &&
thd->lex->sql_command != SQLCOM_SHOW_CREATE)
{
- Field *field=((Item_field*) args[0])->field;
+ Field *field=((Item_field*) (args[0]->real_item()))->field;
if (field->can_be_compared_as_longlong())
{
/*
@@ -1872,7 +1970,9 @@ bool Item_func_case::fix_fields(THD *thd, Item **ref)
buff should match stack usage from
Item_func_case::val_int() -> Item_func_case::find_item()
*/
+#ifndef EMBEDDED_LIBRARY
char buff[MAX_FIELD_WIDTH*2+sizeof(String)*2+sizeof(String*)*2+sizeof(double)*2+sizeof(longlong)*2];
+#endif
bool res= Item_func::fix_fields(thd, ref);
/*
Call check_stack_overrun after fix_fields to be sure that stack variable
@@ -1889,7 +1989,6 @@ void Item_func_case::fix_length_and_dec()
{
Item **agg;
uint nagg;
- THD *thd= current_thd;
uint found_types= 0;
if (!(agg= (Item**) sql_alloc(sizeof(Item*)*(ncases+1))))
return;
@@ -2350,11 +2449,11 @@ void cmp_item_row::store_value(Item *item)
{
if (!comparators[i])
if (!(comparators[i]=
- cmp_item::get_comparator(item->el(i)->result_type(),
- item->el(i)->collation.collation)))
+ cmp_item::get_comparator(item->element_index(i)->result_type(),
+ item->element_index(i)->collation.collation)))
break; // new failed
- comparators[i]->store_value(item->el(i));
- item->null_value|= item->el(i)->null_value;
+ comparators[i]->store_value(item->element_index(i));
+ item->null_value|= item->element_index(i)->null_value;
}
}
DBUG_VOID_RETURN;
@@ -2379,8 +2478,8 @@ void cmp_item_row::store_value_by_template(cmp_item *t, Item *item)
if (!(comparators[i]= tmpl->comparators[i]->make_same()))
break; // new failed
comparators[i]->store_value_by_template(tmpl->comparators[i],
- item->el(i));
- item->null_value|= item->el(i)->null_value;
+ item->element_index(i));
+ item->null_value|= item->element_index(i)->null_value;
}
}
}
@@ -2398,9 +2497,9 @@ int cmp_item_row::cmp(Item *arg)
arg->bring_value();
for (uint i=0; i < n; i++)
{
- if (comparators[i]->cmp(arg->el(i)))
+ if (comparators[i]->cmp(arg->element_index(i)))
{
- if (!arg->el(i)->null_value)
+ if (!arg->element_index(i)->null_value)
return 1;
was_null= 1;
}
@@ -2411,11 +2510,11 @@ int cmp_item_row::cmp(Item *arg)
int cmp_item_row::compare(cmp_item *c)
{
- cmp_item_row *cmp= (cmp_item_row *) c;
+ cmp_item_row *l_cmp= (cmp_item_row *) c;
for (uint i=0; i < n; i++)
{
int res;
- if ((res= comparators[i]->compare(cmp->comparators[i])))
+ if ((res= comparators[i]->compare(l_cmp->comparators[i])))
return res;
}
return 0;
@@ -2442,8 +2541,8 @@ int cmp_item_decimal::cmp(Item *arg)
int cmp_item_decimal::compare(cmp_item *arg)
{
- cmp_item_decimal *cmp= (cmp_item_decimal*) arg;
- return my_decimal_cmp(&value, &cmp->value);
+ cmp_item_decimal *l_cmp= (cmp_item_decimal*) arg;
+ return my_decimal_cmp(&value, &l_cmp->value);
}
@@ -4147,11 +4246,9 @@ longlong Item_equal::val_int()
void Item_equal::fix_length_and_dec()
{
- Item *item= const_item ? const_item : get_first();
+ Item *item= get_first();
eval_item= cmp_item::get_comparator(item->result_type(),
item->collation.collation);
- if (item->result_type() == STRING_RESULT)
- eval_item->cmp_charset= cmp_collation.collation;
}
bool Item_equal::walk(Item_processor processor, bool walk_subquery, byte *arg)