summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/my_pthread.h8
-rw-r--r--mysql-test/r/handler.result37
-rw-r--r--mysql-test/r/myisam.result10
-rw-r--r--mysql-test/r/ndb_charset.result20
-rw-r--r--mysql-test/r/rpl_sp.result25
-rw-r--r--mysql-test/r/sp-error.result103
-rw-r--r--mysql-test/t/disabled.def1
-rw-r--r--mysql-test/t/func_group.test4
-rw-r--r--mysql-test/t/handler.test75
-rw-r--r--mysql-test/t/myisam.test12
-rw-r--r--mysql-test/t/ndb_charset.test15
-rw-r--r--mysql-test/t/rpl_sp.test36
-rw-r--r--mysql-test/t/sp-error.test138
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp17
-rw-r--r--ndb/src/kernel/vm/SimulatedBlock.cpp92
-rw-r--r--ndb/src/kernel/vm/SimulatedBlock.hpp6
-rw-r--r--sql/ha_archive.cc3
-rw-r--r--sql/lock.cc18
-rw-r--r--sql/mysql_priv.h3
-rw-r--r--sql/sp_head.cc39
-rw-r--r--sql/sp_head.h13
-rw-r--r--sql/sql_base.cc7
-rw-r--r--sql/sql_class.cc2
-rw-r--r--sql/sql_handler.cc51
-rw-r--r--sql/sql_parse.cc12
-rw-r--r--sql/sql_select.cc8
-rw-r--r--sql/sql_table.cc24
-rw-r--r--sql/sql_yacc.yy57
28 files changed, 683 insertions, 153 deletions
diff --git a/include/my_pthread.h b/include/my_pthread.h
index ee2c801ff6e..6f60a6df2c1 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -536,9 +536,15 @@ void safe_mutex_end(FILE *file);
#define pthread_cond_timedwait(A,B,C) safe_cond_timedwait((A),(B),(C),__FILE__,__LINE__)
#define pthread_mutex_trylock(A) pthread_mutex_lock(A)
#define pthread_mutex_t safe_mutex_t
-#define safe_mutex_assert_owner(mp) DBUG_ASSERT((mp)->count > 0 && pthread_equal(pthread_self(),(mp)->thread))
+#define safe_mutex_assert_owner(mp) \
+ DBUG_ASSERT((mp)->count > 0 && \
+ pthread_equal(pthread_self(), (mp)->thread))
+#define safe_mutex_assert_not_owner(mp) \
+ DBUG_ASSERT(! (mp)->count || \
+ ! pthread_equal(pthread_self(), (mp)->thread))
#else
#define safe_mutex_assert_owner(mp)
+#define safe_mutex_assert_not_owner(mp)
#endif /* SAFE_MUTEX */
/* READ-WRITE thread locking */
diff --git a/mysql-test/r/handler.result b/mysql-test/r/handler.result
index 072d4582cbc..133683fb273 100644
--- a/mysql-test/r/handler.result
+++ b/mysql-test/r/handler.result
@@ -445,3 +445,40 @@ drop table t2;
drop table t3;
drop table t4;
drop table t5;
+create table t1 (c1 int);
+insert into t1 values (1);
+handler t1 open;
+handler t1 read first;
+c1
+1
+send the below to another connection, do not wait for the result
+ optimize table t1;
+proceed with the normal connection
+handler t1 read next;
+c1
+1
+handler t1 close;
+read the result from the other connection
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+proceed with the normal connection
+drop table t1;
+create table t1 (c1 int);
+insert into t1 values (14397);
+flush tables with read lock;
+drop table t1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+send the below to another connection, do not wait for the result
+ drop table t1;
+proceed with the normal connection
+select * from t1;
+c1
+14397
+unlock tables;
+read the result from the other connection
+proceed with the normal connection
+select * from t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+drop table if exists t1;
+Warnings:
+Note 1051 Unknown table 't1'
diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result
index 7da55b66376..e000cfd9c11 100644
--- a/mysql-test/r/myisam.result
+++ b/mysql-test/r/myisam.result
@@ -505,6 +505,16 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system NULL NULL NULL NULL 1 Using temporary
1 SIMPLE t2 index NULL PRIMARY 4 NULL 2 Using index; Distinct
drop table t1,t2;
+create table t1 (
+c1 varchar(32),
+key (c1)
+) engine=myisam;
+alter table t1 disable keys;
+insert into t1 values ('a'), ('b');
+select c1 from t1 order by c1 limit 1;
+c1
+a
+drop table t1;
CREATE TABLE t1 (`a` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0', UNIQUE KEY `a` USING RTREE (`a`,`b`)) ENGINE=MyISAM;
Got one of the listed errors
create table t1 (a int, b varchar(200), c text not null) checksum=1;
diff --git a/mysql-test/r/ndb_charset.result b/mysql-test/r/ndb_charset.result
index 500b0497890..3763e20e59a 100644
--- a/mysql-test/r/ndb_charset.result
+++ b/mysql-test/r/ndb_charset.result
@@ -306,11 +306,21 @@ count(*)
drop table t1;
create table t1 (
a char(10) primary key
-) engine=ndb;
-insert into t1 values ('jonas % ');
-replace into t1 values ('jonas % ');
-replace into t1 values ('jonas % ');
+) engine=ndbcluster default charset=latin1;
+insert into t1 values ('aaabb');
+select * from t1;
+a
+aaabb
+replace into t1 set a = 'AAABB';
+select * from t1;
+a
+AAABB
+replace into t1 set a = 'aAaBb';
+select * from t1;
+a
+aAaBb
+replace into t1 set a = 'aaabb';
select * from t1;
a
-jonas %
+aaabb
drop table t1;
diff --git a/mysql-test/r/rpl_sp.result b/mysql-test/r/rpl_sp.result
index ba840caf6c2..41bcfc7d72c 100644
--- a/mysql-test/r/rpl_sp.result
+++ b/mysql-test/r/rpl_sp.result
@@ -375,3 +375,28 @@ drop procedure foo;
drop function fn1;
drop database mysqltest1;
drop user "zedjzlcsjhd"@127.0.0.1;
+use test;
+use test;
+drop function if exists f1;
+create function f1() returns int reads sql data
+begin
+declare var integer;
+declare c cursor for select a from v1;
+open c;
+fetch c into var;
+close c;
+return var;
+end|
+create view v1 as select 1 as a;
+create table t1 (a int);
+insert into t1 (a) values (f1());
+select * from t1;
+a
+1
+drop view v1;
+drop function f1;
+select * from t1;
+a
+1
+drop table t1;
+reset master;
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
index fabbf13a96b..2f4b420a2ae 100644
--- a/mysql-test/r/sp-error.result
+++ b/mysql-test/r/sp-error.result
@@ -872,6 +872,109 @@ names
foo4
drop procedure bug13510_3|
drop procedure bug13510_4|
+drop function if exists bug_13627_f|
+CREATE TABLE t1 (a int)|
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN DROP TRIGGER test1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE FUNCTION bug_13627_f() returns int BEGIN DROP TRIGGER test1; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN load table t1 from master; END |
+ERROR 0A000: LOAD TABLE is not allowed in stored procedures
+CREATE FUNCTION bug_13627_f() returns int BEGIN load table t1 from master; return 1; END |
+ERROR 0A000: LOAD TABLE is not allowed in stored procedures
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create table t2 (a int); END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE FUNCTION bug_13627_f() returns int BEGIN create table t2 (a int); return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create index t1_i on t1 (a); END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE FUNCTION bug_13627_f() returns int BEGIN create index t1_i on t1 (a); return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN alter table t1 add column b int; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE FUNCTION bug_13627_f() returns int BEGIN alter table t1 add column b int; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN rename table t1 to t2; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE FUNCTION bug_13627_f() returns int BEGIN rename table t1 to t2; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN truncate table t1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE FUNCTION bug_13627_f() returns int BEGIN truncate table t1; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop table t1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE FUNCTION bug_13627_f() returns int BEGIN drop table t1; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop index t1_i on t1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE FUNCTION bug_13627_f() returns int BEGIN drop index t1_i on t1; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN unlock tables; END |
+ERROR 0A000: UNLOCK is not allowed in stored procedures
+CREATE FUNCTION bug_13627_f() returns int BEGIN unlock tables; return 1; END |
+ERROR 0A000: UNLOCK is not allowed in stored procedures
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN LOCK TABLE t1 READ; END |
+ERROR 0A000: LOCK is not allowed in stored procedures
+CREATE FUNCTION bug_13627_f() returns int BEGIN LOCK TABLE t1 READ; return 1; END |
+ERROR 0A000: LOCK is not allowed in stored procedures
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create database mysqltest; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE FUNCTION bug_13627_f() returns int BEGIN create database mysqltest; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop database mysqltest; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE FUNCTION bug_13627_f() returns int BEGIN drop database mysqltest; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create user 'mysqltest_1'; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE FUNCTION bug_13627_f() returns int BEGIN create user 'mysqltest_1'; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop user 'mysqltest_1'; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE FUNCTION bug_13627_f() returns int BEGIN drop user 'mysqltest_1'; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN rename user 'mysqltest_2' to 'mysqltest_1'; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE FUNCTION bug_13627_f() returns int BEGIN rename user 'mysqltest_2' to 'mysqltest_1'; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create view v1 as select 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE FUNCTION bug_13627_f() returns int BEGIN create view v1 as select 1; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN alter view v1 as select 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE FUNCTION bug_13627_f() returns int BEGIN alter view v1 as select 1; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop view v1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE FUNCTION bug_13627_f() returns int BEGIN drop view v1; return 1; END |
+ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger.
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create trigger tr2 before insert on t1 for each row do select 1; END |
+ERROR 2F003: Can't create a TRIGGER from within another stored routine
+CREATE FUNCTION bug_13627_f() returns int BEGIN create trigger tr2 before insert on t1 for each row do select 1; return 1; END |
+ERROR 2F003: Can't create a TRIGGER from within another stored routine
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop function bug_13627_f; END |
+ERROR HY000: Can't drop or alter a FUNCTION from within another stored routine
+CREATE FUNCTION bug_13627_f() returns int BEGIN drop function bug_13627_f; return 1; END |
+ERROR HY000: Can't drop or alter a FUNCTION from within another stored routine
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create function f2 () returns int return 1; END |
+ERROR 2F003: Can't create a FUNCTION from within another stored routine
+CREATE FUNCTION bug_13627_f() returns int BEGIN create function f2 () returns int return 1; return 1; END |
+ERROR 2F003: Can't create a FUNCTION from within another stored routine
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+CREATE TEMPORARY TABLE t2 (a int);
+DROP TEMPORARY TABLE t2;
+END |
+CREATE FUNCTION bug_13627_f() returns int
+BEGIN
+CREATE TEMPORARY TABLE t2 (a int);
+DROP TEMPORARY TABLE t2;
+return 1;
+END |
+drop table t1|
+drop function bug_13627_f|
create database mysqltest1;
use mysqltest1;
drop database mysqltest1;
diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def
index eedf4b30e73..fe95a543fb5 100644
--- a/mysql-test/t/disabled.def
+++ b/mysql-test/t/disabled.def
@@ -15,4 +15,3 @@ rpl_relayrotate : Unstable test case, bug#12429
rpl_until : Unstable test case, bug#12429
rpl_deadlock : Unstable test case, bug#12429
kill : Unstable test case, bug#9712
-archive_gis : The test fails on 32bit Linux
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index 9237205eeb5..c667f90940c 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -2,8 +2,6 @@
# simple test of all group functions
#
---source include/have_innodb.inc
-
--disable_warnings
drop table if exists t1,t2;
--enable_warnings
@@ -545,10 +543,12 @@ DROP TABLE t1;
# Bug #12882 min/max inconsistent on empty table
#
+--disable_warnings
create table t1m (a int) engine=myisam;
create table t1i (a int) engine=innodb;
create table t2m (a int) engine=myisam;
create table t2i (a int) engine=innodb;
+--enable_warnings
insert into t2m values (5);
insert into t2i values (5);
diff --git a/mysql-test/t/handler.test b/mysql-test/t/handler.test
index 1bb9b1d3504..f3e14c3cd2b 100644
--- a/mysql-test/t/handler.test
+++ b/mysql-test/t/handler.test
@@ -347,4 +347,79 @@ drop table t3;
drop table t4;
drop table t5;
+#
+# Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash
+#
+create table t1 (c1 int);
+insert into t1 values (1);
+# client 1
+handler t1 open;
+handler t1 read first;
+# client 2
+connect (con2,localhost,root,,);
+connection con2;
+--exec echo send the below to another connection, do not wait for the result
+send optimize table t1;
+--sleep 1
+# client 1
+--exec echo proceed with the normal connection
+connection default;
+handler t1 read next;
+handler t1 close;
+# client 2
+--exec echo read the result from the other connection
+connection con2;
+reap;
+# client 1
+--exec echo proceed with the normal connection
+connection default;
+drop table t1;
+
# End of 4.1 tests
+
+#
+# Addendum to Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash
+# Show that DROP TABLE can no longer deadlock against
+# FLUSH TABLES WITH READ LOCK. This is a 5.0 issue.
+#
+create table t1 (c1 int);
+insert into t1 values (14397);
+flush tables with read lock;
+# The thread with the global read lock cannot drop the table itself:
+--error 1223
+drop table t1;
+#
+# client 2
+# We need a second connection to try the drop.
+# The drop waits for the global read lock to go away.
+# Without the addendum fix it locked LOCK_open before entering the wait loop.
+connection con2;
+--exec echo send the below to another connection, do not wait for the result
+send drop table t1;
+--sleep 1
+#
+# client 1
+# Now we need something that wants LOCK_open. A simple table access which
+# opens the table does the trick.
+--exec echo proceed with the normal connection
+connection default;
+# This would hang on LOCK_open without the 5.0 addendum fix.
+select * from t1;
+# Release the read lock. This should make the DROP go through.
+unlock tables;
+#
+# client 2
+# Read the result of the drop command.
+connection con2;
+--exec echo read the result from the other connection
+reap;
+#
+# client 1
+# Now back to normal operation. The table should not exist any more.
+--exec echo proceed with the normal connection
+connection default;
+--error 1146
+select * from t1;
+# Just to be sure and not confuse the next test case writer.
+drop table if exists t1;
+
diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test
index d510ef66677..fb90c16bb86 100644
--- a/mysql-test/t/myisam.test
+++ b/mysql-test/t/myisam.test
@@ -477,6 +477,18 @@ explain select distinct t1.a from t1,t2 order by t2.a;
drop table t1,t2;
#
+# Bug#14616 - Freshly imported table returns error 124 when using LIMIT
+#
+create table t1 (
+ c1 varchar(32),
+ key (c1)
+) engine=myisam;
+alter table t1 disable keys;
+insert into t1 values ('a'), ('b');
+select c1 from t1 order by c1 limit 1;
+drop table t1;
+
+#
# Test RTREE index
#
--error 1235, 1289
diff --git a/mysql-test/t/ndb_charset.test b/mysql-test/t/ndb_charset.test
index fb43e1831f3..5941e5750db 100644
--- a/mysql-test/t/ndb_charset.test
+++ b/mysql-test/t/ndb_charset.test
@@ -237,13 +237,18 @@ drop table t1;
#select a,b,length(a),length(b) from t1 where a='c' and b='c';
#drop table t1;
-# bug
+# bug#14007
create table t1 (
a char(10) primary key
-) engine=ndb;
-insert into t1 values ('jonas % ');
-replace into t1 values ('jonas % ');
-replace into t1 values ('jonas % ');
+) engine=ndbcluster default charset=latin1;
+
+insert into t1 values ('aaabb');
+select * from t1;
+replace into t1 set a = 'AAABB';
+select * from t1;
+replace into t1 set a = 'aAaBb';
+select * from t1;
+replace into t1 set a = 'aaabb';
select * from t1;
drop table t1;
diff --git a/mysql-test/t/rpl_sp.test b/mysql-test/t/rpl_sp.test
index e7a3afca9cb..386582f8f1b 100644
--- a/mysql-test/t/rpl_sp.test
+++ b/mysql-test/t/rpl_sp.test
@@ -360,4 +360,40 @@ connection master;
drop function fn1;
drop database mysqltest1;
drop user "zedjzlcsjhd"@127.0.0.1;
+use test;
sync_slave_with_master;
+use test;
+
+#
+# Bug#14077 "Failure to replicate a stored function with a cursor":
+# verify that stored routines with cursors work on slave.
+#
+connection master;
+--disable_warnings
+drop function if exists f1;
+--enable_warnings
+delimiter |;
+create function f1() returns int reads sql data
+begin
+ declare var integer;
+ declare c cursor for select a from v1;
+ open c;
+ fetch c into var;
+ close c;
+ return var;
+end|
+delimiter ;|
+create view v1 as select 1 as a;
+create table t1 (a int);
+insert into t1 (a) values (f1());
+select * from t1;
+drop view v1;
+drop function f1;
+sync_slave_with_master;
+connection slave;
+select * from t1;
+
+# cleanup
+connection master;
+drop table t1;
+reset master;
diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
index 3c1efe73c18..f16562227f3 100644
--- a/mysql-test/t/sp-error.test
+++ b/mysql-test/t/sp-error.test
@@ -1263,6 +1263,144 @@ call bug13510_4()|
drop procedure bug13510_3|
drop procedure bug13510_4|
+
+
+#
+# Test that statements which implicitly commit transaction are prohibited
+# in stored function and triggers. Attempt to create function or trigger
+# containing such statement should produce error (includes test for
+# bug #13627).
+#
+--disable_warnings
+drop function if exists bug_13627_f|
+--enable_warnings
+
+CREATE TABLE t1 (a int)|
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN DROP TRIGGER test1; END |
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE FUNCTION bug_13627_f() returns int BEGIN DROP TRIGGER test1; return 1; END |
+
+-- error ER_SP_BADSTATEMENT
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN load table t1 from master; END |
+-- error ER_SP_BADSTATEMENT
+CREATE FUNCTION bug_13627_f() returns int BEGIN load table t1 from master; return 1; END |
+
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create table t2 (a int); END |
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE FUNCTION bug_13627_f() returns int BEGIN create table t2 (a int); return 1; END |
+
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create index t1_i on t1 (a); END |
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE FUNCTION bug_13627_f() returns int BEGIN create index t1_i on t1 (a); return 1; END |
+
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN alter table t1 add column b int; END |
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE FUNCTION bug_13627_f() returns int BEGIN alter table t1 add column b int; return 1; END |
+
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN rename table t1 to t2; END |
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE FUNCTION bug_13627_f() returns int BEGIN rename table t1 to t2; return 1; END |
+
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN truncate table t1; END |
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE FUNCTION bug_13627_f() returns int BEGIN truncate table t1; return 1; END |
+
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop table t1; END |
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE FUNCTION bug_13627_f() returns int BEGIN drop table t1; return 1; END |
+
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop index t1_i on t1; END |
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE FUNCTION bug_13627_f() returns int BEGIN drop index t1_i on t1; return 1; END |
+
+-- error ER_SP_BADSTATEMENT
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN unlock tables; END |
+-- error ER_SP_BADSTATEMENT
+CREATE FUNCTION bug_13627_f() returns int BEGIN unlock tables; return 1; END |
+
+-- error ER_SP_BADSTATEMENT
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN LOCK TABLE t1 READ; END |
+-- error ER_SP_BADSTATEMENT
+CREATE FUNCTION bug_13627_f() returns int BEGIN LOCK TABLE t1 READ; return 1; END |
+
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create database mysqltest; END |
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE FUNCTION bug_13627_f() returns int BEGIN create database mysqltest; return 1; END |
+
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop database mysqltest; END |
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE FUNCTION bug_13627_f() returns int BEGIN drop database mysqltest; return 1; END |
+
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create user 'mysqltest_1'; END |
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE FUNCTION bug_13627_f() returns int BEGIN create user 'mysqltest_1'; return 1; END |
+
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop user 'mysqltest_1'; END |
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE FUNCTION bug_13627_f() returns int BEGIN drop user 'mysqltest_1'; return 1; END |
+
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN rename user 'mysqltest_2' to 'mysqltest_1'; END |
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE FUNCTION bug_13627_f() returns int BEGIN rename user 'mysqltest_2' to 'mysqltest_1'; return 1; END |
+
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create view v1 as select 1; END |
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE FUNCTION bug_13627_f() returns int BEGIN create view v1 as select 1; return 1; END |
+
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN alter view v1 as select 1; END |
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE FUNCTION bug_13627_f() returns int BEGIN alter view v1 as select 1; return 1; END |
+
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop view v1; END |
+-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG
+CREATE FUNCTION bug_13627_f() returns int BEGIN drop view v1; return 1; END |
+
+-- error ER_SP_NO_RECURSIVE_CREATE
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create trigger tr2 before insert on t1 for each row do select 1; END |
+-- error ER_SP_NO_RECURSIVE_CREATE
+CREATE FUNCTION bug_13627_f() returns int BEGIN create trigger tr2 before insert on t1 for each row do select 1; return 1; END |
+
+-- error ER_SP_NO_DROP_SP
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop function bug_13627_f; END |
+-- error ER_SP_NO_DROP_SP
+CREATE FUNCTION bug_13627_f() returns int BEGIN drop function bug_13627_f; return 1; END |
+
+-- error ER_SP_NO_RECURSIVE_CREATE
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN create function f2 () returns int return 1; END |
+-- error ER_SP_NO_RECURSIVE_CREATE
+CREATE FUNCTION bug_13627_f() returns int BEGIN create function f2 () returns int return 1; return 1; END |
+
+CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW
+ BEGIN
+ CREATE TEMPORARY TABLE t2 (a int);
+ DROP TEMPORARY TABLE t2;
+ END |
+CREATE FUNCTION bug_13627_f() returns int
+ BEGIN
+ CREATE TEMPORARY TABLE t2 (a int);
+ DROP TEMPORARY TABLE t2;
+ return 1;
+ END |
+
+drop table t1|
+drop function bug_13627_f|
+
delimiter ;|
#
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
index acdad3f9f1a..8a55777ac05 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
@@ -684,6 +684,21 @@ Dbtup::checkUpdateOfPrimaryKey(Uint32* updateBuffer, Tablerec* const regTabPtr)
Uint32 attrDescriptorIndex = regTabPtr->tabDescriptor + (attributeId << ZAD_LOG_SIZE);
Uint32 attrDescriptor = tableDescriptor[attrDescriptorIndex].tabDescr;
Uint32 attributeOffset = tableDescriptor[attrDescriptorIndex + 1].tabDescr;
+
+ Uint32 xfrmBuffer[1 + MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY];
+ Uint32 charsetFlag = AttributeOffset::getCharsetFlag(attributeOffset);
+ if (charsetFlag) {
+ Uint32 csIndex = AttributeOffset::getCharsetPos(attributeOffset);
+ CHARSET_INFO* cs = regTabPtr->charsetArray[csIndex];
+ Uint32 srcPos = 0;
+ Uint32 dstPos = 0;
+ xfrm_attr(attrDescriptor, cs, &updateBuffer[1], srcPos,
+ &xfrmBuffer[1], dstPos, MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY);
+ ahIn.setDataSize(dstPos);
+ xfrmBuffer[0] = ahIn.m_value;
+ updateBuffer = xfrmBuffer;
+ }
+
ReadFunction f = regTabPtr->readFunctionArray[attributeId];
AttributeHeader::init(&attributeHeader, attributeId, 0);
@@ -691,7 +706,7 @@ Dbtup::checkUpdateOfPrimaryKey(Uint32* updateBuffer, Tablerec* const regTabPtr)
tMaxRead = MAX_KEY_SIZE_IN_WORDS;
bool tmp = tXfrmFlag;
- tXfrmFlag = false;
+ tXfrmFlag = true;
ndbrequire((this->*f)(&keyReadBuffer[0], ahOut, attrDescriptor, attributeOffset));
tXfrmFlag = tmp;
ndbrequire(tOutBufIndex == ahOut->getDataSize());
diff --git a/ndb/src/kernel/vm/SimulatedBlock.cpp b/ndb/src/kernel/vm/SimulatedBlock.cpp
index d708052ca4e..4625cd43640 100644
--- a/ndb/src/kernel/vm/SimulatedBlock.cpp
+++ b/ndb/src/kernel/vm/SimulatedBlock.cpp
@@ -1868,49 +1868,9 @@ SimulatedBlock::xfrm_key(Uint32 tab, const Uint32* src,
while (i < noOfKeyAttr)
{
const KeyDescriptor::KeyAttr& keyAttr = desc->keyAttr[i];
-
- Uint32 srcBytes =
- AttributeDescriptor::getSizeInBytes(keyAttr.attributeDescriptor);
- Uint32 srcWords = (srcBytes + 3) / 4;
- Uint32 dstWords = ~0;
- uchar* dstPtr = (uchar*)&dst[dstPos];
- const uchar* srcPtr = (const uchar*)&src[srcPos];
- CHARSET_INFO* cs = keyAttr.charsetInfo;
-
- if (cs == NULL)
- {
- jam();
- memcpy(dstPtr, srcPtr, srcWords << 2);
- dstWords = srcWords;
- }
- else
- {
- jam();
- Uint32 typeId =
- AttributeDescriptor::getType(keyAttr.attributeDescriptor);
- Uint32 lb, len;
- bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len);
- ndbrequire(ok);
- Uint32 xmul = cs->strxfrm_multiply;
- if (xmul == 0)
- xmul = 1;
- /*
- * Varchar is really Char. End spaces do not matter. To get
- * same hash we blank-pad to maximum length via strnxfrm.
- * TODO use MySQL charset-aware hash function instead
- */
- Uint32 dstLen = xmul * (srcBytes - lb);
- ndbrequire(dstLen <= ((dstSize - dstPos) << 2));
- int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
- ndbrequire(n != -1);
- while ((n & 3) != 0)
- {
- dstPtr[n++] = 0;
- }
- dstWords = (n >> 2);
- }
- dstPos += dstWords;
- srcPos += srcWords;
+ Uint32 dstWords =
+ xfrm_attr(keyAttr.attributeDescriptor, keyAttr.charsetInfo,
+ src, srcPos, dst, dstPos, dstSize);
keyPartLen[i++] = dstWords;
}
@@ -1918,6 +1878,52 @@ SimulatedBlock::xfrm_key(Uint32 tab, const Uint32* src,
}
Uint32
+SimulatedBlock::xfrm_attr(Uint32 attrDesc, CHARSET_INFO* cs,
+ const Uint32* src, Uint32 & srcPos,
+ Uint32* dst, Uint32 & dstPos, Uint32 dstSize) const
+{
+ Uint32 srcBytes = AttributeDescriptor::getSizeInBytes(attrDesc);
+ Uint32 srcWords = (srcBytes + 3) / 4;
+ Uint32 dstWords = ~0;
+ uchar* dstPtr = (uchar*)&dst[dstPos];
+ const uchar* srcPtr = (const uchar*)&src[srcPos];
+
+ if (cs == NULL)
+ {
+ jam();
+ memcpy(dstPtr, srcPtr, srcWords << 2);
+ dstWords = srcWords;
+ }
+ else
+ {
+ jam();
+ Uint32 typeId = AttributeDescriptor::getType(attrDesc);
+ Uint32 lb, len;
+ bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len);
+ ndbrequire(ok);
+ Uint32 xmul = cs->strxfrm_multiply;
+ if (xmul == 0)
+ xmul = 1;
+ /*
+ * Varchar end-spaces are ignored in comparisons. To get same hash
+ * we blank-pad to maximum length via strnxfrm.
+ */
+ Uint32 dstLen = xmul * (srcBytes - lb);
+ ndbrequire(dstLen <= ((dstSize - dstPos) << 2));
+ int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
+ ndbrequire(n != -1);
+ while ((n & 3) != 0)
+ {
+ dstPtr[n++] = 0;
+ }
+ dstWords = (n >> 2);
+ }
+ dstPos += dstWords;
+ srcPos += srcWords;
+ return dstWords;
+}
+
+Uint32
SimulatedBlock::create_distr_key(Uint32 tableId,
Uint32 *data,
const Uint32
diff --git a/ndb/src/kernel/vm/SimulatedBlock.hpp b/ndb/src/kernel/vm/SimulatedBlock.hpp
index ce77fa916d8..b7bd8c57ee8 100644
--- a/ndb/src/kernel/vm/SimulatedBlock.hpp
+++ b/ndb/src/kernel/vm/SimulatedBlock.hpp
@@ -395,8 +395,12 @@ protected:
* @return length
*/
Uint32 xfrm_key(Uint32 tab, const Uint32* src,
- Uint32 *dst, Uint32 dstLen,
+ Uint32 *dst, Uint32 dstSize,
Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const;
+
+ Uint32 xfrm_attr(Uint32 attrDesc, CHARSET_INFO* cs,
+ const Uint32* src, Uint32 & srcPos,
+ Uint32* dst, Uint32 & dstPos, Uint32 dstSize) const;
/**
*
diff --git a/sql/ha_archive.cc b/sql/ha_archive.cc
index c4801de5fb2..1e8fc582eb8 100644
--- a/sql/ha_archive.cc
+++ b/sql/ha_archive.cc
@@ -233,7 +233,8 @@ ha_archive::ha_archive(TABLE *table_arg)
buffer.set((char *)byte_buffer, IO_SIZE, system_charset_info);
/* The size of the offset value we will use for position() */
- ref_length = sizeof(z_off_t);
+ ref_length = 2 << ((zlibCompileFlags() >> 6) & 3);
+ DBUG_ASSERT(ref_length <= sizeof(z_off_t));
}
/*
diff --git a/sql/lock.cc b/sql/lock.cc
index f4c4a781e45..fe8dcb3aa5e 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -815,10 +815,13 @@ static void print_lock_error(int error, const char *table)
access to them is protected with a mutex LOCK_global_read_lock
- (XXX: one should never take LOCK_open if LOCK_global_read_lock is taken,
- otherwise a deadlock may occur - see mysql_rm_table. Other mutexes could
- be a problem too - grep the code for global_read_lock if you want to use
- any other mutex here)
+ (XXX: one should never take LOCK_open if LOCK_global_read_lock is
+ taken, otherwise a deadlock may occur. Other mutexes could be a
+ problem too - grep the code for global_read_lock if you want to use
+ any other mutex here) Also one must not hold LOCK_open when calling
+ wait_if_global_read_lock(). When the thread with the global read lock
+ tries to close its tables, it needs to take LOCK_open in
+ close_thread_table().
How blocking of threads by global read lock is achieved: that's
advisory. Any piece of code which should be blocked by global read lock must
@@ -937,6 +940,13 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
DBUG_ENTER("wait_if_global_read_lock");
LINT_INIT(old_message);
+ /*
+ Assert that we do not own LOCK_open. If we would own it, other
+ threads could not close their tables. This would make a pretty
+ deadlock.
+ */
+ safe_mutex_assert_not_owner(&LOCK_open);
+
(void) pthread_mutex_lock(&LOCK_global_read_lock);
if ((need_exit_cond= must_wait))
{
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 15424087a43..905c6550cba 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -891,7 +891,8 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen);
bool mysql_ha_close(THD *thd, TABLE_LIST *tables);
bool mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows);
-int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags);
+int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags,
+ bool is_locked);
/* mysql_ha_flush mode_flags bits */
#define MYSQL_HA_CLOSE_FINAL 0x00
#define MYSQL_HA_REOPEN_ON_USAGE 0x01
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index facd984cc50..e3cdc909048 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -120,6 +120,45 @@ sp_get_flags_for_command(LEX *lex)
case SQLCOM_DEALLOCATE_PREPARE:
flags= sp_head::CONTAINS_DYNAMIC_SQL;
break;
+ case SQLCOM_CREATE_TABLE:
+ if (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)
+ flags= 0;
+ else
+ flags= sp_head::HAS_COMMIT_OR_ROLLBACK;
+ break;
+ case SQLCOM_DROP_TABLE:
+ if (lex->drop_temporary)
+ flags= 0;
+ else
+ flags= sp_head::HAS_COMMIT_OR_ROLLBACK;
+ break;
+ case SQLCOM_CREATE_INDEX:
+ case SQLCOM_CREATE_DB:
+ case SQLCOM_CREATE_VIEW:
+ case SQLCOM_CREATE_TRIGGER:
+ case SQLCOM_CREATE_USER:
+ case SQLCOM_ALTER_TABLE:
+ case SQLCOM_BEGIN:
+ case SQLCOM_RENAME_TABLE:
+ case SQLCOM_RENAME_USER:
+ case SQLCOM_DROP_INDEX:
+ case SQLCOM_DROP_DB:
+ case SQLCOM_DROP_USER:
+ case SQLCOM_DROP_VIEW:
+ case SQLCOM_DROP_TRIGGER:
+ case SQLCOM_TRUNCATE:
+ case SQLCOM_COMMIT:
+ case SQLCOM_ROLLBACK:
+ case SQLCOM_LOAD_MASTER_DATA:
+ case SQLCOM_LOCK_TABLES:
+ case SQLCOM_CREATE_PROCEDURE:
+ case SQLCOM_CREATE_SPFUNCTION:
+ case SQLCOM_ALTER_PROCEDURE:
+ case SQLCOM_ALTER_FUNCTION:
+ case SQLCOM_DROP_PROCEDURE:
+ case SQLCOM_DROP_FUNCTION:
+ flags= sp_head::HAS_COMMIT_OR_ROLLBACK;
+ break;
default:
flags= 0;
break;
diff --git a/sql/sp_head.h b/sql/sp_head.h
index d1a122fd410..8c2d58a696e 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -115,10 +115,13 @@ public:
MULTI_RESULTS= 8, // Is set if a procedure with SELECT(s)
CONTAINS_DYNAMIC_SQL= 16, // Is set if a procedure with PREPARE/EXECUTE
IS_INVOKED= 32, // Is set if this sp_head is being used
- HAS_SET_AUTOCOMMIT_STMT = 64 // Is set if a procedure with 'set autocommit'
+ HAS_SET_AUTOCOMMIT_STMT= 64,// Is set if a procedure with 'set autocommit'
+ /* Is set if a procedure with COMMIT (implicit or explicit) | ROLLBACK */
+ HAS_COMMIT_OR_ROLLBACK= 128
};
- int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE
+ /* TYPE_ENUM_FUNCTION, TYPE_ENUM_PROCEDURE or TYPE_ENUM_TRIGGER */
+ int m_type;
uint m_flags; // Boolean attributes of a stored routine
enum enum_field_types m_returns; // For FUNCTIONs only
Field::geometry_type m_geom_returns;
@@ -292,6 +295,12 @@ public:
my_error(ER_SP_NO_RETSET, MYF(0), where);
else if (m_flags & HAS_SET_AUTOCOMMIT_STMT)
my_error(ER_SP_CANT_SET_AUTOCOMMIT, MYF(0));
+ else if (m_type != TYPE_ENUM_PROCEDURE &&
+ (m_flags & sp_head::HAS_COMMIT_OR_ROLLBACK))
+ {
+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+ return TRUE;
+ }
return test(m_flags &
(CONTAINS_DYNAMIC_SQL|MULTI_RESULTS|HAS_SET_AUTOCOMMIT_STMT));
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index e75b3ac3db5..5753c51fcf4 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -311,7 +311,8 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
thd->proc_info="Flushing tables";
close_old_data_files(thd,thd->open_tables,1,1);
- mysql_ha_flush(thd, tables, MYSQL_HA_REOPEN_ON_USAGE | MYSQL_HA_FLUSH_ALL);
+ mysql_ha_flush(thd, tables, MYSQL_HA_REOPEN_ON_USAGE | MYSQL_HA_FLUSH_ALL,
+ TRUE);
bool found=1;
/* Wait until all threads has closed all the tables we had locked */
DBUG_PRINT("info",
@@ -1238,7 +1239,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
/* close handler tables which are marked for flush */
if (thd->handler_tables)
- mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE);
+ mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, TRUE);
for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ;
table && table->in_use ;
@@ -1642,7 +1643,7 @@ bool wait_for_tables(THD *thd)
{
thd->some_tables_deleted=0;
close_old_data_files(thd,thd->open_tables,0,dropping_tables != 0);
- mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE);
+ mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, TRUE);
if (!table_is_used(thd->open_tables,1))
break;
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 3c8702006f3..d5292be422b 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -376,7 +376,7 @@ void THD::cleanup(void)
close_thread_tables(this);
}
mysql_ha_flush(this, (TABLE_LIST*) 0,
- MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL);
+ MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL, FALSE);
hash_free(&handler_tables_hash);
delete_dynamic(&user_var_events);
hash_free(&user_vars);
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index cc45a7001cd..da72d283259 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -336,6 +336,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
ha_rows select_limit_cnt, ha_rows offset_limit_cnt)
{
TABLE_LIST *hash_tables;
+ TABLE **table_ptr;
TABLE *table;
MYSQL_LOCK *lock;
List<Item> list;
@@ -368,6 +369,28 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
DBUG_PRINT("info-in-hash",("'%s'.'%s' as '%s' tab %p",
hash_tables->db, hash_tables->table_name,
hash_tables->alias, table));
+ /* Table might have been flushed. */
+ if (table && (table->s->version != refresh_version))
+ {
+ /*
+ We must follow the thd->handler_tables chain, as we need the
+ address of the 'next' pointer referencing this table
+ for close_thread_table().
+ */
+ for (table_ptr= &(thd->handler_tables);
+ *table_ptr && (*table_ptr != table);
+ table_ptr= &(*table_ptr)->next)
+ {}
+ (*table_ptr)->file->ha_index_or_rnd_end();
+ VOID(pthread_mutex_lock(&LOCK_open));
+ if (close_thread_table(thd, table_ptr))
+ {
+ /* Tell threads waiting for refresh that something has happened */
+ VOID(pthread_cond_broadcast(&COND_refresh));
+ }
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ table= hash_tables->table= NULL;
+ }
if (!table)
{
/*
@@ -594,6 +617,7 @@ err0:
MYSQL_HA_REOPEN_ON_USAGE mark for reopen.
MYSQL_HA_FLUSH_ALL flush all tables, not only
those marked for flush.
+ is_locked If LOCK_open is locked.
DESCRIPTION
The list of HANDLER tables may be NULL, in which case all HANDLER
@@ -601,7 +625,6 @@ err0:
If 'tables' is NULL and MYSQL_HA_FLUSH_ALL is not set,
all HANDLER tables marked for flush are closed.
Broadcasts a COND_refresh condition, for every table closed.
- The caller must lock LOCK_open.
NOTE
Since mysql_ha_flush() is called when the base table has to be closed,
@@ -611,10 +634,12 @@ err0:
0 ok
*/
-int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags)
+int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags,
+ bool is_locked)
{
TABLE_LIST *tmp_tables;
TABLE **table_ptr;
+ bool did_lock= FALSE;
DBUG_ENTER("mysql_ha_flush");
DBUG_PRINT("enter", ("tables: %p mode_flags: 0x%02x", tables, mode_flags));
@@ -640,6 +665,12 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags)
(*table_ptr)->s->db,
(*table_ptr)->s->table_name,
(*table_ptr)->alias));
+ /* The first time it is required, lock for close_thread_table(). */
+ if (! did_lock && ! is_locked)
+ {
+ VOID(pthread_mutex_lock(&LOCK_open));
+ did_lock= TRUE;
+ }
mysql_ha_flush_table(thd, table_ptr, mode_flags);
continue;
}
@@ -658,6 +689,12 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags)
if ((mode_flags & MYSQL_HA_FLUSH_ALL) ||
((*table_ptr)->s->version != refresh_version))
{
+ /* The first time it is required, lock for close_thread_table(). */
+ if (! did_lock && ! is_locked)
+ {
+ VOID(pthread_mutex_lock(&LOCK_open));
+ did_lock= TRUE;
+ }
mysql_ha_flush_table(thd, table_ptr, mode_flags);
continue;
}
@@ -665,6 +702,10 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags)
}
}
+ /* Release the lock if it was taken by this function. */
+ if (did_lock)
+ VOID(pthread_mutex_unlock(&LOCK_open));
+
DBUG_RETURN(0);
}
@@ -696,8 +737,8 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags)
table->alias, mode_flags));
if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
- (byte*) (*table_ptr)->alias,
- strlen((*table_ptr)->alias) + 1)))
+ (byte*) table->alias,
+ strlen(table->alias) + 1)))
{
if (! (mode_flags & MYSQL_HA_REOPEN_ON_USAGE))
{
@@ -711,7 +752,9 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags)
}
}
+ safe_mutex_assert_owner(&LOCK_open);
(*table_ptr)->file->ha_index_or_rnd_end();
+ safe_mutex_assert_owner(&LOCK_open);
if (close_thread_table(thd, table_ptr))
{
/* Tell threads waiting for refresh that something has happened */
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index b90e45a133f..2659689a4bc 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2403,18 +2403,6 @@ mysql_execute_command(THD *thd)
reset_one_shot_variables(thd);
DBUG_RETURN(0);
}
-#ifndef TO_BE_DELETED
- /*
- This is a workaround to deal with the shortcoming in 3.23.44-3.23.46
- masters in RELEASE_LOCK() logging. We re-write SELECT RELEASE_LOCK()
- as DO RELEASE_LOCK()
- */
- if (lex->sql_command == SQLCOM_SELECT)
- {
- lex->sql_command = SQLCOM_DO;
- lex->insert_list = &select_lex->item_list;
- }
-#endif
}
else
#endif /* HAVE_REPLICATION */
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 0ae598eb094..a847c2a57a5 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -11142,8 +11142,12 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
DBUG_ENTER("test_if_skip_sort_order");
LINT_INIT(ref_key_parts);
- /* Check which keys can be used to resolve ORDER BY */
- usable_keys.set_all();
+ /*
+ Check which keys can be used to resolve ORDER BY.
+ We must not try to use disabled keys.
+ */
+ usable_keys= table->s->keys_in_use;
+
for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next)
{
Item *item= (*tmp_order->item)->real_item();
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index c0748abf333..815cdfe6cc5 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -103,23 +103,28 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
/* mark for close and remove all cached entries */
- thd->mysys_var->current_mutex= &LOCK_open;
- thd->mysys_var->current_cond= &COND_refresh;
- VOID(pthread_mutex_lock(&LOCK_open));
-
if (!drop_temporary)
{
if ((error= wait_if_global_read_lock(thd, 0, 1)))
{
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), tables->table_name);
- goto err;
+ DBUG_RETURN(TRUE);
}
else
need_start_waiters= TRUE;
}
+
+ /*
+ Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
+ LOCK_open during wait_if_global_read_lock(), other threads could not
+ close their tables. This would make a pretty deadlock.
+ */
+ thd->mysys_var->current_mutex= &LOCK_open;
+ thd->mysys_var->current_cond= &COND_refresh;
+ VOID(pthread_mutex_lock(&LOCK_open));
+
error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
-err:
pthread_mutex_unlock(&LOCK_open);
pthread_mutex_lock(&thd->mysys_var->mutex);
@@ -232,7 +237,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
char *db=table->db;
db_type table_type= DB_TYPE_UNKNOWN;
- mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL);
+ mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL, TRUE);
if (!close_temporary_table(thd, db, table->table_name))
{
tmp_table_deleted=1;
@@ -2171,7 +2176,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
- mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL);
+ mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL, FALSE);
for (table= tables; table; table= table->next_local)
{
char table_name[NAME_LEN*2+2];
@@ -3127,8 +3132,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
new_db= db;
used_fields=create_info->used_fields;
+
+ mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL, FALSE);
- mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL);
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index c9ae6179ee9..85c07e6daba 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1159,11 +1159,6 @@ create:
| CREATE opt_unique_or_fulltext INDEX_SYM ident key_alg ON table_ident
{
LEX *lex=Lex;
- if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
lex->sql_command= SQLCOM_CREATE_INDEX;
if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL,
TL_OPTION_UPDATING))
@@ -3299,11 +3294,6 @@ alter:
{
THD *thd= YYTHD;
LEX *lex= thd->lex;
- if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
lex->sql_command= SQLCOM_ALTER_TABLE;
lex->name= 0;
lex->duplicates= DUP_ERROR;
@@ -3614,11 +3604,6 @@ start:
START_SYM TRANSACTION_SYM start_transaction_opts
{
LEX *lex= Lex;
- if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
lex->sql_command= SQLCOM_BEGIN;
lex->start_transaction_opt= $3;
}
@@ -3803,13 +3788,7 @@ opt_no_write_to_binlog:
rename:
RENAME table_or_tables
{
- LEX *lex= Lex;
- if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
- lex->sql_command=SQLCOM_RENAME_TABLE;
+ Lex->sql_command= SQLCOM_RENAME_TABLE;
}
table_to_table_list
{}
@@ -5946,21 +5925,10 @@ drop:
lex->sql_command = SQLCOM_DROP_TABLE;
lex->drop_temporary= $2;
lex->drop_if_exists= $4;
- if (!lex->drop_temporary && lex->sphead &&
- lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
}
| DROP INDEX_SYM ident ON table_ident {}
{
LEX *lex=Lex;
- if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
lex->sql_command= SQLCOM_DROP_INDEX;
lex->alter_info.drop_list.empty();
lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY,
@@ -6006,13 +5974,7 @@ drop:
}
| DROP VIEW_SYM if_exists table_list opt_restrict
{
- THD *thd= YYTHD;
- LEX *lex= thd->lex;
- if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
+ LEX *lex= Lex;
lex->sql_command= SQLCOM_DROP_VIEW;
lex->drop_if_exists= $3;
}
@@ -8652,11 +8614,6 @@ begin:
BEGIN_SYM
{
LEX *lex=Lex;
- if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
lex->sql_command = SQLCOM_BEGIN;
lex->start_transaction_opt= 0;
}
@@ -8689,11 +8646,6 @@ commit:
COMMIT_SYM opt_work opt_chain opt_release
{
LEX *lex=Lex;
- if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
lex->sql_command= SQLCOM_COMMIT;
lex->tx_chain= $3;
lex->tx_release= $4;
@@ -8704,11 +8656,6 @@ rollback:
ROLLBACK_SYM opt_work opt_chain opt_release
{
LEX *lex=Lex;
- if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
lex->sql_command= SQLCOM_ROLLBACK;
lex->tx_chain= $3;
lex->tx_release= $4;