diff --git a/mysql-test/include/wait_show_pattern.inc b/mysql-test/include/wait_show_pattern.inc new file mode 100644 index 00000000000..c9f84ce7f08 --- /dev/null +++ b/mysql-test/include/wait_show_pattern.inc @@ -0,0 +1,51 @@ +# include/wait_show_pattern.inc +# +# SUMMARY +# +# Waits until output produced by SHOW statement which particular type is +# specified as parameter matches certain pattern or maximum time reached. +# +# NOTES +# +# Only the first row produced by the parameter statement is checked. +# +# USAGE +# +# let $show_type= ; +# let $show_pattern= 'Pattern to be used for LIKE matching'; +# --source wait_show_pattern.inc +# +# EXAMPLES +# +# alter_table-big.test, wait_slave_status.inc +# +# SEE ALSO +# +# wait_slave_status.inc, wait_condition.inc (>=5.1) +# +############################################################################### + +--disable_query_log + +# We accept to wait maximum 30 seconds (0.2 sec/loop). +let $wait_counter= 150; +while ($wait_counter) +{ + let $result= `SHOW $show_type`; + let $success= `SELECT '$result' LIKE $show_pattern`; + if ($success) + { + let $wait_counter= 0; + } + if (!$success) + { + real_sleep 0.2; + dec $wait_counter; + } +} +if (!$success) +{ + echo Timeout in wait_show_pattern.inc \$show_type= $show_type \$show_pattern= $show_pattern (\$result= '$result'); +} + +--enable_query_log diff --git a/mysql-test/include/wait_slave_status.inc b/mysql-test/include/wait_slave_status.inc index 7d3636e673c..d8d048527cf 100644 --- a/mysql-test/include/wait_slave_status.inc +++ b/mysql-test/include/wait_slave_status.inc @@ -104,50 +104,21 @@ eval SELECT "let \$result_pattern= $result_pattern ;" AS ""; SELECT '--source include/wait_slave_status.inc' AS ""; -# We accept to wait maximum 30 seconds (0.2 sec/loop). -let $max_wait= 150; -while ($max_wait) -{ - let $my_val= `SHOW SLAVE STATUS`; - # Now we have the first record of the SHOW result set as one fat string - # within the variable $my_val. - - eval SET @my_val = '$my_val'; - # DEBUG eval SELECT @my_val AS "response to SHOW SLAVE STATUS"; - - eval SELECT @my_val LIKE $result_pattern INTO @success; - # @success is '1' if we have a match - # '0' if we have no match - # DEBUG SELECT @success; - - let $success= `SELECT @success`; - let $no_success= `SELECT @success = 0`; - if ($success) - { - # We reached the expected result and want to jump out of the loop - # without unneeded sleeps. - # Attention: Do not set $max_wait to 0, because "while" with negative value - # does not work. - let $max_wait= 1; - } - if ($no_success) - { - # We did not reach the expected result and will have to sleep again - # or jump out of the loop, when max_wait is exhausted. - real_sleep 0.2; - } - dec $max_wait; -} +let $show_type= SLAVE STATUS; +let $show_pattern= $result_pattern; --enable_query_log -if ($no_success) + +--source include/wait_show_pattern.inc + +if (!$success) { let $message= ! Attention: Timeout in wait_slave_status.inc. | Possible reasons with decreasing probability: - | - The LIKE pattern ($result_pattern) is wrong, because the + | - The LIKE pattern is wrong, because the | testcase was altered or the layout of the | SHOW SLAVE STATUS result set changed. | - There is a new bug within the replication. - | - We met an extreme testing environment and $max_wait is + | - We met an extreme testing environment and timeout is | too small.; --source include/show_msg80.inc --echo DEBUG INFO START (wait_slave_status.inc): diff --git a/mysql-test/r/alter_table-big.result b/mysql-test/r/alter_table-big.result new file mode 100644 index 00000000000..873978c60de --- /dev/null +++ b/mysql-test/r/alter_table-big.result @@ -0,0 +1,18 @@ +drop table if exists t1, t2; +create table t1 (n1 int, n2 int, n3 int, +key (n1, n2, n3), +key (n2, n3, n1), +key (n3, n1, n2)); +create table t2 (i int); +alter table t1 disable keys; +reset master; +alter table t1 enable keys;; +insert into t2 values (1); +insert into t1 values (1, 1, 1); +show binlog events in 'master-bin.000001' from 98; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query 1 # use `test`; insert into t2 values (1) +master-bin.000001 # Query 1 # use `test`; alter table t1 enable keys +master-bin.000001 # Query 1 # use `test`; insert into t1 values (1, 1, 1) +drop tables t1, t2; +End of 5.0 tests diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 80ad50b886f..d8de2655c6c 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -703,6 +703,119 @@ SHOW INDEX FROM bug24219_2; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment bug24219_2 1 a 1 a A NULL NULL NULL YES BTREE disabled DROP TABLE bug24219_2; +drop table if exists table_24562; +create table table_24562( +section int, +subsection int, +title varchar(50)); +insert into table_24562 values +(1, 0, "Introduction"), +(1, 1, "Authors"), +(1, 2, "Acknowledgements"), +(2, 0, "Basics"), +(2, 1, "Syntax"), +(2, 2, "Client"), +(2, 3, "Server"), +(3, 0, "Intermediate"), +(3, 1, "Complex queries"), +(3, 2, "Stored Procedures"), +(3, 3, "Stored Functions"), +(4, 0, "Advanced"), +(4, 1, "Replication"), +(4, 2, "Load balancing"), +(4, 3, "High availability"), +(5, 0, "Conclusion"); +select * from table_24562; +section subsection title +1 0 Introduction +1 1 Authors +1 2 Acknowledgements +2 0 Basics +2 1 Syntax +2 2 Client +2 3 Server +3 0 Intermediate +3 1 Complex queries +3 2 Stored Procedures +3 3 Stored Functions +4 0 Advanced +4 1 Replication +4 2 Load balancing +4 3 High availability +5 0 Conclusion +alter table table_24562 add column reviewer varchar(20), +order by title; +select * from table_24562; +section subsection title reviewer +1 2 Acknowledgements NULL +4 0 Advanced NULL +1 1 Authors NULL +2 0 Basics NULL +2 2 Client NULL +3 1 Complex queries NULL +5 0 Conclusion NULL +4 3 High availability NULL +3 0 Intermediate NULL +1 0 Introduction NULL +4 2 Load balancing NULL +4 1 Replication NULL +2 3 Server NULL +3 3 Stored Functions NULL +3 2 Stored Procedures NULL +2 1 Syntax NULL +update table_24562 set reviewer="Me" where section=2; +update table_24562 set reviewer="You" where section=3; +alter table table_24562 +order by section ASC, subsection DESC; +select * from table_24562; +section subsection title reviewer +1 2 Acknowledgements NULL +1 1 Authors NULL +1 0 Introduction NULL +2 3 Server Me +2 2 Client Me +2 1 Syntax Me +2 0 Basics Me +3 3 Stored Functions You +3 2 Stored Procedures You +3 1 Complex queries You +3 0 Intermediate You +4 3 High availability NULL +4 2 Load balancing NULL +4 1 Replication NULL +4 0 Advanced NULL +5 0 Conclusion NULL +alter table table_24562 +order by table_24562.subsection ASC, table_24562.section DESC; +select * from table_24562; +section subsection title reviewer +5 0 Conclusion NULL +4 0 Advanced NULL +3 0 Intermediate You +2 0 Basics Me +1 0 Introduction NULL +4 1 Replication NULL +3 1 Complex queries You +2 1 Syntax Me +1 1 Authors NULL +4 2 Load balancing NULL +3 2 Stored Procedures You +2 2 Client Me +1 2 Acknowledgements NULL +4 3 High availability NULL +3 3 Stored Functions You +2 3 Server Me +alter table table_24562 order by 12; +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 '12' at line 1 +alter table table_24562 order by (section + 12); +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 '(section + 12)' at line 1 +alter table table_24562 order by length(title); +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 'length(title)' at line 1 +alter table table_24562 order by (select 12 from dual); +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 '(select 12 from dual)' at line 1 +alter table table_24562 order by no_such_col; +ERROR 42S22: Unknown column 'no_such_col' in 'order clause' +drop table table_24562; create table t1 (mycol int(10) not null); alter table t1 alter column mycol set default 0; desc t1; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 21d8ba05acc..20bff6bda1c 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1645,4 +1645,20 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM AUTO_INCREMENT=100 DEFAULT CHARSET=latin1 COMMENT='comment for table t1' deallocate prepare stmt; drop table t1, t2; +drop tables if exists t1; +create table t1 (id int primary key auto_increment, value varchar(10)); +insert into t1 (id, value) values (1, 'FIRST'), (2, 'SECOND'), (3, 'THIRD'); +prepare stmt from "insert into t1 (id, value) select * from (select 4 as i, 'FOURTH' as v) as y on duplicate key update v = 'DUP'"; +execute stmt; +ERROR 42S22: Unknown column 'v' in 'field list' +execute stmt; +ERROR 42S22: Unknown column 'v' in 'field list' +deallocate prepare stmt; +prepare stmt from "insert into t1 (id, value) select * from (select 4 as id, 'FOURTH' as value) as y on duplicate key update y.value = 'DUP'"; +execute stmt; +ERROR 42S22: Unknown column 'y.value' in 'field list' +execute stmt; +ERROR 42S22: Unknown column 'y.value' in 'field list' +deallocate prepare stmt; +drop tables t1; End of 5.0 tests. diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 63fd1bfff6d..e7e387f4348 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1250,3 +1250,22 @@ ERROR HY000: View's SELECT contains a variable or parameter PREPARE stmt FROM "CREATE VIEW v AS SELECT ?"; ERROR HY000: View's SELECT contains a variable or parameter DROP TABLE t1; +drop tables if exists t1; +drop procedure if exists bug24491; +create table t1 (id int primary key auto_increment, value varchar(10)); +insert into t1 (id, value) values (1, 'FIRST'), (2, 'SECOND'), (3, 'THIRD'); +create procedure bug24491() +insert into t1 (id, value) select * from (select 4 as i, 'FOURTH' as v) as y on duplicate key update v = 'DUP'; +call bug24491(); +ERROR 42S22: Unknown column 'v' in 'field list' +call bug24491(); +ERROR 42S22: Unknown column 'v' in 'field list' +drop procedure bug24491; +create procedure bug24491() +insert into t1 (id, value) select * from (select 4 as id, 'FOURTH' as value) as y on duplicate key update y.value = 'DUP'; +call bug24491(); +ERROR 42S22: Unknown column 'y.value' in 'field list' +call bug24491(); +ERROR 42S22: Unknown column 'y.value' in 'field list' +drop procedure bug24491; +drop tables t1; diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index a802d83e9a2..45cf5076fe1 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -731,3 +731,46 @@ SELECT * FROM v1; ERROR HY000: There is no 'def_17254'@'localhost' registered DROP USER inv_17254@localhost; DROP DATABASE db17254; +DROP DATABASE IF EXISTS mysqltest_db1; +DROP DATABASE IF EXISTS mysqltest_db2; +DROP USER mysqltest_u1; +DROP USER mysqltest_u2; +CREATE USER mysqltest_u1@localhost; +CREATE USER mysqltest_u2@localhost; +CREATE DATABASE mysqltest_db1; +CREATE DATABASE mysqltest_db2; +GRANT ALL ON mysqltest_db1.* TO mysqltest_u1@localhost WITH GRANT OPTION; +GRANT ALL ON mysqltest_db2.* TO mysqltest_u2@localhost; +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1); +CREATE VIEW v1 AS SELECT i FROM t1 WHERE 1 IN (SELECT * FROM t1); +CREATE TABLE t2 (s CHAR(7)); +INSERT INTO t2 VALUES ('public'); +GRANT SELECT ON v1 TO mysqltest_u2@localhost; +GRANT SELECT ON t2 TO mysqltest_u2@localhost; +SELECT * FROM mysqltest_db1.v1, mysqltest_db1.t2; +i s +1 public +PREPARE stmt1 FROM "SELECT * FROM mysqltest_db1.t2"; +EXECUTE stmt1; +s +public +PREPARE stmt2 FROM "SELECT * FROM mysqltest_db1.v1, mysqltest_db1.t2"; +EXECUTE stmt2; +i s +1 public +REVOKE SELECT ON t2 FROM mysqltest_u2@localhost; +UPDATE t2 SET s = 'private' WHERE s = 'public'; +SELECT * FROM mysqltest_db1.v1, mysqltest_db1.t2; +ERROR 42000: SELECT command denied to user 'mysqltest_u2'@'localhost' for table 't2' +EXECUTE stmt1; +ERROR 42000: SELECT command denied to user 'mysqltest_u2'@'localhost' for table 't2' +EXECUTE stmt2; +ERROR 42000: SELECT command denied to user 'mysqltest_u2'@'localhost' for table 't2' +REVOKE ALL ON mysqltest_db1.* FROM mysqltest_u1@localhost; +REVOKE ALL ON mysqltest_db2.* FROM mysqltest_u2@localhost; +DROP DATABASE mysqltest_db1; +DROP DATABASE mysqltest_db2; +DROP USER mysqltest_u1@localhost; +DROP USER mysqltest_u2@localhost; +End of 5.0 tests. diff --git a/mysql-test/t/alter_table-big.test b/mysql-test/t/alter_table-big.test new file mode 100644 index 00000000000..9a773f48a9c --- /dev/null +++ b/mysql-test/t/alter_table-big.test @@ -0,0 +1,62 @@ +# In order to be more or less robust test for bug#25044 has to take +# significant time (e.g. about 9 seconds on my (Dmitri's) computer) +# so we probably want execute it only in --big-test mode. +# Also in 5.1 this test will require statement-based binlog. +--source include/big_test.inc + + +# +# Test for bug #25044 "ALTER TABLE ... ENABLE KEYS acquires global +# 'opening tables' lock". +# +# ALTER TABLE ... ENABLE KEYS should not acquire LOCK_open mutex for +# the whole its duration as it prevents other queries from execution. +--disable_warnings +drop table if exists t1, t2; +--enable_warnings +connect (addconroot, localhost, root,,); +connection default; +create table t1 (n1 int, n2 int, n3 int, + key (n1, n2, n3), + key (n2, n3, n1), + key (n3, n1, n2)); +create table t2 (i int); + +# Populating 't1' table with keys disabled, so ALTER TABLE .. ENABLE KEYS +# will run for some time +alter table t1 disable keys; +--disable_query_log +insert into t1 values (RAND()*1000,RAND()*1000,RAND()*1000); +let $1=19; +while ($1) +{ + eval insert into t1 select RAND()*1000,RAND()*1000,RAND()*1000 from t1; + dec $1; +} +--enable_query_log + +# Later we use binlog to check the order in which statements are +# executed so let us reset it first. +reset master; +--send alter table t1 enable keys; +connection addconroot; +let $show_type= PROCESSLIST; +let $show_pattern= '%Repair by sorting%alter table t1 enable keys%'; +--source include/wait_show_pattern.inc +# This statement should not be blocked by in-flight ALTER and therefore +# should be executed and written to binlog before ALTER TABLE ... ENABLE KEYS +# finishes. +insert into t2 values (1); +# And this should wait until the end of ALTER TABLE ... ENABLE KEYS. +insert into t1 values (1, 1, 1); +connection default; +--reap +# Check that statements were executed/binlogged in correct order. +--replace_column 2 # 5 # +show binlog events in 'master-bin.000001' from 98; + +# Clean up +drop tables t1, t2; + + +--echo End of 5.0 tests diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index d2c9926c422..01f55931ca4 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -528,6 +528,71 @@ SHOW INDEX FROM bug24219_2; DROP TABLE bug24219_2; +# +# Bug#24562 (ALTER TABLE ... ORDER BY ... with complex expression asserts) +# + +--disable_warnings +drop table if exists table_24562; +--enable_warnings + +create table table_24562( + section int, + subsection int, + title varchar(50)); + +insert into table_24562 values +(1, 0, "Introduction"), +(1, 1, "Authors"), +(1, 2, "Acknowledgements"), +(2, 0, "Basics"), +(2, 1, "Syntax"), +(2, 2, "Client"), +(2, 3, "Server"), +(3, 0, "Intermediate"), +(3, 1, "Complex queries"), +(3, 2, "Stored Procedures"), +(3, 3, "Stored Functions"), +(4, 0, "Advanced"), +(4, 1, "Replication"), +(4, 2, "Load balancing"), +(4, 3, "High availability"), +(5, 0, "Conclusion"); + +select * from table_24562; + +alter table table_24562 add column reviewer varchar(20), +order by title; + +select * from table_24562; + +update table_24562 set reviewer="Me" where section=2; +update table_24562 set reviewer="You" where section=3; + +alter table table_24562 +order by section ASC, subsection DESC; + +select * from table_24562; + +alter table table_24562 +order by table_24562.subsection ASC, table_24562.section DESC; + +select * from table_24562; + +--error ER_PARSE_ERROR +alter table table_24562 order by 12; +--error ER_PARSE_ERROR +alter table table_24562 order by (section + 12); +--error ER_PARSE_ERROR +alter table table_24562 order by length(title); +--error ER_PARSE_ERROR +alter table table_24562 order by (select 12 from dual); + +--error ER_BAD_FIELD_ERROR +alter table table_24562 order by no_such_col; + +drop table table_24562; + # End of 4.1 tests # diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 749864c1f59..3fbcf84a1f9 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1649,6 +1649,7 @@ execute sq; deallocate prepare no_index; deallocate prepare sq; + # # Bug 25027: query with a single-row non-correlated subquery # and IS NULL predicate @@ -1743,4 +1744,34 @@ drop table t1, t2; #deallocate prepare stmt; #set @@character_set_server= @old_character_set_server; + +# +# BUG#24491 "using alias from source table in insert ... on duplicate key" +# +--disable_warnings +drop tables if exists t1; +--enable_warnings +create table t1 (id int primary key auto_increment, value varchar(10)); +insert into t1 (id, value) values (1, 'FIRST'), (2, 'SECOND'), (3, 'THIRD'); +# Let us prepare INSERT ... SELECT ... ON DUPLICATE KEY UPDATE statement +# which in its ON DUPLICATE KEY clause erroneously tries to assign value +# to a column which is mentioned only in SELECT part. +prepare stmt from "insert into t1 (id, value) select * from (select 4 as i, 'FOURTH' as v) as y on duplicate key update v = 'DUP'"; +# Both first and second attempts to execute it should fail +--error ER_BAD_FIELD_ERROR +execute stmt; +--error ER_BAD_FIELD_ERROR +execute stmt; +deallocate prepare stmt; +# And now the same test for more complex case which is more close +# to the one that was reported originally. +prepare stmt from "insert into t1 (id, value) select * from (select 4 as id, 'FOURTH' as value) as y on duplicate key update y.value = 'DUP'"; +--error ER_BAD_FIELD_ERROR +execute stmt; +--error ER_BAD_FIELD_ERROR +execute stmt; +deallocate prepare stmt; +drop tables t1; + + --echo End of 5.0 tests. diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 77bd5259eb5..e77e3df8301 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -1808,6 +1808,38 @@ PREPARE stmt FROM "CREATE VIEW v AS SELECT ?"; DROP TABLE t1; +# +# BUG#24491 "using alias from source table in insert ... on duplicate key" +# +--disable_warnings +drop tables if exists t1; +drop procedure if exists bug24491; +--enable_warnings +create table t1 (id int primary key auto_increment, value varchar(10)); +insert into t1 (id, value) values (1, 'FIRST'), (2, 'SECOND'), (3, 'THIRD'); +# Let us create routine with INSERT ... SELECT ... ON DUPLICATE KEY UPDATE +# statement which in its ON DUPLICATE KEY clause erroneously tries to assign +# value to a column which is mentioned only in SELECT part. +create procedure bug24491() + insert into t1 (id, value) select * from (select 4 as i, 'FOURTH' as v) as y on duplicate key update v = 'DUP'; +# Both first and second calls to it should fail +--error ER_BAD_FIELD_ERROR +call bug24491(); +--error ER_BAD_FIELD_ERROR +call bug24491(); +drop procedure bug24491; +# And now the same test for more complex case which is more close +# to the one that was reported originally. +create procedure bug24491() + insert into t1 (id, value) select * from (select 4 as id, 'FOURTH' as value) as y on duplicate key update y.value = 'DUP'; +--error ER_BAD_FIELD_ERROR +call bug24491(); +--error ER_BAD_FIELD_ERROR +call bug24491(); +drop procedure bug24491; +drop tables t1; + + # # BUG#NNNN: New bug synopsis # diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index 67e0ab6bcbd..0785b74dd47 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -927,6 +927,7 @@ DROP VIEW v2; DROP VIEW v1; DROP USER mysqltest_u1@localhost; + # # Bug#17254: Error for DEFINER security on VIEW provides too much info # @@ -964,4 +965,74 @@ DROP DATABASE db17254; disconnect def; disconnect inv; -# End of 5.0 tests. + +# +# BUG#24404: strange bug with view+permission+prepared statement +# +--disable_warnings +DROP DATABASE IF EXISTS mysqltest_db1; +DROP DATABASE IF EXISTS mysqltest_db2; +--enable_warnings +--error 0,ER_CANNOT_USER +DROP USER mysqltest_u1; +--error 0,ER_CANNOT_USER +DROP USER mysqltest_u2; + +CREATE USER mysqltest_u1@localhost; +CREATE USER mysqltest_u2@localhost; + +CREATE DATABASE mysqltest_db1; +CREATE DATABASE mysqltest_db2; + +GRANT ALL ON mysqltest_db1.* TO mysqltest_u1@localhost WITH GRANT OPTION; +GRANT ALL ON mysqltest_db2.* TO mysqltest_u2@localhost; + +connect (conn1, localhost, mysqltest_u1, , mysqltest_db1); + +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1); + +# Use view with subquery for better coverage. +CREATE VIEW v1 AS SELECT i FROM t1 WHERE 1 IN (SELECT * FROM t1); + +CREATE TABLE t2 (s CHAR(7)); +INSERT INTO t2 VALUES ('public'); + +GRANT SELECT ON v1 TO mysqltest_u2@localhost; +GRANT SELECT ON t2 TO mysqltest_u2@localhost; + +connect (conn2, localhost, mysqltest_u2, , mysqltest_db2); + +SELECT * FROM mysqltest_db1.v1, mysqltest_db1.t2; +PREPARE stmt1 FROM "SELECT * FROM mysqltest_db1.t2"; +EXECUTE stmt1; +PREPARE stmt2 FROM "SELECT * FROM mysqltest_db1.v1, mysqltest_db1.t2"; +EXECUTE stmt2; + +connection conn1; +# Make table 't2' private. +REVOKE SELECT ON t2 FROM mysqltest_u2@localhost; +UPDATE t2 SET s = 'private' WHERE s = 'public'; + +connection conn2; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM mysqltest_db1.v1, mysqltest_db1.t2; +--error ER_TABLEACCESS_DENIED_ERROR +EXECUTE stmt1; +# Original bug was here: the statement didn't fail. +--error ER_TABLEACCESS_DENIED_ERROR +EXECUTE stmt2; + +# Cleanup. +disconnect conn2; +disconnect conn1; +connection default; +REVOKE ALL ON mysqltest_db1.* FROM mysqltest_u1@localhost; +REVOKE ALL ON mysqltest_db2.* FROM mysqltest_u2@localhost; +DROP DATABASE mysqltest_db1; +DROP DATABASE mysqltest_db2; +DROP USER mysqltest_u1@localhost; +DROP USER mysqltest_u2@localhost; + + +--echo End of 5.0 tests. diff --git a/sql/item.h b/sql/item.h index 13f0b95c1d1..c7c1218d3e9 100644 --- a/sql/item.h +++ b/sql/item.h @@ -336,23 +336,18 @@ public: { save_table_list= context->table_list; save_first_name_resolution_table= context->first_name_resolution_table; - save_next_name_resolution_table= (context->first_name_resolution_table) ? - context->first_name_resolution_table-> - next_name_resolution_table : - NULL; save_resolve_in_select_list= context->resolve_in_select_list; save_next_local= table_list->next_local; + save_next_name_resolution_table= table_list->next_name_resolution_table; } /* Restore a name resolution context from saved state. */ void restore_state(Name_resolution_context *context, TABLE_LIST *table_list) { table_list->next_local= save_next_local; + table_list->next_name_resolution_table= save_next_name_resolution_table; context->table_list= save_table_list; context->first_name_resolution_table= save_first_name_resolution_table; - if (context->first_name_resolution_table) - context->first_name_resolution_table-> - next_name_resolution_table= save_next_name_resolution_table; context->resolve_in_select_list= save_resolve_in_select_list; } }; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 4f5f4c29854..d9dadfbfd81 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3163,19 +3163,30 @@ view_err: if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) && !table->s->tmp_table) // no need to touch frm { - VOID(pthread_mutex_lock(&LOCK_open)); - switch (alter_info->keys_onoff) { case LEAVE_AS_IS: error= 0; break; case ENABLE: + /* + wait_while_table_is_used() ensures that table being altered is + opened only by this thread and that TABLE::TABLE_SHARE::version + of TABLE object corresponding to this table is 0. + The latter guarantees that no DML statement will open this table + until ALTER TABLE finishes (i.e. until close_thread_tables()) + while the fact that the table is still open gives us protection + from concurrent DDL statements. + */ + VOID(pthread_mutex_lock(&LOCK_open)); wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); + VOID(pthread_mutex_unlock(&LOCK_open)); error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); /* COND_refresh will be signaled in close_thread_tables() */ break; case DISABLE: + VOID(pthread_mutex_lock(&LOCK_open)); wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); + VOID(pthread_mutex_unlock(&LOCK_open)); error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); /* COND_refresh will be signaled in close_thread_tables() */ break; @@ -3188,6 +3199,16 @@ view_err: error= 0; } + VOID(pthread_mutex_lock(&LOCK_open)); + /* + Unlike to the above case close_cached_table() below will remove ALL + instances of TABLE from table cache (it will also remove table lock + held by this thread). So to make actual table renaming and writing + to binlog atomic we have to put them into the same critical section + protected by LOCK_open mutex. This also removes gap for races between + access() and mysql_rename_table() calls. + */ + if (!error && (new_name != table_name || new_db != db)) { thd->proc_info="rename"; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 0d6c38ee50e..18ef3eaf29c 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1135,13 +1135,17 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, /* Prepare a security context to check underlying objects of the view */ - Security_context *save_security_ctx= thd->security_ctx; if (!(table->view_sctx= (Security_context *) thd->stmt_arena->alloc(sizeof(Security_context)))) goto err; /* Assign the context to the tables referenced in the view */ - for (tbl= view_tables; tbl; tbl= tbl->next_global) - tbl->security_ctx= table->view_sctx; + if (view_tables) + { + DBUG_ASSERT(view_tables_tail); + for (tbl= view_tables; tbl != view_tables_tail->next_global; + tbl= tbl->next_global) + tbl->security_ctx= table->view_sctx; + } /* assign security context to SELECT name resolution contexts of view */ for(SELECT_LEX *sl= lex->all_selects_list; sl; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 92640ea58d6..0f29c3e1028 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3722,7 +3722,7 @@ alter_list_item: { Lex->alter_info.flags|= ALTER_FORCE; } - | order_clause + | alter_order_clause { LEX *lex=Lex; lex->alter_info.flags|= ALTER_ORDER; @@ -5942,6 +5942,29 @@ olap_opt: } ; +/* + Order by statement in ALTER TABLE +*/ + +alter_order_clause: + ORDER_SYM BY alter_order_list + ; + +alter_order_list: + alter_order_list ',' alter_order_item + | alter_order_item + ; + +alter_order_item: + simple_ident_nospvar order_dir + { + THD *thd= YYTHD; + bool ascending= ($2 == 1) ? true : false; + if (add_order_to_list(thd, $1, ascending)) + YYABORT; + } + ; + /* Order by statement in select */