mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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.
This commit is contained in:
@ -111,3 +111,35 @@ id
|
|||||||
5
|
5
|
||||||
9
|
9
|
||||||
drop table t1;
|
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;
|
||||||
|
@ -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)
|
_latin1'B' in (_latin1'a',_latin1'b' collate latin1_bin)
|
||||||
0
|
0
|
||||||
select _latin2'B' in (_latin1'a',_latin1'b');
|
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');
|
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');
|
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');
|
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);
|
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));
|
select collation(bin(130)), coercibility(bin(130));
|
||||||
collation(bin(130)) coercibility(bin(130))
|
collation(bin(130)) coercibility(bin(130))
|
||||||
latin1_swedish_ci 3
|
latin1_swedish_ci 3
|
||||||
|
@ -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);
|
select * from t1 where id in (2,5,9);
|
||||||
drop table t1;
|
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;
|
||||||
|
@ -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' 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' collate latin1_bin,_latin1'b');
|
||||||
select _latin1'B' in (_latin1'a',_latin1'b' collate latin1_bin);
|
select _latin1'B' in (_latin1'a',_latin1'b' collate latin1_bin);
|
||||||
--error 1269
|
--error 1268
|
||||||
select _latin2'B' in (_latin1'a',_latin1'b');
|
select _latin2'B' in (_latin1'a',_latin1'b');
|
||||||
--error 1269
|
--error 1268
|
||||||
select _latin1'B' in (_latin2'a',_latin1'b');
|
select _latin1'B' in (_latin2'a',_latin1'b');
|
||||||
--error 1269
|
--error 1268
|
||||||
select _latin1'B' in (_latin1'a',_latin2'b');
|
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');
|
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 _latin1'B' COLLATE latin1_general_ci in (_latin1'a',_latin1'b' COLLATE latin1_bin);
|
||||||
|
|
||||||
select collation(bin(130)), coercibility(bin(130));
|
select collation(bin(130)), coercibility(bin(130));
|
||||||
|
@ -1420,7 +1420,7 @@ int cmp_item_row::compare(cmp_item *c)
|
|||||||
bool Item_func_in::nulls_in_row()
|
bool Item_func_in::nulls_in_row()
|
||||||
{
|
{
|
||||||
Item **arg,**arg_end;
|
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())
|
if ((*arg)->null_inside())
|
||||||
return 1;
|
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()
|
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 =>
|
Row item with NULLs inside can return NULL or FALSE =>
|
||||||
they can't be processed as static
|
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:
|
case STRING_RESULT:
|
||||||
uint i;
|
uint i;
|
||||||
cmp_collation.set(item->collation);
|
array=new in_string(arg_count-1,(qsort2_cmp) srtcmp_in,
|
||||||
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,
|
|
||||||
cmp_collation.collation);
|
cmp_collation.collation);
|
||||||
break;
|
break;
|
||||||
case INT_RESULT:
|
case INT_RESULT:
|
||||||
array= new in_longlong(arg_count);
|
array= new in_longlong(arg_count-1);
|
||||||
break;
|
break;
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
array= new in_double(arg_count);
|
array= new in_double(arg_count-1);
|
||||||
break;
|
break;
|
||||||
case ROW_RESULT:
|
case ROW_RESULT:
|
||||||
array= new in_row(arg_count, item);
|
array= new in_row(arg_count-1, args[0]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint j=0;
|
uint j=0;
|
||||||
for (uint i=0 ; i < arg_count ; i++)
|
for (uint i=1 ; i < arg_count ; i++)
|
||||||
{
|
{
|
||||||
array->set(j,args[i]);
|
array->set(j,args[i]);
|
||||||
if (!args[i]->null_value) // Skip NULL values
|
if (!args[i]->null_value) // Skip NULL values
|
||||||
@ -1485,19 +1486,19 @@ void Item_func_in::fix_length_and_dec()
|
|||||||
}
|
}
|
||||||
else
|
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;
|
max_length= 1;
|
||||||
used_tables_cache|=item->used_tables();
|
const_item_cache&=args[0]->const_item();
|
||||||
const_item_cache&=item->const_item();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_func_in::print(String *str)
|
void Item_func_in::print(String *str)
|
||||||
{
|
{
|
||||||
str->append('(');
|
str->append('(');
|
||||||
item->print(str);
|
|
||||||
Item_func::print(str);
|
Item_func::print(str);
|
||||||
str->append(')');
|
str->append(')');
|
||||||
}
|
}
|
||||||
@ -1507,15 +1508,15 @@ longlong Item_func_in::val_int()
|
|||||||
{
|
{
|
||||||
if (array)
|
if (array)
|
||||||
{
|
{
|
||||||
int tmp=array->find(item);
|
int tmp=array->find(args[0]);
|
||||||
null_value=item->null_value || (!tmp && have_null);
|
null_value=args[0]->null_value || (!tmp && have_null);
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
in_item->store_value(item);
|
in_item->store_value(args[0]);
|
||||||
if ((null_value=item->null_value))
|
if ((null_value=args[0]->null_value))
|
||||||
return 0;
|
return 0;
|
||||||
have_null= 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)
|
if (!in_item->cmp(args[i]) && !args[i]->null_value)
|
||||||
return 1; // Would maybe be nice with i ?
|
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()
|
longlong Item_func_bit_or::val_int()
|
||||||
{
|
{
|
||||||
ulonglong arg1= (ulonglong) args[0]->val_int();
|
ulonglong arg1= (ulonglong) args[0]->val_int();
|
||||||
|
@ -600,42 +600,26 @@ public:
|
|||||||
|
|
||||||
class Item_func_in :public Item_int_func
|
class Item_func_in :public Item_int_func
|
||||||
{
|
{
|
||||||
Item *item;
|
|
||||||
in_vector *array;
|
in_vector *array;
|
||||||
cmp_item *in_item;
|
cmp_item *in_item;
|
||||||
bool have_null;
|
bool have_null;
|
||||||
DTCollation cmp_collation;
|
DTCollation cmp_collation;
|
||||||
public:
|
public:
|
||||||
Item_func_in(Item *a,List<Item> &list)
|
Item_func_in(List<Item> &list)
|
||||||
:Item_int_func(list), item(a), array(0), in_item(0), have_null(0)
|
: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();
|
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();
|
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
|
optimize_type select_optimize() const
|
||||||
{ return array ? OPTIMIZE_KEY : OPTIMIZE_NONE; }
|
{ return array ? OPTIMIZE_KEY : OPTIMIZE_NONE; }
|
||||||
Item *key_item() const { return item; }
|
Item *key_item() const { return args[0]; }
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
enum Functype functype() const { return IN_FUNC; }
|
enum Functype functype() const { return IN_FUNC; }
|
||||||
const char *func_name() const { return " IN "; }
|
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();
|
bool nulls_in_row();
|
||||||
void set_outer_resolving()
|
|
||||||
{
|
|
||||||
item->set_outer_resolving();
|
|
||||||
Item_int_func::set_outer_resolving();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Functions used by where clause */
|
/* Functions used by where clause */
|
||||||
|
@ -832,10 +832,10 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
|
|||||||
Field *field=((Item_field*) (func->key_item()))->field;
|
Field *field=((Item_field*) (func->key_item()))->field;
|
||||||
Item_result cmp_type=field->cmp_type();
|
Item_result cmp_type=field->cmp_type();
|
||||||
tree= get_mm_parts(param,field,Item_func::EQ_FUNC,
|
tree= get_mm_parts(param,field,Item_func::EQ_FUNC,
|
||||||
func->arguments()[0],cmp_type);
|
func->arguments()[1],cmp_type);
|
||||||
if (!tree)
|
if (!tree)
|
||||||
DBUG_RETURN(tree); // Not key field
|
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,
|
SEL_TREE *new_tree=get_mm_parts(param,field,Item_func::EQ_FUNC,
|
||||||
func->arguments()[i],cmp_type);
|
func->arguments()[i],cmp_type);
|
||||||
|
@ -2109,9 +2109,9 @@ all_or_any: ALL { $$ = 1; }
|
|||||||
/* expressions that begin with 'expr' */
|
/* expressions that begin with 'expr' */
|
||||||
expr_expr:
|
expr_expr:
|
||||||
expr IN_SYM '(' expr_list ')'
|
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 ')'
|
| 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
|
| expr IN_SYM in_subselect
|
||||||
{ $$= new Item_in_subselect(YYTHD, $1, $3); }
|
{ $$= new Item_in_subselect(YYTHD, $1, $3); }
|
||||||
| expr NOT IN_SYM in_subselect
|
| expr NOT IN_SYM in_subselect
|
||||||
@ -2211,9 +2211,9 @@ no_in_expr:
|
|||||||
/* expressions that begin with 'expr' that does NOT follow AND */
|
/* expressions that begin with 'expr' that does NOT follow AND */
|
||||||
no_and_expr:
|
no_and_expr:
|
||||||
no_and_expr IN_SYM '(' expr_list ')'
|
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 ')'
|
| 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
|
| no_and_expr IN_SYM in_subselect
|
||||||
{ $$= new Item_in_subselect(YYTHD, $1, $3); }
|
{ $$= new Item_in_subselect(YYTHD, $1, $3); }
|
||||||
| no_and_expr NOT IN_SYM in_subselect
|
| no_and_expr NOT IN_SYM in_subselect
|
||||||
|
Reference in New Issue
Block a user