mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
Merge kaamos.(none):/data/src/mysql-5.1
into kaamos.(none):/data/src/opt/mysql-5.1-opt client/mysql.cc: Auto merged client/mysqltest.c: Auto merged sql/log.cc: Auto merged sql/repl_failsafe.cc: Auto merged sql/set_var.cc: Auto merged sql/sql_base.cc: Auto merged sql/sql_class.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_db.cc: Auto merged sql/sql_select.cc: Auto merged sql/sql_show.cc: Auto merged
This commit is contained in:
commit
824ced465e
41 changed files with 678 additions and 149 deletions
|
@ -3113,7 +3113,10 @@ com_connect(String *buffer, char *line)
|
|||
Two null bytes are needed in the end of buff to allow
|
||||
get_arg to find end of string the second time it's called.
|
||||
*/
|
||||
strmake(buff, line, sizeof(buff)-2);
|
||||
tmp= strmake(buff, line, sizeof(buff)-2);
|
||||
#ifdef EXTRA_DEBUG
|
||||
tmp[1]= 0;
|
||||
#endif
|
||||
tmp= get_arg(buff, 0);
|
||||
if (tmp && *tmp)
|
||||
{
|
||||
|
|
|
@ -590,7 +590,9 @@ static void write_header(FILE *sql_file, char *db_name)
|
|||
{
|
||||
if (opt_comments)
|
||||
{
|
||||
fprintf(sql_file, "-- MySQL dump %s\n--\n", DUMP_VERSION);
|
||||
fprintf(sql_file,
|
||||
"-- MySQL dump %s Distrib %s, for %s (%s)\n--\n",
|
||||
DUMP_VERSION, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
|
||||
fprintf(sql_file, "-- Host: %s Database: %s\n",
|
||||
current_host ? current_host : "localhost", db_name ? db_name :
|
||||
"");
|
||||
|
|
|
@ -3654,7 +3654,7 @@ void do_get_file_name(struct st_command *command,
|
|||
if (*p)
|
||||
*p++= 0;
|
||||
command->last_argument= p;
|
||||
strmake(dest, name, dest_max_len);
|
||||
strmake(dest, name, dest_max_len - 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -6975,7 +6975,7 @@ int main(int argc, char **argv)
|
|||
|
||||
if (save_file[0])
|
||||
{
|
||||
strmake(command->require_file, save_file, sizeof(save_file));
|
||||
strmake(command->require_file, save_file, sizeof(save_file) - 1);
|
||||
save_file[0]= 0;
|
||||
}
|
||||
run_query(cur_con, command, flags);
|
||||
|
|
35
mysql-test/r/bdb_notembedded.result
Normal file
35
mysql-test/r/bdb_notembedded.result
Normal file
|
@ -0,0 +1,35 @@
|
|||
set autocommit=1;
|
||||
reset master;
|
||||
create table bug16206 (a int);
|
||||
insert into bug16206 values(1);
|
||||
start transaction;
|
||||
insert into bug16206 values(2);
|
||||
commit;
|
||||
show binlog events;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
f n Format_desc 1 n Server ver: VERSION, Binlog ver: 4
|
||||
f n Query 1 n use `test`; create table bug16206 (a int)
|
||||
f n Query 1 n use `test`; insert into bug16206 values(1)
|
||||
f n Query 1 n use `test`; insert into bug16206 values(2)
|
||||
drop table bug16206;
|
||||
reset master;
|
||||
create table bug16206 (a int) engine= bdb;
|
||||
insert into bug16206 values(0);
|
||||
insert into bug16206 values(1);
|
||||
start transaction;
|
||||
insert into bug16206 values(2);
|
||||
commit;
|
||||
insert into bug16206 values(3);
|
||||
show binlog events;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
f n Format_desc 1 n Server ver: VERSION, Binlog ver: 4
|
||||
f n Query 1 n use `test`; create table bug16206 (a int) engine= bdb
|
||||
f n Query 1 n use `test`; insert into bug16206 values(0)
|
||||
f n Query 1 n use `test`; insert into bug16206 values(1)
|
||||
f n Query 1 n use `test`; BEGIN
|
||||
f n Query 1 n use `test`; insert into bug16206 values(2)
|
||||
f n Query 1 n use `test`; COMMIT
|
||||
f n Query 1 n use `test`; insert into bug16206 values(3)
|
||||
drop table bug16206;
|
||||
set autocommit=0;
|
||||
End of 5.0 tests
|
|
@ -271,7 +271,7 @@ group_concat(distinct s1 order by s2)
|
|||
c,b,a
|
||||
select group_concat(distinct s1 order by s2) from t1;
|
||||
group_concat(distinct s1 order by s2)
|
||||
c,b,a,c
|
||||
c,b,a
|
||||
drop table t1;
|
||||
create table t1 (a int, c int);
|
||||
insert into t1 values (1, 2), (2, 3), (2, 4), (3, 5);
|
||||
|
@ -876,4 +876,65 @@ select group_concat(f1) from t1;
|
|||
group_concat(f1)
|
||||
,
|
||||
drop table t1;
|
||||
CREATE TABLE t1 (a INT, b INT);
|
||||
INSERT INTO t1 VALUES (1, 1), (2, 2), (2, 3);
|
||||
SELECT GROUP_CONCAT(DISTINCT a ORDER BY b) FROM t1;
|
||||
GROUP_CONCAT(DISTINCT a ORDER BY b)
|
||||
1,2
|
||||
SELECT GROUP_CONCAT(DISTINCT a ORDER BY b DESC) FROM t1;
|
||||
GROUP_CONCAT(DISTINCT a ORDER BY b DESC)
|
||||
2,1
|
||||
SELECT GROUP_CONCAT(DISTINCT a) FROM t1;
|
||||
GROUP_CONCAT(DISTINCT a)
|
||||
1,2
|
||||
SELECT GROUP_CONCAT(DISTINCT a + 1 ORDER BY 3 - b) FROM t1;
|
||||
GROUP_CONCAT(DISTINCT a + 1 ORDER BY 3 - b)
|
||||
3,2
|
||||
SELECT GROUP_CONCAT(DISTINCT a + 1 ORDER BY b) FROM t1;
|
||||
GROUP_CONCAT(DISTINCT a + 1 ORDER BY b)
|
||||
2,3
|
||||
SELECT GROUP_CONCAT(a ORDER BY 3 - b) FROM t1;
|
||||
GROUP_CONCAT(a ORDER BY 3 - b)
|
||||
2,2,1
|
||||
CREATE TABLE t2 (a INT, b INT, c INT, d INT);
|
||||
INSERT INTO t2 VALUES (1,1, 1,1), (1,1, 2,2), (1,2, 2,1), (2,1, 1,2);
|
||||
SELECT GROUP_CONCAT(DISTINCT a, b ORDER BY c, d) FROM t2;
|
||||
GROUP_CONCAT(DISTINCT a, b ORDER BY c, d)
|
||||
11,21,12
|
||||
SELECT GROUP_CONCAT(DISTINCT a, b ORDER BY d, c) FROM t2;
|
||||
GROUP_CONCAT(DISTINCT a, b ORDER BY d, c)
|
||||
11,12,21
|
||||
CREATE TABLE t3 (a INT, b INT, c INT);
|
||||
INSERT INTO t3 VALUES (1, 1, 1), (2, 1, 2), (3, 2, 1);
|
||||
SELECT GROUP_CONCAT(DISTINCT a, b ORDER BY b, c) FROM t3;
|
||||
GROUP_CONCAT(DISTINCT a, b ORDER BY b, c)
|
||||
11,21,32
|
||||
SELECT GROUP_CONCAT(DISTINCT a, b ORDER BY c, b) FROM t3;
|
||||
GROUP_CONCAT(DISTINCT a, b ORDER BY c, b)
|
||||
11,32,21
|
||||
SELECT GROUP_CONCAT(DISTINCT a, b ORDER BY a, b) FROM t1;
|
||||
GROUP_CONCAT(DISTINCT a, b ORDER BY a, b)
|
||||
11,22,23
|
||||
SELECT GROUP_CONCAT(DISTINCT b, a ORDER BY a, b) FROM t1;
|
||||
GROUP_CONCAT(DISTINCT b, a ORDER BY a, b)
|
||||
11,22,32
|
||||
SELECT GROUP_CONCAT(DISTINCT a, b ORDER BY b, a) FROM t1;
|
||||
GROUP_CONCAT(DISTINCT a, b ORDER BY b, a)
|
||||
11,22,23
|
||||
SELECT GROUP_CONCAT(DISTINCT b, a ORDER BY a, b) FROM t1;
|
||||
GROUP_CONCAT(DISTINCT b, a ORDER BY a, b)
|
||||
11,22,32
|
||||
SELECT GROUP_CONCAT(DISTINCT a ORDER BY a, b) FROM t1;
|
||||
GROUP_CONCAT(DISTINCT a ORDER BY a, b)
|
||||
1,2
|
||||
SELECT GROUP_CONCAT(DISTINCT b ORDER BY b, a) FROM t1;
|
||||
GROUP_CONCAT(DISTINCT b ORDER BY b, a)
|
||||
1,2,3
|
||||
SELECT GROUP_CONCAT(DISTINCT a, b ORDER BY a) FROM t1;
|
||||
GROUP_CONCAT(DISTINCT a, b ORDER BY a)
|
||||
11,23,22
|
||||
SELECT GROUP_CONCAT(DISTINCT b, a ORDER BY b) FROM t1;
|
||||
GROUP_CONCAT(DISTINCT b, a ORDER BY b)
|
||||
11,22,32
|
||||
DROP TABLE t1, t2, t3;
|
||||
End of 5.0 tests
|
||||
|
|
|
@ -1398,4 +1398,16 @@ SELECT COUNT(*), a FROM t1;
|
|||
COUNT(*) a
|
||||
4 1
|
||||
DROP TABLE t1;
|
||||
set SQL_MODE=ONLY_FULL_GROUP_BY;
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (1),(2),(3),(4);
|
||||
CREATE VIEW v1 AS SELECT a,(a + 1) AS y FROM t1;
|
||||
EXPLAIN EXTENDED SELECT y FROM v1 GROUP BY v1.y;
|
||||
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 4 100.00 Using temporary; Using filesort
|
||||
Warnings:
|
||||
Note 1003 select (`test`.`t1`.`a` + 1) AS `y` from `test`.`t1` group by (`test`.`t1`.`a` + 1)
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
SET SQL_MODE=DEFAULT;
|
||||
End of 5.0 tests
|
||||
|
|
|
@ -1258,6 +1258,9 @@ DATE_ADD('20071108', INTERVAL 1 DAY)
|
|||
select DATE_ADD(20071108, INTERVAL 1 DAY);
|
||||
DATE_ADD(20071108, INTERVAL 1 DAY)
|
||||
2007-11-09
|
||||
select LAST_DAY('2007-12-06 08:59:19.05') - INTERVAL 1 SECOND;
|
||||
LAST_DAY('2007-12-06 08:59:19.05') - INTERVAL 1 SECOND
|
||||
2007-12-30 23:59:59
|
||||
End of 5.0 tests
|
||||
select date_sub("0050-01-01 00:00:01",INTERVAL 2 SECOND);
|
||||
date_sub("0050-01-01 00:00:01",INTERVAL 2 SECOND)
|
||||
|
|
|
@ -72,10 +72,6 @@ count(*)
|
|||
select count(*) from information_schema.USER_PRIVILEGES;
|
||||
count(*)
|
||||
0
|
||||
CREATE FUNCTION a RETURNS STRING SONAME '';
|
||||
ERROR HY000: Can't initialize function 'a'; UDFs are unavailable with the --skip-grant-tables option
|
||||
DROP FUNCTION a;
|
||||
ERROR 42000: FUNCTION test.a does not exist
|
||||
End of 5.0 tests
|
||||
#
|
||||
# Bug#29817 Queries with UDF fail with non-descriptive error
|
||||
|
|
|
@ -4282,6 +4282,15 @@ SELECT 2 FROM t1 WHERE EXISTS ((SELECT 1 FROM t2 WHERE t1.a=t2.a) UNION
|
|||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNION
|
||||
(SELECT 1 FROM t2 WHERE t1.a = t2.a))' at line 2
|
||||
DROP TABLE t1,t2;
|
||||
create table t1(f11 int, f12 int);
|
||||
create table t2(f21 int unsigned not null, f22 int, f23 varchar(10));
|
||||
insert into t1 values(1,1),(2,2), (3, 3);
|
||||
set session sort_buffer_size= 33*1024;
|
||||
select count(*) from t1 where f12 =
|
||||
(select f22 from t2 where f22 = f12 order by f21 desc, f22, f23 limit 1);
|
||||
count(*)
|
||||
3
|
||||
drop table t1,t2;
|
||||
End of 5.0 tests.
|
||||
CREATE TABLE t1 (a int, b int);
|
||||
INSERT INTO t1 VALUES (2,22),(1,11),(2,22);
|
||||
|
|
|
@ -260,6 +260,11 @@ INSERT INTO t1 VALUES ('1000-00-00');
|
|||
ERROR 22007: Incorrect date value: '1000-00-00' for column 'a' at row 1
|
||||
SET SQL_MODE=DEFAULT;
|
||||
DROP TABLE t1,t2;
|
||||
CREATE TABLE t1 SELECT curdate() AS f1;
|
||||
SELECT hour(f1), minute(f1), second(f1) FROM t1;
|
||||
hour(f1) minute(f1) second(f1)
|
||||
0 0 0
|
||||
DROP TABLE t1;
|
||||
End of 5.0 tests
|
||||
create table t1 (a date, primary key (a))engine=memory;
|
||||
insert into t1 values ('0000-01-01'), ('0000-00-01'), ('0001-01-01');
|
||||
|
|
|
@ -786,10 +786,6 @@ from (select 1 as s,'t' as t union select null, null ) as sub1;
|
|||
select group_concat(t) from t1 group by week(date)/10;
|
||||
group_concat(t)
|
||||
t
|
||||
Warnings:
|
||||
Warning 1292 Incorrect datetime value: '0000-00-00'
|
||||
Warning 1292 Incorrect datetime value: '0000-00-00'
|
||||
Warning 1292 Incorrect datetime value: '0000-00-00'
|
||||
drop table t1;
|
||||
CREATE TABLE t1 (
|
||||
qty decimal(16,6) default NULL,
|
||||
|
|
5
mysql-test/r/udf_skip_grants.result
Normal file
5
mysql-test/r/udf_skip_grants.result
Normal file
|
@ -0,0 +1,5 @@
|
|||
CREATE FUNCTION a RETURNS STRING SONAME '';
|
||||
ERROR HY000: Can't initialize function 'a'; UDFs are unavailable with the --skip-grant-tables option
|
||||
DROP FUNCTION a;
|
||||
ERROR 42000: FUNCTION test.a does not exist
|
||||
End of 5.0 tests
|
|
@ -1445,4 +1445,79 @@ select @var;
|
|||
1
|
||||
(select 2) union (select 1 into @var);
|
||||
ERROR 42000: Result consisted of more than one row
|
||||
CREATE TABLE t1 (a int);
|
||||
INSERT INTO t1 VALUES (10), (20);
|
||||
CREATE TABLE t2 (b int);
|
||||
INSERT INTO t2 VALUES (10), (50), (50);
|
||||
SELECT a,1 FROM t1
|
||||
UNION
|
||||
SELECT b, COUNT(*) FROM t2 GROUP BY b WITH ROLLUP
|
||||
ORDER BY a;
|
||||
a 1
|
||||
NULL 3
|
||||
10 1
|
||||
20 1
|
||||
50 2
|
||||
SELECT a,1 FROM t1
|
||||
UNION
|
||||
SELECT b, COUNT(*) FROM t2 GROUP BY b WITH ROLLUP
|
||||
ORDER BY a DESC;
|
||||
a 1
|
||||
50 2
|
||||
20 1
|
||||
10 1
|
||||
NULL 3
|
||||
SELECT a,1 FROM t1
|
||||
UNION
|
||||
SELECT b, COUNT(*) FROM t2 GROUP BY b WITH ROLLUP
|
||||
ORDER BY a ASC LIMIT 3;
|
||||
a 1
|
||||
NULL 3
|
||||
10 1
|
||||
20 1
|
||||
SELECT a,1 FROM t1
|
||||
UNION ALL
|
||||
SELECT b, COUNT(*) FROM t2 GROUP BY b WITH ROLLUP
|
||||
ORDER BY a DESC;
|
||||
a 1
|
||||
50 2
|
||||
20 1
|
||||
10 1
|
||||
10 1
|
||||
NULL 3
|
||||
SELECT a,1 FROM t1
|
||||
UNION
|
||||
(SELECT b, COUNT(*) FROM t2 GROUP BY b WITH ROLLUP ORDER BY a);
|
||||
ERROR HY000: Incorrect usage of CUBE/ROLLUP and ORDER BY
|
||||
SELECT a,1 FROM t1
|
||||
UNION ALL
|
||||
SELECT b, COUNT(*) FROM t2 GROUP BY b WITH ROLLUP ORDER BY a
|
||||
UNION
|
||||
SELECT 1,1;
|
||||
ERROR HY000: Incorrect usage of UNION and ORDER BY
|
||||
DROP TABLE t1,t2;
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (1), (2), (3);
|
||||
CREATE TABLE t2 SELECT * FROM (SELECT NULL) a UNION SELECT a FROM t1;
|
||||
DESC t2;
|
||||
Field Type Null Key Default Extra
|
||||
NULL int(11) YES NULL
|
||||
CREATE TABLE t3 SELECT a FROM t1 UNION SELECT * FROM (SELECT NULL) a;
|
||||
DESC t3;
|
||||
Field Type Null Key Default Extra
|
||||
a int(11) YES NULL
|
||||
CREATE TABLE t4 SELECT NULL;
|
||||
DESC t4;
|
||||
Field Type Null Key Default Extra
|
||||
NULL binary(0) YES NULL
|
||||
CREATE TABLE t5 SELECT NULL UNION SELECT NULL;
|
||||
DESC t5;
|
||||
Field Type Null Key Default Extra
|
||||
NULL binary(0) YES NULL
|
||||
CREATE TABLE t6
|
||||
SELECT * FROM (SELECT * FROM (SELECT NULL)a) b UNION SELECT a FROM t1;
|
||||
DESC t6;
|
||||
Field Type Null Key Default Extra
|
||||
NULL int(11) YES NULL
|
||||
DROP TABLE t1, t2, t3, t4, t5, t6;
|
||||
End of 5.0 tests
|
||||
|
|
|
@ -91,21 +91,25 @@ select a=b && a=c from t1;
|
|||
a=b && a=c
|
||||
1
|
||||
SELECT routine_name, definer
|
||||
FROM information_schema.routines;
|
||||
FROM information_schema.routines
|
||||
WHERE routine_name = 'bug12480';
|
||||
routine_name definer
|
||||
bug12480 root@localhost
|
||||
SELECT trigger_name, definer
|
||||
FROM information_schema.triggers;
|
||||
FROM information_schema.triggers
|
||||
WHERE trigger_name = 't1_first';
|
||||
trigger_name definer
|
||||
t1_first root@localhost
|
||||
|
||||
--- On slave --
|
||||
SELECT routine_name, definer
|
||||
FROM information_schema.routines;
|
||||
FROM information_schema.routines
|
||||
WHERE routine_name = 'bug12480';
|
||||
routine_name definer
|
||||
bug12480 root@localhost
|
||||
SELECT trigger_name, definer
|
||||
FROM information_schema.triggers;
|
||||
FROM information_schema.triggers
|
||||
WHERE trigger_name = 't1_first';
|
||||
trigger_name definer
|
||||
t1_first root@localhost
|
||||
select a=b && a=c from t1;
|
||||
|
|
|
@ -101,10 +101,12 @@ let $time=`select a from t1`;
|
|||
# - dump definers on the slave;
|
||||
|
||||
SELECT routine_name, definer
|
||||
FROM information_schema.routines;
|
||||
FROM information_schema.routines
|
||||
WHERE routine_name = 'bug12480';
|
||||
|
||||
SELECT trigger_name, definer
|
||||
FROM information_schema.triggers;
|
||||
FROM information_schema.triggers
|
||||
WHERE trigger_name = 't1_first';
|
||||
|
||||
save_master_pos;
|
||||
connection slave;
|
||||
|
@ -119,10 +121,12 @@ select "--- On slave --" as "";
|
|||
# item.
|
||||
|
||||
SELECT routine_name, definer
|
||||
FROM information_schema.routines;
|
||||
FROM information_schema.routines
|
||||
WHERE routine_name = 'bug12480';
|
||||
|
||||
SELECT trigger_name, definer
|
||||
FROM information_schema.triggers;
|
||||
FROM information_schema.triggers
|
||||
WHERE trigger_name = 't1_first';
|
||||
|
||||
select a=b && a=c from t1;
|
||||
--disable_query_log
|
||||
|
|
38
mysql-test/t/bdb_notembedded.test
Normal file
38
mysql-test/t/bdb_notembedded.test
Normal file
|
@ -0,0 +1,38 @@
|
|||
-- source include/not_embedded.inc
|
||||
-- source include/have_bdb.inc
|
||||
|
||||
#
|
||||
# Bug #16206: Superfluous COMMIT event in binlog when updating BDB in autocommit mode
|
||||
#
|
||||
set autocommit=1;
|
||||
|
||||
let $VERSION=`select version()`;
|
||||
|
||||
reset master;
|
||||
create table bug16206 (a int);
|
||||
insert into bug16206 values(1);
|
||||
start transaction;
|
||||
insert into bug16206 values(2);
|
||||
commit;
|
||||
--replace_result $VERSION VERSION
|
||||
--replace_column 1 f 2 n 5 n
|
||||
show binlog events;
|
||||
drop table bug16206;
|
||||
|
||||
reset master;
|
||||
create table bug16206 (a int) engine= bdb;
|
||||
insert into bug16206 values(0);
|
||||
insert into bug16206 values(1);
|
||||
start transaction;
|
||||
insert into bug16206 values(2);
|
||||
commit;
|
||||
insert into bug16206 values(3);
|
||||
--replace_result $VERSION VERSION
|
||||
--replace_column 1 f 2 n 5 n
|
||||
show binlog events;
|
||||
drop table bug16206;
|
||||
|
||||
set autocommit=0;
|
||||
|
||||
|
||||
--echo End of 5.0 tests
|
|
@ -598,5 +598,46 @@ insert into t1 values (''),('');
|
|||
select group_concat(distinct f1) from t1;
|
||||
select group_concat(f1) from t1;
|
||||
drop table t1;
|
||||
# Bug#32798: DISTINCT in GROUP_CONCAT clause fails when ordering by a column
|
||||
# with null values
|
||||
#'
|
||||
CREATE TABLE t1 (a INT, b INT);
|
||||
|
||||
INSERT INTO t1 VALUES (1, 1), (2, 2), (2, 3);
|
||||
|
||||
SELECT GROUP_CONCAT(DISTINCT a ORDER BY b) FROM t1;
|
||||
SELECT GROUP_CONCAT(DISTINCT a ORDER BY b DESC) FROM t1;
|
||||
SELECT GROUP_CONCAT(DISTINCT a) FROM t1;
|
||||
|
||||
SELECT GROUP_CONCAT(DISTINCT a + 1 ORDER BY 3 - b) FROM t1;
|
||||
SELECT GROUP_CONCAT(DISTINCT a + 1 ORDER BY b) FROM t1;
|
||||
SELECT GROUP_CONCAT(a ORDER BY 3 - b) FROM t1;
|
||||
|
||||
CREATE TABLE t2 (a INT, b INT, c INT, d INT);
|
||||
|
||||
# There is one duplicate in the expression list: 1,10
|
||||
# There is one duplicate in ORDER BY list, but that shouldnt matter: 1,10
|
||||
INSERT INTO t2 VALUES (1,1, 1,1), (1,1, 2,2), (1,2, 2,1), (2,1, 1,2);
|
||||
|
||||
SELECT GROUP_CONCAT(DISTINCT a, b ORDER BY c, d) FROM t2;
|
||||
SELECT GROUP_CONCAT(DISTINCT a, b ORDER BY d, c) FROM t2;
|
||||
|
||||
CREATE TABLE t3 (a INT, b INT, c INT);
|
||||
|
||||
INSERT INTO t3 VALUES (1, 1, 1), (2, 1, 2), (3, 2, 1);
|
||||
|
||||
SELECT GROUP_CONCAT(DISTINCT a, b ORDER BY b, c) FROM t3;
|
||||
SELECT GROUP_CONCAT(DISTINCT a, b ORDER BY c, b) FROM t3;
|
||||
|
||||
SELECT GROUP_CONCAT(DISTINCT a, b ORDER BY a, b) FROM t1;
|
||||
SELECT GROUP_CONCAT(DISTINCT b, a ORDER BY a, b) FROM t1;
|
||||
SELECT GROUP_CONCAT(DISTINCT a, b ORDER BY b, a) FROM t1;
|
||||
SELECT GROUP_CONCAT(DISTINCT b, a ORDER BY a, b) FROM t1;
|
||||
SELECT GROUP_CONCAT(DISTINCT a ORDER BY a, b) FROM t1;
|
||||
SELECT GROUP_CONCAT(DISTINCT b ORDER BY b, a) FROM t1;
|
||||
SELECT GROUP_CONCAT(DISTINCT a, b ORDER BY a) FROM t1;
|
||||
SELECT GROUP_CONCAT(DISTINCT b, a ORDER BY b) FROM t1;
|
||||
|
||||
DROP TABLE t1, t2, t3;
|
||||
|
||||
--echo End of 5.0 tests
|
||||
|
|
|
@ -908,5 +908,20 @@ SELECT COUNT(*), a FROM t1;
|
|||
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Bug #33133: Views are not transparent
|
||||
#
|
||||
|
||||
set SQL_MODE=ONLY_FULL_GROUP_BY;
|
||||
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (1),(2),(3),(4);
|
||||
CREATE VIEW v1 AS SELECT a,(a + 1) AS y FROM t1;
|
||||
EXPLAIN EXTENDED SELECT y FROM v1 GROUP BY v1.y;
|
||||
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
SET SQL_MODE=DEFAULT;
|
||||
|
||||
###
|
||||
--echo End of 5.0 tests
|
||||
|
|
|
@ -776,6 +776,13 @@ select DATE_ADD(20071108181000, INTERVAL 1 DAY);
|
|||
select DATE_ADD('20071108', INTERVAL 1 DAY);
|
||||
select DATE_ADD(20071108, INTERVAL 1 DAY);
|
||||
|
||||
#
|
||||
# Bug#32770: LAST_DAY() returns a DATE, but somehow internally keeps
|
||||
# track of the TIME.
|
||||
#
|
||||
|
||||
select LAST_DAY('2007-12-06 08:59:19.05') - INTERVAL 1 SECOND;
|
||||
|
||||
--echo End of 5.0 tests
|
||||
|
||||
#
|
||||
|
|
|
@ -122,16 +122,6 @@ select count(*) from information_schema.COLUMN_PRIVILEGES;
|
|||
select count(*) from information_schema.SCHEMA_PRIVILEGES;
|
||||
select count(*) from information_schema.TABLE_PRIVILEGES;
|
||||
select count(*) from information_schema.USER_PRIVILEGES;
|
||||
#
|
||||
# Bug #32020: loading udfs while --skip-grant-tables is enabled causes out of
|
||||
# memory errors
|
||||
#
|
||||
|
||||
--error ER_CANT_INITIALIZE_UDF
|
||||
CREATE FUNCTION a RETURNS STRING SONAME '';
|
||||
--error ER_SP_DOES_NOT_EXIST
|
||||
DROP FUNCTION a;
|
||||
|
||||
--echo End of 5.0 tests
|
||||
|
||||
--echo #
|
||||
|
|
|
@ -3136,6 +3136,28 @@ SELECT 2 FROM t1 WHERE EXISTS ((SELECT 1 FROM t2 WHERE t1.a=t2.a) UNION
|
|||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
#
|
||||
# Bug#33675: Usage of an uninitialized memory by filesort in a subquery
|
||||
# caused server crash.
|
||||
#
|
||||
create table t1(f11 int, f12 int);
|
||||
create table t2(f21 int unsigned not null, f22 int, f23 varchar(10));
|
||||
insert into t1 values(1,1),(2,2), (3, 3);
|
||||
let $i=10000;
|
||||
--disable_query_log
|
||||
--disable_warnings
|
||||
while ($i)
|
||||
{
|
||||
eval insert into t2 values (-1 , $i/5000 + 1, '$i');
|
||||
dec $i;
|
||||
}
|
||||
--enable_warnings
|
||||
--enable_query_log
|
||||
set session sort_buffer_size= 33*1024;
|
||||
select count(*) from t1 where f12 =
|
||||
(select f22 from t2 where f22 = f12 order by f21 desc, f22, f23 limit 1);
|
||||
|
||||
drop table t1,t2;
|
||||
|
||||
--echo End of 5.0 tests.
|
||||
|
||||
|
@ -3165,6 +3187,7 @@ SELECT a FROM t1 t0
|
|||
SET @@sql_mode=default;
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Bug#20835 (literal string with =any values)
|
||||
#
|
||||
CREATE TABLE t1 (s1 char(1));
|
||||
|
|
|
@ -213,6 +213,14 @@ INSERT INTO t1 VALUES ('1000-00-00');
|
|||
SET SQL_MODE=DEFAULT;
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
#
|
||||
# Bug #31990: MINUTE() and SECOND() return bogus results when used on a DATE
|
||||
#
|
||||
|
||||
CREATE TABLE t1 SELECT curdate() AS f1;
|
||||
SELECT hour(f1), minute(f1), second(f1) FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo End of 5.0 tests
|
||||
|
||||
#
|
||||
|
|
1
mysql-test/t/udf_skip_grants-master.opt
Normal file
1
mysql-test/t/udf_skip_grants-master.opt
Normal file
|
@ -0,0 +1 @@
|
|||
--skip-grant-tables
|
28
mysql-test/t/udf_skip_grants.test
Normal file
28
mysql-test/t/udf_skip_grants.test
Normal file
|
@ -0,0 +1,28 @@
|
|||
####################### udf_skip_grants.test ###########################
|
||||
# #
|
||||
# Test for bug #32020 "loading udfs while --skip-grant-tables is #
|
||||
# enabled causes out of memory errors" #
|
||||
# #
|
||||
# Creation: #
|
||||
# 2007-12-24 akopytov Moved the test case for bug #32020 from #
|
||||
# skip_grants.test to a separate test to ensure #
|
||||
# that it is only run when the server is built #
|
||||
# with support for dynamically loaded libraries #
|
||||
# (see bug #33305). #
|
||||
# #
|
||||
########################################################################
|
||||
|
||||
-- source include/not_embedded.inc
|
||||
-- source include/have_udf.inc
|
||||
|
||||
#
|
||||
# Bug #32020: loading udfs while --skip-grant-tables is enabled causes out of
|
||||
# memory errors
|
||||
#
|
||||
|
||||
--error ER_CANT_INITIALIZE_UDF
|
||||
CREATE FUNCTION a RETURNS STRING SONAME '';
|
||||
--error ER_SP_DOES_NOT_EXIST
|
||||
DROP FUNCTION a;
|
||||
|
||||
--echo End of 5.0 tests
|
|
@ -922,4 +922,70 @@ DROP TABLE t1;
|
|||
select @var;
|
||||
--error 1172
|
||||
(select 2) union (select 1 into @var);
|
||||
|
||||
#
|
||||
# Bug#27848: order-by of union clashes with rollup of select part
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (a int);
|
||||
INSERT INTO t1 VALUES (10), (20);
|
||||
CREATE TABLE t2 (b int);
|
||||
INSERT INTO t2 VALUES (10), (50), (50);
|
||||
|
||||
SELECT a,1 FROM t1
|
||||
UNION
|
||||
SELECT b, COUNT(*) FROM t2 GROUP BY b WITH ROLLUP
|
||||
ORDER BY a;
|
||||
|
||||
SELECT a,1 FROM t1
|
||||
UNION
|
||||
SELECT b, COUNT(*) FROM t2 GROUP BY b WITH ROLLUP
|
||||
ORDER BY a DESC;
|
||||
|
||||
SELECT a,1 FROM t1
|
||||
UNION
|
||||
SELECT b, COUNT(*) FROM t2 GROUP BY b WITH ROLLUP
|
||||
ORDER BY a ASC LIMIT 3;
|
||||
|
||||
SELECT a,1 FROM t1
|
||||
UNION ALL
|
||||
SELECT b, COUNT(*) FROM t2 GROUP BY b WITH ROLLUP
|
||||
ORDER BY a DESC;
|
||||
|
||||
--error ER_WRONG_USAGE
|
||||
SELECT a,1 FROM t1
|
||||
UNION
|
||||
(SELECT b, COUNT(*) FROM t2 GROUP BY b WITH ROLLUP ORDER BY a);
|
||||
|
||||
--error ER_WRONG_USAGE
|
||||
SELECT a,1 FROM t1
|
||||
UNION ALL
|
||||
SELECT b, COUNT(*) FROM t2 GROUP BY b WITH ROLLUP ORDER BY a
|
||||
UNION
|
||||
SELECT 1,1;
|
||||
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
# Bug#32848: Data type conversion bug in union subselects in MySQL 5.0.38
|
||||
#
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (1), (2), (3);
|
||||
|
||||
CREATE TABLE t2 SELECT * FROM (SELECT NULL) a UNION SELECT a FROM t1;
|
||||
DESC t2;
|
||||
|
||||
CREATE TABLE t3 SELECT a FROM t1 UNION SELECT * FROM (SELECT NULL) a;
|
||||
DESC t3;
|
||||
|
||||
CREATE TABLE t4 SELECT NULL;
|
||||
DESC t4;
|
||||
|
||||
CREATE TABLE t5 SELECT NULL UNION SELECT NULL;
|
||||
DESC t5;
|
||||
|
||||
CREATE TABLE t6
|
||||
SELECT * FROM (SELECT * FROM (SELECT NULL)a) b UNION SELECT a FROM t1;
|
||||
DESC t6;
|
||||
|
||||
DROP TABLE t1, t2, t3, t4, t5, t6;
|
||||
--echo End of 5.0 tests
|
||||
|
|
|
@ -282,7 +282,7 @@ void symdirget(char *dir)
|
|||
|
||||
SYNOPSIS
|
||||
unpack_dirname()
|
||||
to Store result here. May be = from
|
||||
to result-buffer, FN_REFLEN characters. may be == from
|
||||
from 'Packed' directory name (may contain ~)
|
||||
|
||||
IMPLEMENTATION
|
||||
|
@ -408,7 +408,7 @@ size_t unpack_filename(char * to, const char *from)
|
|||
|
||||
/* Convert filename (unix standard) to system standard */
|
||||
/* Used before system command's like open(), create() .. */
|
||||
/* Returns length of to */
|
||||
/* Returns used length of to; total length should be FN_REFLEN */
|
||||
|
||||
size_t system_filename(char * to, const char *from)
|
||||
{
|
||||
|
|
10
sql/field.cc
10
sql/field.cc
|
@ -1307,7 +1307,8 @@ Field::Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
|
|||
field_name(field_name_arg),
|
||||
key_start(0), part_of_key(0), part_of_key_not_clustered(0),
|
||||
part_of_sortkey(0), unireg_check(unireg_check_arg),
|
||||
field_length(length_arg), null_bit(null_bit_arg)
|
||||
field_length(length_arg), null_bit(null_bit_arg),
|
||||
is_created_from_null_item(FALSE)
|
||||
{
|
||||
flags=null_ptr ? 0: NOT_NULL_FLAG;
|
||||
comment.str= (char*) "";
|
||||
|
@ -5636,6 +5637,13 @@ String *Field_date::val_str(String *val_buffer,
|
|||
}
|
||||
|
||||
|
||||
bool Field_date::get_time(MYSQL_TIME *ltime)
|
||||
{
|
||||
bzero((char *)ltime, sizeof(MYSQL_TIME));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Field_date::cmp(const uchar *a_ptr, const uchar *b_ptr)
|
||||
{
|
||||
int32 a,b;
|
||||
|
|
15
sql/field.h
15
sql/field.h
|
@ -90,6 +90,16 @@ public:
|
|||
uint32 flags;
|
||||
uint16 field_index; // field number in fields array
|
||||
uchar null_bit; // Bit used to test null bit
|
||||
/**
|
||||
If true, this field was created in create_tmp_field_from_item from a NULL
|
||||
value. This means that the type of the field is just a guess, and the type
|
||||
may be freely coerced to another type.
|
||||
|
||||
@see create_tmp_field_from_item
|
||||
@see Item_type_holder::get_real_type
|
||||
|
||||
*/
|
||||
bool is_created_from_null_item;
|
||||
|
||||
Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
|
||||
uchar null_bit_arg, utype unireg_check_arg,
|
||||
|
@ -1240,6 +1250,7 @@ public:
|
|||
double val_real(void);
|
||||
longlong val_int(void);
|
||||
String *val_str(String*,String *);
|
||||
bool get_time(MYSQL_TIME *ltime);
|
||||
bool send_binary(Protocol *protocol);
|
||||
int cmp(const uchar *,const uchar *);
|
||||
void sort_string(uchar *buff,uint length);
|
||||
|
@ -1258,6 +1269,10 @@ public:
|
|||
:Field_str(ptr_arg, 10, null_ptr_arg, null_bit_arg,
|
||||
unireg_check_arg, field_name_arg, cs)
|
||||
{}
|
||||
Field_newdate(bool maybe_null_arg, const char *field_name_arg,
|
||||
CHARSET_INFO *cs)
|
||||
:Field_str((uchar*) 0,10, maybe_null_arg ? (uchar*) "": 0,0,
|
||||
NONE, field_name_arg, cs) {}
|
||||
enum_field_types type() const { return MYSQL_TYPE_DATE;}
|
||||
enum_field_types real_type() const { return MYSQL_TYPE_NEWDATE; }
|
||||
enum ha_base_keytype key_type() const { return HA_KEYTYPE_UINT24; }
|
||||
|
|
|
@ -37,7 +37,8 @@ if (my_b_write((file),(uchar*) (from),param->ref_length)) \
|
|||
|
||||
static char **make_char_array(char **old_pos, register uint fields,
|
||||
uint length, myf my_flag);
|
||||
static BUFFPEK *read_buffpek_from_file(IO_CACHE *buffer_file, uint count);
|
||||
static uchar *read_buffpek_from_file(IO_CACHE *buffer_file, uint count,
|
||||
uchar *buf);
|
||||
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
|
||||
uchar * *sort_keys, IO_CACHE *buffer_file,
|
||||
IO_CACHE *tempfile,IO_CACHE *indexfile);
|
||||
|
@ -244,9 +245,14 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!table_sort.buffpek && table_sort.buffpek_len < maxbuffer &&
|
||||
!(table_sort.buffpek=
|
||||
(uchar *) read_buffpek_from_file(&buffpek_pointers, maxbuffer)))
|
||||
if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer)
|
||||
{
|
||||
x_free(table_sort.buffpek);
|
||||
table_sort.buffpek= 0;
|
||||
}
|
||||
if (!(table_sort.buffpek=
|
||||
(uchar *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
|
||||
table_sort.buffpek)))
|
||||
goto err;
|
||||
buffpek= (BUFFPEK *) table_sort.buffpek;
|
||||
table_sort.buffpek_len= maxbuffer;
|
||||
|
@ -374,14 +380,16 @@ static char **make_char_array(char **old_pos, register uint fields,
|
|||
|
||||
/* Read 'count' number of buffer pointers into memory */
|
||||
|
||||
static BUFFPEK *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count)
|
||||
static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count,
|
||||
uchar *buf)
|
||||
{
|
||||
ulong length;
|
||||
BUFFPEK *tmp;
|
||||
ulong length= sizeof(BUFFPEK)*count;
|
||||
uchar *tmp= buf;
|
||||
DBUG_ENTER("read_buffpek_from_file");
|
||||
if (count > UINT_MAX/sizeof(BUFFPEK))
|
||||
return 0; /* sizeof(BUFFPEK)*count will overflow */
|
||||
tmp=(BUFFPEK*) my_malloc(length=sizeof(BUFFPEK)*count, MYF(MY_WME));
|
||||
if (!tmp)
|
||||
tmp= (uchar *)my_malloc(length, MYF(MY_WME));
|
||||
if (tmp)
|
||||
{
|
||||
if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
|
||||
|
|
|
@ -4467,7 +4467,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length)
|
|||
break;
|
||||
case MYSQL_TYPE_NEWDATE:
|
||||
case MYSQL_TYPE_DATE:
|
||||
field= new Field_date(maybe_null, name, &my_charset_bin);
|
||||
field= new Field_newdate(maybe_null, name, &my_charset_bin);
|
||||
break;
|
||||
case MYSQL_TYPE_TIME:
|
||||
field= new Field_time(maybe_null, name, &my_charset_bin);
|
||||
|
@ -6707,6 +6707,8 @@ enum_field_types Item_type_holder::get_real_type(Item *item)
|
|||
*/
|
||||
Field *field= ((Item_field *) item)->field;
|
||||
enum_field_types type= field->real_type();
|
||||
if (field->is_created_from_null_item)
|
||||
return MYSQL_TYPE_NULL;
|
||||
/* work around about varchar type field detection */
|
||||
if (type == MYSQL_TYPE_STRING && field->type() == MYSQL_TYPE_VAR_STRING)
|
||||
return MYSQL_TYPE_VAR_STRING;
|
||||
|
@ -6965,6 +6967,8 @@ Field *Item_type_holder::make_field_by_type(TABLE *table)
|
|||
if (field)
|
||||
field->init(table);
|
||||
return field;
|
||||
case MYSQL_TYPE_NULL:
|
||||
return make_string_field(table);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
157
sql/item_sum.cc
157
sql/item_sum.cc
|
@ -633,7 +633,7 @@ Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table,
|
|||
*/
|
||||
switch (args[0]->field_type()) {
|
||||
case MYSQL_TYPE_DATE:
|
||||
field= new Field_date(maybe_null, name, collation.collation);
|
||||
field= new Field_newdate(maybe_null, name, collation.collation);
|
||||
break;
|
||||
case MYSQL_TYPE_TIME:
|
||||
field= new Field_time(maybe_null, name, collation.collation);
|
||||
|
@ -2849,45 +2849,51 @@ String *Item_sum_udf_str::val_str(String *str)
|
|||
concat of values from "group by" operation
|
||||
|
||||
BUGS
|
||||
DISTINCT and ORDER BY only works if ORDER BY uses all fields and only fields
|
||||
in expression list
|
||||
Blobs doesn't work with DISTINCT or ORDER BY
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
function of sort for syntax:
|
||||
GROUP_CONCAT(DISTINCT expr,...)
|
||||
|
||||
|
||||
/**
|
||||
Compares the values for fields in expr list of GROUP_CONCAT.
|
||||
@note
|
||||
|
||||
GROUP_CONCAT([DISTINCT] expr [,expr ...]
|
||||
[ORDER BY {unsigned_integer | col_name | expr}
|
||||
[ASC | DESC] [,col_name ...]]
|
||||
[SEPARATOR str_val])
|
||||
|
||||
@return
|
||||
@retval -1 : key1 < key2
|
||||
@retval 0 : key1 = key2
|
||||
@retval 1 : key1 > key2
|
||||
*/
|
||||
|
||||
int group_concat_key_cmp_with_distinct(void* arg, uchar* key1,
|
||||
uchar* key2)
|
||||
int group_concat_key_cmp_with_distinct(void* arg, const void* key1,
|
||||
const void* key2)
|
||||
{
|
||||
Item_func_group_concat* grp_item= (Item_func_group_concat*)arg;
|
||||
TABLE *table= grp_item->table;
|
||||
Item **field_item, **end;
|
||||
Item_func_group_concat *item_func= (Item_func_group_concat*)arg;
|
||||
TABLE *table= item_func->table;
|
||||
|
||||
for (field_item= grp_item->args, end= field_item + grp_item->arg_count_field;
|
||||
field_item < end;
|
||||
field_item++)
|
||||
for (uint i= 0; i < item_func->arg_count_field; i++)
|
||||
{
|
||||
Item *item= item_func->args[i];
|
||||
/*
|
||||
If field_item is a const item then either get_tp_table_field returns 0
|
||||
or it is an item over a const table.
|
||||
*/
|
||||
if (item->const_item())
|
||||
continue;
|
||||
/*
|
||||
We have to use get_tmp_table_field() instead of
|
||||
real_item()->get_tmp_table_field() because we want the field in
|
||||
the temporary table, not the original field
|
||||
*/
|
||||
Field *field= (*field_item)->get_tmp_table_field();
|
||||
/*
|
||||
If field_item is a const item then either get_tmp_table_field returns 0
|
||||
or it is an item over a const table.
|
||||
*/
|
||||
if (field && !(*field_item)->const_item())
|
||||
{
|
||||
int res;
|
||||
uint offset= (field->offset(field->table->record[0]) -
|
||||
table->s->null_bytes);
|
||||
if ((res= field->cmp(key1 + offset, key2 + offset)))
|
||||
return res;
|
||||
}
|
||||
Field *field= item->get_tmp_table_field();
|
||||
int res;
|
||||
uint offset= field->offset(field->table->record[0])-table->s->null_bytes;
|
||||
if((res= field->cmp((uchar*)key1 + offset, (uchar*)key2 + offset)))
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -2898,7 +2904,8 @@ int group_concat_key_cmp_with_distinct(void* arg, uchar* key1,
|
|||
GROUP_CONCAT(expr,... ORDER BY col,... )
|
||||
*/
|
||||
|
||||
int group_concat_key_cmp_with_order(void* arg, uchar* key1, uchar* key2)
|
||||
int group_concat_key_cmp_with_order(void* arg, const void* key1,
|
||||
const void* key2)
|
||||
{
|
||||
Item_func_group_concat* grp_item= (Item_func_group_concat*) arg;
|
||||
ORDER **order_item, **end;
|
||||
|
@ -2924,7 +2931,7 @@ int group_concat_key_cmp_with_order(void* arg, uchar* key1, uchar* key2)
|
|||
int res;
|
||||
uint offset= (field->offset(field->table->record[0]) -
|
||||
table->s->null_bytes);
|
||||
if ((res= field->cmp(key1 + offset, key2 + offset)))
|
||||
if ((res= field->cmp((uchar*)key1 + offset, (uchar*)key2 + offset)))
|
||||
return (*order_item)->asc ? res : -res;
|
||||
}
|
||||
}
|
||||
|
@ -2937,25 +2944,6 @@ int group_concat_key_cmp_with_order(void* arg, uchar* key1, uchar* key2)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
function of sort for syntax:
|
||||
GROUP_CONCAT(DISTINCT expr,... ORDER BY col,... )
|
||||
|
||||
BUG:
|
||||
This doesn't work in the case when the order by contains data that
|
||||
is not part of the field list because tree-insert will not notice
|
||||
the duplicated values when inserting things sorted by ORDER BY
|
||||
*/
|
||||
|
||||
int group_concat_key_cmp_with_distinct_and_order(void* arg,uchar* key1,
|
||||
uchar* key2)
|
||||
{
|
||||
if (!group_concat_key_cmp_with_distinct(arg,key1,key2))
|
||||
return 0;
|
||||
return(group_concat_key_cmp_with_order(arg,key1,key2));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Append data from current leaf to item->result
|
||||
*/
|
||||
|
@ -3041,7 +3029,7 @@ Item_func_group_concat(Name_resolution_context *context_arg,
|
|||
bool distinct_arg, List<Item> *select_list,
|
||||
SQL_LIST *order_list, String *separator_arg)
|
||||
:tmp_table_param(0), warning(0),
|
||||
separator(separator_arg), tree(0), table(0),
|
||||
separator(separator_arg), tree(0), unique_filter(NULL), table(0),
|
||||
order(0), context(context_arg),
|
||||
arg_count_order(order_list ? order_list->elements : 0),
|
||||
arg_count_field(select_list->elements),
|
||||
|
@ -3096,6 +3084,7 @@ Item_func_group_concat::Item_func_group_concat(THD *thd,
|
|||
warning(item->warning),
|
||||
separator(item->separator),
|
||||
tree(item->tree),
|
||||
unique_filter(item->unique_filter),
|
||||
table(item->table),
|
||||
order(item->order),
|
||||
context(item->context),
|
||||
|
@ -3146,6 +3135,11 @@ void Item_func_group_concat::cleanup()
|
|||
delete_tree(tree);
|
||||
tree= 0;
|
||||
}
|
||||
if (unique_filter)
|
||||
{
|
||||
delete unique_filter;
|
||||
unique_filter= NULL;
|
||||
}
|
||||
if (warning)
|
||||
{
|
||||
char warn_buff[MYSQL_ERRMSG_SIZE];
|
||||
|
@ -3175,6 +3169,8 @@ void Item_func_group_concat::clear()
|
|||
no_appended= TRUE;
|
||||
if (tree)
|
||||
reset_tree(tree);
|
||||
if (distinct)
|
||||
unique_filter->reset();
|
||||
/* No need to reset the table as we never call write_row */
|
||||
}
|
||||
|
||||
|
@ -3198,9 +3194,19 @@ bool Item_func_group_concat::add()
|
|||
}
|
||||
|
||||
null_value= FALSE;
|
||||
bool row_eligible= TRUE;
|
||||
|
||||
if (distinct)
|
||||
{
|
||||
/* Filter out duplicate rows. */
|
||||
uint count= unique_filter->elements_in_tree();
|
||||
unique_filter->unique_add(table->record[0] + table->s->null_bytes);
|
||||
if (count == unique_filter->elements_in_tree())
|
||||
row_eligible= FALSE;
|
||||
}
|
||||
|
||||
TREE_ELEMENT *el= 0; // Only for safety
|
||||
if (tree)
|
||||
if (row_eligible && tree)
|
||||
el= tree_insert(tree, table->record[0] + table->s->null_bytes, 0,
|
||||
tree->custom_arg);
|
||||
/*
|
||||
|
@ -3208,7 +3214,7 @@ bool Item_func_group_concat::add()
|
|||
we can dump the row here in case of GROUP_CONCAT(DISTINCT...)
|
||||
instead of doing tree traverse later.
|
||||
*/
|
||||
if (!warning_for_row &&
|
||||
if (row_eligible && !warning_for_row &&
|
||||
(!tree || (el->count == 1 && distinct && !arg_count_order)))
|
||||
dump_leaf_key(table->record[0] + table->s->null_bytes, 1, this);
|
||||
|
||||
|
@ -3284,7 +3290,6 @@ bool Item_func_group_concat::setup(THD *thd)
|
|||
{
|
||||
List<Item> list;
|
||||
SELECT_LEX *select_lex= thd->lex->current_select;
|
||||
qsort_cmp2 compare_key;
|
||||
DBUG_ENTER("Item_func_group_concat::setup");
|
||||
|
||||
/*
|
||||
|
@ -3374,38 +3379,33 @@ bool Item_func_group_concat::setup(THD *thd)
|
|||
table->file->extra(HA_EXTRA_NO_ROWS);
|
||||
table->no_rows= 1;
|
||||
|
||||
/*
|
||||
Need sorting or uniqueness: init tree and choose a function to sort.
|
||||
Don't reserve space for NULLs: if any of gconcat arguments is NULL,
|
||||
the row is not added to the result.
|
||||
*/
|
||||
uint tree_key_length= table->s->reclength - table->s->null_bytes;
|
||||
|
||||
if (distinct || arg_count_order)
|
||||
if (arg_count_order)
|
||||
{
|
||||
/*
|
||||
Need sorting: init tree and choose a function to sort.
|
||||
Don't reserve space for NULLs: if any of gconcat arguments is NULL,
|
||||
the row is not added to the result.
|
||||
*/
|
||||
uint tree_key_length= table->s->reclength - table->s->null_bytes;
|
||||
|
||||
tree= &tree_base;
|
||||
if (arg_count_order)
|
||||
{
|
||||
if (distinct)
|
||||
compare_key= (qsort_cmp2) group_concat_key_cmp_with_distinct_and_order;
|
||||
else
|
||||
compare_key= (qsort_cmp2) group_concat_key_cmp_with_order;
|
||||
}
|
||||
else
|
||||
{
|
||||
compare_key= (qsort_cmp2) group_concat_key_cmp_with_distinct;
|
||||
}
|
||||
/*
|
||||
Create a tree for sorting. The tree is used to sort and to remove
|
||||
duplicate values (according to the syntax of this function). If there
|
||||
is no DISTINCT or ORDER BY clauses, we don't create this tree.
|
||||
Create a tree for sorting. The tree is used to sort (according to the
|
||||
syntax of this function). If there is no ORDER BY clause, we don't
|
||||
create this tree.
|
||||
*/
|
||||
init_tree(tree, (uint) min(thd->variables.max_heap_table_size,
|
||||
thd->variables.sortbuff_size/16), 0,
|
||||
tree_key_length, compare_key, 0, NULL, (void*) this);
|
||||
tree_key_length,
|
||||
group_concat_key_cmp_with_order , 0, NULL, (void*) this);
|
||||
}
|
||||
|
||||
if (distinct)
|
||||
unique_filter= new Unique(group_concat_key_cmp_with_distinct,
|
||||
(void*)this,
|
||||
tree_key_length,
|
||||
thd->variables.max_heap_table_size);
|
||||
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
|
@ -3475,3 +3475,10 @@ void Item_func_group_concat::print(String *str)
|
|||
str->append(*separator);
|
||||
str->append(STRING_WITH_LEN("\')"));
|
||||
}
|
||||
|
||||
|
||||
Item_func_group_concat::~Item_func_group_concat()
|
||||
{
|
||||
if (unique_filter)
|
||||
delete unique_filter;
|
||||
}
|
||||
|
|
|
@ -1173,11 +1173,22 @@ class Item_func_group_concat : public Item_sum
|
|||
String *separator;
|
||||
TREE tree_base;
|
||||
TREE *tree;
|
||||
|
||||
/**
|
||||
If DISTINCT is used with this GROUP_CONCAT, this member is used to filter
|
||||
out duplicates.
|
||||
@see Item_func_group_concat::setup
|
||||
@see Item_func_group_concat::add
|
||||
@see Item_func_group_concat::clear
|
||||
*/
|
||||
Unique *unique_filter;
|
||||
TABLE *table;
|
||||
ORDER **order;
|
||||
Name_resolution_context *context;
|
||||
uint arg_count_order; // total count of ORDER BY items
|
||||
uint arg_count_field; // count of arguments
|
||||
/** The number of ORDER BY items. */
|
||||
uint arg_count_order;
|
||||
/** The number of selected items, aka the expr list. */
|
||||
uint arg_count_field;
|
||||
uint count_cut_values;
|
||||
bool distinct;
|
||||
bool warning_for_row;
|
||||
|
@ -1190,13 +1201,10 @@ class Item_func_group_concat : public Item_sum
|
|||
*/
|
||||
Item_func_group_concat *original;
|
||||
|
||||
friend int group_concat_key_cmp_with_distinct(void* arg, uchar* key1,
|
||||
uchar* key2);
|
||||
friend int group_concat_key_cmp_with_order(void* arg, uchar* key1,
|
||||
uchar* key2);
|
||||
friend int group_concat_key_cmp_with_distinct_and_order(void* arg,
|
||||
uchar* key1,
|
||||
uchar* key2);
|
||||
friend int group_concat_key_cmp_with_distinct(void* arg, const void* key1,
|
||||
const void* key2);
|
||||
friend int group_concat_key_cmp_with_order(void* arg, const void* key1,
|
||||
const void* key2);
|
||||
friend int dump_leaf_key(uchar* key,
|
||||
element_count count __attribute__((unused)),
|
||||
Item_func_group_concat *group_concat_item);
|
||||
|
@ -1207,7 +1215,7 @@ public:
|
|||
SQL_LIST *is_order, String *is_separator);
|
||||
|
||||
Item_func_group_concat(THD *thd, Item_func_group_concat *item);
|
||||
~Item_func_group_concat() {}
|
||||
~Item_func_group_concat();
|
||||
void cleanup();
|
||||
|
||||
enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;}
|
||||
|
|
|
@ -3344,6 +3344,8 @@ bool Item_func_last_day::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
|
|||
ltime->day= days_in_month[month_idx];
|
||||
if ( month_idx == 1 && calc_days_in_year(ltime->year) == 366)
|
||||
ltime->day= 29;
|
||||
ltime->hour= ltime->minute= ltime->second= 0;
|
||||
ltime->second_part= 0;
|
||||
ltime->time_type= MYSQL_TIMESTAMP_DATE;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3005,10 +3005,10 @@ err:
|
|||
void MYSQL_BIN_LOG::make_log_name(char* buf, const char* log_ident)
|
||||
{
|
||||
uint dir_len = dirname_length(log_file_name);
|
||||
if (dir_len > FN_REFLEN)
|
||||
if (dir_len >= FN_REFLEN)
|
||||
dir_len=FN_REFLEN-1;
|
||||
strnmov(buf, log_file_name, dir_len);
|
||||
strmake(buf+dir_len, log_ident, FN_REFLEN - dir_len);
|
||||
strmake(buf+dir_len, log_ident, FN_REFLEN - dir_len -1);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -927,7 +927,7 @@ bool load_master_data(THD* thd)
|
|||
0, (SLAVE_IO | SLAVE_SQL)))
|
||||
my_message(ER_MASTER_INFO, ER(ER_MASTER_INFO), MYF(0));
|
||||
strmake(active_mi->master_log_name, row[0],
|
||||
sizeof(active_mi->master_log_name));
|
||||
sizeof(active_mi->master_log_name) -1);
|
||||
active_mi->master_log_pos= my_strtoll10(row[1], (char**) 0, &error_2);
|
||||
/* at least in recent versions, the condition below should be false */
|
||||
if (active_mi->master_log_pos < BIN_LOG_HEADER_SIZE)
|
||||
|
|
|
@ -6400,7 +6400,36 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
|
|||
*resolution= RESOLVED_IGNORING_ALIAS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (table_name && item->type() == Item::REF_ITEM &&
|
||||
((Item_ref *)item)->ref_type() == Item_ref::VIEW_REF)
|
||||
{
|
||||
/*
|
||||
TODO:Here we process prefixed view references only. What we should
|
||||
really do is process all types of Item_refs. But this will currently
|
||||
lead to a clash with the way references to outer SELECTs (from the
|
||||
HAVING clause) are handled in e.g. :
|
||||
SELECT 1 FROM t1 AS t1_o GROUP BY a
|
||||
HAVING (SELECT t1_o.a FROM t1 AS t1_i GROUP BY t1_i.a LIMIT 1).
|
||||
Processing all Item_refs here will cause t1_o.a to resolve to itself.
|
||||
We still need to process the special case of Item_direct_view_ref
|
||||
because in the context of views they have the same meaning as
|
||||
Item_field for tables.
|
||||
*/
|
||||
Item_ident *item_ref= (Item_ident *) item;
|
||||
if (item_ref->name && item_ref->table_name &&
|
||||
!my_strcasecmp(system_charset_info, item_ref->name, field_name) &&
|
||||
!my_strcasecmp(table_alias_charset, item_ref->table_name,
|
||||
table_name) &&
|
||||
(!db_name || (item_ref->db_name &&
|
||||
!strcmp (item_ref->db_name, db_name))))
|
||||
{
|
||||
found= li.ref();
|
||||
*counter= i;
|
||||
*resolution= RESOLVED_IGNORING_ALIAS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
|
|
|
@ -1396,7 +1396,7 @@ static void backup_current_db_name(THD *thd,
|
|||
}
|
||||
else
|
||||
{
|
||||
strmake(saved_db_name->str, thd->db, saved_db_name->length);
|
||||
strmake(saved_db_name->str, thd->db, saved_db_name->length - 1);
|
||||
saved_db_name->length= thd->db_length;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9276,6 +9276,8 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
|
|||
*((*copy_func)++) = item; // Save for copy_funcs
|
||||
if (modify_item)
|
||||
item->set_result_field(new_field);
|
||||
if (item->type() == Item::NULL_ITEM)
|
||||
new_field->is_created_from_null_item= TRUE;
|
||||
return new_field;
|
||||
}
|
||||
|
||||
|
|
|
@ -6151,6 +6151,14 @@ select_paren:
|
|||
my_parse_error(ER(ER_SYNTAX_ERROR));
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
if (sel->linkage == UNION_TYPE &&
|
||||
sel->olap != UNSPECIFIED_OLAP_TYPE &&
|
||||
sel->master_unit()->fake_select_lex)
|
||||
{
|
||||
my_error(ER_WRONG_USAGE, MYF(0),
|
||||
"CUBE/ROLLUP", "ORDER BY");
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
/* select in braces, can't contain global parameters */
|
||||
if (sel->master_unit()->fake_select_lex)
|
||||
sel->master_unit()->global_parameters=
|
||||
|
@ -8039,7 +8047,8 @@ order_clause:
|
|||
SELECT_LEX *sel= lex->current_select;
|
||||
SELECT_LEX_UNIT *unit= sel-> master_unit();
|
||||
if (sel->linkage != GLOBAL_OPTIONS_TYPE &&
|
||||
sel->olap != UNSPECIFIED_OLAP_TYPE)
|
||||
sel->olap != UNSPECIFIED_OLAP_TYPE &&
|
||||
(sel->linkage != UNION_TYPE || sel->braces))
|
||||
{
|
||||
my_error(ER_WRONG_USAGE, MYF(0),
|
||||
"CUBE/ROLLUP", "ORDER BY");
|
||||
|
|
|
@ -227,6 +227,14 @@ bool mysql_create_frm(THD *thd, const char *file_name,
|
|||
strmake((char*) forminfo+47, create_info->comment.str ?
|
||||
create_info->comment.str : "", create_info->comment.length);
|
||||
forminfo[46]=(uchar) create_info->comment.length;
|
||||
#ifdef EXTRA_DEBUG
|
||||
/*
|
||||
EXTRA_DEBUG causes strmake() to initialize its buffer behind the
|
||||
payload with a magic value to detect wrong buffer-sizes. We
|
||||
explicitly zero that segment again.
|
||||
*/
|
||||
memset((char*) forminfo+47 + forminfo[46], 0, 61 - forminfo[46]);
|
||||
#endif
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
if (part_info)
|
||||
{
|
||||
|
|
|
@ -27,23 +27,25 @@
|
|||
#include <my_global.h>
|
||||
#include "m_string.h"
|
||||
|
||||
#ifdef BAD_STRING_COMPILER
|
||||
|
||||
char *strmake(char *dst,const char *src,uint length)
|
||||
{
|
||||
reg1 char *res;
|
||||
|
||||
if ((res=memccpy(dst,src,0,length)))
|
||||
return res-1;
|
||||
dst[length]=0;
|
||||
return dst+length;
|
||||
}
|
||||
|
||||
#define strmake strmake_overlapp /* Use orginal for overlapping str */
|
||||
#endif
|
||||
|
||||
char *strmake(register char *dst, register const char *src, size_t length)
|
||||
{
|
||||
#ifdef EXTRA_DEBUG
|
||||
/*
|
||||
'length' is the maximum length of the string; the buffer needs
|
||||
to be one character larger to accomodate the terminating '\0'.
|
||||
This is easy to get wrong, so we make sure we write to the
|
||||
entire length of the buffer to identify incorrect buffer-sizes.
|
||||
We only initialise the "unused" part of the buffer here, a) for
|
||||
efficiency, and b) because dst==src is allowed, so initialising
|
||||
the entire buffer would overwrite the source-string. Also, we
|
||||
write a character rather than '\0' as this makes spotting these
|
||||
problems in the results easier.
|
||||
*/
|
||||
uint n= strlen(src) + 1;
|
||||
if (n <= length)
|
||||
memset(dst + n, (int) 'Z', length - n + 1);
|
||||
#endif
|
||||
|
||||
while (length--)
|
||||
if (! (*dst++ = *src++))
|
||||
return dst-1;
|
||||
|
|
Loading…
Reference in a new issue