Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
31b1bdc5
Commit
31b1bdc5
authored
Jul 26, 2005
by
bar@mysql.com
Browse files
Options
Browse Files
Download
Plain Diff
Merge abarkov@bk-internal.mysql.com:/home/bk/mysql-4.1
into mysql.com:/usr/home/bar/mysql-4.1.b10201
parents
d3567611
0c2035b7
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
232 additions
and
165 deletions
+232
-165
mysql-test/r/func_gconcat.result
mysql-test/r/func_gconcat.result
+24
-0
mysql-test/t/func_gconcat.test
mysql-test/t/func_gconcat.test
+18
-0
sql/item.cc
sql/item.cc
+164
-0
sql/item.h
sql/item.h
+9
-0
sql/item_func.cc
sql/item_func.cc
+0
-162
sql/item_func.h
sql/item_func.h
+13
-3
sql/item_sum.cc
sql/item_sum.cc
+4
-0
No files found.
mysql-test/r/func_gconcat.result
View file @
31b1bdc5
...
...
@@ -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
...
...
mysql-test/t/func_gconcat.test
View file @
31b1bdc5
...
...
@@ -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
#
...
...
sql/item.cc
View file @
31b1bdc5
...
...
@@ -523,6 +523,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
(
NullS
,
f
->
table_name
,
f
->
field_name
)
{
...
...
sql/item.h
View file @
31b1bdc5
...
...
@@ -330,6 +330,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:
...
...
sql/item_func.cc
View file @
31b1bdc5
...
...
@@ -39,73 +39,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
...
...
@@ -115,101 +48,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
;
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
,
func_name
());
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
;
}
void
Item_func
::
set_arguments
(
List
<
Item
>
&
list
)
{
allowed_arg_cols
=
1
;
...
...
sql/item_func.h
View file @
31b1bdc5
...
...
@@ -145,12 +145,22 @@ public:
Item
*
get_tmp_table_item
(
THD
*
thd
);
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
);
};
...
...
sql/item_sum.cc
View file @
31b1bdc5
...
...
@@ -1925,6 +1925,10 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, 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
;
max_length
=
group_concat_max_len
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment