diff options
author | unknown <bar@bar.mysql.r18.ru> | 2003-07-16 11:29:16 +0500 |
---|---|---|
committer | unknown <bar@bar.mysql.r18.ru> | 2003-07-16 11:29:16 +0500 |
commit | a41a43f99d053b96821d0c7388126ca581146933 (patch) | |
tree | 96c3e55c00f579733c300a701e2e951e7520885a | |
parent | 6b52f58255dd67a91d7cd0afa45f69607f498d0a (diff) | |
download | mariadb-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.result | 32 | ||||
-rw-r--r-- | mysql-test/r/func_str.result | 10 | ||||
-rw-r--r-- | mysql-test/t/func_in.test | 19 | ||||
-rw-r--r-- | mysql-test/t/func_str.test | 10 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 78 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 26 | ||||
-rw-r--r-- | sql/opt_range.cc | 4 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 8 |
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 |