diff --git a/.bzrignore b/.bzrignore index c38cb22d0fd..e1ad5a89015 100644 --- a/.bzrignore +++ b/.bzrignore @@ -476,6 +476,9 @@ contrib/*.vcproj core core.* core.2430 +cscope.in.out +cscope.out +cscope.po.out db-*.*.* dbug/*.ds? dbug/*.vcproj diff --git a/client/mysqldump.c b/client/mysqldump.c index 25c11b5e71d..582e9e3b3b9 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -3039,6 +3039,18 @@ static void dump_table(char *table, char *db) DBUG_VOID_RETURN; } + /* + Check --skip-events flag: it is not enough to skip creation of events + discarding SHOW CREATE EVENT statements generation. The myslq.event + table data should be skipped too. + */ + if (!opt_events && !my_strcasecmp(&my_charset_latin1, db, "mysql") && + !my_strcasecmp(&my_charset_latin1, table, "event")) + { + verbose_msg("-- Skipping data table mysql.event, --skip-events was used\n"); + DBUG_VOID_RETURN; + } + result_table= quote_name(table,table_buff, 1); opt_quoted_table= quote_name(table, table_buff2, 0); @@ -3848,7 +3860,7 @@ int init_dumping_tables(char *qdatabase) /* Old server version, dump generic CREATE DATABASE */ if (opt_drop_database) fprintf(md_result_file, - "\n/*!40000 DROP DATABASE IF EXISTS %s;*/\n", + "\n/*!40000 DROP DATABASE IF EXISTS %s*/;\n", qdatabase); fprintf(md_result_file, "\nCREATE DATABASE /*!32312 IF NOT EXISTS*/ %s;\n", diff --git a/include/my_pthread.h b/include/my_pthread.h index 3041d43c773..eb390c2acc4 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -519,6 +519,7 @@ typedef struct st_my_pthread_fastmutex_t pthread_mutex_t mutex; uint spins; } my_pthread_fastmutex_t; +void fastmutex_global_init(void); int my_pthread_fastmutex_init(my_pthread_fastmutex_t *mp, const pthread_mutexattr_t *attr); diff --git a/mysql-test/include/mix1.inc b/mysql-test/include/mix1.inc index 5e6a535fce5..a55e0f22a7c 100644 --- a/mysql-test/include/mix1.inc +++ b/mysql-test/include/mix1.inc @@ -969,6 +969,33 @@ ROLLBACK; ROLLBACK; DROP TABLE t1; +# +# Bug#30596: GROUP BY optimization gives wrong result order +# +CREATE TABLE t1( + a INT, + b INT NOT NULL, + c INT NOT NULL, + d INT, + UNIQUE KEY (c,b) +) engine=innodb; + +INSERT INTO t1 VALUES (1,1,1,50), (1,2,3,40), (2,1,3,4); + +EXPLAIN SELECT c,b,d FROM t1 GROUP BY c,b,d; +SELECT c,b,d FROM t1 GROUP BY c,b,d; +EXPLAIN SELECT c,b,d FROM t1 GROUP BY c,b,d ORDER BY NULL; +SELECT c,b,d FROM t1 GROUP BY c,b,d ORDER BY NULL; +EXPLAIN SELECT c,b,d FROM t1 ORDER BY c,b,d; +SELECT c,b,d FROM t1 ORDER BY c,b,d; + +EXPLAIN SELECT c,b,d FROM t1 GROUP BY c,b; +SELECT c,b,d FROM t1 GROUP BY c,b; +EXPLAIN SELECT c,b FROM t1 GROUP BY c,b; +SELECT c,b FROM t1 GROUP BY c,b; + +DROP TABLE t1; + --echo End of 5.0 tests # Fix for BUG#19243 "wrong LAST_INSERT_ID() after ON DUPLICATE KEY diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result index 4bdf1c770d3..d333425f23a 100644 --- a/mysql-test/r/delete.result +++ b/mysql-test/r/delete.result @@ -223,3 +223,40 @@ ERROR 42S22: Unknown column 't2.x' in 'order clause' DELETE FROM t1 ORDER BY (SELECT x); ERROR 42S22: Unknown column 'x' in 'field list' DROP TABLE t1; +CREATE TABLE t1 ( +a INT +); +CREATE TABLE t2 ( +a INT +); +CREATE DATABASE db1; +CREATE TABLE db1.t1 ( +a INT +); +INSERT INTO db1.t1 (a) SELECT * FROM t1; +CREATE DATABASE db2; +CREATE TABLE db2.t1 ( +a INT +); +INSERT INTO db2.t1 (a) SELECT * FROM t2; +DELETE FROM t1 alias USING t1, t2 alias WHERE t1.a = alias.a; +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 'alias USING t1, t2 alias WHERE t1.a = alias.a' at line 1 +DELETE FROM alias USING t1, t2 alias WHERE t1.a = alias.a; +DELETE FROM t1, alias USING t1, t2 alias WHERE t1.a = alias.a; +DELETE FROM t1, t2 USING t1, t2 alias WHERE t1.a = alias.a; +ERROR 42S02: Unknown table 't2' in MULTI DELETE +DELETE FROM db1.t1 alias USING db1.t1, db2.t1 alias WHERE db1.t1.a = alias.a; +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 'alias USING db1.t1, db2.t1 alias WHERE db1.t1.a = alias.a' at line 1 +DELETE FROM alias USING db1.t1, db2.t1 alias WHERE db1.t1.a = alias.a; +ERROR 42S02: Unknown table 'alias' in MULTI DELETE +DELETE FROM db2.alias USING db1.t1, db2.t1 alias WHERE db1.t1.a = alias.a; +DELETE FROM t1 USING t1 WHERE a = 1; +SELECT * FROM t1; +a +DELETE FROM t1 alias USING t1 alias WHERE a = 2; +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 'alias USING t1 alias WHERE a = 2' at line 1 +SELECT * FROM t1; +a +DROP TABLE t1, t2; +DROP DATABASE db1; +DROP DATABASE db2; diff --git a/mysql-test/r/distinct.result b/mysql-test/r/distinct.result index 795d8956a08..b2a9eb04c04 100644 --- a/mysql-test/r/distinct.result +++ b/mysql-test/r/distinct.result @@ -526,10 +526,10 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL PRIMARY 4 NULL 3 Using index EXPLAIN SELECT a,b FROM t1 GROUP BY a,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using filesort EXPLAIN SELECT DISTINCT a,b FROM t1 GROUP BY a,b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using filesort CREATE TABLE t2(a INT, b INT NOT NULL, c INT NOT NULL, d INT, PRIMARY KEY (a,b)); INSERT INTO t2 VALUES (1,1,1,50), (1,2,3,40), (2,1,3,4); @@ -554,7 +554,7 @@ id select_type table type possible_keys key key_len ref rows Extra CREATE UNIQUE INDEX c_b_unq ON t2 (c,b); EXPLAIN SELECT DISTINCT a,b,d FROM t2 GROUP BY c,b,d; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 Using filesort DROP TABLE t1,t2; create table t1 (id int, dsc varchar(50)); insert into t1 values (1, "line number one"), (2, "line number two"), (3, "line number three"); diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 13ddccaee92..2faf7832aca 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -1093,7 +1093,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 144 EXPLAIN SELECT a FROM t1 IGNORE INDEX FOR GROUP BY (PRIMARY,i2) GROUP BY a; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index NULL PRIMARY 4 NULL 144 Using index +1 SIMPLE t1 index NULL PRIMARY 4 NULL 144 Using index; Using filesort EXPLAIN SELECT a FROM t1 IGNORE INDEX FOR ORDER BY (PRIMARY,i2) ORDER BY a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index NULL PRIMARY 4 NULL 144 Using index; Using filesort @@ -1129,7 +1129,7 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp EXPLAIN SELECT a FROM t1 USE INDEX FOR JOIN (i2) USE INDEX FOR GROUP BY (i2) GROUP BY a; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index NULL i2 9 NULL 144 Using index +1 SIMPLE t1 # NULL i2 # NULL # # EXPLAIN SELECT a FROM t1 FORCE INDEX FOR JOIN (i2) FORCE INDEX FOR GROUP BY (i2) GROUP BY a; id select_type table type possible_keys key key_len ref rows Extra @@ -1176,3 +1176,94 @@ old OFF SET @@old = off; ERROR HY000: Variable 'old' is a read only variable DROP TABLE t1, t2; +CREATE TABLE t1( +a INT, +b INT NOT NULL, +c INT NOT NULL, +d INT, +UNIQUE KEY (c,b) +); +INSERT INTO t1 VALUES (1,1,1,50), (1,2,3,40), (2,1,3,4); +CREATE TABLE t2( +a INT, +b INT, +UNIQUE KEY(a,b) +); +INSERT INTO t2 VALUES (NULL, NULL), (NULL, NULL), (NULL, 1), (1, NULL), (1, 1), (1,2); +EXPLAIN SELECT c,b,d FROM t1 GROUP BY c,b,d; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using filesort +SELECT c,b,d FROM t1 GROUP BY c,b,d; +c b d +1 1 50 +3 1 4 +3 2 40 +EXPLAIN SELECT c,b,d FROM t1 GROUP BY c,b,d ORDER BY NULL; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +SELECT c,b,d FROM t1 GROUP BY c,b,d ORDER BY NULL; +c b d +1 1 50 +3 2 40 +3 1 4 +EXPLAIN SELECT c,b,d FROM t1 ORDER BY c,b,d; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using filesort +SELECT c,b,d FROM t1 ORDER BY c,b,d; +c b d +1 1 50 +3 1 4 +3 2 40 +EXPLAIN SELECT c,b,d FROM t1 GROUP BY c,b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using filesort +SELECT c,b,d FROM t1 GROUP BY c,b; +c b d +1 1 50 +3 1 4 +3 2 40 +EXPLAIN SELECT c,b FROM t1 GROUP BY c,b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL c 8 NULL 3 Using index +SELECT c,b FROM t1 GROUP BY c,b; +c b +1 1 +3 1 +3 2 +EXPLAIN SELECT a,b from t2 ORDER BY a,b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 index NULL a 10 NULL 6 Using index +SELECT a,b from t2 ORDER BY a,b; +a b +NULL NULL +NULL NULL +NULL 1 +1 NULL +1 1 +1 2 +EXPLAIN SELECT a,b from t2 GROUP BY a,b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 index NULL a 10 NULL 6 Using index +SELECT a,b from t2 GROUP BY a,b; +a b +NULL NULL +NULL 1 +1 NULL +1 1 +1 2 +EXPLAIN SELECT a from t2 GROUP BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 index NULL a 10 NULL 6 Using index +SELECT a from t2 GROUP BY a; +a +NULL +1 +EXPLAIN SELECT b from t2 GROUP BY b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 index NULL a 10 NULL 6 Using index; Using temporary; Using filesort +SELECT b from t2 GROUP BY b; +b +NULL +1 +2 +DROP TABLE t1; diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 32c692501ad..3293f05a1f9 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -1141,6 +1141,55 @@ a b ROLLBACK; ROLLBACK; DROP TABLE t1; +CREATE TABLE t1( +a INT, +b INT NOT NULL, +c INT NOT NULL, +d INT, +UNIQUE KEY (c,b) +) engine=innodb; +INSERT INTO t1 VALUES (1,1,1,50), (1,2,3,40), (2,1,3,4); +EXPLAIN SELECT c,b,d FROM t1 GROUP BY c,b,d; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using filesort +SELECT c,b,d FROM t1 GROUP BY c,b,d; +c b d +1 1 50 +3 1 4 +3 2 40 +EXPLAIN SELECT c,b,d FROM t1 GROUP BY c,b,d ORDER BY NULL; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +SELECT c,b,d FROM t1 GROUP BY c,b,d ORDER BY NULL; +c b d +1 1 50 +3 1 4 +3 2 40 +EXPLAIN SELECT c,b,d FROM t1 ORDER BY c,b,d; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using filesort +SELECT c,b,d FROM t1 ORDER BY c,b,d; +c b d +1 1 50 +3 1 4 +3 2 40 +EXPLAIN SELECT c,b,d FROM t1 GROUP BY c,b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL c 8 NULL 3 +SELECT c,b,d FROM t1 GROUP BY c,b; +c b d +1 1 50 +3 1 4 +3 2 40 +EXPLAIN SELECT c,b FROM t1 GROUP BY c,b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL c 8 NULL 3 Using index +SELECT c,b FROM t1 GROUP BY c,b; +c b +1 1 +3 1 +3 2 +DROP TABLE t1; End of 5.0 tests CREATE TABLE `t2` ( `k` int(11) NOT NULL auto_increment, diff --git a/mysql-test/r/mysqldump-compat.result b/mysql-test/r/mysqldump-compat.result new file mode 100644 index 00000000000..f15cc7a1d7a --- /dev/null +++ b/mysql-test/r/mysqldump-compat.result @@ -0,0 +1,4 @@ +CREATE DATABASE mysqldump_30126; +USE mysqldump_30126; +CREATE TABLE t1 (c1 int); +DROP DATABASE mysqldump_30126; diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 58bcac42f9c..d8688ea5509 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -4177,5 +4177,18 @@ set names latin1; # Cleanup. DROP DATABASE mysqldump_test_db; # +# BUG#29938: wrong behavior of mysqldump --skip-events +# with --all-databases +# +TRUNCATE mysql.event; +USE test; +CREATE event e29938 ON SCHEDULE AT '2035-12-31 20:01:23' DO SET @bug29938=29938; +SHOW EVENTS; +Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation +test e29938 root@localhost SYSTEM ONE TIME 2035-12-31 20:01:23 NULL NULL NULL NULL ENABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci +TRUNCATE mysql.event; +SHOW EVENTS; +Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation +# # End of 5.1 tests # diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 163bbb4aab4..3be5aa374b4 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -6546,4 +6546,26 @@ DROP VIEW v1; DROP FUNCTION f1; DROP FUNCTION f2; DROP TABLE t1; +create function f1() +returns int(11) +not deterministic +contains sql +sql security definer +comment '' +begin +declare x int(11); +set x=-1; +return x; +end| +create view v1 as select 1 as one, f1() as days; +show create view test.v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `test`.`v1` AS select 1 AS `one`,`f1`() AS `days` latin1 latin1_swedish_ci +select column_name from information_schema.columns +where table_name='v1' and table_schema='test'; +column_name +one +days +drop view v1; +drop function f1; End of 5.0 tests diff --git a/mysql-test/r/status.result b/mysql-test/r/status.result index 8a2c3ae344e..db75044ee5d 100644 --- a/mysql-test/r/status.result +++ b/mysql-test/r/status.result @@ -87,6 +87,54 @@ SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME LIKE 'max_us VARIABLE_NAME VARIABLE_VALUE MAX_USED_CONNECTIONS 4 SET GLOBAL thread_cache_size=@save_thread_cache_size; +CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES (1), (2); +SELECT a FROM t1 LIMIT 1; +a +1 +SHOW SESSION STATUS LIKE 'Last_query_cost'; +Variable_name Value +Last_query_cost 2.402418 +EXPLAIN SELECT a FROM t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 +SHOW SESSION STATUS LIKE 'Last_query_cost'; +Variable_name Value +Last_query_cost 2.402418 +SELECT a FROM t1 UNION SELECT a FROM t1 ORDER BY a; +a +1 +2 +SHOW SESSION STATUS LIKE 'Last_query_cost'; +Variable_name Value +Last_query_cost 0.000000 +EXPLAIN SELECT a FROM t1 UNION SELECT a FROM t1 ORDER BY a; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 +2 UNION t1 ALL NULL NULL NULL NULL 2 +NULL UNION RESULT ALL NULL NULL NULL NULL NULL Using filesort +SHOW SESSION STATUS LIKE 'Last_query_cost'; +Variable_name Value +Last_query_cost 0.000000 +SELECT a IN (SELECT a FROM t1) FROM t1 LIMIT 1; +a IN (SELECT a FROM t1) +1 +SHOW SESSION STATUS LIKE 'Last_query_cost'; +Variable_name Value +Last_query_cost 0.000000 +SELECT (SELECT a FROM t1 LIMIT 1) x FROM t1 LIMIT 1; +x +1 +SHOW SESSION STATUS LIKE 'Last_query_cost'; +Variable_name Value +Last_query_cost 0.000000 +SELECT * FROM t1 a, t1 b LIMIT 1; +a a +1 1 +SHOW SESSION STATUS LIKE 'Last_query_cost'; +Variable_name Value +Last_query_cost 4.805836 +DROP TABLE t1; show status like 'com_show_status'; Variable_name Value Com_show_status 3 diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result index e6641cab7f6..559fde80c12 100644 --- a/mysql-test/r/type_bit.result +++ b/mysql-test/r/type_bit.result @@ -642,6 +642,21 @@ b+0 COUNT(DISTINCT a) 1 1 3 2 DROP TABLE t1; +CREATE TABLE t1 (b BIT); +INSERT INTO t1 (b) VALUES (1), (0); +SELECT DISTINCT b FROM t1; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def test t1 t1 b b 16 1 1 Y 32 0 63 +b +# +# +SELECT b FROM t1 GROUP BY b; +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def test t1 t1 b b 16 1 1 Y 32 0 63 +b +# +# +DROP TABLE t1; End of 5.0 tests create table t1(a bit(7)); insert into t1 values(0x40); diff --git a/mysql-test/suite/rpl/r/rpl_row_unsafe_funcs.result b/mysql-test/suite/rpl/r/rpl_row_unsafe_funcs.result new file mode 100644 index 00000000000..800670b78ae --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_row_unsafe_funcs.result @@ -0,0 +1,22 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (a INT, b INT); +INSERT INTO t1 SELECT 1; +INSERT INTO t1 VALUES (2),(3),(4),(5),(6); +INSERT INTO t2 SELECT 1, ROW_COUNT(); +INSERT INTO t1 VALUES (2),(3),(4); +INSERT INTO t2 SELECT 2, ROW_COUNT(); +SELECT b FROM t2 ORDER BY a; +b +1 +3 +SELECT b FROM t2 ORDER BY a; +b +1 +3 +DROP TABLE t1, t2; diff --git a/mysql-test/suite/rpl/t/rpl_row_unsafe_funcs.test b/mysql-test/suite/rpl/t/rpl_row_unsafe_funcs.test new file mode 100644 index 00000000000..069700546ce --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_unsafe_funcs.test @@ -0,0 +1,35 @@ +source include/master-slave.inc; +source include/have_binlog_format_mixed.inc; + +# +# Bug #30244: row_count/found_rows does not replicate well +# + +connection master; + +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (a INT, b INT); + +INSERT INTO t1 SELECT 1; + +connection master1; +INSERT INTO t1 VALUES (2),(3),(4),(5),(6); + +connection master; +INSERT INTO t2 SELECT 1, ROW_COUNT(); + +INSERT INTO t1 VALUES (2),(3),(4); +INSERT INTO t2 SELECT 2, ROW_COUNT(); + +#must return 1 and 3 +SELECT b FROM t2 ORDER BY a; + +sync_slave_with_master; + +#must return 1 and 3 +SELECT b FROM t2 ORDER BY a; + +connection master; +DROP TABLE t1, t2; +sync_slave_with_master; +connection master; diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test index 36d627209db..e3713d248c4 100644 --- a/mysql-test/t/delete.test +++ b/mysql-test/t/delete.test @@ -221,3 +221,47 @@ DELETE FROM t1 ORDER BY t2.x; DELETE FROM t1 ORDER BY (SELECT x); DROP TABLE t1; + +# +# Bug #30234: Unexpected behavior using DELETE with AS and USING +# ' +CREATE TABLE t1 ( + a INT +); + +CREATE TABLE t2 ( + a INT +); + +CREATE DATABASE db1; +CREATE TABLE db1.t1 ( + a INT +); +INSERT INTO db1.t1 (a) SELECT * FROM t1; + +CREATE DATABASE db2; +CREATE TABLE db2.t1 ( + a INT +); +INSERT INTO db2.t1 (a) SELECT * FROM t2; + +--error ER_PARSE_ERROR +DELETE FROM t1 alias USING t1, t2 alias WHERE t1.a = alias.a; +DELETE FROM alias USING t1, t2 alias WHERE t1.a = alias.a; +DELETE FROM t1, alias USING t1, t2 alias WHERE t1.a = alias.a; +--error ER_UNKNOWN_TABLE +DELETE FROM t1, t2 USING t1, t2 alias WHERE t1.a = alias.a; +--error ER_PARSE_ERROR +DELETE FROM db1.t1 alias USING db1.t1, db2.t1 alias WHERE db1.t1.a = alias.a; +--error ER_UNKNOWN_TABLE +DELETE FROM alias USING db1.t1, db2.t1 alias WHERE db1.t1.a = alias.a; +DELETE FROM db2.alias USING db1.t1, db2.t1 alias WHERE db1.t1.a = alias.a; +DELETE FROM t1 USING t1 WHERE a = 1; +SELECT * FROM t1; +--error ER_PARSE_ERROR +DELETE FROM t1 alias USING t1 alias WHERE a = 2; +SELECT * FROM t1; + +DROP TABLE t1, t2; +DROP DATABASE db1; +DROP DATABASE db2; diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 5db110e8d36..ae616df0dfd 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -828,6 +828,11 @@ EXPLAIN SELECT a FROM t1 USE INDEX (i2) USE INDEX (); EXPLAIN SELECT a FROM t1 FORCE INDEX (); --error ER_PARSE_ERROR EXPLAIN SELECT a FROM t1 IGNORE INDEX (); +# disable the columns irrelevant to this test here. On some systems +# without support for large files the rowid is shorter and its size affects +# the cost calculations. This causes the optimizer to choose loose index +# scan over normal index access. +--replace_column 4 # 7 # 9 # 10 # EXPLAIN SELECT a FROM t1 USE INDEX FOR JOIN (i2) USE INDEX FOR GROUP BY (i2) GROUP BY a; EXPLAIN SELECT a FROM t1 FORCE INDEX FOR JOIN (i2) @@ -861,3 +866,47 @@ SHOW VARIABLES LIKE 'old'; SET @@old = off; DROP TABLE t1, t2; + +# +# Bug#30596: GROUP BY optimization gives wrong result order +# +CREATE TABLE t1( + a INT, + b INT NOT NULL, + c INT NOT NULL, + d INT, + UNIQUE KEY (c,b) +); + +INSERT INTO t1 VALUES (1,1,1,50), (1,2,3,40), (2,1,3,4); + +CREATE TABLE t2( + a INT, + b INT, + UNIQUE KEY(a,b) +); + +INSERT INTO t2 VALUES (NULL, NULL), (NULL, NULL), (NULL, 1), (1, NULL), (1, 1), (1,2); + +EXPLAIN SELECT c,b,d FROM t1 GROUP BY c,b,d; +SELECT c,b,d FROM t1 GROUP BY c,b,d; +EXPLAIN SELECT c,b,d FROM t1 GROUP BY c,b,d ORDER BY NULL; +SELECT c,b,d FROM t1 GROUP BY c,b,d ORDER BY NULL; +EXPLAIN SELECT c,b,d FROM t1 ORDER BY c,b,d; +SELECT c,b,d FROM t1 ORDER BY c,b,d; + +EXPLAIN SELECT c,b,d FROM t1 GROUP BY c,b; +SELECT c,b,d FROM t1 GROUP BY c,b; +EXPLAIN SELECT c,b FROM t1 GROUP BY c,b; +SELECT c,b FROM t1 GROUP BY c,b; + +EXPLAIN SELECT a,b from t2 ORDER BY a,b; +SELECT a,b from t2 ORDER BY a,b; +EXPLAIN SELECT a,b from t2 GROUP BY a,b; +SELECT a,b from t2 GROUP BY a,b; +EXPLAIN SELECT a from t2 GROUP BY a; +SELECT a from t2 GROUP BY a; +EXPLAIN SELECT b from t2 GROUP BY b; +SELECT b from t2 GROUP BY b; + +DROP TABLE t1; diff --git a/mysql-test/t/mysqldump-compat.opt b/mysql-test/t/mysqldump-compat.opt new file mode 100644 index 00000000000..40d4ac738a6 --- /dev/null +++ b/mysql-test/t/mysqldump-compat.opt @@ -0,0 +1 @@ +--loose-debug=d,4x_server_emul diff --git a/mysql-test/t/mysqldump-compat.test b/mysql-test/t/mysqldump-compat.test new file mode 100644 index 00000000000..848d66cc728 --- /dev/null +++ b/mysql-test/t/mysqldump-compat.test @@ -0,0 +1,13 @@ +# Embedded server doesn't support external clients +--source include/not_embedded.inc + +# +# Bug #30126: semicolon before closing */ in /*!... CREATE DATABASE ;*/ +# + +CREATE DATABASE mysqldump_30126; +USE mysqldump_30126; +CREATE TABLE t1 (c1 int); +--exec $MYSQL_DUMP --add-drop-database mysqldump_30126 > $MYSQLTEST_VARDIR/tmp/bug30126.sql +--exec $MYSQL mysqldump_30126 < $MYSQLTEST_VARDIR/tmp/bug30126.sql +DROP DATABASE mysqldump_30126; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 171434f9dfd..0440b0fb63a 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -1755,6 +1755,22 @@ DROP DATABASE mysqldump_test_db; ########################################################################### +--echo # +--echo # BUG#29938: wrong behavior of mysqldump --skip-events +--echo # with --all-databases +--echo # + +TRUNCATE mysql.event; + +USE test; +CREATE event e29938 ON SCHEDULE AT '2035-12-31 20:01:23' DO SET @bug29938=29938; +SHOW EVENTS; +--exec $MYSQL_DUMP --skip-events --all-databases > $MYSQLTEST_VARDIR/tmp/bug29938.sql + +TRUNCATE mysql.event; +--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug29938.sql +SHOW EVENTS; + --echo # --echo # End of 5.1 tests --echo # diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 46ef6bc6ddd..952fdb58659 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -7494,4 +7494,37 @@ DROP FUNCTION f1; DROP FUNCTION f2; DROP TABLE t1; +# +# Bug#29408 Cannot find view in columns table if the selection contains a function +# +delimiter |; + +create function f1() + returns int(11) +not deterministic +contains sql +sql security definer +comment '' +begin + declare x int(11); + set x=-1; + return x; +end| + +delimiter ;| + +create view v1 as select 1 as one, f1() as days; + +connect (bug29408, localhost, root,,*NO-ONE*); +connection bug29408; + +show create view test.v1; +select column_name from information_schema.columns +where table_name='v1' and table_schema='test'; + +connection default; +disconnect bug29408; +drop view v1; +drop function f1; + --echo End of 5.0 tests diff --git a/mysql-test/t/status.test b/mysql-test/t/status.test index 7fd995e70c7..1cd5aa1726a 100644 --- a/mysql-test/t/status.test +++ b/mysql-test/t/status.test @@ -186,6 +186,38 @@ disconnect con3; disconnect con2; disconnect con1; + +# +# Bug #30377: EXPLAIN loses last_query_cost when used with UNION +# + +CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES (1), (2); + +SELECT a FROM t1 LIMIT 1; +SHOW SESSION STATUS LIKE 'Last_query_cost'; + +EXPLAIN SELECT a FROM t1; +SHOW SESSION STATUS LIKE 'Last_query_cost'; + +SELECT a FROM t1 UNION SELECT a FROM t1 ORDER BY a; +SHOW SESSION STATUS LIKE 'Last_query_cost'; + +EXPLAIN SELECT a FROM t1 UNION SELECT a FROM t1 ORDER BY a; +SHOW SESSION STATUS LIKE 'Last_query_cost'; + +SELECT a IN (SELECT a FROM t1) FROM t1 LIMIT 1; +SHOW SESSION STATUS LIKE 'Last_query_cost'; + +SELECT (SELECT a FROM t1 LIMIT 1) x FROM t1 LIMIT 1; +SHOW SESSION STATUS LIKE 'Last_query_cost'; + +SELECT * FROM t1 a, t1 b LIMIT 1; +SHOW SESSION STATUS LIKE 'Last_query_cost'; + +DROP TABLE t1; + + # End of 5.0 tests # diff --git a/mysql-test/t/type_bit.test b/mysql-test/t/type_bit.test index f51b2c1d612..2a6e36011a6 100644 --- a/mysql-test/t/type_bit.test +++ b/mysql-test/t/type_bit.test @@ -291,6 +291,19 @@ INSERT INTO t1 (b, a) VALUES (1, 1), (3, 2), (0, 3), (3, 4); SELECT b+0, COUNT(DISTINCT a) FROM t1 GROUP BY b; DROP TABLE t1; +# +# Bug#30245: A wrong type of a BIT field is reported when grouped by it. +# +CREATE TABLE t1 (b BIT); +INSERT INTO t1 (b) VALUES (1), (0); +--enable_metadata +--replace_column 1 # +SELECT DISTINCT b FROM t1; +--replace_column 1 # +SELECT b FROM t1 GROUP BY b; +--disable_metadata +DROP TABLE t1; + --echo End of 5.0 tests # diff --git a/mysys/my_init.c b/mysys/my_init.c index 257edb351b4..b2eefe97ee8 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -78,6 +78,9 @@ my_bool my_init(void) my_umask_dir= 0700; /* Default umask for new directories */ #if defined(THREAD) && defined(SAFE_MUTEX) safe_mutex_global_init(); /* Must be called early */ +#endif +#if defined(THREAD) && defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX) + fastmutex_global_init(); /* Must be called early */ #endif netware_init(); #ifdef THREAD diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c index 007bae2accf..e7a927e562a 100644 --- a/mysys/thr_mutex.c +++ b/mysys/thr_mutex.c @@ -394,15 +394,11 @@ ulong mutex_delay(ulong delayloops) #define MY_PTHREAD_FASTMUTEX_SPINS 8 #define MY_PTHREAD_FASTMUTEX_DELAY 4 +static int cpu_count= 0; + int my_pthread_fastmutex_init(my_pthread_fastmutex_t *mp, const pthread_mutexattr_t *attr) { - static int cpu_count= 0; -#ifdef _SC_NPROCESSORS_CONF - if (!cpu_count && (attr == MY_MUTEX_INIT_FAST)) - cpu_count= sysconf(_SC_NPROCESSORS_CONF); -#endif - if ((cpu_count > 1) && (attr == MY_MUTEX_INIT_FAST)) mp->spins= MY_PTHREAD_FASTMUTEX_SPINS; else @@ -432,4 +428,13 @@ int my_pthread_fastmutex_lock(my_pthread_fastmutex_t *mp) } return pthread_mutex_lock(&mp->mutex); } + + +void fastmutex_global_init(void) +{ +#ifdef _SC_NPROCESSORS_CONF + cpu_count= sysconf(_SC_NPROCESSORS_CONF); +#endif +} + #endif /* defined(THREAD) && defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX) */ diff --git a/sql/item_create.cc b/sql/item_create.cc index 03424da80a8..12b795e79a1 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -3339,6 +3339,7 @@ Create_func_found_rows Create_func_found_rows::s_singleton; Item* Create_func_found_rows::create(THD *thd) { + thd->lex->set_stmt_unsafe(); thd->lex->safe_to_cache_query= 0; return new (thd->mem_root) Item_func_found_rows(); } @@ -4234,6 +4235,7 @@ Create_func_row_count Create_func_row_count::s_singleton; Item* Create_func_row_count::create(THD *thd) { + thd->lex->set_stmt_unsafe(); thd->lex->safe_to_cache_query= 0; return new (thd->mem_root) Item_func_row_count(); } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 057d59d3ccf..d8549be44c7 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1799,6 +1799,28 @@ typedef struct st_lex : public Query_tables_list bool table_or_sp_used(); bool is_partition_management() const; + + /** + @brief check if the statement is a single-level join + @return result of the check + @retval TRUE The statement doesn't contain subqueries, unions and + stored procedure calls. + @retval FALSE There are subqueries, UNIONs or stored procedure calls. + */ + bool is_single_level_stmt() + { + /* + This check exploits the fact that the last added to all_select_list is + on its top. So select_lex (as the first added) will be at the tail + of the list. + */ + if (&select_lex == all_selects_list && !sroutines.records) + { + DBUG_ASSERT(!all_selects_list->next_select_in_list()); + return TRUE; + } + return FALSE; + } } LEX; struct st_lex_local: public st_lex diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2e4ce65f1c4..1b6e179aa09 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1003,14 +1003,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* Locked closure of all tables */ TABLE_LIST table_list; LEX_STRING conv_name; - size_t dummy; /* used as fields initializator */ lex_start(thd); status_var_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS]); bzero((char*) &table_list,sizeof(table_list)); - if (thd->copy_db_to(&table_list.db, &dummy)) + if (thd->copy_db_to(&table_list.db, &table_list.db_length)) break; /* We have name + wildcard in packet, separated by endzero @@ -1732,8 +1731,7 @@ mysql_execute_command(THD *thd) variables, but for now this is probably good enough. Don't reset warnings when executing a stored routine. */ - if ((all_tables || &lex->select_lex != lex->all_selects_list || - lex->sroutines.records) && !thd->spcont) + if ((all_tables || !lex->is_single_level_stmt()) && !thd->spcont) mysql_reset_errors(thd, 0); #ifdef HAVE_REPLICATION @@ -3260,6 +3258,8 @@ end_with_restore_list: } case SQLCOM_SHOW_CREATE_DB: { + DBUG_EXECUTE_IF("4x_server_emul", + my_error(ER_UNKNOWN_ERROR, MYF(0)); goto error;); if (check_db_name(&lex->name)) { my_error(ER_WRONG_DB_NAME, MYF(0), lex->name.str); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index fd3be1aef08..b903e7ae13c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -195,6 +195,7 @@ static bool setup_new_fields(THD *thd, List &fields, List &all_fields, ORDER *new_order); static ORDER *create_distinct_group(THD *thd, Item **ref_pointer_array, ORDER *order, List &fields, + List &all_fields, bool *all_order_by_fields_used); static bool test_if_subpart(ORDER *a,ORDER *b); static TABLE *get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables); @@ -543,6 +544,28 @@ JOIN::prepare(Item ***rref_pointer_array, fix_inner_refs(thd, all_fields, select_lex, ref_pointer_array)) DBUG_RETURN(-1); + if (group_list) + { + /* + Because HEAP tables can't index BIT fields we need to use an + additional hidden field for grouping because later it will be + converted to a LONG field. Original field will remain of the + BIT type and will be returned to a client. + */ + for (ORDER *ord= group_list; ord; ord= ord->next) + { + if ((*ord->item)->type() == Item::FIELD_ITEM && + (*ord->item)->field_type() == MYSQL_TYPE_BIT) + { + Item_field *field= new Item_field(thd, *(Item_field**)ord->item); + int el= all_fields.elements; + ref_pointer_array[el]= field; + all_fields.push_front(field); + ord->item= ref_pointer_array + el; + } + } + } + if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */ DBUG_RETURN(-1); @@ -1046,6 +1069,20 @@ JOIN::optimize() find_field_in_order_list, (void *) group_list)) { + /* + We have found that grouping can be removed since groups correspond to + only one row anyway, but we still have to guarantee correct result + order. The line below effectively rewrites the query from GROUP BY + to ORDER BY . One exception is if skip_sort_order is + set (see above), then we can simply skip GROUP BY. + */ + order= skip_sort_order ? 0 : group_list; + /* + If we have an IGNORE INDEX FOR GROUP BY(fields) clause, this must be + rewritten to IGNORE INDEX FOR ORDER BY(fields). + */ + join_tab->table->keys_in_use_for_order_by= + join_tab->table->keys_in_use_for_group_by; group_list= 0; group= 0; } @@ -1085,12 +1122,13 @@ JOIN::optimize() skip_sort_order= test_if_skip_sort_order(tab, order, select_limit, 1, &tab->table->keys_in_use_for_order_by); if ((group_list=create_distinct_group(thd, select_lex->ref_pointer_array, - order, fields_list, + order, fields_list, all_fields, &all_order_fields_used))) { bool skip_group= (skip_sort_order && test_if_skip_sort_order(tab, group_list, select_limit, 1, &tab->table->keys_in_use_for_group_by) != 0); + count_field_types(select_lex, &tmp_table_param, all_fields, 0); if ((skip_group && all_order_fields_used) || select_limit == HA_POS_ERROR || (order && !skip_sort_order)) @@ -4467,8 +4505,12 @@ choose_plan(JOIN *join, table_map join_tables) /* Store the cost of this query into a user variable + Don't update last_query_cost for statements that are not "flat joins" : + i.e. they have subqueries, unions or call stored procedures. + TODO: calculate a correct cost for a query with subqueries and UNIONs. */ - join->thd->status_var.last_query_cost= join->best_read; + if (join->thd->lex->is_single_level_stmt()) + join->thd->status_var.last_query_cost= join->best_read; DBUG_RETURN(FALSE); } @@ -14092,11 +14134,12 @@ setup_new_fields(THD *thd, List &fields, static ORDER * create_distinct_group(THD *thd, Item **ref_pointer_array, - ORDER *order_list, List &fields, + ORDER *order_list, List &fields, + List &all_fields, bool *all_order_by_fields_used) { List_iterator li(fields); - Item *item; + Item *item, **orig_ref_pointer_array= ref_pointer_array; ORDER *order,*group,**prev; *all_order_by_fields_used= 1; @@ -14136,12 +14179,31 @@ create_distinct_group(THD *thd, Item **ref_pointer_array, ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER)); if (!ord) return 0; - /* - We have here only field_list (not all_field_list), so we can use - simple indexing of ref_pointer_array (order in the array and in the - list are same) - */ - ord->item= ref_pointer_array; + + if (item->type() == Item::FIELD_ITEM && + item->field_type() == MYSQL_TYPE_BIT) + { + /* + Because HEAP tables can't index BIT fields we need to use an + additional hidden field for grouping because later it will be + converted to a LONG field. Original field will remain of the + BIT type and will be returned to a client. + */ + Item_field *new_item= new Item_field(thd, (Item_field*)item); + int el= all_fields.elements; + orig_ref_pointer_array[el]= new_item; + all_fields.push_front(new_item); + ord->item= orig_ref_pointer_array + el; + } + else + { + /* + We have here only field_list (not all_field_list), so we can use + simple indexing of ref_pointer_array (order in the array and in the + list are same) + */ + ord->item= ref_pointer_array; + } ord->asc=1; *prev=ord; prev= &ord->next; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 38d7174b7ca..b444992f4e9 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1044,10 +1044,20 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, table->view= lex= thd->lex= (LEX*) new(thd->mem_root) st_lex_local; { + char old_db_buf[NAME_LEN+1]; + LEX_STRING old_db= { old_db_buf, sizeof(old_db_buf) }; + bool dbchanged; Lex_input_stream lip(thd, table->select_stmt.str, table->select_stmt.length); + /* + Use view db name as thread default database, in order to ensure + that the view is parsed and prepared correctly. + */ + if ((result= sp_use_new_db(thd, table->view_db, &old_db, 1, &dbchanged))) + goto end; + lex_start(thd); view_select= &lex->select_lex; view_select->select_number= ++thd->select_number; @@ -1091,6 +1101,9 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, lex->sql_command= old_lex->sql_command; thd->variables.sql_mode= saved_mode; + + if (dbchanged && mysql_change_db(thd, &old_db, TRUE)) + goto err; } if (!parse_status) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2d6baf5b846..4e96ab13347 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1251,7 +1251,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); field_opt_list opt_binary table_lock_list table_lock ref_list opt_on_delete opt_on_delete_list opt_on_delete_item use opt_delete_options opt_delete_option varchar nchar nvarchar - opt_outer table_list table_name opt_option opt_place + opt_outer table_list table_name table_alias_ref_list table_alias_ref + opt_option opt_place opt_attribute opt_attribute_list attribute column_list column_list_id opt_column_list grant_privileges grant_ident grant_list grant_option object_privilege object_privilege_list user_list rename_list @@ -8610,6 +8611,20 @@ table_name: } ; +table_alias_ref_list: + table_alias_ref + | table_alias_ref_list ',' table_alias_ref; + +table_alias_ref: + table_ident + { + if (!Select->add_table_to_list(YYTHD, $1, NULL, + TL_OPTION_UPDATING | TL_OPTION_ALIAS, + Lex->lock_option )) + MYSQL_YYABORT; + } + ; + if_exists: /* empty */ { $$= 0; } | IF EXISTS { $$= 1; } @@ -8899,7 +8914,7 @@ single_multi: if (multi_delete_set_locks_and_link_aux_tables(Lex)) MYSQL_YYABORT; } - | FROM table_wild_list + | FROM table_alias_ref_list { mysql_init_multi_delete(Lex); } USING join_table_list where_clause {