Allow IN to convert arguments into Unicode in some cases.
This commit is contained in:
parent
4f32cd2b3d
commit
153e18a252
@ -148,6 +148,16 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||||||
Warnings:
|
Warnings:
|
||||||
Note 1003 select test.t1.a AS `a`,test.t1.b AS `b`,test.t1.c AS `c` from test.t1 where (_latin1'a' in (test.t1.a,test.t1.b,(test.t1.c collate _latin1'latin1_bin')))
|
Note 1003 select test.t1.a AS `a`,test.t1.b AS `b`,test.t1.c AS `c` from test.t1 where (_latin1'a' in (test.t1.a,test.t1.b,(test.t1.c collate _latin1'latin1_bin')))
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
set names utf8;
|
||||||
|
create table t1 (a char(10) character set utf8 not null);
|
||||||
|
insert into t1 values ('bbbb'),(_koi8r'ÃÃÃÃ'),(_latin1'ÄÄÄÄ');
|
||||||
|
select a from t1 where a in ('bbbb',_koi8r'ÃÃÃÃ',_latin1'ÄÄÄÄ') order by a;
|
||||||
|
a
|
||||||
|
ÄÄÄÄ
|
||||||
|
bbbb
|
||||||
|
цццц
|
||||||
|
drop table t1;
|
||||||
|
set names latin1;
|
||||||
select '1.0' in (1,2);
|
select '1.0' in (1,2);
|
||||||
'1.0' in (1,2)
|
'1.0' in (1,2)
|
||||||
1
|
1
|
||||||
|
@ -75,6 +75,13 @@ select * from t1 where 'a' in (a,b,c collate latin1_bin);
|
|||||||
explain extended select * from t1 where 'a' in (a,b,c collate latin1_bin);
|
explain extended select * from t1 where 'a' in (a,b,c collate latin1_bin);
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
set names utf8;
|
||||||
|
create table t1 (a char(10) character set utf8 not null);
|
||||||
|
insert into t1 values ('bbbb'),(_koi8r'ÃÃÃÃ'),(_latin1'ÄÄÄÄ');
|
||||||
|
select a from t1 where a in ('bbbb',_koi8r'ÃÃÃÃ',_latin1'ÄÄÄÄ') order by a;
|
||||||
|
drop table t1;
|
||||||
|
set names latin1;
|
||||||
|
|
||||||
select '1.0' in (1,2);
|
select '1.0' in (1,2);
|
||||||
select 1 in ('1.0',2);
|
select 1 in ('1.0',2);
|
||||||
select 1 in (1,'2.0');
|
select 1 in (1,'2.0');
|
||||||
|
@ -1735,12 +1735,58 @@ void Item_func_in::fix_length_and_dec()
|
|||||||
uint const_itm= 1;
|
uint const_itm= 1;
|
||||||
|
|
||||||
agg_cmp_type(&cmp_type, args, arg_count);
|
agg_cmp_type(&cmp_type, args, arg_count);
|
||||||
if ((cmp_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++)
|
for (arg=args+1, arg_end=args+arg_count; arg != arg_end ; arg++)
|
||||||
const_itm&= arg[0]->const_item();
|
const_itm&= arg[0]->const_item();
|
||||||
|
|
||||||
|
|
||||||
|
if (cmp_type == STRING_RESULT)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
We allow consts character set conversion for
|
||||||
|
|
||||||
|
item IN (const1, const2, const3, ...)
|
||||||
|
|
||||||
|
if item is in a superset for all arguments,
|
||||||
|
and if it is a stong side according to coercibility rules.
|
||||||
|
|
||||||
|
TODO: add covnersion for non-constant IN values
|
||||||
|
via creating Item_func_conv_charset().
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (agg_arg_collations_for_comparison(cmp_collation,
|
||||||
|
args, arg_count, TRUE))
|
||||||
|
return;
|
||||||
|
if ((!my_charset_same(args[0]->collation.collation,
|
||||||
|
cmp_collation.collation) || !const_itm))
|
||||||
|
{
|
||||||
|
if (agg_arg_collations_for_comparison(cmp_collation,
|
||||||
|
args, arg_count, FALSE))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Conversion is possible:
|
||||||
|
All IN arguments are constants.
|
||||||
|
*/
|
||||||
|
for (arg= args+1, arg_end= args+arg_count; arg < arg_end; arg++)
|
||||||
|
{
|
||||||
|
if (!my_charset_same(cmp_collation.collation,
|
||||||
|
arg[0]->collation.collation))
|
||||||
|
{
|
||||||
|
Item_string *conv;
|
||||||
|
String tmp, cstr, *ostr= arg[0]->val_str(&tmp);
|
||||||
|
cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(),
|
||||||
|
cmp_collation.collation);
|
||||||
|
conv= new Item_string(cstr.ptr(),cstr.length(), cstr.charset(),
|
||||||
|
arg[0]->collation.derivation);
|
||||||
|
conv->str_value.copy();
|
||||||
|
arg[0]= conv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Row item with NULLs inside can return NULL or FALSE =>
|
Row item with NULLs inside can return NULL or FALSE =>
|
||||||
|
@ -75,13 +75,16 @@ static void my_coll_agg_error(Item** args, uint count, const char *fname)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_func::agg_arg_collations(DTCollation &c, Item **av, uint count)
|
bool Item_func::agg_arg_collations(DTCollation &c, Item **av, uint count,
|
||||||
|
bool allow_superset_conversion)
|
||||||
{
|
{
|
||||||
uint i;
|
uint i;
|
||||||
|
c.nagg= 0;
|
||||||
|
c.strong= 0;
|
||||||
c.set(av[0]->collation);
|
c.set(av[0]->collation);
|
||||||
for (i= 1; i < count; i++)
|
for (i= 1; i < count; i++)
|
||||||
{
|
{
|
||||||
if (c.aggregate(av[i]->collation))
|
if (c.aggregate(av[i]->collation, allow_superset_conversion))
|
||||||
{
|
{
|
||||||
my_coll_agg_error(av, count, func_name());
|
my_coll_agg_error(av, count, func_name());
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -92,9 +95,10 @@ bool Item_func::agg_arg_collations(DTCollation &c, Item **av, uint count)
|
|||||||
|
|
||||||
|
|
||||||
bool Item_func::agg_arg_collations_for_comparison(DTCollation &c,
|
bool Item_func::agg_arg_collations_for_comparison(DTCollation &c,
|
||||||
Item **av, uint count)
|
Item **av, uint count,
|
||||||
|
bool allow_superset_conv)
|
||||||
{
|
{
|
||||||
if (agg_arg_collations(c, av, count))
|
if (agg_arg_collations(c, av, count, allow_superset_conv))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
if (c.derivation == DERIVATION_NONE)
|
if (c.derivation == DERIVATION_NONE)
|
||||||
|
@ -140,8 +140,11 @@ public:
|
|||||||
Field *tmp_table_field(TABLE *t_arg);
|
Field *tmp_table_field(TABLE *t_arg);
|
||||||
Item *get_tmp_table_item(THD *thd);
|
Item *get_tmp_table_item(THD *thd);
|
||||||
|
|
||||||
bool agg_arg_collations(DTCollation &c, Item **items, uint nitems);
|
bool agg_arg_collations(DTCollation &c, Item **items, uint nitems,
|
||||||
bool agg_arg_collations_for_comparison(DTCollation &c, Item **items, uint nitems);
|
bool allow_superset_conversion= FALSE);
|
||||||
|
bool agg_arg_collations_for_comparison(DTCollation &c,
|
||||||
|
Item **items, uint nitems,
|
||||||
|
bool allow_superset_comversion= FALSE);
|
||||||
|
|
||||||
bool walk(Item_processor processor, byte *arg);
|
bool walk(Item_processor processor, byte *arg);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user