mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Merge mysql.com:/usr/home/bar/mysql-4.1.b10201
into mysql.com:/usr/home/bar/mysql-5.0 mysql-test/r/func_gconcat.result: Auto merged mysql-test/t/func_gconcat.test: Auto merged ndb/src/mgmapi/mgmapi.cpp: Auto merged ndb/src/mgmsrv/ConfigInfo.cpp: Auto merged ndb/src/mgmsrv/ConfigInfo.hpp: Auto merged sql/item.cc: Auto merged sql/item.h: Auto merged sql/item_func.h: Auto merged sql/item_sum.cc: Auto merged include/config-netware.h: auto merge fix libmysql/libmysql.def: after merge fix sql/item_func.cc: SCCS merged
This commit is contained in:
@ -46,6 +46,7 @@ extern "C" {
|
||||
#undef HAVE_SYS_MMAN_H
|
||||
#undef HAVE_SYNCH_H
|
||||
#undef HAVE_MMAP
|
||||
#undef HAVE_RINT
|
||||
|
||||
#define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1
|
||||
#define HAVE_PTHREAD_SIGMASK 1
|
||||
|
@ -148,6 +148,7 @@ EXPORTS
|
||||
mysql_embedded
|
||||
mysql_server_init
|
||||
mysql_server_end
|
||||
get_defaults_files
|
||||
mysql_set_character_set
|
||||
mysql_get_character_set_info
|
||||
get_defaults_options
|
||||
|
@ -445,6 +445,30 @@ group_concat(distinct b order by b)
|
||||
Warnings:
|
||||
Warning 1260 2 line(s) were cut by GROUP_CONCAT()
|
||||
drop table t1;
|
||||
create table t1 (a varchar(255) character set cp1250 collate cp1250_general_ci,
|
||||
b varchar(255) character set koi8r);
|
||||
insert into t1 values ('xxx','yyy');
|
||||
select collation(a) from t1;
|
||||
collation(a)
|
||||
cp1250_general_ci
|
||||
select collation(group_concat(a)) from t1;
|
||||
collation(group_concat(a))
|
||||
cp1250_general_ci
|
||||
create table t2 select group_concat(a) as a from t1;
|
||||
show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`a` longtext character set cp1250
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
select collation(group_concat(a,_koi8r'test')) from t1;
|
||||
collation(group_concat(a,_koi8r'test'))
|
||||
cp1250_general_ci
|
||||
select collation(group_concat(a,_koi8r 0xC1C2)) from t1;
|
||||
ERROR HY000: Illegal mix of collations (cp1250_general_ci,IMPLICIT) and (koi8r_general_ci,COERCIBLE) for operation 'group_concat'
|
||||
select collation(group_concat(a,b)) from t1;
|
||||
ERROR HY000: Illegal mix of collations (cp1250_general_ci,IMPLICIT) and (koi8r_general_ci,IMPLICIT) for operation 'group_concat'
|
||||
drop table t1;
|
||||
drop table t2;
|
||||
CREATE TABLE t1 (id int);
|
||||
SELECT GROUP_CONCAT(id) AS gc FROM t1 HAVING gc IS NULL;
|
||||
gc
|
||||
|
@ -263,6 +263,24 @@ select group_concat(distinct b order by b) from t1 group by a;
|
||||
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug#10201
|
||||
#
|
||||
create table t1 (a varchar(255) character set cp1250 collate cp1250_general_ci,
|
||||
b varchar(255) character set koi8r);
|
||||
insert into t1 values ('xxx','yyy');
|
||||
select collation(a) from t1;
|
||||
select collation(group_concat(a)) from t1;
|
||||
create table t2 select group_concat(a) as a from t1;
|
||||
show create table t2;
|
||||
select collation(group_concat(a,_koi8r'test')) from t1;
|
||||
--error 1267
|
||||
select collation(group_concat(a,_koi8r 0xC1C2)) from t1;
|
||||
--error 1267
|
||||
select collation(group_concat(a,b)) from t1;
|
||||
drop table t1;
|
||||
drop table t2;
|
||||
|
||||
#
|
||||
# bug #7769: group_concat returning null is checked in having
|
||||
#
|
||||
|
164
sql/item.cc
164
sql/item.cc
@ -1082,6 +1082,170 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************/
|
||||
static
|
||||
void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname)
|
||||
{
|
||||
my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0),
|
||||
c1.collation->name,c1.derivation_name(),
|
||||
c2.collation->name,c2.derivation_name(),
|
||||
fname);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
void my_coll_agg_error(DTCollation &c1, DTCollation &c2, DTCollation &c3,
|
||||
const char *fname)
|
||||
{
|
||||
my_error(ER_CANT_AGGREGATE_3COLLATIONS,MYF(0),
|
||||
c1.collation->name,c1.derivation_name(),
|
||||
c2.collation->name,c2.derivation_name(),
|
||||
c3.collation->name,c3.derivation_name(),
|
||||
fname);
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
void my_coll_agg_error(Item** args, uint count, const char *fname)
|
||||
{
|
||||
if (count == 2)
|
||||
my_coll_agg_error(args[0]->collation, args[1]->collation, fname);
|
||||
else if (count == 3)
|
||||
my_coll_agg_error(args[0]->collation, args[1]->collation,
|
||||
args[2]->collation, fname);
|
||||
else
|
||||
my_error(ER_CANT_AGGREGATE_NCOLLATIONS,MYF(0),fname);
|
||||
}
|
||||
|
||||
|
||||
bool agg_item_collations(DTCollation &c, const char *fname,
|
||||
Item **av, uint count, uint flags)
|
||||
{
|
||||
uint i;
|
||||
c.set(av[0]->collation);
|
||||
for (i= 1; i < count; i++)
|
||||
{
|
||||
if (c.aggregate(av[i]->collation, flags))
|
||||
{
|
||||
my_coll_agg_error(av, count, fname);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if ((flags & MY_COLL_DISALLOW_NONE) &&
|
||||
c.derivation == DERIVATION_NONE)
|
||||
{
|
||||
my_coll_agg_error(av, count, fname);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
bool agg_item_collations_for_comparison(DTCollation &c, const char *fname,
|
||||
Item **av, uint count, uint flags)
|
||||
{
|
||||
return (agg_item_collations(c, fname, av, count,
|
||||
flags | MY_COLL_DISALLOW_NONE));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Collect arguments' character sets together.
|
||||
We allow to apply automatic character set conversion in some cases.
|
||||
The conditions when conversion is possible are:
|
||||
- arguments A and B have different charsets
|
||||
- A wins according to coercibility rules
|
||||
(i.e. a column is stronger than a string constant,
|
||||
an explicit COLLATE clause is stronger than a column)
|
||||
- character set of A is either superset for character set of B,
|
||||
or B is a string constant which can be converted into the
|
||||
character set of A without data loss.
|
||||
|
||||
If all of the above is true, then it's possible to convert
|
||||
B into the character set of A, and then compare according
|
||||
to the collation of A.
|
||||
|
||||
For functions with more than two arguments:
|
||||
|
||||
collect(A,B,C) ::= collect(collect(A,B),C)
|
||||
*/
|
||||
|
||||
bool agg_item_charsets(DTCollation &coll, const char *fname,
|
||||
Item **args, uint nargs, uint flags)
|
||||
{
|
||||
Item **arg, **last, *safe_args[2];
|
||||
if (agg_item_collations(coll, fname, args, nargs, flags))
|
||||
return TRUE;
|
||||
|
||||
/*
|
||||
For better error reporting: save the first and the second argument.
|
||||
We need this only if the the number of args is 3 or 2:
|
||||
- for a longer argument list, "Illegal mix of collations"
|
||||
doesn't display each argument's characteristics.
|
||||
- if nargs is 1, then this error cannot happen.
|
||||
*/
|
||||
if (nargs >=2 && nargs <= 3)
|
||||
{
|
||||
safe_args[0]= args[0];
|
||||
safe_args[1]= args[1];
|
||||
}
|
||||
|
||||
THD *thd= current_thd;
|
||||
Item_arena *arena, backup;
|
||||
bool res= FALSE;
|
||||
/*
|
||||
In case we're in statement prepare, create conversion item
|
||||
in its memory: it will be reused on each execute.
|
||||
*/
|
||||
arena= thd->change_arena_if_needed(&backup);
|
||||
|
||||
for (arg= args, last= args + nargs; arg < last; arg++)
|
||||
{
|
||||
Item* conv;
|
||||
uint32 dummy_offset;
|
||||
if (!String::needs_conversion(0, coll.collation,
|
||||
(*arg)->collation.collation,
|
||||
&dummy_offset))
|
||||
continue;
|
||||
|
||||
if (!(conv= (*arg)->safe_charset_converter(coll.collation)))
|
||||
{
|
||||
if (nargs >=2 && nargs <= 3)
|
||||
{
|
||||
/* restore the original arguments for better error message */
|
||||
args[0]= safe_args[0];
|
||||
args[1]= safe_args[1];
|
||||
}
|
||||
my_coll_agg_error(args, nargs, fname);
|
||||
res= TRUE;
|
||||
break; // we cannot return here, we need to restore "arena".
|
||||
}
|
||||
conv->fix_fields(thd, 0, &conv);
|
||||
/*
|
||||
If in statement prepare, then we create a converter for two
|
||||
constant items, do it once and then reuse it.
|
||||
If we're in execution of a prepared statement, arena is NULL,
|
||||
and the conv was created in runtime memory. This can be
|
||||
the case only if the argument is a parameter marker ('?'),
|
||||
because for all true constants the charset converter has already
|
||||
been created in prepare. In this case register the change for
|
||||
rollback.
|
||||
*/
|
||||
if (arena)
|
||||
*arg= conv;
|
||||
else
|
||||
thd->change_item_tree(arg, conv);
|
||||
}
|
||||
if (arena)
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**********************************************/
|
||||
|
||||
Item_field::Item_field(Field *f)
|
||||
:Item_ident(0, NullS, *f->table_name, f->field_name),
|
||||
item_equal(0), no_const_subst(0),
|
||||
|
@ -767,6 +767,15 @@ public:
|
||||
};
|
||||
|
||||
|
||||
bool agg_item_collations(DTCollation &c, const char *name,
|
||||
Item **items, uint nitems, uint flags= 0);
|
||||
bool agg_item_collations_for_comparison(DTCollation &c, const char *name,
|
||||
Item **items, uint nitems,
|
||||
uint flags= 0);
|
||||
bool agg_item_charsets(DTCollation &c, const char *name,
|
||||
Item **items, uint nitems, uint flags= 0);
|
||||
|
||||
|
||||
class Item_num: public Item
|
||||
{
|
||||
public:
|
||||
|
168
sql/item_func.cc
168
sql/item_func.cc
@ -42,73 +42,6 @@ bool check_reserved_words(LEX_STRING *name)
|
||||
}
|
||||
|
||||
|
||||
static void my_coll_agg_error(DTCollation &c1, DTCollation &c2,
|
||||
const char *fname)
|
||||
{
|
||||
my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0),
|
||||
c1.collation->name, c1.derivation_name(),
|
||||
c2.collation->name, c2.derivation_name(),
|
||||
fname);
|
||||
}
|
||||
|
||||
static void my_coll_agg_error(DTCollation &c1,
|
||||
DTCollation &c2,
|
||||
DTCollation &c3,
|
||||
const char *fname)
|
||||
{
|
||||
my_error(ER_CANT_AGGREGATE_3COLLATIONS, MYF(0),
|
||||
c1.collation->name, c1.derivation_name(),
|
||||
c2.collation->name, c2.derivation_name(),
|
||||
c3.collation->name, c3.derivation_name(),
|
||||
fname);
|
||||
}
|
||||
|
||||
|
||||
static void my_coll_agg_error(Item** args, uint count, const char *fname)
|
||||
{
|
||||
if (count == 2)
|
||||
my_coll_agg_error(args[0]->collation, args[1]->collation, fname);
|
||||
else if (count == 3)
|
||||
my_coll_agg_error(args[0]->collation,
|
||||
args[1]->collation,
|
||||
args[2]->collation,
|
||||
fname);
|
||||
else
|
||||
my_error(ER_CANT_AGGREGATE_NCOLLATIONS, MYF(0), fname);
|
||||
}
|
||||
|
||||
|
||||
bool Item_func::agg_arg_collations(DTCollation &c, Item **av, uint count,
|
||||
uint flags)
|
||||
{
|
||||
uint i;
|
||||
c.set(av[0]->collation);
|
||||
for (i= 1; i < count; i++)
|
||||
{
|
||||
if (c.aggregate(av[i]->collation, flags))
|
||||
{
|
||||
my_coll_agg_error(av, count, func_name());
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if ((flags & MY_COLL_DISALLOW_NONE) &&
|
||||
c.derivation == DERIVATION_NONE)
|
||||
{
|
||||
my_coll_agg_error(av, count, func_name());
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
bool Item_func::agg_arg_collations_for_comparison(DTCollation &c,
|
||||
Item **av, uint count,
|
||||
uint flags)
|
||||
{
|
||||
return (agg_arg_collations(c, av, count, flags | MY_COLL_DISALLOW_NONE));
|
||||
}
|
||||
|
||||
|
||||
/* return TRUE if item is a constant */
|
||||
|
||||
bool
|
||||
@ -118,107 +51,6 @@ eval_const_cond(COND *cond)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Collect arguments' character sets together.
|
||||
We allow to apply automatic character set conversion in some cases.
|
||||
The conditions when conversion is possible are:
|
||||
- arguments A and B have different charsets
|
||||
- A wins according to coercibility rules
|
||||
(i.e. a column is stronger than a string constant,
|
||||
an explicit COLLATE clause is stronger than a column)
|
||||
- character set of A is either superset for character set of B,
|
||||
or B is a string constant which can be converted into the
|
||||
character set of A without data loss.
|
||||
|
||||
If all of the above is true, then it's possible to convert
|
||||
B into the character set of A, and then compare according
|
||||
to the collation of A.
|
||||
|
||||
For functions with more than two arguments:
|
||||
|
||||
collect(A,B,C) ::= collect(collect(A,B),C)
|
||||
*/
|
||||
|
||||
bool Item_func::agg_arg_charsets(DTCollation &coll,
|
||||
Item **args, uint nargs, uint flags)
|
||||
{
|
||||
Item **arg, **last, *safe_args[2];
|
||||
if (agg_arg_collations(coll, args, nargs, flags))
|
||||
return TRUE;
|
||||
|
||||
/*
|
||||
For better error reporting: save the first and the second argument.
|
||||
We need this only if the the number of args is 3 or 2:
|
||||
- for a longer argument list, "Illegal mix of collations"
|
||||
doesn't display each argument's characteristics.
|
||||
- if nargs is 1, then this error cannot happen.
|
||||
*/
|
||||
if (nargs >=2 && nargs <= 3)
|
||||
{
|
||||
safe_args[0]= args[0];
|
||||
safe_args[1]= args[1];
|
||||
}
|
||||
|
||||
THD *thd= current_thd;
|
||||
Query_arena *arena, backup;
|
||||
bool res= FALSE;
|
||||
/*
|
||||
In case we're in statement prepare, create conversion item
|
||||
in its memory: it will be reused on each execute.
|
||||
*/
|
||||
arena= thd->change_arena_if_needed(&backup);
|
||||
|
||||
for (arg= args, last= args + nargs; arg < last; arg++)
|
||||
{
|
||||
Item* conv;
|
||||
uint32 dummy_offset;
|
||||
if (!String::needs_conversion(0, coll.collation,
|
||||
(*arg)->collation.collation,
|
||||
&dummy_offset))
|
||||
continue;
|
||||
|
||||
if (!(conv= (*arg)->safe_charset_converter(coll.collation)))
|
||||
{
|
||||
if (nargs >=2 && nargs <= 3)
|
||||
{
|
||||
/* restore the original arguments for better error message */
|
||||
args[0]= safe_args[0];
|
||||
args[1]= safe_args[1];
|
||||
}
|
||||
my_coll_agg_error(args, nargs, func_name());
|
||||
res= TRUE;
|
||||
break; // we cannot return here, we need to restore "arena".
|
||||
}
|
||||
if ((*arg)->type() == FIELD_ITEM)
|
||||
((Item_field *)(*arg))->no_const_subst= 1;
|
||||
/*
|
||||
If in statement prepare, then we create a converter for two
|
||||
constant items, do it once and then reuse it.
|
||||
If we're in execution of a prepared statement, arena is NULL,
|
||||
and the conv was created in runtime memory. This can be
|
||||
the case only if the argument is a parameter marker ('?'),
|
||||
because for all true constants the charset converter has already
|
||||
been created in prepare. In this case register the change for
|
||||
rollback.
|
||||
*/
|
||||
if (arena)
|
||||
*arg= conv;
|
||||
else
|
||||
thd->change_item_tree(arg, conv);
|
||||
/*
|
||||
We do not check conv->fixed, because Item_func_conv_charset which can
|
||||
be return by safe_charset_converter can't be fixed at creation
|
||||
*/
|
||||
conv->fix_fields(thd, arg);
|
||||
}
|
||||
if (arena)
|
||||
thd->restore_backup_item_arena(arena, &backup);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Item_func::set_arguments(List<Item> &list)
|
||||
{
|
||||
allowed_arg_cols= 1;
|
||||
|
@ -166,12 +166,22 @@ public:
|
||||
my_decimal *val_decimal(my_decimal *);
|
||||
|
||||
bool agg_arg_collations(DTCollation &c, Item **items, uint nitems,
|
||||
uint flags= 0);
|
||||
uint flags= 0)
|
||||
{
|
||||
return agg_item_collations(c, func_name(), items, nitems, flags);
|
||||
}
|
||||
bool agg_arg_collations_for_comparison(DTCollation &c,
|
||||
Item **items, uint nitems,
|
||||
uint flags= 0);
|
||||
uint flags= 0)
|
||||
{
|
||||
return agg_item_collations_for_comparison(c, func_name(),
|
||||
items, nitems, flags);
|
||||
}
|
||||
bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems,
|
||||
uint flags= 0);
|
||||
uint flags= 0)
|
||||
{
|
||||
return agg_item_charsets(c, func_name(), items, nitems, flags);
|
||||
}
|
||||
bool walk(Item_processor processor, byte *arg);
|
||||
Item *transform(Item_transformer transformer, byte *arg);
|
||||
void traverse_cond(Cond_traverser traverser,
|
||||
|
@ -2976,6 +2976,10 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref)
|
||||
maybe_null|= args[i]->maybe_null;
|
||||
}
|
||||
|
||||
if (agg_item_charsets(collation, func_name(),
|
||||
args, arg_count, MY_COLL_ALLOW_CONV))
|
||||
return 1;
|
||||
|
||||
result_field= 0;
|
||||
null_value= 1;
|
||||
thd->allow_sum_func= 1;
|
||||
|
Reference in New Issue
Block a user