diff options
author | unknown <joerg@trift2.> | 2008-01-24 15:58:23 +0100 |
---|---|---|
committer | unknown <joerg@trift2.> | 2008-01-24 15:58:23 +0100 |
commit | 016f33c8d18e2b532add23ae98659edaed2a1483 (patch) | |
tree | aefb175e7165a169a1f39e599945766cb73d778a | |
parent | 68fd74d7644c525bacb41510b1874ba9bc1bce9a (diff) | |
parent | b3233513685b92697e17f1760b9d68da3ab269e9 (diff) | |
download | mariadb-git-016f33c8d18e2b532add23ae98659edaed2a1483.tar.gz |
Merge trift2.:/MySQL/M51/bug33536-5.1
into trift2.:/MySQL/M51/clone-5.1
45 files changed, 637 insertions, 158 deletions
diff --git a/client/mysql.cc b/client/mysql.cc index 8f118a06935..1d673348f58 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -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) { diff --git a/client/mysqldump.c b/client/mysqldump.c index 01b484e924e..f119e0b40b0 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -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 : ""); diff --git a/client/mysqltest.c b/client/mysqltest.c index e0662fc2251..31e419244e6 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -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); diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp index 1d5a95820bb..262b5cb3b8b 100644 --- a/extra/yassl/src/handshake.cpp +++ b/extra/yassl/src/handshake.cpp @@ -527,6 +527,11 @@ void ProcessOldClientHello(input_buffer& input, SSL& ssl) input.read(len, sizeof(len)); uint16 randomLen; ato16(len, randomLen); + if (ch.suite_len_ > MAX_SUITE_SZ || sessionLen > ID_LEN || + randomLen > RAN_LEN) { + ssl.SetError(bad_input); + return; + } int j = 0; for (uint16 i = 0; i < ch.suite_len_; i += 3) { diff --git a/extra/yassl/src/template_instnt.cpp b/extra/yassl/src/template_instnt.cpp index f82f7924359..fe3a251b865 100644 --- a/extra/yassl/src/template_instnt.cpp +++ b/extra/yassl/src/template_instnt.cpp @@ -101,6 +101,7 @@ template void ysArrayDelete<unsigned char>(unsigned char*); template void ysArrayDelete<char>(char*); template int min<int>(int, int); +template uint16 min<uint16>(uint16, uint16); template unsigned int min<unsigned int>(unsigned int, unsigned int); template unsigned long min<unsigned long>(unsigned long, unsigned long); } diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp index 0bc95f64abc..b43d9c27355 100644 --- a/extra/yassl/src/yassl_imp.cpp +++ b/extra/yassl/src/yassl_imp.cpp @@ -621,6 +621,10 @@ void HandShakeHeader::Process(input_buffer& input, SSL& ssl) } uint len = c24to32(length_); + if (len > input.get_remaining()) { + ssl.SetError(bad_input); + return; + } hashHandShake(ssl, input, len); hs->set_length(len); @@ -1391,10 +1395,15 @@ input_buffer& operator>>(input_buffer& input, ClientHello& hello) // Suites byte tmp[2]; + uint16 len; tmp[0] = input[AUTO]; tmp[1] = input[AUTO]; - ato16(tmp, hello.suite_len_); + ato16(tmp, len); + + hello.suite_len_ = min(len, static_cast<uint16>(MAX_SUITE_SZ)); input.read(hello.cipher_suites_, hello.suite_len_); + if (len > hello.suite_len_) // ignore extra suites + input.set_current(input.get_current() + len - hello.suite_len_); // Compression hello.comp_len_ = input[AUTO]; diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index d257e526abf..b5bfadf1f57 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -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 diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index abf717091af..4c1abb160c6 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -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 diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 5e3726a06d6..4dd8fb1531d 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -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) diff --git a/mysql-test/r/skip_grants.result b/mysql-test/r/skip_grants.result index bf0f16a174f..b523f2edc9f 100644 --- a/mysql-test/r/skip_grants.result +++ b/mysql-test/r/skip_grants.result @@ -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 diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index d1173fed7f4..762457d57a6 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -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); diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result index 5921991bf50..7cb71831bce 100644 --- a/mysql-test/r/type_date.result +++ b/mysql-test/r/type_date.result @@ -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'); diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result index e37a398d22e..a25ffc4c6fc 100644 --- a/mysql-test/r/type_decimal.result +++ b/mysql-test/r/type_decimal.result @@ -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, diff --git a/mysql-test/r/udf_skip_grants.result b/mysql-test/r/udf_skip_grants.result new file mode 100644 index 00000000000..8d7081ebf6f --- /dev/null +++ b/mysql-test/r/udf_skip_grants.result @@ -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 diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 6fc630ec33c..295451867c8 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -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 diff --git a/mysql-test/suite/rpl/r/rpl_trigger.result b/mysql-test/suite/rpl/r/rpl_trigger.result index b4ce3ee1d36..68c82ed037f 100644 --- a/mysql-test/suite/rpl/r/rpl_trigger.result +++ b/mysql-test/suite/rpl/r/rpl_trigger.result @@ -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; diff --git a/mysql-test/suite/rpl/t/rpl_trigger.test b/mysql-test/suite/rpl/t/rpl_trigger.test index 4a496ea4923..911110d17dc 100644 --- a/mysql-test/suite/rpl/t/rpl_trigger.test +++ b/mysql-test/suite/rpl/t/rpl_trigger.test @@ -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 diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index 322be2b7b8e..826e00bf74f 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -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 diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index 8beed28cfbf..36d360780cf 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -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 diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 97087abd668..13c5da1285a 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -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 # diff --git a/mysql-test/t/skip_grants.test b/mysql-test/t/skip_grants.test index 72a073ac541..6f4d23e1e14 100644 --- a/mysql-test/t/skip_grants.test +++ b/mysql-test/t/skip_grants.test @@ -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 # diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 077e00a4c6e..ad940f3f5ad 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -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)); diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test index d714229c217..9bc428c3715 100644 --- a/mysql-test/t/type_date.test +++ b/mysql-test/t/type_date.test @@ -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 # diff --git a/mysql-test/t/udf_skip_grants-master.opt b/mysql-test/t/udf_skip_grants-master.opt new file mode 100644 index 00000000000..5699a3387b8 --- /dev/null +++ b/mysql-test/t/udf_skip_grants-master.opt @@ -0,0 +1 @@ +--skip-grant-tables diff --git a/mysql-test/t/udf_skip_grants.test b/mysql-test/t/udf_skip_grants.test new file mode 100644 index 00000000000..bd9402e0d8a --- /dev/null +++ b/mysql-test/t/udf_skip_grants.test @@ -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 diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index a57ab469ac2..70789404d6e 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -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 diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c index a31b9595c85..63525e4d927 100644 --- a/mysys/mf_pack.c +++ b/mysys/mf_pack.c @@ -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) { diff --git a/sql/field.cc b/sql/field.cc index 93588992fed..668ced4a229 100644 --- a/sql/field.cc +++ b/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; diff --git a/sql/field.h b/sql/field.h index 9f76deb18bc..a6a1d8bfabc 100644 --- a/sql/field.h +++ b/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; } diff --git a/sql/filesort.cc b/sql/filesort.cc index 2e6f0ecaf05..f2216c12ce4 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -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) || diff --git a/sql/handler.cc b/sql/handler.cc index a4926071598..3b1667b0d59 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3710,6 +3710,8 @@ int handler::ha_reset() DBUG_ASSERT(inited == NONE); /* Free cache used by filesort */ free_io_cache(table); + /* reset the bitmaps to point to defaults */ + table->default_column_bitmaps(); DBUG_RETURN(reset()); } diff --git a/sql/item.cc b/sql/item.cc index 4d579597d21..922c3b7a976 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -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; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index a7574cf4d60..881f472d766 100644 --- a/sql/item_sum.cc +++ b/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; } } @@ -2938,25 +2945,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; +} diff --git a/sql/item_sum.h b/sql/item_sum.h index b3a382012f1..a3582967736 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -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;} diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 3d4a6de83ac..56a6480d859 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -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; } diff --git a/sql/log.cc b/sql/log.cc index 0cea59eed98..99ac9cf509d 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -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); } diff --git a/sql/log_event.cc b/sql/log_event.cc index 00e3dc89f6b..b438bc3f840 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -7837,7 +7837,7 @@ int Rows_log_event::find_row(const Relay_log_info *rli) { DBUG_PRINT("info",("ha_index_init returns error %d",error)); table->file->print_error(error, MYF(0)); - DBUG_RETURN(error); + goto err; } /* Fill key data for the row */ @@ -7870,7 +7870,7 @@ int Rows_log_event::find_row(const Relay_log_info *rli) DBUG_PRINT("info",("no record matching the key found in the table")); table->file->print_error(error, MYF(0)); table->file->ha_index_end(); - DBUG_RETURN(error); + goto err; } /* @@ -7898,7 +7898,7 @@ int Rows_log_event::find_row(const Relay_log_info *rli) if (table->key_info->flags & HA_NOSAME) { table->file->ha_index_end(); - DBUG_RETURN(0); + goto ok; } /* @@ -7930,7 +7930,7 @@ int Rows_log_event::find_row(const Relay_log_info *rli) DBUG_PRINT("info",("no record matching the given row found")); table->file->print_error(error, MYF(0)); table->file->ha_index_end(); - DBUG_RETURN(error); + goto err; } } @@ -7951,7 +7951,7 @@ int Rows_log_event::find_row(const Relay_log_info *rli) DBUG_PRINT("info",("error initializing table scan" " (ha_rnd_init returns %d)",error)); table->file->print_error(error, MYF(0)); - DBUG_RETURN(error); + goto err; } /* Continue until we find the right record or have made a full loop */ @@ -7975,7 +7975,7 @@ int Rows_log_event::find_row(const Relay_log_info *rli) " (rnd_next returns %d)",error)); table->file->print_error(error, MYF(0)); table->file->ha_rnd_end(); - DBUG_RETURN(error); + goto err; } } while (restart_count < 2 && record_compare(table)); @@ -7995,10 +7995,16 @@ int Rows_log_event::find_row(const Relay_log_info *rli) table->file->ha_rnd_end(); DBUG_ASSERT(error == HA_ERR_END_OF_FILE || error == HA_ERR_RECORD_DELETED || error == 0); - DBUG_RETURN(error); + goto err; } +ok: + table->default_column_bitmaps(); DBUG_RETURN(0); + +err: + table->default_column_bitmaps(); + DBUG_RETURN(error); } #endif diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index e294cf8ae2d..69f4df723b7 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -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) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 67aba1a3a0d..763195f6516 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -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) { diff --git a/sql/sql_db.cc b/sql/sql_db.cc index f158b5488d0..b5f49b97ec9 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -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; } } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 93486aa7b65..8f9562eb5e2 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -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; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index b4d8bb2dfb8..6d2e4ea9a59 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -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"); diff --git a/sql/unireg.cc b/sql/unireg.cc index dbdefd8d5b1..aab3f5606a8 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -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) { diff --git a/storage/ndb/src/common/util/OutputStream.cpp b/storage/ndb/src/common/util/OutputStream.cpp index 0943e47e33f..cd619380e5a 100644 --- a/storage/ndb/src/common/util/OutputStream.cpp +++ b/storage/ndb/src/common/util/OutputStream.cpp @@ -62,7 +62,7 @@ SocketOutputStream::print(const char * fmt, ...){ if(ret >= 0) m_timeout_remain-=time; - if(errno==ETIMEDOUT || m_timeout_remain<=0) + if((ret < 0 && errno==ETIMEDOUT) || m_timeout_remain<=0) { m_timedout= true; ret= -1; @@ -84,7 +84,7 @@ SocketOutputStream::println(const char * fmt, ...){ if(ret >= 0) m_timeout_remain-=time; - if (errno==ETIMEDOUT || m_timeout_remain<=0) + if ((ret < 0 && errno==ETIMEDOUT) || m_timeout_remain<=0) { m_timedout= true; ret= -1; diff --git a/strings/strmake.c b/strings/strmake.c index 0d26e1b61a9..df8d78e8476 100644 --- a/strings/strmake.c +++ b/strings/strmake.c @@ -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) +char *strmake(register char *dst, register const char *src, size_t 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 */ +#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 -char *strmake(register char *dst, register const char *src, size_t length) -{ while (length--) if (! (*dst++ = *src++)) return dst-1; |