Commit 491ef6af authored by unknown's avatar unknown

Merge bk-internal.mysql.com:/home/bk/mysql-5.1

into  mockturtle.local:/home/dlenev/src/mysql-5.1-merge


mysql-test/t/disabled.def:
  Auto merged
mysql-test/t/ps.test:
  Auto merged
sql/sql_view.cc:
  Auto merged
parents e57ef96a 07b6b2f8
# 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
# 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= <Tail of SHOW statement>;
# 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
...@@ -104,50 +104,21 @@ ...@@ -104,50 +104,21 @@
eval SELECT "let \$result_pattern= $result_pattern ;" AS ""; eval SELECT "let \$result_pattern= $result_pattern ;" AS "";
SELECT '--source include/wait_slave_status.inc' AS ""; SELECT '--source include/wait_slave_status.inc' AS "";
# We accept to wait maximum 30 seconds (0.2 sec/loop). let $show_type= SLAVE STATUS;
let $max_wait= 150; let $show_pattern= $result_pattern;
while ($max_wait) --enable_query_log
{
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; --source include/wait_show_pattern.inc
# @success is '1' if we have a match
# '0' if we have no match
# DEBUG SELECT @success;
let $success= `SELECT @success`; if (!$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;
}
--enable_query_log
if ($no_success)
{ {
let $message= ! Attention: Timeout in wait_slave_status.inc. let $message= ! Attention: Timeout in wait_slave_status.inc.
| Possible reasons with decreasing probability: | 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 | testcase was altered or the layout of the
| SHOW SLAVE STATUS result set changed. | SHOW SLAVE STATUS result set changed.
| - There is a new bug within the replication. | - 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.; | too small.;
--source include/show_msg80.inc --source include/show_msg80.inc
--echo DEBUG INFO START (wait_slave_status.inc): --echo DEBUG INFO START (wait_slave_status.inc):
......
# include/wait_until_rows_count.inc # include/wait_until_rows_count.inc
# inspired by wait_for_slave_status by Matthias Leich
# #
# SUMMARY # 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 # USAGE
# #
# Set vars like # let $count= 5;
# let $count=11; # let $table= t1;
# let $table=t1; # --source include/wait_until_rows_count.inc
# # invoke the macro
# --include wait_until_rows_count.inc
# #
# EXAMPLE # 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 let $wait_condition=
if ($no_success) select count(*) = $count from $table;
{ --source include/wait_condition.inc
--die Timeout in wait_until_rows_count.inc, required table never had a prescribed number of rows.
}
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
...@@ -703,6 +703,119 @@ SHOW INDEX FROM bug24219_2; ...@@ -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 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 bug24219_2 1 a 1 a A NULL NULL NULL YES BTREE disabled
DROP TABLE bug24219_2; 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); create table t1 (mycol int(10) not null);
alter table t1 alter column mycol set default 0; alter table t1 alter column mycol set default 0;
desc t1; desc t1;
......
...@@ -49,7 +49,7 @@ begin ...@@ -49,7 +49,7 @@ begin
select get_lock('test_bug16407', 60); select get_lock('test_bug16407', 60);
drop table "hashed_num"; drop table "hashed_num";
end| 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; 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 user host db info
root localhost events_test select get_lock('test_bug16407', 60) root localhost events_test select get_lock('test_bug16407', 60)
...@@ -239,26 +239,83 @@ insert into t1 values (2); ...@@ -239,26 +239,83 @@ insert into t1 values (2);
create table t2 (a char(20)); create table t2 (a char(20));
insert into t2 values ("e22830_1"); insert into t2 values ("e22830_1");
create function f22830 () returns int return 5; 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' 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_1 on schedule every 1 hour do
create event e22830_2 on schedule every 1 hour do alter event e22830_2 on schedule every (select 8 from t1) hour; begin
create event e22830_3 on schedule every 1 hour do alter event e22830_3 on schedule every f22830() hour; call p22830_wait();
create event e22830_4 on schedule every 1 hour do alter event e22830_4 on schedule every (select f22830() from dual) hour; 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; 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 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_1 begin
e22830_2 alter event e22830_2 on schedule every (select 8 from t1) hour 1 HOUR call p22830_wait();
e22830_3 alter event e22830_3 on schedule every f22830() hour 1 HOUR alter event e22830_1 on schedule every (select 8 from dual) hour;
e22830_4 alter event e22830_4 on schedule every (select f22830() from dual) hour 1 HOUR end 1 HOUR
set global event_scheduler=on; 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; set global event_scheduler=off;
select event_name, event_definition, interval_value, interval_field from information_schema.events order by event_name; 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 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_1 begin
e22830_2 alter event e22830_2 on schedule every (select 8 from t1) hour 1 HOUR call p22830_wait();
e22830_3 alter event e22830_3 on schedule every f22830() hour 1 HOUR alter event e22830_1 on schedule every (select 8 from dual) hour;
e22830_4 alter event e22830_4 on schedule every (select f22830() from dual) hour 1 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 function f22830;
drop event (select a from t2); 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 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
......
...@@ -1544,6 +1544,22 @@ a ...@@ -1544,6 +1544,22 @@ a
2 2
DEALLOCATE PREPARE stmt; DEALLOCATE PREPARE stmt;
DROP TABLE t1,t2; 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. End of 5.0 tests.
create procedure proc_1() reset query cache; create procedure proc_1() reset query cache;
call proc_1(); call proc_1();
......
...@@ -1250,6 +1250,25 @@ ERROR HY000: View's SELECT contains a variable or parameter ...@@ -1250,6 +1250,25 @@ ERROR HY000: View's SELECT contains a variable or parameter
PREPARE stmt FROM "CREATE VIEW v AS SELECT ?"; PREPARE stmt FROM "CREATE VIEW v AS SELECT ?";
ERROR HY000: View's SELECT contains a variable or parameter ERROR HY000: View's SELECT contains a variable or parameter
DROP TABLE t1; 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 End of 5.0 tests
drop function if exists bug16164; drop function if exists bug16164;
create function bug16164() returns int create function bug16164() returns int
......
...@@ -733,3 +733,46 @@ SELECT * FROM v1; ...@@ -733,3 +733,46 @@ SELECT * FROM v1;
ERROR HY000: There is no 'def_17254'@'localhost' registered ERROR HY000: There is no 'def_17254'@'localhost' registered
DROP USER inv_17254@localhost; DROP USER inv_17254@localhost;
DROP DATABASE db17254; 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.
# 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
...@@ -528,6 +528,71 @@ SHOW INDEX FROM bug24219_2; ...@@ -528,6 +528,71 @@ SHOW INDEX FROM bug24219_2;
DROP TABLE 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 # End of 4.1 tests
# #
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
############################################################################## ##############################################################################
user_limits : Bug#23921 random failure of user_limits.test 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 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 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 ndb_autodiscover : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog
......
...@@ -78,8 +78,13 @@ begin ...@@ -78,8 +78,13 @@ begin
drop table "hashed_num"; drop table "hashed_num";
end| end|
delimiter ;| 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 /*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'); select release_lock('test_bug16407');
...@@ -127,10 +132,22 @@ begin ...@@ -127,10 +132,22 @@ begin
end| end|
delimiter ;| delimiter ;|
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name; 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 /*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'); 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; 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; set global event_scheduler= off;
select * from events_smode_test order by ev_name, a; select * from events_smode_test order by ev_name, a;
...@@ -150,6 +167,7 @@ set global event_scheduler= on; ...@@ -150,6 +167,7 @@ set global event_scheduler= on;
set sql_mode='traditional'; set sql_mode='traditional';
delimiter |; 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_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 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 create event ee_16407_5 on schedule every 60 second do
...@@ -165,11 +183,23 @@ begin ...@@ -165,11 +183,23 @@ begin
call events_test.ee_16407_6_pendant(); call events_test.ee_16407_6_pendant();
end| end|
delimiter ;| 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" --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 /*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'); 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" --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 /*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; select * from events_smode_test order by ev_name, a;
...@@ -272,17 +302,58 @@ insert into t1 values (2); ...@@ -272,17 +302,58 @@ insert into t1 values (2);
create table t2 (a char(20)); create table t2 (a char(20));
insert into t2 values ("e22830_1"); insert into t2 values ("e22830_1");
create function f22830 () returns int return 5; create function f22830 () returns int return 5;
select get_lock('ee_22830', 60);
set global event_scheduler=on;
delimiter |;
create procedure p22830_wait()
begin
select get_lock('ee_22830', 60);
select release_lock('ee_22830');
end|
--error ER_NOT_SUPPORTED_YET --error ER_NOT_SUPPORTED_YET
create event e22830 on schedule every f22830() second do select 123; create event e22830 on schedule every f22830() second do
create event e22830_1 on schedule every 1 hour do alter event e22830_1 on schedule every (select 8 from dual) hour; begin
create event e22830_2 on schedule every 1 hour do alter event e22830_2 on schedule every (select 8 from t1) hour; call p22830_wait();
create event e22830_3 on schedule every 1 hour do alter event e22830_3 on schedule every f22830() hour; select 123;
create event e22830_4 on schedule every 1 hour do alter event e22830_4 on schedule every (select f22830() from dual) hour; 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 event_name, event_definition, interval_value, interval_field from information_schema.events order by event_name;
set global event_scheduler=on;
--sleep 4 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; set global event_scheduler=off;
select event_name, event_definition, interval_value, interval_field from information_schema.events order by event_name; select event_name, event_definition, interval_value, interval_field from information_schema.events order by event_name;
drop procedure p22830_wait;
drop function f22830; drop function f22830;
--error ER_PARSE_ERROR --error ER_PARSE_ERROR
drop event (select a from t2); drop event (select a from t2);
......
...@@ -1574,6 +1574,7 @@ execute sq; ...@@ -1574,6 +1574,7 @@ execute sq;
deallocate prepare no_index; deallocate prepare no_index;
deallocate prepare sq; deallocate prepare sq;
# #
# Bug 25027: query with a single-row non-correlated subquery # Bug 25027: query with a single-row non-correlated subquery
# and IS NULL predicate # and IS NULL predicate
...@@ -1597,6 +1598,36 @@ DEALLOCATE PREPARE stmt; ...@@ -1597,6 +1598,36 @@ DEALLOCATE PREPARE stmt;
DROP TABLE t1,t2; 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. --echo End of 5.0 tests.
# #
......
...@@ -1812,6 +1812,38 @@ PREPARE stmt FROM "CREATE VIEW v AS SELECT ?"; ...@@ -1812,6 +1812,38 @@ PREPARE stmt FROM "CREATE VIEW v AS SELECT ?";
DROP TABLE t1; 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 # End of 5.0 tests
# #
...@@ -1853,6 +1885,7 @@ drop function bug20701; ...@@ -1853,6 +1885,7 @@ drop function bug20701;
--echo End of 5.1 tests --echo End of 5.1 tests
# #
# BUG#NNNN: New bug synopsis # BUG#NNNN: New bug synopsis
# #
......
...@@ -933,6 +933,7 @@ DROP VIEW v2; ...@@ -933,6 +933,7 @@ DROP VIEW v2;
DROP VIEW v1; DROP VIEW v1;
DROP USER mysqltest_u1@localhost; DROP USER mysqltest_u1@localhost;
# #
# Bug#17254: Error for DEFINER security on VIEW provides too much info # Bug#17254: Error for DEFINER security on VIEW provides too much info
# #
...@@ -970,4 +971,74 @@ DROP DATABASE db17254; ...@@ -970,4 +971,74 @@ DROP DATABASE db17254;
disconnect def; disconnect def;
disconnect inv; 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.
...@@ -336,23 +336,18 @@ public: ...@@ -336,23 +336,18 @@ public:
{ {
save_table_list= context->table_list; save_table_list= context->table_list;
save_first_name_resolution_table= context->first_name_resolution_table; 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_resolve_in_select_list= context->resolve_in_select_list;
save_next_local= table_list->next_local; 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. */ /* Restore a name resolution context from saved state. */
void restore_state(Name_resolution_context *context, TABLE_LIST *table_list) void restore_state(Name_resolution_context *context, TABLE_LIST *table_list)
{ {
table_list->next_local= save_next_local; 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->table_list= save_table_list;
context->first_name_resolution_table= save_first_name_resolution_table; 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; context->resolve_in_select_list= save_resolve_in_select_list;
} }
}; };
......
...@@ -5542,19 +5542,30 @@ view_err: ...@@ -5542,19 +5542,30 @@ view_err:
if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) && if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
!table->s->tmp_table) // no need to touch frm !table->s->tmp_table) // no need to touch frm
{ {
VOID(pthread_mutex_lock(&LOCK_open));
switch (alter_info->keys_onoff) { switch (alter_info->keys_onoff) {
case LEAVE_AS_IS: case LEAVE_AS_IS:
error= 0; error= 0;
break; break;
case ENABLE: 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); 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); error= table->file->enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
/* COND_refresh will be signaled in close_thread_tables() */ /* COND_refresh will be signaled in close_thread_tables() */
break; break;
case DISABLE: case DISABLE:
VOID(pthread_mutex_lock(&LOCK_open));
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN); 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); error=table->file->disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
/* COND_refresh will be signaled in close_thread_tables() */ /* COND_refresh will be signaled in close_thread_tables() */
break; break;
...@@ -5571,6 +5582,16 @@ view_err: ...@@ -5571,6 +5582,16 @@ view_err:
error= 0; 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)) if (!error && (new_name != table_name || new_db != db))
{ {
thd->proc_info="rename"; thd->proc_info="rename";
......
...@@ -1144,13 +1144,17 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, ...@@ -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 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 *) if (!(table->view_sctx= (Security_context *)
thd->stmt_arena->alloc(sizeof(Security_context)))) thd->stmt_arena->alloc(sizeof(Security_context))))
goto err; goto err;
/* Assign the context to the tables referenced in the view */ /* Assign the context to the tables referenced in the view */
for (tbl= view_tables; tbl; tbl= tbl->next_global) if (view_tables)
tbl->security_ctx= table->view_sctx; {
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 */ /* assign security context to SELECT name resolution contexts of view */
for(SELECT_LEX *sl= lex->all_selects_list; for(SELECT_LEX *sl= lex->all_selects_list;
sl; sl;
......
...@@ -5425,7 +5425,7 @@ alter_list_item: ...@@ -5425,7 +5425,7 @@ alter_list_item:
{ {
Lex->alter_info.flags|= ALTER_FORCE; Lex->alter_info.flags|= ALTER_FORCE;
} }
| order_clause | alter_order_clause
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->alter_info.flags|= ALTER_ORDER; lex->alter_info.flags|= ALTER_ORDER;
...@@ -7569,6 +7569,29 @@ olap_opt: ...@@ -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 Order by statement in select
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment