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..5084498c01c 100644 --- a/mysql-test/r/delete.result +++ b/mysql-test/r/delete.result @@ -183,6 +183,17 @@ select @a; @a 1 drop table t1; +CREATE TABLE t1 ( +`date` date , +`time` time , +`seq` int(10) unsigned NOT NULL auto_increment, +PRIMARY KEY (`seq`), +KEY `seq` (`seq`), +KEY `time` (`time`), +KEY `date` (`date`) +); +DELETE FROM t1 ORDER BY date ASC, time ASC LIMIT 1; +drop table t1; End of 4.1 tests CREATE TABLE t1 (a int not null,b int not null); CREATE TABLE t2 (a int not null, b int not null, primary key (a,b)); @@ -223,3 +234,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/partition_pruning.result b/mysql-test/r/partition_pruning.result index 776e6f3a15a..9595676016c 100644 --- a/mysql-test/r/partition_pruning.result +++ b/mysql-test/r/partition_pruning.result @@ -631,7 +631,7 @@ flush status; delete from t2 where b > 5; show status like 'Handler_read_rnd_next'; Variable_name Value -Handler_read_rnd_next 1115 +Handler_read_rnd_next 1215 show status like 'Handler_read_key'; Variable_name Value Handler_read_key 0 @@ -645,7 +645,7 @@ flush status; delete from t2 where b < 5 or b > 3; show status like 'Handler_read_rnd_next'; Variable_name Value -Handler_read_rnd_next 1115 +Handler_read_rnd_next 1215 show status like 'Handler_read_key'; Variable_name Value Handler_read_key 0 diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index fd09701c125..6c0bc930a8e 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -6546,6 +6546,28 @@ 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; # Bug#13675. 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..8a03cb6c715 100644 --- a/mysql-test/t/delete.test +++ b/mysql-test/t/delete.test @@ -173,8 +173,20 @@ delete from t1 where (@a:= f1) order by f1 limit 1; select @a; drop table t1; +# BUG#30385 "Server crash when deleting with order by and limit" +CREATE TABLE t1 ( + `date` date , + `time` time , + `seq` int(10) unsigned NOT NULL auto_increment, + PRIMARY KEY (`seq`), + KEY `seq` (`seq`), + KEY `time` (`time`), + KEY `date` (`date`) +); +DELETE FROM t1 ORDER BY date ASC, time ASC LIMIT 1; +drop table t1; + --echo End of 4.1 tests -# End of 4.1 tests # # Test of multi-delete where we are not scanning the first table @@ -221,3 +233,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 27e559f4463..4e4102dd1ef 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -7494,6 +7494,39 @@ 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; + # # Bug#13675: DATETIME/DATE type in store proc param seems to be converted as # varbinary 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/ha_partition.cc b/sql/ha_partition.cc index 42cbaa1cdb0..ac105855c02 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3235,14 +3235,9 @@ end_dont_reset_start_part: void ha_partition::position(const uchar *record) { - handler *file; + handler *file= m_file[m_last_part]; DBUG_ENTER("ha_partition::position"); - if (unlikely(get_part_for_delete(record, m_rec0, m_part_info, &m_last_part))) - m_last_part= 0; - - file= m_file[m_last_part]; - file->position(record); int2store(ref, m_last_part); memcpy((ref + PARTITION_BYTES_IN_POS), file->ref, @@ -3300,6 +3295,36 @@ int ha_partition::rnd_pos(uchar * buf, uchar *pos) } +/* + Read row using position using given record to find + + SYNOPSIS + rnd_pos_by_record() + record Current record in MySQL Row Format + + RETURN VALUE + >0 Error code + 0 Success + + DESCRIPTION + this works as position()+rnd_pos() functions, but does some extra work, + calculating m_last_part - the partition to where the 'record' + should go. + + called from replication (log_event.cc) +*/ + +int ha_partition::rnd_pos_by_record(uchar *record) +{ + DBUG_ENTER("ha_partition::rnd_pos_by_record"); + + if (unlikely(get_part_for_delete(record, m_rec0, m_part_info, &m_last_part))) + DBUG_RETURN(1); + + DBUG_RETURN(handler::rnd_pos_by_record(record)); +} + + /**************************************************************************** MODULE index scan ****************************************************************************/ diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 434d90a4487..8fe512fadb3 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -353,6 +353,7 @@ public: virtual int rnd_end(); virtual int rnd_next(uchar * buf); virtual int rnd_pos(uchar * buf, uchar * pos); + virtual int rnd_pos_by_record(uchar *record); virtual void position(const uchar * record); /* diff --git a/sql/handler.h b/sql/handler.h index 557b9fd7887..b91d8a39b88 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1343,6 +1343,17 @@ public: virtual int ft_read(uchar *buf) { return HA_ERR_WRONG_COMMAND; } virtual int rnd_next(uchar *buf)=0; virtual int rnd_pos(uchar * buf, uchar *pos)=0; + /* + one has to use this method when to find + random position by record as the plain + position() call doesn't work for some + handlers for random position + */ + virtual int rnd_pos_by_record(uchar *record) + { + position(record); + return rnd_pos(record, ref); + } virtual int read_first_row(uchar *buf, uint primary_key); /* The following function is only needed for tables that may be temporary 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/log_event.cc b/sql/log_event.cc index 44898ca8639..9094a7c38b2 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -7501,8 +7501,7 @@ int Rows_log_event::find_row(const Relay_log_info *rli) */ DBUG_PRINT("info",("locating record using primary key (position)")); - table->file->position(table->record[0]); - error= table->file->rnd_pos(table->record[0], table->file->ref); + int error= table->file->rnd_pos_by_record(table->record[0]); if (error) { DBUG_PRINT("info",("rnd_pos returns error %d",error)); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index c027ce20e89..7bb5ba831ab 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1778,6 +1778,7 @@ uint get_index_for_order(TABLE *table, ORDER *order, ha_rows limit) if (!(table->keys_in_use_for_query.is_set(idx))) continue; KEY_PART_INFO *keyinfo= table->key_info[idx].key_part; + uint n_parts= table->key_info[idx].key_parts; uint partno= 0; /* @@ -1787,7 +1788,7 @@ uint get_index_for_order(TABLE *table, ORDER *order, ha_rows limit) */ if (!(table->file->index_flags(idx, 0, 1) & HA_READ_ORDER)) continue; - for (ord= order; ord; ord= ord->next, partno++) + for (ord= order; ord && partno < n_parts; ord= ord->next, partno++) { Item *item= order->item[0]; if (!(item->type() == Item::FIELD_ITEM && diff --git a/sql/sql_lex.h b/sql/sql_lex.h index da0134a7f72..08104769704 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1798,6 +1798,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 bbd6cb16d11..ae347bebb47 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 efd8c20e6d7..68680addc58 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1253,7 +1253,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 @@ -8656,6 +8657,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; } @@ -8945,7 +8960,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 {