summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <bar@bar.mysql.r18.ru>2003-07-16 11:29:16 +0500
committerunknown <bar@bar.mysql.r18.ru>2003-07-16 11:29:16 +0500
commita41a43f99d053b96821d0c7388126ca581146933 (patch)
tree96c3e55c00f579733c300a701e2e951e7520885a
parent6b52f58255dd67a91d7cd0afa45f69607f498d0a (diff)
downloadmariadb-git-a41a43f99d053b96821d0c7388126ca581146933.tar.gz
Item_func_null doesn't have a separate Item for the first argument anymore.
args[0] is used instead. This allowed to resuse a lot of code.
-rw-r--r--mysql-test/r/func_in.result32
-rw-r--r--mysql-test/r/func_str.result10
-rw-r--r--mysql-test/t/func_in.test19
-rw-r--r--mysql-test/t/func_str.test10
-rw-r--r--sql/item_cmpfunc.cc78
-rw-r--r--sql/item_cmpfunc.h26
-rw-r--r--sql/opt_range.cc4
-rw-r--r--sql/sql_yacc.yy8
8 files changed, 100 insertions, 87 deletions
diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result
index 006dc8abef0..4b15c44fdb1 100644
--- a/mysql-test/r/func_in.result
+++ b/mysql-test/r/func_in.result
@@ -111,3 +111,35 @@ id
5
9
drop table t1;
+create table t1 (
+a char(1) character set latin1 collate latin1_general_ci,
+b char(1) character set latin1 collate latin1_swedish_ci,
+c char(1) character set latin1 collate latin1_danish_ci
+);
+insert into t1 values ('A','B','C');
+insert into t1 values ('a','c','c');
+select * from t1 where a in (b);
+ERROR HY000: Illegal mix of collations (latin1_general_ci,IMPLICIT) and (latin1_swedish_ci,IMPLICIT) for operation ' IN '
+select * from t1 where a in (b,c);
+ERROR HY000: Illegal mix of collations (latin1_general_ci,IMPLICIT), (latin1_swedish_ci,IMPLICIT), (latin1_danish_ci,IMPLICIT) for operation ' IN '
+select * from t1 where 'a' in (a,b,c);
+ERROR HY000: Illegal mix of collations for operation ' IN '
+select * from t1 where 'a' in (a);
+a b c
+A B C
+a c c
+select * from t1 where a in ('a');
+a b c
+A B C
+a c c
+select * from t1 where 'a' collate latin1_general_ci in (a,b,c);
+a b c
+A B C
+a c c
+select * from t1 where 'a' collate latin1_bin in (a,b,c);
+a b c
+a c c
+select * from t1 where 'a' in (a,b,c collate latin1_bin);
+a b c
+a c c
+drop table t1;
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 12969449e3f..37694ad2f0a 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -363,15 +363,15 @@ select _latin1'B' in (_latin1'a',_latin1'b' collate latin1_bin);
_latin1'B' in (_latin1'a',_latin1'b' collate latin1_bin)
0
select _latin2'B' in (_latin1'a',_latin1'b');
-ERROR HY000: Illegal mix of collations for operation ' IN '
+ERROR HY000: Illegal mix of collations (latin2_general_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE) for operation ' IN '
select _latin1'B' in (_latin2'a',_latin1'b');
-ERROR HY000: Illegal mix of collations for operation ' IN '
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (latin2_general_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE) for operation ' IN '
select _latin1'B' in (_latin1'a',_latin2'b');
-ERROR HY000: Illegal mix of collations for operation ' IN '
+ERROR HY000: Illegal mix of collations (latin1_swedish_ci,COERCIBLE), (latin1_swedish_ci,COERCIBLE), (latin2_general_ci,COERCIBLE) for operation ' IN '
select _latin1'B' COLLATE latin1_general_ci in (_latin1'a' COLLATE latin1_bin,_latin1'b');
-ERROR HY000: Illegal mix of collations for operation ' IN '
+ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT), (latin1_bin,EXPLICIT), (latin1_swedish_ci,COERCIBLE) for operation ' IN '
select _latin1'B' COLLATE latin1_general_ci in (_latin1'a',_latin1'b' COLLATE latin1_bin);
-ERROR HY000: Illegal mix of collations for operation ' IN '
+ERROR HY000: Illegal mix of collations (latin1_general_ci,EXPLICIT), (latin1_swedish_ci,COERCIBLE), (latin1_bin,EXPLICIT) for operation ' IN '
select collation(bin(130)), coercibility(bin(130));
collation(bin(130)) coercibility(bin(130))
latin1_swedish_ci 3
diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test
index 723f1707a42..dca068f368a 100644
--- a/mysql-test/t/func_in.test
+++ b/mysql-test/t/func_in.test
@@ -54,3 +54,22 @@ insert into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9);
select * from t1 where id in (2,5,9);
drop table t1;
+create table t1 (
+a char(1) character set latin1 collate latin1_general_ci,
+b char(1) character set latin1 collate latin1_swedish_ci,
+c char(1) character set latin1 collate latin1_danish_ci
+);
+insert into t1 values ('A','B','C');
+insert into t1 values ('a','c','c');
+--error 1265
+select * from t1 where a in (b);
+--error 1268
+select * from t1 where a in (b,c);
+--error 1269
+select * from t1 where 'a' in (a,b,c);
+select * from t1 where 'a' in (a);
+select * from t1 where a in ('a');
+select * from t1 where 'a' collate latin1_general_ci in (a,b,c);
+select * from t1 where 'a' collate latin1_bin in (a,b,c);
+select * from t1 where 'a' in (a,b,c collate latin1_bin);
+drop table t1;
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index 38633e87c4b..f158eaa3764 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -217,15 +217,15 @@ select _latin1'B' in (_latin1'a',_latin1'b');
select _latin1'B' collate latin1_bin in (_latin1'a',_latin1'b');
select _latin1'B' in (_latin1'a' collate latin1_bin,_latin1'b');
select _latin1'B' in (_latin1'a',_latin1'b' collate latin1_bin);
---error 1269
+--error 1268
select _latin2'B' in (_latin1'a',_latin1'b');
---error 1269
+--error 1268
select _latin1'B' in (_latin2'a',_latin1'b');
---error 1269
+--error 1268
select _latin1'B' in (_latin1'a',_latin2'b');
---error 1269
+--error 1268
select _latin1'B' COLLATE latin1_general_ci in (_latin1'a' COLLATE latin1_bin,_latin1'b');
---error 1269
+--error 1268
select _latin1'B' COLLATE latin1_general_ci in (_latin1'a',_latin1'b' COLLATE latin1_bin);
select collation(bin(130)), coercibility(bin(130));
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index ff805e05346..758733aaa2c 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1420,7 +1420,7 @@ int cmp_item_row::compare(cmp_item *c)
bool Item_func_in::nulls_in_row()
{
Item **arg,**arg_end;
- for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
+ for (arg= args+1, arg_end= args+arg_count; arg != arg_end ; arg++)
{
if ((*arg)->null_inside())
return 1;
@@ -1437,42 +1437,43 @@ static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
void Item_func_in::fix_length_and_dec()
{
+ Item **arg, **arg_end;
+ uint const_itm= 1;
+
+ if ((args[0]->result_type() == STRING_RESULT) &&
+ (agg_arg_collations_for_comparison(cmp_collation, args, arg_count)))
+ return;
+
+ for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++)
+ const_itm&= arg[0]->const_item();
+
/*
Row item with NULLs inside can return NULL or FALSE =>
they can't be processed as static
*/
- if (const_item() && !nulls_in_row())
+ if (const_itm && !nulls_in_row())
{
- switch (item->result_type()) {
+ switch (args[0]->result_type()) {
case STRING_RESULT:
uint i;
- cmp_collation.set(item->collation);
- for (i=0 ; i<arg_count; i++)
- if (cmp_collation.aggregate(args[i]->collation))
- break;
- if (cmp_collation.derivation == DERIVATION_NONE)
- {
- my_error(ER_CANT_AGGREGATE_NCOLLATIONS,MYF(0),func_name());
- return;
- }
- array=new in_string(arg_count,(qsort2_cmp) srtcmp_in,
+ array=new in_string(arg_count-1,(qsort2_cmp) srtcmp_in,
cmp_collation.collation);
break;
case INT_RESULT:
- array= new in_longlong(arg_count);
+ array= new in_longlong(arg_count-1);
break;
case REAL_RESULT:
- array= new in_double(arg_count);
+ array= new in_double(arg_count-1);
break;
case ROW_RESULT:
- array= new in_row(arg_count, item);
+ array= new in_row(arg_count-1, args[0]);
break;
default:
DBUG_ASSERT(0);
return;
}
uint j=0;
- for (uint i=0 ; i < arg_count ; i++)
+ for (uint i=1 ; i < arg_count ; i++)
{
array->set(j,args[i]);
if (!args[i]->null_value) // Skip NULL values
@@ -1485,19 +1486,19 @@ void Item_func_in::fix_length_and_dec()
}
else
{
- in_item= cmp_item::get_comparator(item);
+ in_item= cmp_item::get_comparator(args[0]);
+ if (args[0]->result_type() == STRING_RESULT)
+ in_item->cmp_charset= cmp_collation.collation;
}
- maybe_null= item->maybe_null;
+ maybe_null= args[0]->maybe_null;
max_length= 1;
- used_tables_cache|=item->used_tables();
- const_item_cache&=item->const_item();
+ const_item_cache&=args[0]->const_item();
}
void Item_func_in::print(String *str)
{
str->append('(');
- item->print(str);
Item_func::print(str);
str->append(')');
}
@@ -1507,15 +1508,15 @@ longlong Item_func_in::val_int()
{
if (array)
{
- int tmp=array->find(item);
- null_value=item->null_value || (!tmp && have_null);
+ int tmp=array->find(args[0]);
+ null_value=args[0]->null_value || (!tmp && have_null);
return tmp;
}
- in_item->store_value(item);
- if ((null_value=item->null_value))
+ in_item->store_value(args[0]);
+ if ((null_value=args[0]->null_value))
return 0;
have_null= 0;
- for (uint i=0 ; i < arg_count ; i++)
+ for (uint i=1 ; i < arg_count ; i++)
{
if (!in_item->cmp(args[i]) && !args[i]->null_value)
return 1; // Would maybe be nice with i ?
@@ -1526,29 +1527,6 @@ longlong Item_func_in::val_int()
}
-void Item_func_in::update_used_tables()
-{
- Item_func::update_used_tables();
- item->update_used_tables();
- used_tables_cache|=item->used_tables();
- const_item_cache&=item->const_item();
-}
-
-void Item_func_in::split_sum_func(Item **ref_pointer_array, List<Item> &fields)
-{
- if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
- item->split_sum_func(ref_pointer_array, fields);
- else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
- {
- uint el= fields.elements;
- fields.push_front(item);
- ref_pointer_array[el]= item;
- item= new Item_ref(ref_pointer_array + el, 0, item->name);
- }
- Item_func::split_sum_func(ref_pointer_array, fields);
-}
-
-
longlong Item_func_bit_or::val_int()
{
ulonglong arg1= (ulonglong) args[0]->val_int();
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 8309cd25a72..9de222aafaf 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -600,42 +600,26 @@ public:
class Item_func_in :public Item_int_func
{
- Item *item;
in_vector *array;
cmp_item *in_item;
bool have_null;
DTCollation cmp_collation;
public:
- Item_func_in(Item *a,List<Item> &list)
- :Item_int_func(list), item(a), array(0), in_item(0), have_null(0)
+ Item_func_in(List<Item> &list)
+ :Item_int_func(list), array(0), in_item(0), have_null(0)
{
- allowed_arg_cols= item->cols();
+ allowed_arg_cols= args[0]->cols();
}
longlong val_int();
- bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
- {
- // We do not check item->cols(), because allowed_arg_cols assigned from it
- bool res=(item->fix_fields(thd, tlist, &item) ||
- Item_func::fix_fields(thd, tlist, ref));
- with_sum_func= with_sum_func || item->with_sum_func;
- return res;
- }
void fix_length_and_dec();
- ~Item_func_in() { delete item; delete array; delete in_item; }
+ ~Item_func_in() { delete array; delete in_item; }
optimize_type select_optimize() const
{ return array ? OPTIMIZE_KEY : OPTIMIZE_NONE; }
- Item *key_item() const { return item; }
+ Item *key_item() const { return args[0]; }
void print(String *str);
enum Functype functype() const { return IN_FUNC; }
const char *func_name() const { return " IN "; }
- void update_used_tables();
- void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
bool nulls_in_row();
- void set_outer_resolving()
- {
- item->set_outer_resolving();
- Item_int_func::set_outer_resolving();
- }
};
/* Functions used by where clause */
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 7eb66c4e30f..18c465ffde3 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -832,10 +832,10 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
Field *field=((Item_field*) (func->key_item()))->field;
Item_result cmp_type=field->cmp_type();
tree= get_mm_parts(param,field,Item_func::EQ_FUNC,
- func->arguments()[0],cmp_type);
+ func->arguments()[1],cmp_type);
if (!tree)
DBUG_RETURN(tree); // Not key field
- for (uint i=1 ; i < func->argument_count(); i++)
+ for (uint i=2 ; i < func->argument_count(); i++)
{
SEL_TREE *new_tree=get_mm_parts(param,field,Item_func::EQ_FUNC,
func->arguments()[i],cmp_type);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 45a647cd8ab..0bb20b74016 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -2109,9 +2109,9 @@ all_or_any: ALL { $$ = 1; }
/* expressions that begin with 'expr' */
expr_expr:
expr IN_SYM '(' expr_list ')'
- { $$= new Item_func_in($1,*$4); }
+ { $4->push_front($1); $$= new Item_func_in(*$4); }
| expr NOT IN_SYM '(' expr_list ')'
- { $$= new Item_func_not(new Item_func_in($1,*$5)); }
+ { $5->push_front($1); $$= new Item_func_not(new Item_func_in(*$5)); }
| expr IN_SYM in_subselect
{ $$= new Item_in_subselect(YYTHD, $1, $3); }
| expr NOT IN_SYM in_subselect
@@ -2211,9 +2211,9 @@ no_in_expr:
/* expressions that begin with 'expr' that does NOT follow AND */
no_and_expr:
no_and_expr IN_SYM '(' expr_list ')'
- { $$= new Item_func_in($1,*$4); }
+ { $4->push_front($1); $$= new Item_func_in(*$4); }
| no_and_expr NOT IN_SYM '(' expr_list ')'
- { $$= new Item_func_not(new Item_func_in($1,*$5)); }
+ { $5->push_front($1); $$= new Item_func_not(new Item_func_in(*$5)); }
| no_and_expr IN_SYM in_subselect
{ $$= new Item_in_subselect(YYTHD, $1, $3); }
| no_and_expr NOT IN_SYM in_subselect