summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <joerg@trift2.>2008-01-24 15:58:23 +0100
committerunknown <joerg@trift2.>2008-01-24 15:58:23 +0100
commit016f33c8d18e2b532add23ae98659edaed2a1483 (patch)
treeaefb175e7165a169a1f39e599945766cb73d778a
parent68fd74d7644c525bacb41510b1874ba9bc1bce9a (diff)
parentb3233513685b92697e17f1760b9d68da3ab269e9 (diff)
downloadmariadb-git-016f33c8d18e2b532add23ae98659edaed2a1483.tar.gz
Merge trift2.:/MySQL/M51/bug33536-5.1
into trift2.:/MySQL/M51/clone-5.1
-rw-r--r--client/mysql.cc5
-rw-r--r--client/mysqldump.c4
-rw-r--r--client/mysqltest.c4
-rw-r--r--extra/yassl/src/handshake.cpp5
-rw-r--r--extra/yassl/src/template_instnt.cpp1
-rw-r--r--extra/yassl/src/yassl_imp.cpp11
-rw-r--r--mysql-test/r/func_gconcat.result63
-rw-r--r--mysql-test/r/func_group.result12
-rw-r--r--mysql-test/r/func_time.result3
-rw-r--r--mysql-test/r/skip_grants.result4
-rw-r--r--mysql-test/r/subselect.result9
-rw-r--r--mysql-test/r/type_date.result5
-rw-r--r--mysql-test/r/type_decimal.result4
-rw-r--r--mysql-test/r/udf_skip_grants.result5
-rw-r--r--mysql-test/r/union.result75
-rw-r--r--mysql-test/suite/rpl/r/rpl_trigger.result12
-rw-r--r--mysql-test/suite/rpl/t/rpl_trigger.test12
-rw-r--r--mysql-test/t/func_gconcat.test41
-rw-r--r--mysql-test/t/func_group.test15
-rw-r--r--mysql-test/t/func_time.test7
-rw-r--r--mysql-test/t/skip_grants.test10
-rw-r--r--mysql-test/t/subselect.test23
-rw-r--r--mysql-test/t/type_date.test8
-rw-r--r--mysql-test/t/udf_skip_grants-master.opt1
-rw-r--r--mysql-test/t/udf_skip_grants.test28
-rw-r--r--mysql-test/t/union.test66
-rw-r--r--mysys/mf_pack.c4
-rw-r--r--sql/field.cc10
-rw-r--r--sql/field.h15
-rw-r--r--sql/filesort.cc24
-rw-r--r--sql/handler.cc2
-rw-r--r--sql/item.cc6
-rw-r--r--sql/item_sum.cc157
-rw-r--r--sql/item_sum.h28
-rw-r--r--sql/item_timefunc.cc2
-rw-r--r--sql/log.cc4
-rw-r--r--sql/log_event.cc20
-rw-r--r--sql/repl_failsafe.cc2
-rw-r--r--sql/sql_base.cc31
-rw-r--r--sql/sql_db.cc2
-rw-r--r--sql/sql_select.cc2
-rw-r--r--sql/sql_yacc.yy11
-rw-r--r--sql/unireg.cc8
-rw-r--r--storage/ndb/src/common/util/OutputStream.cpp4
-rw-r--r--strings/strmake.c30
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;