diff --git a/mysql-test/include/wait_condition.inc b/mysql-test/include/wait_condition.inc new file mode 100644 index 00000000000..cd80b58d44e --- /dev/null +++ b/mysql-test/include/wait_condition.inc @@ -0,0 +1,39 @@ +# include/wait_condition.inc +# +# SUMMARY +# +# Waits until the passed statement returns true, or the operation +# times out. +# +# USAGE +# +# let $wait_condition= +# SELECT c = 3 FROM t; +# --source include/wait_condition.inc +# +# EXAMPLE +# events_bugs.test +# + +--disable_query_log + +let $wait_counter= 300; +while ($wait_counter) +{ + let $success= `$wait_condition`; + if ($success) + { + let $wait_counter= 0; + } + if (!$success) + { + real_sleep 0.1; + dec $wait_counter; + } +} +if (!$success) +{ + echo Timeout in wait_condition.inc for $wait_condition; +} + +--enable_query_log 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/include/wait_until_rows_count.inc b/mysql-test/include/wait_until_rows_count.inc index cf2a21d335a..f1b79c54424 100644 --- a/mysql-test/include/wait_until_rows_count.inc +++ b/mysql-test/include/wait_until_rows_count.inc @@ -1,52 +1,20 @@ # include/wait_until_rows_count.inc -# inspired by wait_for_slave_status by Matthias Leich # # SUMMARY # -# Waits until SELECT count(*)-$count from $table returns zero +# Waits until SELECT count(*) = $count from $table returns true, or +# the operation times out. # # USAGE # -# Set vars like -# let $count=11; -# let $table=t1; -# # invoke the macro -# --include wait_until_rows_count.inc +# let $count= 5; +# let $table= t1; +# --source include/wait_until_rows_count.inc # # EXAMPLE -# extra/binlog/binlog_insert_delayed.test +# extra/binlog/binlog_insert_delayed.test # -# -# TODO: generalize up to wait_[until|while] with arbitrary select or even query and -# a condition to wait or get awakened -# It's impossible to implement such a "most" general macro without -# extending mysqltest. Just no way to pass a query as an argument and -# evaluate it here, like eval "$quuery". One is bound -# to specify it inside of the macro ---disable_query_log - -let $wait_counter= 300; # max wait in 0.1 seconds -while ($wait_counter) -{ - eval select count(*)-$count from $table into @rez; - let $rez=`select @rez`; - let $success=`SELECT @rez = 0`; - let $no_success=1; - if ($success) - { - let $wait_counter= 1; # droppping counter to leave loop - let $no_success=0; - } - if ($no_success) - { - --sleep 0.1 - } - dec $wait_counter; -} - ---enable_query_log -if ($no_success) -{ - --die Timeout in wait_until_rows_count.inc, required table never had a prescribed number of rows. -} +let $wait_condition= + select count(*) = $count from $table; +--source include/wait_condition.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..a9d0515d6bb --- /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 102; +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 9a534539523..571ac8498b3 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 '(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/events_bugs.result b/mysql-test/r/events_bugs.result index 363033e487a..44b930e0705 100644 --- a/mysql-test/r/events_bugs.result +++ b/mysql-test/r/events_bugs.result @@ -49,7 +49,7 @@ begin select get_lock('test_bug16407', 60); drop table "hashed_num"; end| -"Now if everything is fine the event has compiled and is locked +"Now if everything is fine the event has compiled and is locked" select /*1*/ user, host, db, info from information_schema.processlist where command!='Daemon' and (info is null or info not like '%processlist%') order by info; user host db info root localhost events_test select get_lock('test_bug16407', 60) @@ -239,26 +239,83 @@ insert into t1 values (2); create table t2 (a char(20)); insert into t2 values ("e22830_1"); create function f22830 () returns int return 5; -create event e22830 on schedule every f22830() second do select 123; +select get_lock('ee_22830', 60); +get_lock('ee_22830', 60) +1 +set global event_scheduler=on; +create procedure p22830_wait() +begin +select get_lock('ee_22830', 60); +select release_lock('ee_22830'); +end| +create event e22830 on schedule every f22830() second do +begin +call p22830_wait(); +select 123; +end| ERROR 42000: This version of MySQL doesn't yet support 'Usage of subqueries or stored function calls as part of this statement' -create event e22830_1 on schedule every 1 hour do alter event e22830_1 on schedule every (select 8 from dual) hour; -create event e22830_2 on schedule every 1 hour do alter event e22830_2 on schedule every (select 8 from t1) hour; -create event e22830_3 on schedule every 1 hour do alter event e22830_3 on schedule every f22830() hour; -create event e22830_4 on schedule every 1 hour do alter event e22830_4 on schedule every (select f22830() from dual) hour; +create event e22830_1 on schedule every 1 hour do +begin +call p22830_wait(); +alter event e22830_1 on schedule every (select 8 from dual) hour; +end| +create event e22830_2 on schedule every 1 hour do +begin +call p22830_wait(); +alter event e22830_2 on schedule every (select 8 from t1) hour; +end| +create event e22830_3 on schedule every 1 hour do +begin +call p22830_wait(); +alter event e22830_3 on schedule every f22830() hour; +end| +create event e22830_4 on schedule every 1 hour do +begin +call p22830_wait(); +alter event e22830_4 on schedule every (select f22830() from dual) hour; +end| +"All events should be blocked in get_lock()" select event_name, event_definition, interval_value, interval_field from information_schema.events order by event_name; event_name event_definition interval_value interval_field -e22830_1 alter event e22830_1 on schedule every (select 8 from dual) hour 1 HOUR -e22830_2 alter event e22830_2 on schedule every (select 8 from t1) hour 1 HOUR -e22830_3 alter event e22830_3 on schedule every f22830() hour 1 HOUR -e22830_4 alter event e22830_4 on schedule every (select f22830() from dual) hour 1 HOUR -set global event_scheduler=on; +e22830_1 begin +call p22830_wait(); +alter event e22830_1 on schedule every (select 8 from dual) hour; +end 1 HOUR +e22830_2 begin +call p22830_wait(); +alter event e22830_2 on schedule every (select 8 from t1) hour; +end 1 HOUR +e22830_3 begin +call p22830_wait(); +alter event e22830_3 on schedule every f22830() hour; +end 1 HOUR +e22830_4 begin +call p22830_wait(); +alter event e22830_4 on schedule every (select f22830() from dual) hour; +end 1 HOUR +select release_lock('ee_22830'); +release_lock('ee_22830') +1 set global event_scheduler=off; select event_name, event_definition, interval_value, interval_field from information_schema.events order by event_name; event_name event_definition interval_value interval_field -e22830_1 alter event e22830_1 on schedule every (select 8 from dual) hour 8 HOUR -e22830_2 alter event e22830_2 on schedule every (select 8 from t1) hour 1 HOUR -e22830_3 alter event e22830_3 on schedule every f22830() hour 1 HOUR -e22830_4 alter event e22830_4 on schedule every (select f22830() from dual) hour 1 HOUR +e22830_1 begin +call p22830_wait(); +alter event e22830_1 on schedule every (select 8 from dual) hour; +end 8 HOUR +e22830_2 begin +call p22830_wait(); +alter event e22830_2 on schedule every (select 8 from t1) hour; +end 1 HOUR +e22830_3 begin +call p22830_wait(); +alter event e22830_3 on schedule every f22830() hour; +end 1 HOUR +e22830_4 begin +call p22830_wait(); +alter event e22830_4 on schedule every (select f22830() from dual) hour; +end 1 HOUR +drop procedure p22830_wait; drop function f22830; drop event (select a from t2); 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 a from t2)' at line 1 diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index d82b07fa7d3..a99fdb16868 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1544,6 +1544,22 @@ a 2 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. create procedure proc_1() reset query cache; call proc_1(); diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index d955b69bde2..0ed92aa9e7a 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1250,6 +1250,25 @@ 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; End of 5.0 tests drop function if exists bug16164; create function bug16164() returns int diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index e05a84a8f2d..a95184b8576 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -733,3 +733,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..befe6e14977 --- /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. +--source include/big_test.inc +--source include/have_binlog_format_mixed_or_statement.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 102; + +# 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 990f0f4adf5..297813dfead 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/disabled.def b/mysql-test/t/disabled.def index 8c2c4740f5e..2c525742bc4 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -11,7 +11,7 @@ ############################################################################## user_limits : Bug#23921 random failure of user_limits.test -im_daemon_life_cycle : Bug#24415 see note: [19 Dec 23:17] Trudy Pelzer +# im_daemon_life_cycle : Bug#24415 see note: [19 Dec 23:17] Trudy Pelzer im_options : Bug#20294 2006-07-24 stewart Instance manager test im_options fails randomly concurrent_innodb : BUG#21579 2006-08-11 mleich innodb_concurrent random failures with varying differences ndb_autodiscover : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog diff --git a/mysql-test/t/events_bugs.test b/mysql-test/t/events_bugs.test index e9751608a46..26abf663ce1 100644 --- a/mysql-test/t/events_bugs.test +++ b/mysql-test/t/events_bugs.test @@ -78,8 +78,13 @@ begin drop table "hashed_num"; end| delimiter ;| ---sleep 0.8 ---echo "Now if everything is fine the event has compiled and is locked + +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where info = 'select get_lock(\'test_bug16407\', 60)'; +--source include/wait_condition.inc + +--echo "Now if everything is fine the event has compiled and is locked" select /*1*/ user, host, db, info from information_schema.processlist where command!='Daemon' and (info is null or info not like '%processlist%') order by info; select release_lock('test_bug16407'); @@ -127,10 +132,22 @@ begin end| delimiter ;| select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name; ---sleep 1 + +let $wait_condition= + select count(*) = 3 from information_schema.processlist + where info = 'select get_lock(\'ee_16407_2\', 60)'; +--source include/wait_condition.inc + select /*2*/ user, host, db, info from information_schema.processlist where (command!='Daemon' || user='event_scheduler') and (info is null or info not like '%processlist%') order by info; select release_lock('ee_16407_2'); ---sleep 1.2 + +let $wait_condition= + select count(*) = 1 and user = 'event_scheduler' and info is null + from information_schema.processlist + where (command!='Daemon' || user='event_scheduler') + and (info is null or info not like '%processlist%'); +--source include/wait_condition.inc + select /*3*/ user, host, db, info from information_schema.processlist where (command!='Daemon' || user='event_scheduler') and (info is null or info not like '%processlist%') order by info; set global event_scheduler= off; select * from events_smode_test order by ev_name, a; @@ -150,6 +167,7 @@ set global event_scheduler= on; set sql_mode='traditional'; delimiter |; +# ee_16407_5_pendant() should not insert anything because of invalid date. create procedure ee_16407_5_pendant() begin insert into events_test.events_smode_test values('ee_16407_5','2001-02-29'); end| create procedure ee_16407_6_pendant() begin insert into events_test.events_smode_test values('ee_16407_6','2004-02-29'); end| create event ee_16407_5 on schedule every 60 second do @@ -165,11 +183,23 @@ begin call events_test.ee_16407_6_pendant(); end| delimiter ;| ---sleep 1 + +let $wait_condition= + select count(*) = 2 from information_schema.processlist + where info = 'select get_lock(\'ee_16407_5\', 60)'; +--source include/wait_condition.inc + --echo "Should have 2 locked processes" select /*4*/ user, host, db, info from information_schema.processlist where (command!='Daemon' || user='event_scheduler') and (info is null or info not like '%processlist%') order by info; select release_lock('ee_16407_5'); ---sleep 1.3 + +let $wait_condition= + select count(*) = 1 and user = 'event_scheduler' and info is null + from information_schema.processlist + where (command!='Daemon' || user='event_scheduler') + and (info is null or info not like '%processlist%'); +--source include/wait_condition.inc + --echo "Should have 0 processes locked" select /*5*/ user, host, db, info from information_schema.processlist where (command!='Daemon' || user='event_scheduler') and (info is null or info not like '%processlist%') order by info; select * from events_smode_test order by ev_name, a; @@ -272,17 +302,58 @@ insert into t1 values (2); create table t2 (a char(20)); insert into t2 values ("e22830_1"); create function f22830 () returns int return 5; ---error ER_NOT_SUPPORTED_YET -create event e22830 on schedule every f22830() second do select 123; -create event e22830_1 on schedule every 1 hour do alter event e22830_1 on schedule every (select 8 from dual) hour; -create event e22830_2 on schedule every 1 hour do alter event e22830_2 on schedule every (select 8 from t1) hour; -create event e22830_3 on schedule every 1 hour do alter event e22830_3 on schedule every f22830() hour; -create event e22830_4 on schedule every 1 hour do alter event e22830_4 on schedule every (select f22830() from dual) hour; -select event_name, event_definition, interval_value, interval_field from information_schema.events order by event_name; + +select get_lock('ee_22830', 60); set global event_scheduler=on; ---sleep 4 + +delimiter |; +create procedure p22830_wait() +begin + select get_lock('ee_22830', 60); + select release_lock('ee_22830'); +end| + +--error ER_NOT_SUPPORTED_YET +create event e22830 on schedule every f22830() second do +begin + call p22830_wait(); + select 123; +end| +create event e22830_1 on schedule every 1 hour do +begin + call p22830_wait(); + alter event e22830_1 on schedule every (select 8 from dual) hour; +end| +create event e22830_2 on schedule every 1 hour do +begin + call p22830_wait(); + alter event e22830_2 on schedule every (select 8 from t1) hour; +end| +create event e22830_3 on schedule every 1 hour do +begin + call p22830_wait(); + alter event e22830_3 on schedule every f22830() hour; +end| +create event e22830_4 on schedule every 1 hour do +begin + call p22830_wait(); + alter event e22830_4 on schedule every (select f22830() from dual) hour; +end| +delimiter ;| + +--echo "All events should be blocked in get_lock()" +select event_name, event_definition, interval_value, interval_field from information_schema.events order by event_name; + +select release_lock('ee_22830'); + +let $wait_condition= + select group_concat(interval_value order by interval_value) = '1,1,1,8' + from information_schema.events; +--source include/wait_condition.inc + set global event_scheduler=off; select event_name, event_definition, interval_value, interval_field from information_schema.events order by event_name; +drop procedure p22830_wait; drop function f22830; --error ER_PARSE_ERROR drop event (select a from t2); diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 34f9a6fb699..805abe99426 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -1574,6 +1574,7 @@ execute sq; deallocate prepare no_index; deallocate prepare sq; + # # Bug 25027: query with a single-row non-correlated subquery # and IS NULL predicate @@ -1597,6 +1598,36 @@ DEALLOCATE PREPARE stmt; DROP TABLE t1,t2; + +# +# 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 456a23123d3..3e334bb61e8 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -1812,6 +1812,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; + + # # End of 5.0 tests # @@ -1853,6 +1885,7 @@ drop function bug20701; --echo End of 5.1 tests + # # BUG#NNNN: New bug synopsis # diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index 9c06e79e2ca..a4a1cefd0aa 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -933,6 +933,7 @@ DROP VIEW v2; DROP VIEW v1; DROP USER mysqltest_u1@localhost; + # # Bug#17254: Error for DEFINER security on VIEW provides too much info # @@ -970,4 +971,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 8c97010389e..b2e363dce52 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 35a5547a730..b625b0c9d19 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5542,19 +5542,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; @@ -5571,6 +5582,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 55f6fc04442..a57d21ba7b2 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1144,13 +1144,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 841c0f19c1e..3755f6d3b67 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5425,7 +5425,7 @@ alter_list_item: { Lex->alter_info.flags|= ALTER_FORCE; } - | order_clause + | alter_order_clause { LEX *lex=Lex; lex->alter_info.flags|= ALTER_ORDER; @@ -7569,6 +7569,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 */