summaryrefslogtreecommitdiff
path: root/mysql-test/suite/handler
diff options
context:
space:
mode:
Diffstat (limited to 'mysql-test/suite/handler')
-rw-r--r--mysql-test/suite/handler/aria.result990
-rw-r--r--mysql-test/suite/handler/handler.inc1084
-rw-r--r--mysql-test/suite/handler/heap.result970
-rw-r--r--mysql-test/suite/handler/heap.test1
-rw-r--r--mysql-test/suite/handler/init.inc6
-rw-r--r--mysql-test/suite/handler/innodb.result992
-rw-r--r--mysql-test/suite/handler/interface.result73
-rw-r--r--mysql-test/suite/handler/interface.test148
-rw-r--r--mysql-test/suite/handler/myisam.result990
9 files changed, 5126 insertions, 128 deletions
diff --git a/mysql-test/suite/handler/aria.result b/mysql-test/suite/handler/aria.result
index efddd7784fd..72d096132e6 100644
--- a/mysql-test/suite/handler/aria.result
+++ b/mysql-test/suite/handler/aria.result
@@ -1,6 +1,6 @@
SET SESSION STORAGE_ENGINE = Aria;
drop table if exists t1,t3,t4,t5;
-create table t1 (a int, b char(10), key a (a), key b (a,b));
+create table t1 (a int, b char(10), key a using btree (a), key b using btree (a,b));
insert into t1 values
(17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"),
(14,"aaa"),(16,"ccc"),(16,"xxx"),
@@ -362,7 +362,8 @@ prepare stmt from 'handler t1 read a=(?)';
flush tables;
set @a=17;
execute stmt using @a;
-ERROR HY000: Prepared statement needs to be re-prepared
+a b c
+17 ddd NULL
deallocate prepare stmt;
handler t1 close;
handler t1 open as t2;
@@ -372,7 +373,7 @@ insert into t1 values (17);
handler t2 read first;
ERROR 42S02: Unknown table 't2' in HANDLER
handler t1 open as t2;
-alter table t1 engine=CSV;
+alter table t1 engine=csv;
handler t2 read first;
ERROR 42S02: Unknown table 't2' in HANDLER
drop table t1;
@@ -395,7 +396,7 @@ handler t1 read first;
a
6
drop table t1;
-create table t1(a int, index (a));
+create table t1(a int, index using btree (a));
insert into t1 values (1), (2), (3);
handler t1 open;
handler t1 read a=(W);
@@ -421,7 +422,7 @@ Ok
handler t close;
use test;
drop table t1;
-create table t1 ( a int, b int, INDEX a (a) );
+create table t1 ( a int, b int, INDEX a using btree (a) );
insert into t1 values (1,2), (2,1);
handler t1 open;
handler t1 read a=(1) where b=2;
@@ -549,7 +550,7 @@ Table Op Msg_type Msg_text
test.t1 optimize status OK
proceed with the normal connection
drop table t1;
-CREATE TABLE t1 ( no1 smallint(5) NOT NULL default '0', no2 int(10) NOT NULL default '0', PRIMARY KEY (no1,no2));
+CREATE TABLE t1 ( no1 smallint(5) NOT NULL default '0', no2 int(10) NOT NULL default '0', PRIMARY KEY using btree (no1,no2));
INSERT INTO t1 VALUES (1,274),(1,275),(2,6),(2,8),(4,1),(4,2);
HANDLER t1 OPEN;
HANDLER t1 READ `primary` = (1, 1000);
@@ -582,7 +583,7 @@ ERROR 42S02: Table 'test.t1' doesn't exist
drop table if exists t1;
Warnings:
Note 1051 Unknown table 't1'
-create table t1 (a int not null) ENGINE=CSV;
+create table t1 (a int not null) ENGINE=csv;
--> client 2
handler t1 open;
ERROR HY000: Table storage engine for 't1' doesn't have this option
@@ -600,7 +601,7 @@ handler t1_alias READ a next where inexistent > 0;
ERROR 42S22: Unknown column 'inexistent' in 'field list'
handler t1_alias close;
drop table t1;
-create temporary table t1 (a int, b char(1), key a (a), key b (a,b));
+create temporary table t1 (a int, b char(1), key a using btree (a), key b using btree (a,b));
insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"),
(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"),(9,'k');
select a,b from t1;
@@ -671,7 +672,7 @@ a b
handler a2 close;
drop table t1;
create table t1 (a int);
-create temporary table t2 (a int, key (a));
+create temporary table t2 (a int, key using btree (a));
handler t1 open as a1;
handler t2 open as a2;
handler a2 read a first;
@@ -681,7 +682,7 @@ handler a2 read a next;
ERROR 42S02: Unknown table 'a2' in HANDLER
handler a1 close;
ERROR 42S02: Unknown table 'a1' in HANDLER
-create table t1 (a int, key (a));
+create table t1 (a int, key using btree (a));
create table t2 like t1;
handler t1 open as a1;
handler t2 open as a2;
@@ -694,7 +695,7 @@ handler a1 close;
ERROR 42S02: Unknown table 'a1' in HANDLER
handler a2 close;
drop table t1, t2;
-create table t1 (a int, key (a));
+create table t1 (a int, key using btree (a));
handler t1 open as a1;
handler a1 read a first;
a
@@ -702,7 +703,7 @@ rename table t1 to t2;
handler a1 read a first;
ERROR 42S02: Unknown table 'a1' in HANDLER
drop table t2;
-create table t1 (a int, key (a));
+create table t1 (a int, key using btree (a));
create table t2 like t1;
handler t1 open as a1;
handler t2 open as a2;
@@ -718,9 +719,972 @@ ERROR 42S02: Unknown table 'a1' in HANDLER
handler a2 close;
drop table t1, t2;
#
+# Add test coverage for HANDLER and LOCK TABLES, HANDLER and DDL.
+#
+drop table if exists t1, t2, t3;
+create table t1 (a int, key a (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t2 (a int, key a (a)) select * from t1;
+create temporary table t3 (a int, key a (a)) select * from t2;
+handler t1 open;
+handler t2 open;
+handler t3 open;
+#
+# No HANDLER sql is allowed under LOCK TABLES.
+# But it does not implicitly closes all handlers.
+#
+lock table t1 read;
+handler t1 open;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+handler t1 read next;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+handler t2 close;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+handler t3 open;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+# After UNLOCK TABLES handlers should be around and
+# we should be able to continue reading through them.
+unlock tables;
+handler t1 read next;
+a
+1
+handler t1 close;
+handler t2 read next;
+a
+1
+handler t2 close;
+handler t3 read next;
+a
+1
+handler t3 close;
+drop temporary table t3;
+#
+# Other operations that implicitly close handler:
+#
+# TRUNCATE
+#
+handler t1 open;
+truncate table t1;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler t1 open;
+#
+# CREATE TRIGGER
+#
+create trigger t1_ai after insert on t1 for each row set @a=1;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# DROP TRIGGER
+#
+handler t1 open;
+drop trigger t1_ai;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# ALTER TABLE
+#
+handler t1 open;
+alter table t1 add column b int;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# ANALYZE TABLE
+#
+handler t1 open;
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status Table is already up to date
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# OPTIMIZE TABLE
+#
+handler t1 open;
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# REPAIR TABLE
+#
+handler t1 open;
+repair table t1;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# DROP TABLE, naturally.
+#
+handler t1 open;
+drop table t1;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+create table t1 (a int, b int, key a using btree (a)) select a from t2;
+#
+# RENAME TABLE, naturally
+#
+handler t1 open;
+rename table t1 to t3;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# CREATE TABLE (even with IF NOT EXISTS clause,
+# and the table exists).
+#
+handler t2 open;
+create table if not exists t2 (a int);
+Warnings:
+Note 1050 Table 't2' already exists
+handler t2 read next;
+ERROR 42S02: Unknown table 't2' in HANDLER
+rename table t3 to t1;
+drop table t2;
+#
+# FLUSH TABLE doesn't close the table but loses the position
+#
+handler t1 open;
+handler t1 read a prev;
+b a
+NULL 5
+flush table t1;
+handler t1 read a prev;
+b a
+NULL 5
+handler t1 close;
+#
+# FLUSH TABLES WITH READ LOCK behaves like FLUSH TABLE.
+#
+handler t1 open;
+handler t1 read a prev;
+b a
+NULL 5
+flush tables with read lock;
+handler t1 read a prev;
+b a
+NULL 5
+handler t1 close;
+unlock tables;
+#
+# Let us also check that these operations behave in similar
+# way under LOCK TABLES.
+#
+# TRUNCATE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+truncate table t1;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler t1 open;
+#
+# CREATE TRIGGER under LOCK TABLES.
+#
+lock tables t1 write;
+create trigger t1_ai after insert on t1 for each row set @a=1;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# DROP TRIGGER under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+drop trigger t1_ai;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# ALTER TABLE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+alter table t1 drop column b;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# ANALYZE TABLE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status Table is already up to date
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# OPTIMIZE TABLE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# REPAIR TABLE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+repair table t1;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# DROP TABLE under LOCK TABLES, naturally.
+#
+handler t1 open;
+lock tables t1 write;
+drop table t1;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+create table t1 (a int, b int, key a using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+#
+# FLUSH TABLE doesn't close the table but loses the position
+#
+handler t1 open;
+handler t1 read a prev;
+a b
+5 NULL
+lock tables t1 write;
+flush table t1;
+unlock tables;
+handler t1 read a prev;
+a b
+5 NULL
+handler t1 close;
+#
+# Explore the effect of HANDLER locks on concurrent DDL
+#
+handler t1 open;
+# Establishing auxiliary connections con1, con2, con3
+# --> connection con1;
+# Sending:
+drop table t1 ;
+# We can't use connection 'default' as wait_condition will
+# autoclose handlers.
+# --> connection con2
+# Waitng for 'drop table t1' to get blocked...
+# --> connection default
+handler t1 read a prev;
+a b
+5 NULL
+handler t1 read a prev;
+a b
+4 NULL
+handler t1 close;
+# --> connection con1
+# Reaping 'drop table t1'...
+# --> connection default
+#
+# Explore the effect of HANDLER locks in parallel with SELECT
+#
+create table t1 (a int, key a using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+begin;
+select * from t1;
+a
+1
+2
+3
+4
+5
+handler t1 open;
+handler t1 read a prev;
+a
+5
+handler t1 read a prev;
+a
+4
+handler t1 close;
+# --> connection con1;
+# Sending:
+drop table t1 ;
+# --> connection con2
+# Waiting for 'drop table t1' to get blocked...
+# --> connection default
+# We can still use the table, it's part of the transaction
+select * from t1;
+a
+1
+2
+3
+4
+5
+# Such are the circumstances that t1 is a part of transaction,
+# thus we can reopen it in the handler
+handler t1 open;
+# We can commit the transaction, it doesn't close the handler
+# and doesn't let DROP to proceed.
+commit;
+handler t1 read a prev;
+a
+5
+handler t1 read a prev;
+a
+4
+handler t1 read a prev;
+a
+3
+handler t1 close;
+# --> connection con1
+# Now drop can proceed
+# Reaping 'drop table t1'...
+# --> connection default
+#
+# Demonstrate that HANDLER locks and transaction locks
+# reside in the same context, and we don't back-off
+# when have transaction or handler locks.
+#
+create table t1 (a int, key a (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t0 (a int, key a using btree (a));
+insert into t0 (a) values (1), (2), (3), (4), (5);
+begin;
+select * from t1;
+a
+1
+2
+3
+4
+5
+# --> connection con2
+# Sending:
+rename table t0 to t3, t1 to t0, t3 to t1;
+# --> connection con1
+# Waiting for 'rename table ...' to get blocked...
+# --> connection default
+handler t0 open;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+select * from t0;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+handler t1 open;
+commit;
+handler t1 close;
+# --> connection con2
+# Reaping 'rename table ...'...
+# --> connection default
+handler t1 open;
+handler t1 read a prev;
+a
+5
+handler t1 close;
+drop table t0;
+#
+# Originally there was a deadlock error in this test.
+# With implementation of deadlock detector
+# we no longer deadlock, but block and wait on a lock.
+# The HANDLER is auto-closed as soon as the connection
+# sees a pending conflicting lock against it.
+#
+create table t2 (a int, key a (a));
+handler t1 open;
+# --> connection con1
+lock tables t2 read;
+# --> connection con2
+# Sending 'drop table t2'...
+drop table t2;
+# --> connection con1
+# Waiting for 'drop table t2' to get blocked...
+# --> connection default
+# Sending 'select * from t2'
+select * from t2;
+# --> connection con1
+# Waiting for 'select * from t2' to get blocked...
+unlock tables;
+# --> connection con2
+# Reaping 'drop table t2'...
+# --> connection default
+# Reaping 'select * from t2'
+ERROR 42S02: Table 'test.t2' doesn't exist
+handler t1 close;
+#
+# ROLLBACK TO SAVEPOINT releases transactional locks,
+# but has no effect on open HANDLERs
+#
+create table t2 like t1;
+create table t3 like t1;
+begin;
+# Have something before the savepoint
+select * from t3;
+a
+savepoint sv;
+handler t1 open;
+handler t1 read a first;
+a
+1
+handler t1 read a next;
+a
+2
+select * from t2;
+a
+# --> connection con1
+# Sending:
+drop table t1;
+# --> connection con2
+# Sending:
+drop table t2;
+# --> connection default
+# Let DROP TABLE statements sync in. We must use
+# a separate connection for that, because otherwise SELECT
+# will auto-close the HANDLERs, becaues there are pending
+# exclusive locks against them.
+# --> connection con3
+# Waiting for 'drop table t1' to get blocked...
+# Waiting for 'drop table t2' to get blocked...
+# Demonstrate that t2 lock was released and t2 was dropped
+# after ROLLBACK TO SAVEPOINT
+# --> connection default
+rollback to savepoint sv;
+# --> connection con2
+# Reaping 'drop table t2'...
+# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
+# lock.
+# --> connection default
+handler t1 read a next;
+a
+3
+handler t1 read a next;
+a
+4
+# Demonstrate that the drop will go through as soon as we close the
+# HANDLER
+handler t1 close;
+# connection con1
+# Reaping 'drop table t1'...
+# --> connection default
+commit;
+drop table t3;
+#
+# A few special cases when using SAVEPOINT/ROLLBACK TO
+# SAVEPOINT and HANDLER.
+#
+# Show that rollback to the savepoint taken in the beginning
+# of the transaction doesn't release mdl lock on
+# the HANDLER that was opened later.
+#
+create table t1 (a int, key using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t2 like t1;
+begin;
+savepoint sv;
+handler t1 open;
+handler t1 read a first;
+a
+1
+handler t1 read a next;
+a
+2
+select * from t2;
+a
+# --> connection con1
+# Sending:
+drop table t1;
+# --> connection con2
+# Sending:
+drop table t2;
+# --> connection default
+# Let DROP TABLE statements sync in. We must use
+# a separate connection for that, because otherwise SELECT
+# will auto-close the HANDLERs, becaues there are pending
+# exclusive locks against them.
+# --> connection con3
+# Waiting for 'drop table t1' to get blocked...
+# Waiting for 'drop table t2' to get blocked...
+# Demonstrate that t2 lock was released and t2 was dropped
+# after ROLLBACK TO SAVEPOINT
+# --> connection default
+rollback to savepoint sv;
+# --> connection con2
+# Reaping 'drop table t2'...
+# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
+# lock.
+# --> connection default
+handler t1 read a next;
+a
+3
+handler t1 read a next;
+a
+4
+# Demonstrate that the drop will go through as soon as we close the
+# HANDLER
+handler t1 close;
+# connection con1
+# Reaping 'drop table t1'...
+# --> connection default
+commit;
+#
+# Show that rollback to the savepoint taken in the beginning
+# of the transaction works properly (no valgrind warnins, etc),
+# even though it's done after the HANDLER mdl lock that was there
+# at the beginning is released and added again.
+#
+create table t1 (a int, key using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t2 like t1;
+create table t3 like t1;
+insert into t3 (a) select a from t1;
+begin;
+handler t1 open;
+savepoint sv;
+handler t1 read a first;
+a
+1
+select * from t2;
+a
+handler t1 close;
+handler t3 open;
+handler t3 read a first;
+a
+1
+rollback to savepoint sv;
+# --> connection con1
+drop table t1, t2;
+# Sending:
+drop table t3;
+# Let DROP TABLE statement sync in.
+# --> connection con2
+# Waiting for 'drop table t3' to get blocked...
+# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
+# lock.
+# --> connection default
+handler t3 read a next;
+a
+2
+# Demonstrate that the drop will go through as soon as we close the
+# HANDLER
+handler t3 close;
+# connection con1
+# Reaping 'drop table t3'...
+# --> connection default
+commit;
+#
+# If we have to wait on an exclusive locks while having
+# an open HANDLER, ER_LOCK_DEADLOCK is reported.
+#
+create table t1 (a int, key a(a));
+create table t2 like t1;
+handler t1 open;
+# --> connection con1
+lock table t1 write, t2 write;
+# --> connection default
+drop table t2;
+# --> connection con2
+# Waiting for 'drop table t2' to get blocked...
+# --> connection con1
+drop table t1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+unlock tables;
+# --> connection default
+# Demonstrate that there is no deadlock with FLUSH TABLE,
+# even though it is waiting for the other table to go away
+create table t2 like t1;
+# Sending:
+flush table t2;
+# --> connection con2
+drop table t1;
+# --> connection con1
+unlock tables;
+# --> connection default
+# Reaping 'flush table t2'...
+drop table t2;
+#
+# Bug #46224 HANDLER statements within a transaction might
+# lead to deadlocks
+#
+create table t1 (a int, key using btree (a));
+insert into t1 values (1), (2);
+# --> connection default
+begin;
+select * from t1;
+a
+1
+2
+handler t1 open;
+# --> connection con1
+# Sending:
+lock tables t1 write;
+# --> connection con2
+# Check that 'lock tables t1 write' waits until transaction which
+# has read from the table commits.
+# --> connection default
+# The below 'handler t1 read ...' should not be blocked as
+# 'lock tables t1 write' has not succeeded yet.
+handler t1 read a next;
+a
+1
+# Unblock 'lock tables t1 write'.
+commit;
+# --> connection con1
+# Reap 'lock tables t1 write'.
+# --> connection default
+# Sending:
+handler t1 read a next;
+# --> connection con1
+# Waiting for 'handler t1 read a next' to get blocked...
+# The below 'drop table t1' should be able to proceed without
+# waiting as it will force HANDLER to be closed.
+drop table t1;
+unlock tables;
+# --> connection default
+# Reaping 'handler t1 read a next'...
+ERROR 42S02: Table 'test.t1' doesn't exist
+handler t1 close;
+# --> connection con1
+# --> connection con2
+# --> connection con3
+#
+# A temporary table test.
+# Check that we don't loose positions of HANDLER opened
+# against a temporary table.
+#
+create table t1 (a int, b int, key using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create temporary table t2 (a int, b int, key using btree (a));
+insert into t2 (a) select a from t1;
+handler t1 open;
+handler t1 read a next;
+a b
+1 NULL
+handler t2 open;
+handler t2 read a next;
+a b
+1 NULL
+flush table t1;
+handler t2 read a next;
+a b
+2 NULL
+# Sic: the position is lost
+handler t1 read a next;
+a b
+1 NULL
+select * from t1;
+a b
+1 NULL
+2 NULL
+3 NULL
+4 NULL
+5 NULL
+# Sic: the position is not lost
+handler t2 read a next;
+a b
+3 NULL
+select * from t2;
+ERROR HY000: Can't reopen table: 't2'
+handler t2 read a next;
+a b
+4 NULL
+drop table t1;
+drop temporary table t2;
+#
+# A test for lock_table_names()/unlock_table_names() function.
+# It should work properly in presence of open HANDLER.
+#
+create table t1 (a int, b int, key a (a));
+create table t2 like t1;
+create table t3 like t1;
+create table t4 like t1;
+handler t1 open;
+handler t2 open;
+rename table t4 to t5, t3 to t4, t5 to t3;
+handler t1 read first;
+a b
+handler t2 read first;
+a b
+drop table t1, t2, t3, t4;
+#
+# A test for FLUSH TABLES WITH READ LOCK and HANDLER statements.
+#
+set autocommit=0;
+create table t1 (a int, b int, key a (a));
+insert into t1 (a, b) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 5);
+create table t2 like t1;
+insert into t2 (a, b) select a, b from t1;
+create table t3 like t1;
+insert into t3 (a, b) select a, b from t1;
+commit;
+flush tables with read lock;
+handler t1 open;
+lock table t1 read;
+handler t1 read next;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+# This implicitly leaves LOCK TABLES but doesn't drop the GLR
+lock table not_exists_write read;
+ERROR 42S02: Table 'test.not_exists_write' doesn't exist
+# We still have the read lock.
+drop table t1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+handler t1 open;
+select a from t2;
+a
+1
+2
+3
+4
+5
+handler t1 read next;
+a b
+1 1
+flush tables with read lock;
+handler t2 open;
+flush tables with read lock;
+handler t1 read next;
+a b
+1 1
+select a from t3;
+a
+1
+2
+3
+4
+5
+handler t2 read next;
+a b
+1 1
+handler t1 close;
+rollback;
+handler t2 close;
+drop table t1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+commit;
+flush tables;
+drop table t1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+unlock tables;
+drop table t1;
+set autocommit=default;
+drop table t2, t3;
+#
+# HANDLER statement and operation-type aware metadata locks.
+# Check that when we clone a ticket for HANDLER we downrade
+# the lock.
+#
+# Establish an auxiliary connection con1.
+# -> connection default
+create table t1 (a int, b int, key using btree (a));
+insert into t1 (a, b) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 5);
+begin;
+insert into t1 (a, b) values (6, 6);
+handler t1 open;
+handler t1 read a last;
+a b
+6 6
+insert into t1 (a, b) values (7, 7);
+handler t1 read a last;
+a b
+7 7
+commit;
+# -> connection con1
+# Demonstrate that the HANDLER doesn't hold MDL_SHARED_WRITE.
+lock table t1 write;
+unlock tables;
+# -> connection default
+handler t1 read a prev;
+a b
+6 6
+handler t1 close;
+# Cleanup.
+drop table t1;
+# -> connection con1
+# -> connection default
+#
+# A test for Bug#50555 "handler commands crash server in
+# my_hash_first()".
+#
+handler no_such_table read no_such_index first;
+ERROR 42S02: Unknown table 'no_such_table' in HANDLER
+handler no_such_table close;
+ERROR 42S02: Unknown table 'no_such_table' in HANDLER
+#
+# Bug#50907 Assertion `hash_tables->table->next == __null' on
+# HANDLER OPEN
+#
+DROP TABLE IF EXISTS t1, t2;
+CREATE TEMPORARY TABLE t1 (i INT);
+CREATE TEMPORARY TABLE t2 (i INT);
+HANDLER t2 OPEN;
+HANDLER t2 READ FIRST;
+i
+HANDLER t2 CLOSE;
+DROP TABLE t1, t2;
+#
+# Bug#50912 Assertion `ticket->m_type >= mdl_request->type'
+# failed on HANDLER + I_S
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (id INT);
+HANDLER t1 OPEN;
+SELECT table_name, table_comment FROM information_schema.tables
+WHERE table_schema= 'test' AND table_name= 't1';
+table_name table_comment
+t1
+HANDLER t1 CLOSE;
+DROP TABLE t1;
+#
+# Test for bug #50908 "Assertion `handler_tables_hash.records == 0'
+# failed in enter_locked_tables_mode".
+#
+drop tables if exists t1, t2;
+drop function if exists f1;
+create table t1 (i int);
+insert into t1 values (1), (2);
+create table t2 (j int);
+insert into t2 values (1);
+create function f1() returns int return (select count(*) from t2);
+# Check that open HANDLER survives statement executed in
+# prelocked mode.
+handler t1 open;
+handler t1 read next;
+i
+1
+# The below statement were aborted due to an assertion failure.
+select f1() from t2;
+f1()
+1
+handler t1 read next;
+i
+2
+handler t1 close;
+# Check that the same happens under GLOBAL READ LOCK.
+flush tables with read lock;
+handler t1 open;
+handler t1 read next;
+i
+1
+select f1() from t2;
+f1()
+1
+handler t1 read next;
+i
+2
+unlock tables;
+handler t1 close;
+# Now, check that the same happens if LOCK TABLES is executed.
+handler t1 open;
+handler t1 read next;
+i
+1
+lock table t2 read;
+select * from t2;
+j
+1
+unlock tables;
+handler t1 read next;
+i
+2
+handler t1 close;
+# Finally, check scenario with GRL and LOCK TABLES.
+flush tables with read lock;
+handler t1 open;
+handler t1 read next;
+i
+1
+lock table t2 read;
+select * from t2;
+j
+1
+# This unlocks both tables and GRL.
+unlock tables;
+handler t1 read next;
+i
+2
+handler t1 close;
+# Clean-up.
+drop function f1;
+drop tables t1, t2;
+#
+# Test for bug #51136 "Crash in pthread_rwlock_rdlock on TEMPORARY +
+# HANDLER + LOCK + SP".
+# Also see additional coverage for this bug in flush.test.
+#
+drop tables if exists t1, t2;
+create table t1 (i int);
+create temporary table t2 (j int);
+handler t1 open;
+lock table t2 read;
+# This commit should not release any MDL locks.
+commit;
+unlock tables;
+# The below statement crashed before the bug fix as it
+# has attempted to release metadata lock which was
+# already released by commit.
+handler t1 close;
+drop tables t1, t2;
+#
+# Bug#51355 handler stmt cause assertion in
+# bool MDL_context::try_acquire_lock(MDL_request*)
+#
+DROP TABLE IF EXISTS t1;
+# Connection default
+CREATE TABLE t1(id INT, KEY id(id));
+HANDLER t1 OPEN;
+# Connection con51355
+# Sending:
+DROP TABLE t1;
+# Connection default
+# This I_S query will cause the handler table to be closed and
+# the metadata lock to be released. This will allow DROP TABLE
+# to proceed. Waiting for the table to be removed.
+# Connection con51355
+# Reaping: DROP TABLE t1
+# Connection default
+HANDLER t1 READ id NEXT;
+ERROR 42S02: Table 'test.t1' doesn't exist
+HANDLER t1 READ id NEXT;
+ERROR 42S02: Table 'test.t1' doesn't exist
+HANDLER t1 CLOSE;
+# Connection con51355
+# Connection default
+#
+# Bug#54401 assert in Diagnostics_area::set_eof_status , HANDLER
+#
+DROP TABLE IF EXISTS t1, t2;
+DROP FUNCTION IF EXISTS f1;
+CREATE FUNCTION f1() RETURNS INTEGER
+BEGIN
+SELECT 1 FROM t2 INTO @a;
+RETURN 1;
+END|
+SELECT f1();
+ERROR 42S02: Table 'test.t2' doesn't exist
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES (1);
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST WHERE f1() = 1;
+ERROR 42000: This version of MySQL doesn't yet support 'stored functions in HANDLER ... READ'
+HANDLER t1 CLOSE;
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
+# Bug#54920 Stored functions are allowed in HANDLER statements,
+# but broken.
+#
+DROP TABLE IF EXISTS t1;
+DROP FUNCTION IF EXISTS f1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1), (2);
+CREATE FUNCTION f1() RETURNS INT RETURN 1;
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST WHERE f1() = 1;
+ERROR 42000: This version of MySQL doesn't yet support 'stored functions in HANDLER ... READ'
+HANDLER t1 CLOSE;
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
# BUG#51877 - HANDLER interface causes invalid memory read
#
-CREATE TABLE t1(a INT, KEY (a));
+CREATE TABLE t1(a INT, KEY using btree (a));
HANDLER t1 OPEN;
HANDLER t1 READ a FIRST;
a
diff --git a/mysql-test/suite/handler/handler.inc b/mysql-test/suite/handler/handler.inc
index 5c87652f2b5..e099d22e3ce 100644
--- a/mysql-test/suite/handler/handler.inc
+++ b/mysql-test/suite/handler/handler.inc
@@ -4,7 +4,6 @@
#
# The variables
# $engine_type -- storage engine to be tested
-# $other_engine_type -- storage engine <> $engine_type
# $other_handler_engine_type -- storage engine <> $engine_type, if possible
# 1. $other_handler_engine_type must support handler
# 2. $other_handler_engine_type must point to an all
@@ -19,6 +18,8 @@
# main testing code put into handler.inc
#
+source include/have_csv.inc;
+
#
# Start testing the table created in init.inc
#
@@ -215,7 +216,6 @@ handler t1 open;
prepare stmt from 'handler t1 read a=(?)';
flush tables;
set @a=17;
---error ER_NEED_REPREPARE
execute stmt using @a;
deallocate prepare stmt;
handler t1 close;
@@ -230,7 +230,7 @@ insert into t1 values (17);
--error 1109
handler t2 read first;
handler t1 open as t2;
-eval alter table t1 engine=$other_engine_type;
+alter table t1 engine=csv;
--error 1109
handler t2 read first;
drop table t1;
@@ -252,7 +252,7 @@ drop table t1;
#
# Test for #751
#
-eval create table t1(a int, index $key_type (a));
+create table t1(a int, index using btree (a));
insert into t1 values (1), (2), (3);
handler t1 open;
--error 1054
@@ -279,7 +279,7 @@ drop table t1;
#
# BUG#3649
#
-eval create table t1 ( a int, b int, INDEX a $key_type (a) );
+create table t1 ( a int, b int, INDEX a using btree (a) );
insert into t1 values (1,2), (2,1);
handler t1 open;
handler t1 read a=(1) where b=2;
@@ -371,24 +371,24 @@ 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
+--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
+--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
+--echo read the result from the other connection
connection con2;
reap;
# client 1
---exec echo proceed with the normal connection
+--echo proceed with the normal connection
connection default;
drop table t1;
-eval CREATE TABLE t1 ( no1 smallint(5) NOT NULL default '0', no2 int(10) NOT NULL default '0', PRIMARY KEY $key_type (no1,no2));
+CREATE TABLE t1 ( no1 smallint(5) NOT NULL default '0', no2 int(10) NOT NULL default '0', PRIMARY KEY using btree (no1,no2));
INSERT INTO t1 VALUES (1,274),(1,275),(2,6),(2,8),(4,1),(4,2);
HANDLER t1 OPEN;
HANDLER t1 READ `primary` = (1, 1000);
@@ -416,14 +416,14 @@ drop table t1;
# 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
+--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
+--echo proceed with the normal connection
connection default;
# This would hang on LOCK_open without the 5.0 addendum fix.
select * from t1;
@@ -433,12 +433,12 @@ unlock tables;
# client 2
# Read the result of the drop command.
connection con2;
---exec echo read the result from the other connection
+--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
+--echo proceed with the normal connection
connection default;
--error 1146
select * from t1;
@@ -448,7 +448,7 @@ drop table if exists t1;
#
# Bug#25856 - HANDLER table OPEN in one connection lock DROP TABLE in another one
#
-eval create table t1 (a int not null) ENGINE=$other_engine_type;
+create table t1 (a int not null) ENGINE=csv;
--echo --> client 2
connection con2;
--error 1031
@@ -481,7 +481,7 @@ drop table t1;
# is open by a HANDLER, no other statement can access it.
#
-eval create temporary table t1 (a int, b char(1), key a $key_type (a), key b $key_type (a,b));
+create temporary table t1 (a int, b char(1), key a using btree (a), key b using btree (a,b));
insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"),
(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"),(9,'k');
select a,b from t1;
@@ -509,7 +509,7 @@ drop table t1;
# Test that temporary tables associated with handlers are properly dropped.
create table t1 (a int);
-eval create temporary table t2 (a int, key $key_type (a));
+create temporary table t2 (a int, key using btree (a));
handler t1 open as a1;
handler t2 open as a2;
handler a2 read a first;
@@ -521,7 +521,7 @@ handler a1 close;
# Alter table drop handlers
-eval create table t1 (a int, key $key_type (a));
+create table t1 (a int, key using btree (a));
create table t2 like t1;
handler t1 open as a1;
handler t2 open as a2;
@@ -535,7 +535,7 @@ drop table t1, t2;
# Rename table drop handlers
-eval create table t1 (a int, key $key_type (a));
+create table t1 (a int, key using btree (a));
handler t1 open as a1;
handler a1 read a first;
rename table t1 to t2;
@@ -545,7 +545,7 @@ drop table t2;
# Optimize table drop handlers
-eval create table t1 (a int, key $key_type (a));
+create table t1 (a int, key using btree (a));
create table t2 like t1;
handler t1 open as a1;
handler t2 open as a2;
@@ -558,9 +558,1051 @@ handler a2 close;
drop table t1, t2;
--echo #
+--echo # Add test coverage for HANDLER and LOCK TABLES, HANDLER and DDL.
+--echo #
+--disable_warnings
+drop table if exists t1, t2, t3;
+--enable_warnings
+create table t1 (a int, key a (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t2 (a int, key a (a)) select * from t1;
+create temporary table t3 (a int, key a (a)) select * from t2;
+handler t1 open;
+handler t2 open;
+handler t3 open;
+--echo #
+--echo # No HANDLER sql is allowed under LOCK TABLES.
+--echo # But it does not implicitly closes all handlers.
+--echo #
+lock table t1 read;
+--error ER_LOCK_OR_ACTIVE_TRANSACTION
+handler t1 open;
+--error ER_LOCK_OR_ACTIVE_TRANSACTION
+handler t1 read next;
+--error ER_LOCK_OR_ACTIVE_TRANSACTION
+handler t2 close;
+--error ER_LOCK_OR_ACTIVE_TRANSACTION
+handler t3 open;
+--echo # After UNLOCK TABLES handlers should be around and
+--echo # we should be able to continue reading through them.
+unlock tables;
+handler t1 read next;
+handler t1 close;
+handler t2 read next;
+handler t2 close;
+handler t3 read next;
+handler t3 close;
+drop temporary table t3;
+--echo #
+--echo # Other operations that implicitly close handler:
+--echo #
+--echo # TRUNCATE
+--echo #
+handler t1 open;
+truncate table t1;
+--error ER_UNKNOWN_TABLE
+handler t1 read next;
+handler t1 open;
+--echo #
+--echo # CREATE TRIGGER
+--echo #
+create trigger t1_ai after insert on t1 for each row set @a=1;
+--error ER_UNKNOWN_TABLE
+handler t1 read next;
+--echo #
+--echo # DROP TRIGGER
+--echo #
+handler t1 open;
+drop trigger t1_ai;
+--error ER_UNKNOWN_TABLE
+handler t1 read next;
+--echo #
+--echo # ALTER TABLE
+--echo #
+handler t1 open;
+alter table t1 add column b int;
+--error ER_UNKNOWN_TABLE
+handler t1 read next;
+--echo #
+--echo # ANALYZE TABLE
+--echo #
+handler t1 open;
+analyze table t1;
+--error ER_UNKNOWN_TABLE
+handler t1 read next;
+--echo #
+--echo # OPTIMIZE TABLE
+--echo #
+handler t1 open;
+optimize table t1;
+--error ER_UNKNOWN_TABLE
+handler t1 read next;
+--echo #
+--echo # REPAIR TABLE
+--echo #
+handler t1 open;
+repair table t1;
+--error ER_UNKNOWN_TABLE
+handler t1 read next;
+--echo #
+--echo # DROP TABLE, naturally.
+--echo #
+handler t1 open;
+drop table t1;
+--error ER_UNKNOWN_TABLE
+handler t1 read next;
+create table t1 (a int, b int, key a using btree (a)) select a from t2;
+--echo #
+--echo # RENAME TABLE, naturally
+--echo #
+handler t1 open;
+rename table t1 to t3;
+--error ER_UNKNOWN_TABLE
+handler t1 read next;
+--echo #
+--echo # CREATE TABLE (even with IF NOT EXISTS clause,
+--echo # and the table exists).
+--echo #
+handler t2 open;
+create table if not exists t2 (a int);
+--error ER_UNKNOWN_TABLE
+handler t2 read next;
+rename table t3 to t1;
+drop table t2;
+--echo #
+--echo # FLUSH TABLE doesn't close the table but loses the position
+--echo #
+handler t1 open;
+handler t1 read a prev;
+flush table t1;
+handler t1 read a prev;
+handler t1 close;
+--echo #
+--echo # FLUSH TABLES WITH READ LOCK behaves like FLUSH TABLE.
+--echo #
+handler t1 open;
+handler t1 read a prev;
+flush tables with read lock;
+handler t1 read a prev;
+handler t1 close;
+unlock tables;
+--echo #
+--echo # Let us also check that these operations behave in similar
+--echo # way under LOCK TABLES.
+--echo #
+--echo # TRUNCATE under LOCK TABLES.
+--echo #
+handler t1 open;
+lock tables t1 write;
+truncate table t1;
+unlock tables;
+--error ER_UNKNOWN_TABLE
+handler t1 read next;
+handler t1 open;
+--echo #
+--echo # CREATE TRIGGER under LOCK TABLES.
+--echo #
+lock tables t1 write;
+create trigger t1_ai after insert on t1 for each row set @a=1;
+unlock tables;
+--error ER_UNKNOWN_TABLE
+handler t1 read next;
+--echo #
+--echo # DROP TRIGGER under LOCK TABLES.
+--echo #
+handler t1 open;
+lock tables t1 write;
+drop trigger t1_ai;
+unlock tables;
+--error ER_UNKNOWN_TABLE
+handler t1 read next;
+--echo #
+--echo # ALTER TABLE under LOCK TABLES.
+--echo #
+handler t1 open;
+lock tables t1 write;
+alter table t1 drop column b;
+unlock tables;
+--error ER_UNKNOWN_TABLE
+handler t1 read next;
+--echo #
+--echo # ANALYZE TABLE under LOCK TABLES.
+--echo #
+handler t1 open;
+lock tables t1 write;
+analyze table t1;
+unlock tables;
+--error ER_UNKNOWN_TABLE
+handler t1 read next;
+--echo #
+--echo # OPTIMIZE TABLE under LOCK TABLES.
+--echo #
+handler t1 open;
+lock tables t1 write;
+optimize table t1;
+unlock tables;
+--error ER_UNKNOWN_TABLE
+handler t1 read next;
+--echo #
+--echo # REPAIR TABLE under LOCK TABLES.
+--echo #
+handler t1 open;
+lock tables t1 write;
+repair table t1;
+unlock tables;
+--error ER_UNKNOWN_TABLE
+handler t1 read next;
+--echo #
+--echo # DROP TABLE under LOCK TABLES, naturally.
+--echo #
+handler t1 open;
+lock tables t1 write;
+drop table t1;
+unlock tables;
+--error ER_UNKNOWN_TABLE
+handler t1 read next;
+create table t1 (a int, b int, key a using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+--echo #
+--echo # FLUSH TABLE doesn't close the table but loses the position
+--echo #
+handler t1 open;
+handler t1 read a prev;
+lock tables t1 write;
+flush table t1;
+unlock tables;
+handler t1 read a prev;
+handler t1 close;
+--echo #
+--echo # Explore the effect of HANDLER locks on concurrent DDL
+--echo #
+handler t1 open;
+--echo # Establishing auxiliary connections con1, con2, con3
+connect(con1, localhost, root,,);
+connect(con2, localhost, root,,);
+connect(con3, localhost, root,,);
+--echo # --> connection con1;
+connection con1;
+--echo # Sending:
+--send drop table t1
+--echo # We can't use connection 'default' as wait_condition will
+--echo # autoclose handlers.
+--echo # --> connection con2
+connection con2;
+--echo # Waitng for 'drop table t1' to get blocked...
+let $wait_condition=select count(*)=1 from information_schema.processlist
+ where state='Waiting for table metadata lock' and
+ info='drop table t1';
+--source include/wait_condition.inc
+--echo # --> connection default
+connection default;
+handler t1 read a prev;
+handler t1 read a prev;
+handler t1 close;
+--echo # --> connection con1
+connection con1;
+--echo # Reaping 'drop table t1'...
+--reap
+--echo # --> connection default
+connection default;
+--echo #
+--echo # Explore the effect of HANDLER locks in parallel with SELECT
+--echo #
+create table t1 (a int, key a using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+begin;
+select * from t1;
+handler t1 open;
+handler t1 read a prev;
+handler t1 read a prev;
+handler t1 close;
+--echo # --> connection con1;
+connection con1;
+--echo # Sending:
+--send drop table t1
+--echo # --> connection con2
+connection con2;
+--echo # Waiting for 'drop table t1' to get blocked...
+let $wait_condition=select count(*)=1 from information_schema.processlist
+ where state='Waiting for table metadata lock' and
+ info='drop table t1';
+--source include/wait_condition.inc
+--echo # --> connection default
+connection default;
+--echo # We can still use the table, it's part of the transaction
+select * from t1;
+--echo # Such are the circumstances that t1 is a part of transaction,
+--echo # thus we can reopen it in the handler
+handler t1 open;
+--echo # We can commit the transaction, it doesn't close the handler
+--echo # and doesn't let DROP to proceed.
+commit;
+handler t1 read a prev;
+handler t1 read a prev;
+handler t1 read a prev;
+handler t1 close;
+--echo # --> connection con1
+connection con1;
+--echo # Now drop can proceed
+--echo # Reaping 'drop table t1'...
+--reap
+--echo # --> connection default
+connection default;
+--echo #
+--echo # Demonstrate that HANDLER locks and transaction locks
+--echo # reside in the same context, and we don't back-off
+--echo # when have transaction or handler locks.
+--echo #
+create table t1 (a int, key a (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t0 (a int, key a using btree (a));
+insert into t0 (a) values (1), (2), (3), (4), (5);
+begin;
+select * from t1;
+--echo # --> connection con2
+connection con2;
+--echo # Sending:
+send rename table t0 to t3, t1 to t0, t3 to t1;
+--echo # --> connection con1
+connection con1;
+--echo # Waiting for 'rename table ...' to get blocked...
+let $wait_condition=select count(*)=1 from information_schema.processlist
+ where state='Waiting for table metadata lock' and
+ info='rename table t0 to t3, t1 to t0, t3 to t1';
+--source include/wait_condition.inc
+--echo # --> connection default
+connection default;
+--error ER_LOCK_DEADLOCK
+handler t0 open;
+--error ER_LOCK_DEADLOCK
+select * from t0;
+handler t1 open;
+commit;
+handler t1 close;
+--echo # --> connection con2
+connection con2;
+--echo # Reaping 'rename table ...'...
+--reap
+--echo # --> connection default
+connection default;
+handler t1 open;
+handler t1 read a prev;
+handler t1 close;
+drop table t0;
+--echo #
+--echo # Originally there was a deadlock error in this test.
+--echo # With implementation of deadlock detector
+--echo # we no longer deadlock, but block and wait on a lock.
+--echo # The HANDLER is auto-closed as soon as the connection
+--echo # sees a pending conflicting lock against it.
+--echo #
+create table t2 (a int, key a (a));
+handler t1 open;
+--echo # --> connection con1
+connection con1;
+lock tables t2 read;
+--echo # --> connection con2
+connection con2;
+--echo # Sending 'drop table t2'...
+--send drop table t2
+--echo # --> connection con1
+connection con1;
+--echo # Waiting for 'drop table t2' to get blocked...
+let $wait_condition=select count(*)=1 from information_schema.processlist
+ where state='Waiting for table metadata lock' and
+ info='drop table t2';
+--source include/wait_condition.inc
+--echo # --> connection default
+connection default;
+--echo # Sending 'select * from t2'
+send select * from t2;
+--echo # --> connection con1
+connection con1;
+--echo # Waiting for 'select * from t2' to get blocked...
+let $wait_condition=select count(*)=1 from information_schema.processlist
+ where state='Waiting for table metadata lock' and
+ info='select * from t2';
+unlock tables;
+--echo # --> connection con2
+connection con2;
+--echo # Reaping 'drop table t2'...
+--reap
+--echo # --> connection default
+connection default;
+--echo # Reaping 'select * from t2'
+--error ER_NO_SUCH_TABLE
+reap;
+handler t1 close;
+
+--echo #
+--echo # ROLLBACK TO SAVEPOINT releases transactional locks,
+--echo # but has no effect on open HANDLERs
+--echo #
+create table t2 like t1;
+create table t3 like t1;
+begin;
+--echo # Have something before the savepoint
+select * from t3;
+savepoint sv;
+handler t1 open;
+handler t1 read a first;
+handler t1 read a next;
+select * from t2;
+--echo # --> connection con1
+connection con1;
+--echo # Sending:
+--send drop table t1
+--echo # --> connection con2
+connection con2;
+--echo # Sending:
+--send drop table t2
+--echo # --> connection default
+connection default;
+--echo # Let DROP TABLE statements sync in. We must use
+--echo # a separate connection for that, because otherwise SELECT
+--echo # will auto-close the HANDLERs, becaues there are pending
+--echo # exclusive locks against them.
+--echo # --> connection con3
+connection con3;
+--echo # Waiting for 'drop table t1' to get blocked...
+let $wait_condition=select count(*)=1 from information_schema.processlist
+ where state='Waiting for table metadata lock' and
+ info='drop table t1';
+--source include/wait_condition.inc
+--echo # Waiting for 'drop table t2' to get blocked...
+let $wait_condition=select count(*)=1 from information_schema.processlist
+ where state='Waiting for table metadata lock' and
+ info='drop table t2';
+--source include/wait_condition.inc
+--echo # Demonstrate that t2 lock was released and t2 was dropped
+--echo # after ROLLBACK TO SAVEPOINT
+--echo # --> connection default
+connection default;
+rollback to savepoint sv;
+--echo # --> connection con2
+connection con2;
+--echo # Reaping 'drop table t2'...
+--reap
+--echo # Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
+--echo # lock.
+--echo # --> connection default
+connection default;
+handler t1 read a next;
+handler t1 read a next;
+--echo # Demonstrate that the drop will go through as soon as we close the
+--echo # HANDLER
+handler t1 close;
+--echo # connection con1
+connection con1;
+--echo # Reaping 'drop table t1'...
+--reap
+--echo # --> connection default
+connection default;
+commit;
+drop table t3;
+--echo #
+--echo # A few special cases when using SAVEPOINT/ROLLBACK TO
+--echo # SAVEPOINT and HANDLER.
+--echo #
+--echo # Show that rollback to the savepoint taken in the beginning
+--echo # of the transaction doesn't release mdl lock on
+--echo # the HANDLER that was opened later.
+--echo #
+create table t1 (a int, key using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t2 like t1;
+begin;
+savepoint sv;
+handler t1 open;
+handler t1 read a first;
+handler t1 read a next;
+select * from t2;
+--echo # --> connection con1
+connection con1;
+--echo # Sending:
+--send drop table t1
+--echo # --> connection con2
+connection con2;
+--echo # Sending:
+--send drop table t2
+--echo # --> connection default
+connection default;
+--echo # Let DROP TABLE statements sync in. We must use
+--echo # a separate connection for that, because otherwise SELECT
+--echo # will auto-close the HANDLERs, becaues there are pending
+--echo # exclusive locks against them.
+--echo # --> connection con3
+connection con3;
+--echo # Waiting for 'drop table t1' to get blocked...
+let $wait_condition=select count(*)=1 from information_schema.processlist
+ where state='Waiting for table metadata lock' and
+ info='drop table t1';
+--source include/wait_condition.inc
+--echo # Waiting for 'drop table t2' to get blocked...
+let $wait_condition=select count(*)=1 from information_schema.processlist
+ where state='Waiting for table metadata lock' and
+ info='drop table t2';
+--source include/wait_condition.inc
+--echo # Demonstrate that t2 lock was released and t2 was dropped
+--echo # after ROLLBACK TO SAVEPOINT
+--echo # --> connection default
+connection default;
+rollback to savepoint sv;
+--echo # --> connection con2
+connection con2;
+--echo # Reaping 'drop table t2'...
+--reap
+--echo # Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
+--echo # lock.
+--echo # --> connection default
+connection default;
+handler t1 read a next;
+handler t1 read a next;
+--echo # Demonstrate that the drop will go through as soon as we close the
+--echo # HANDLER
+handler t1 close;
+--echo # connection con1
+connection con1;
+--echo # Reaping 'drop table t1'...
+--reap
+--echo # --> connection default
+connection default;
+commit;
+--echo #
+--echo # Show that rollback to the savepoint taken in the beginning
+--echo # of the transaction works properly (no valgrind warnins, etc),
+--echo # even though it's done after the HANDLER mdl lock that was there
+--echo # at the beginning is released and added again.
+--echo #
+create table t1 (a int, key using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t2 like t1;
+create table t3 like t1;
+insert into t3 (a) select a from t1;
+begin;
+handler t1 open;
+savepoint sv;
+handler t1 read a first;
+select * from t2;
+handler t1 close;
+handler t3 open;
+handler t3 read a first;
+rollback to savepoint sv;
+--echo # --> connection con1
+connection con1;
+drop table t1, t2;
+--echo # Sending:
+--send drop table t3
+--echo # Let DROP TABLE statement sync in.
+--echo # --> connection con2
+connection con2;
+--echo # Waiting for 'drop table t3' to get blocked...
+let $wait_condition=select count(*)=1 from information_schema.processlist
+ where state='Waiting for table metadata lock' and
+ info='drop table t3';
+--source include/wait_condition.inc
+--echo # Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
+--echo # lock.
+--echo # --> connection default
+connection default;
+handler t3 read a next;
+--echo # Demonstrate that the drop will go through as soon as we close the
+--echo # HANDLER
+handler t3 close;
+--echo # connection con1
+connection con1;
+--echo # Reaping 'drop table t3'...
+--reap
+--echo # --> connection default
+connection default;
+commit;
+
+--echo #
+--echo # If we have to wait on an exclusive locks while having
+--echo # an open HANDLER, ER_LOCK_DEADLOCK is reported.
+--echo #
+create table t1 (a int, key a(a));
+create table t2 like t1;
+handler t1 open;
+--echo # --> connection con1
+connection con1;
+lock table t1 write, t2 write;
+--echo # --> connection default
+connection default;
+send drop table t2;
+--echo # --> connection con2
+connection con2;
+--echo # Waiting for 'drop table t2' to get blocked...
+let $wait_condition=select count(*)=1 from information_schema.processlist
+ where state='Waiting for table metadata lock' and
+ info='drop table t2';
+--source include/wait_condition.inc
+--echo # --> connection con1
+connection con1;
+--error ER_LOCK_DEADLOCK
+drop table t1;
+unlock tables;
+--echo # --> connection default
+connection default;
+reap;
+
+--echo # Demonstrate that there is no deadlock with FLUSH TABLE,
+--echo # even though it is waiting for the other table to go away
+create table t2 like t1;
+--echo # Sending:
+--send flush table t2
+--echo # --> connection con2
+connection con2;
+drop table t1;
+--echo # --> connection con1
+connection con1;
+unlock tables;
+--echo # --> connection default
+connection default;
+--echo # Reaping 'flush table t2'...
+--reap
+drop table t2;
+
+--echo #
+--echo # Bug #46224 HANDLER statements within a transaction might
+--echo # lead to deadlocks
+--echo #
+create table t1 (a int, key using btree (a));
+insert into t1 values (1), (2);
+
+--echo # --> connection default
+connection default;
+begin;
+select * from t1;
+handler t1 open;
+
+--echo # --> connection con1
+connection con1;
+--echo # Sending:
+--send lock tables t1 write
+
+--echo # --> connection con2
+connection con2;
+--echo # Check that 'lock tables t1 write' waits until transaction which
+--echo # has read from the table commits.
+let $wait_condition=
+ select count(*) = 1 from information_schema.processlist
+ where state = "Waiting for table metadata lock" and
+ info = "lock tables t1 write";
+--source include/wait_condition.inc
+
+--echo # --> connection default
+connection default;
+--echo # The below 'handler t1 read ...' should not be blocked as
+--echo # 'lock tables t1 write' has not succeeded yet.
+handler t1 read a next;
+
+--echo # Unblock 'lock tables t1 write'.
+commit;
+
+--echo # --> connection con1
+connection con1;
+--echo # Reap 'lock tables t1 write'.
+--reap
+
+--echo # --> connection default
+connection default;
+--echo # Sending:
+--send handler t1 read a next
+
+--echo # --> connection con1
+connection con1;
+--echo # Waiting for 'handler t1 read a next' to get blocked...
+let $wait_condition=
+ select count(*) = 1 from information_schema.processlist
+ where state = "Waiting for table level lock" and
+ info = "handler t1 read a next";
+--source include/wait_condition.inc
+
+--echo # The below 'drop table t1' should be able to proceed without
+--echo # waiting as it will force HANDLER to be closed.
+drop table t1;
+unlock tables;
+
+--echo # --> connection default
+connection default;
+--echo # Reaping 'handler t1 read a next'...
+--error ER_NO_SUCH_TABLE
+--reap
+handler t1 close;
+
+--echo # --> connection con1
+connection con1;
+disconnect con1;
+--source include/wait_until_disconnected.inc
+--echo # --> connection con2
+connection con2;
+disconnect con2;
+--source include/wait_until_disconnected.inc
+--echo # --> connection con3
+connection con3;
+disconnect con3;
+--source include/wait_until_disconnected.inc
+connection default;
+
+--echo #
+--echo # A temporary table test.
+--echo # Check that we don't loose positions of HANDLER opened
+--echo # against a temporary table.
+--echo #
+create table t1 (a int, b int, key using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create temporary table t2 (a int, b int, key using btree (a));
+insert into t2 (a) select a from t1;
+handler t1 open;
+handler t1 read a next;
+handler t2 open;
+handler t2 read a next;
+flush table t1;
+handler t2 read a next;
+--echo # Sic: the position is lost
+handler t1 read a next;
+select * from t1;
+--echo # Sic: the position is not lost
+handler t2 read a next;
+--error ER_CANT_REOPEN_TABLE
+select * from t2;
+handler t2 read a next;
+drop table t1;
+drop temporary table t2;
+
+--echo #
+--echo # A test for lock_table_names()/unlock_table_names() function.
+--echo # It should work properly in presence of open HANDLER.
+--echo #
+create table t1 (a int, b int, key a (a));
+create table t2 like t1;
+create table t3 like t1;
+create table t4 like t1;
+handler t1 open;
+handler t2 open;
+rename table t4 to t5, t3 to t4, t5 to t3;
+handler t1 read first;
+handler t2 read first;
+drop table t1, t2, t3, t4;
+
+--echo #
+--echo # A test for FLUSH TABLES WITH READ LOCK and HANDLER statements.
+--echo #
+set autocommit=0;
+create table t1 (a int, b int, key a (a));
+insert into t1 (a, b) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 5);
+create table t2 like t1;
+insert into t2 (a, b) select a, b from t1;
+create table t3 like t1;
+insert into t3 (a, b) select a, b from t1;
+commit;
+flush tables with read lock;
+handler t1 open;
+lock table t1 read;
+--error ER_LOCK_OR_ACTIVE_TRANSACTION
+handler t1 read next;
+--echo # This implicitly leaves LOCK TABLES but doesn't drop the GLR
+--error ER_NO_SUCH_TABLE
+lock table not_exists_write read;
+--echo # We still have the read lock.
+--error ER_CANT_UPDATE_WITH_READLOCK
+drop table t1;
+handler t1 open;
+select a from t2;
+handler t1 read next;
+flush tables with read lock;
+handler t2 open;
+flush tables with read lock;
+handler t1 read next;
+select a from t3;
+handler t2 read next;
+handler t1 close;
+rollback;
+handler t2 close;
+--error ER_CANT_UPDATE_WITH_READLOCK
+drop table t1;
+commit;
+flush tables;
+--error ER_CANT_UPDATE_WITH_READLOCK
+drop table t1;
+unlock tables;
+drop table t1;
+set autocommit=default;
+drop table t2, t3;
+
+--echo #
+--echo # HANDLER statement and operation-type aware metadata locks.
+--echo # Check that when we clone a ticket for HANDLER we downrade
+--echo # the lock.
+--echo #
+--echo # Establish an auxiliary connection con1.
+connect (con1,localhost,root,,);
+--echo # -> connection default
+connection default;
+create table t1 (a int, b int, key using btree (a));
+insert into t1 (a, b) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 5);
+begin;
+insert into t1 (a, b) values (6, 6);
+handler t1 open;
+handler t1 read a last;
+insert into t1 (a, b) values (7, 7);
+handler t1 read a last;
+commit;
+--echo # -> connection con1
+connection con1;
+--echo # Demonstrate that the HANDLER doesn't hold MDL_SHARED_WRITE.
+lock table t1 write;
+unlock tables;
+--echo # -> connection default
+connection default;
+handler t1 read a prev;
+handler t1 close;
+--echo # Cleanup.
+drop table t1;
+--echo # -> connection con1
+connection con1;
+disconnect con1;
+--source include/wait_until_disconnected.inc
+--echo # -> connection default
+connection default;
+
+--echo #
+--echo # A test for Bug#50555 "handler commands crash server in
+--echo # my_hash_first()".
+--echo #
+--error ER_UNKNOWN_TABLE
+handler no_such_table read no_such_index first;
+--error ER_UNKNOWN_TABLE
+handler no_such_table close;
+
+
+--echo #
+--echo # Bug#50907 Assertion `hash_tables->table->next == __null' on
+--echo # HANDLER OPEN
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2;
+--enable_warnings
+
+CREATE TEMPORARY TABLE t1 (i INT);
+CREATE TEMPORARY TABLE t2 (i INT);
+
+# This used to trigger the assert
+HANDLER t2 OPEN;
+
+# This also used to trigger the assert
+HANDLER t2 READ FIRST;
+
+HANDLER t2 CLOSE;
+DROP TABLE t1, t2;
+
+
+--echo #
+--echo # Bug#50912 Assertion `ticket->m_type >= mdl_request->type'
+--echo # failed on HANDLER + I_S
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (id INT);
+HANDLER t1 OPEN;
+
+# This used to trigger the assert.
+SELECT table_name, table_comment FROM information_schema.tables
+ WHERE table_schema= 'test' AND table_name= 't1';
+
+HANDLER t1 CLOSE;
+DROP TABLE t1;
+
+
+--echo #
+--echo # Test for bug #50908 "Assertion `handler_tables_hash.records == 0'
+--echo # failed in enter_locked_tables_mode".
+--echo #
+--disable_warnings
+drop tables if exists t1, t2;
+drop function if exists f1;
+--enable_warnings
+create table t1 (i int);
+insert into t1 values (1), (2);
+create table t2 (j int);
+insert into t2 values (1);
+create function f1() returns int return (select count(*) from t2);
+--echo # Check that open HANDLER survives statement executed in
+--echo # prelocked mode.
+handler t1 open;
+handler t1 read next;
+--echo # The below statement were aborted due to an assertion failure.
+select f1() from t2;
+handler t1 read next;
+handler t1 close;
+--echo # Check that the same happens under GLOBAL READ LOCK.
+flush tables with read lock;
+handler t1 open;
+handler t1 read next;
+select f1() from t2;
+handler t1 read next;
+unlock tables;
+handler t1 close;
+--echo # Now, check that the same happens if LOCK TABLES is executed.
+handler t1 open;
+handler t1 read next;
+lock table t2 read;
+select * from t2;
+unlock tables;
+handler t1 read next;
+handler t1 close;
+--echo # Finally, check scenario with GRL and LOCK TABLES.
+flush tables with read lock;
+handler t1 open;
+handler t1 read next;
+lock table t2 read;
+select * from t2;
+--echo # This unlocks both tables and GRL.
+unlock tables;
+handler t1 read next;
+handler t1 close;
+--echo # Clean-up.
+drop function f1;
+drop tables t1, t2;
+
+
+--echo #
+--echo # Test for bug #51136 "Crash in pthread_rwlock_rdlock on TEMPORARY +
+--echo # HANDLER + LOCK + SP".
+--echo # Also see additional coverage for this bug in flush.test.
+--echo #
+--disable_warnings
+drop tables if exists t1, t2;
+--enable_warnings
+create table t1 (i int);
+create temporary table t2 (j int);
+handler t1 open;
+lock table t2 read;
+--echo # This commit should not release any MDL locks.
+commit;
+unlock tables;
+--echo # The below statement crashed before the bug fix as it
+--echo # has attempted to release metadata lock which was
+--echo # already released by commit.
+handler t1 close;
+drop tables t1, t2;
+
+
+--echo #
+--echo # Bug#51355 handler stmt cause assertion in
+--echo # bool MDL_context::try_acquire_lock(MDL_request*)
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+connect(con51355, localhost, root);
+
+--echo # Connection default
+connection default;
+CREATE TABLE t1(id INT, KEY id(id));
+HANDLER t1 OPEN;
+
+--echo # Connection con51355
+connection con51355;
+--echo # Sending:
+--send DROP TABLE t1
+
+--echo # Connection default
+connection default;
+--echo # This I_S query will cause the handler table to be closed and
+--echo # the metadata lock to be released. This will allow DROP TABLE
+--echo # to proceed. Waiting for the table to be removed.
+let $wait_condition=
+ SELECT COUNT(*) = 0 FROM information_schema.tables WHERE table_name = "t1";
+--source include/wait_condition.inc
+
+--echo # Connection con51355
+connection con51355;
+--echo # Reaping: DROP TABLE t1
+--reap
+
+--echo # Connection default
+connection default;
+--error ER_NO_SUCH_TABLE
+HANDLER t1 READ id NEXT;
+# This caused an assertion
+--error ER_NO_SUCH_TABLE
+HANDLER t1 READ id NEXT;
+
+HANDLER t1 CLOSE;
+--echo # Connection con51355
+connection con51355;
+disconnect con51355;
+--source include/wait_until_disconnected.inc
+--echo # Connection default
+connection default;
+
+
+--echo #
+--echo # Bug#54401 assert in Diagnostics_area::set_eof_status , HANDLER
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2;
+DROP FUNCTION IF EXISTS f1;
+--enable_warnings
+
+delimiter |;
+CREATE FUNCTION f1() RETURNS INTEGER
+BEGIN
+ SELECT 1 FROM t2 INTO @a;
+ RETURN 1;
+END|
+delimiter ;|
+
+# Get f1() parsed and cached
+--error ER_NO_SUCH_TABLE
+SELECT f1();
+
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES (1);
+HANDLER t1 OPEN;
+# This used to cause the assert
+--error ER_NOT_SUPPORTED_YET
+HANDLER t1 READ FIRST WHERE f1() = 1;
+HANDLER t1 CLOSE;
+
+DROP FUNCTION f1;
+DROP TABLE t1;
+
+--echo #
+--echo # Bug#54920 Stored functions are allowed in HANDLER statements,
+--echo # but broken.
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP FUNCTION IF EXISTS f1;
+--enable_warnings
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1), (2);
+CREATE FUNCTION f1() RETURNS INT RETURN 1;
+HANDLER t1 OPEN;
+
+--error ER_NOT_SUPPORTED_YET
+HANDLER t1 READ FIRST WHERE f1() = 1;
+
+HANDLER t1 CLOSE;
+DROP FUNCTION f1;
+DROP TABLE t1;
+
+--echo #
--echo # BUG#51877 - HANDLER interface causes invalid memory read
--echo #
-eval CREATE TABLE t1(a INT, KEY $key_type (a));
+CREATE TABLE t1(a INT, KEY using btree (a));
HANDLER t1 OPEN;
HANDLER t1 READ a FIRST;
INSERT INTO t1 VALUES(1);
diff --git a/mysql-test/suite/handler/heap.result b/mysql-test/suite/handler/heap.result
index 04bc9c73159..0d59440f88a 100644
--- a/mysql-test/suite/handler/heap.result
+++ b/mysql-test/suite/handler/heap.result
@@ -362,7 +362,8 @@ prepare stmt from 'handler t1 read a=(?)';
flush tables;
set @a=17;
execute stmt using @a;
-ERROR HY000: Prepared statement needs to be re-prepared
+a b c
+17 ddd NULL
deallocate prepare stmt;
handler t1 close;
handler t1 open as t2;
@@ -372,7 +373,7 @@ insert into t1 values (17);
handler t2 read first;
ERROR 42S02: Unknown table 't2' in HANDLER
handler t1 open as t2;
-alter table t1 engine=CSV;
+alter table t1 engine=csv;
handler t2 read first;
ERROR 42S02: Unknown table 't2' in HANDLER
drop table t1;
@@ -582,7 +583,7 @@ ERROR 42S02: Table 'test.t1' doesn't exist
drop table if exists t1;
Warnings:
Note 1051 Unknown table 't1'
-create table t1 (a int not null) ENGINE=CSV;
+create table t1 (a int not null) ENGINE=csv;
--> client 2
handler t1 open;
ERROR HY000: Table storage engine for 't1' doesn't have this option
@@ -718,6 +719,969 @@ ERROR 42S02: Unknown table 'a1' in HANDLER
handler a2 close;
drop table t1, t2;
#
+# Add test coverage for HANDLER and LOCK TABLES, HANDLER and DDL.
+#
+drop table if exists t1, t2, t3;
+create table t1 (a int, key a (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t2 (a int, key a (a)) select * from t1;
+create temporary table t3 (a int, key a (a)) select * from t2;
+handler t1 open;
+handler t2 open;
+handler t3 open;
+#
+# No HANDLER sql is allowed under LOCK TABLES.
+# But it does not implicitly closes all handlers.
+#
+lock table t1 read;
+handler t1 open;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+handler t1 read next;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+handler t2 close;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+handler t3 open;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+# After UNLOCK TABLES handlers should be around and
+# we should be able to continue reading through them.
+unlock tables;
+handler t1 read next;
+a
+1
+handler t1 close;
+handler t2 read next;
+a
+1
+handler t2 close;
+handler t3 read next;
+a
+1
+handler t3 close;
+drop temporary table t3;
+#
+# Other operations that implicitly close handler:
+#
+# TRUNCATE
+#
+handler t1 open;
+truncate table t1;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler t1 open;
+#
+# CREATE TRIGGER
+#
+create trigger t1_ai after insert on t1 for each row set @a=1;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# DROP TRIGGER
+#
+handler t1 open;
+drop trigger t1_ai;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# ALTER TABLE
+#
+handler t1 open;
+alter table t1 add column b int;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# ANALYZE TABLE
+#
+handler t1 open;
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze note The storage engine for the table doesn't support analyze
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# OPTIMIZE TABLE
+#
+handler t1 open;
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize note The storage engine for the table doesn't support optimize
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# REPAIR TABLE
+#
+handler t1 open;
+repair table t1;
+Table Op Msg_type Msg_text
+test.t1 repair note The storage engine for the table doesn't support repair
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# DROP TABLE, naturally.
+#
+handler t1 open;
+drop table t1;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+create table t1 (a int, b int, key a using btree (a)) select a from t2;
+#
+# RENAME TABLE, naturally
+#
+handler t1 open;
+rename table t1 to t3;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# CREATE TABLE (even with IF NOT EXISTS clause,
+# and the table exists).
+#
+handler t2 open;
+create table if not exists t2 (a int);
+Warnings:
+Note 1050 Table 't2' already exists
+handler t2 read next;
+ERROR 42S02: Unknown table 't2' in HANDLER
+rename table t3 to t1;
+drop table t2;
+#
+# FLUSH TABLE doesn't close the table but loses the position
+#
+handler t1 open;
+handler t1 read a prev;
+b a
+NULL 5
+flush table t1;
+handler t1 read a prev;
+b a
+NULL 5
+handler t1 close;
+#
+# FLUSH TABLES WITH READ LOCK behaves like FLUSH TABLE.
+#
+handler t1 open;
+handler t1 read a prev;
+b a
+NULL 5
+flush tables with read lock;
+handler t1 read a prev;
+b a
+NULL 5
+handler t1 close;
+unlock tables;
+#
+# Let us also check that these operations behave in similar
+# way under LOCK TABLES.
+#
+# TRUNCATE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+truncate table t1;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler t1 open;
+#
+# CREATE TRIGGER under LOCK TABLES.
+#
+lock tables t1 write;
+create trigger t1_ai after insert on t1 for each row set @a=1;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# DROP TRIGGER under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+drop trigger t1_ai;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# ALTER TABLE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+alter table t1 drop column b;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# ANALYZE TABLE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze note The storage engine for the table doesn't support analyze
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# OPTIMIZE TABLE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize note The storage engine for the table doesn't support optimize
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# REPAIR TABLE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+repair table t1;
+Table Op Msg_type Msg_text
+test.t1 repair note The storage engine for the table doesn't support repair
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# DROP TABLE under LOCK TABLES, naturally.
+#
+handler t1 open;
+lock tables t1 write;
+drop table t1;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+create table t1 (a int, b int, key a using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+#
+# FLUSH TABLE doesn't close the table but loses the position
+#
+handler t1 open;
+handler t1 read a prev;
+a b
+5 NULL
+lock tables t1 write;
+flush table t1;
+unlock tables;
+handler t1 read a prev;
+a b
+5 NULL
+handler t1 close;
+#
+# Explore the effect of HANDLER locks on concurrent DDL
+#
+handler t1 open;
+# Establishing auxiliary connections con1, con2, con3
+# --> connection con1;
+# Sending:
+drop table t1 ;
+# We can't use connection 'default' as wait_condition will
+# autoclose handlers.
+# --> connection con2
+# Waitng for 'drop table t1' to get blocked...
+# --> connection default
+handler t1 read a prev;
+a b
+5 NULL
+handler t1 read a prev;
+a b
+4 NULL
+handler t1 close;
+# --> connection con1
+# Reaping 'drop table t1'...
+# --> connection default
+#
+# Explore the effect of HANDLER locks in parallel with SELECT
+#
+create table t1 (a int, key a using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+begin;
+select * from t1;
+a
+1
+2
+3
+4
+5
+handler t1 open;
+handler t1 read a prev;
+a
+5
+handler t1 read a prev;
+a
+4
+handler t1 close;
+# --> connection con1;
+# Sending:
+drop table t1 ;
+# --> connection con2
+# Waiting for 'drop table t1' to get blocked...
+# --> connection default
+# We can still use the table, it's part of the transaction
+select * from t1;
+a
+1
+2
+3
+4
+5
+# Such are the circumstances that t1 is a part of transaction,
+# thus we can reopen it in the handler
+handler t1 open;
+# We can commit the transaction, it doesn't close the handler
+# and doesn't let DROP to proceed.
+commit;
+handler t1 read a prev;
+a
+5
+handler t1 read a prev;
+a
+4
+handler t1 read a prev;
+a
+3
+handler t1 close;
+# --> connection con1
+# Now drop can proceed
+# Reaping 'drop table t1'...
+# --> connection default
+#
+# Demonstrate that HANDLER locks and transaction locks
+# reside in the same context, and we don't back-off
+# when have transaction or handler locks.
+#
+create table t1 (a int, key a (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t0 (a int, key a using btree (a));
+insert into t0 (a) values (1), (2), (3), (4), (5);
+begin;
+select * from t1;
+a
+1
+2
+3
+4
+5
+# --> connection con2
+# Sending:
+rename table t0 to t3, t1 to t0, t3 to t1;
+# --> connection con1
+# Waiting for 'rename table ...' to get blocked...
+# --> connection default
+handler t0 open;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+select * from t0;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+handler t1 open;
+commit;
+handler t1 close;
+# --> connection con2
+# Reaping 'rename table ...'...
+# --> connection default
+handler t1 open;
+handler t1 read a prev;
+a
+5
+handler t1 close;
+drop table t0;
+#
+# Originally there was a deadlock error in this test.
+# With implementation of deadlock detector
+# we no longer deadlock, but block and wait on a lock.
+# The HANDLER is auto-closed as soon as the connection
+# sees a pending conflicting lock against it.
+#
+create table t2 (a int, key a (a));
+handler t1 open;
+# --> connection con1
+lock tables t2 read;
+# --> connection con2
+# Sending 'drop table t2'...
+drop table t2;
+# --> connection con1
+# Waiting for 'drop table t2' to get blocked...
+# --> connection default
+# Sending 'select * from t2'
+select * from t2;
+# --> connection con1
+# Waiting for 'select * from t2' to get blocked...
+unlock tables;
+# --> connection con2
+# Reaping 'drop table t2'...
+# --> connection default
+# Reaping 'select * from t2'
+ERROR 42S02: Table 'test.t2' doesn't exist
+handler t1 close;
+#
+# ROLLBACK TO SAVEPOINT releases transactional locks,
+# but has no effect on open HANDLERs
+#
+create table t2 like t1;
+create table t3 like t1;
+begin;
+# Have something before the savepoint
+select * from t3;
+a
+savepoint sv;
+handler t1 open;
+handler t1 read a first;
+a
+1
+handler t1 read a next;
+a
+2
+select * from t2;
+a
+# --> connection con1
+# Sending:
+drop table t1;
+# --> connection con2
+# Sending:
+drop table t2;
+# --> connection default
+# Let DROP TABLE statements sync in. We must use
+# a separate connection for that, because otherwise SELECT
+# will auto-close the HANDLERs, becaues there are pending
+# exclusive locks against them.
+# --> connection con3
+# Waiting for 'drop table t1' to get blocked...
+# Waiting for 'drop table t2' to get blocked...
+# Demonstrate that t2 lock was released and t2 was dropped
+# after ROLLBACK TO SAVEPOINT
+# --> connection default
+rollback to savepoint sv;
+# --> connection con2
+# Reaping 'drop table t2'...
+# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
+# lock.
+# --> connection default
+handler t1 read a next;
+a
+3
+handler t1 read a next;
+a
+4
+# Demonstrate that the drop will go through as soon as we close the
+# HANDLER
+handler t1 close;
+# connection con1
+# Reaping 'drop table t1'...
+# --> connection default
+commit;
+drop table t3;
+#
+# A few special cases when using SAVEPOINT/ROLLBACK TO
+# SAVEPOINT and HANDLER.
+#
+# Show that rollback to the savepoint taken in the beginning
+# of the transaction doesn't release mdl lock on
+# the HANDLER that was opened later.
+#
+create table t1 (a int, key using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t2 like t1;
+begin;
+savepoint sv;
+handler t1 open;
+handler t1 read a first;
+a
+1
+handler t1 read a next;
+a
+2
+select * from t2;
+a
+# --> connection con1
+# Sending:
+drop table t1;
+# --> connection con2
+# Sending:
+drop table t2;
+# --> connection default
+# Let DROP TABLE statements sync in. We must use
+# a separate connection for that, because otherwise SELECT
+# will auto-close the HANDLERs, becaues there are pending
+# exclusive locks against them.
+# --> connection con3
+# Waiting for 'drop table t1' to get blocked...
+# Waiting for 'drop table t2' to get blocked...
+# Demonstrate that t2 lock was released and t2 was dropped
+# after ROLLBACK TO SAVEPOINT
+# --> connection default
+rollback to savepoint sv;
+# --> connection con2
+# Reaping 'drop table t2'...
+# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
+# lock.
+# --> connection default
+handler t1 read a next;
+a
+3
+handler t1 read a next;
+a
+4
+# Demonstrate that the drop will go through as soon as we close the
+# HANDLER
+handler t1 close;
+# connection con1
+# Reaping 'drop table t1'...
+# --> connection default
+commit;
+#
+# Show that rollback to the savepoint taken in the beginning
+# of the transaction works properly (no valgrind warnins, etc),
+# even though it's done after the HANDLER mdl lock that was there
+# at the beginning is released and added again.
+#
+create table t1 (a int, key using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t2 like t1;
+create table t3 like t1;
+insert into t3 (a) select a from t1;
+begin;
+handler t1 open;
+savepoint sv;
+handler t1 read a first;
+a
+1
+select * from t2;
+a
+handler t1 close;
+handler t3 open;
+handler t3 read a first;
+a
+1
+rollback to savepoint sv;
+# --> connection con1
+drop table t1, t2;
+# Sending:
+drop table t3;
+# Let DROP TABLE statement sync in.
+# --> connection con2
+# Waiting for 'drop table t3' to get blocked...
+# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
+# lock.
+# --> connection default
+handler t3 read a next;
+a
+2
+# Demonstrate that the drop will go through as soon as we close the
+# HANDLER
+handler t3 close;
+# connection con1
+# Reaping 'drop table t3'...
+# --> connection default
+commit;
+#
+# If we have to wait on an exclusive locks while having
+# an open HANDLER, ER_LOCK_DEADLOCK is reported.
+#
+create table t1 (a int, key a(a));
+create table t2 like t1;
+handler t1 open;
+# --> connection con1
+lock table t1 write, t2 write;
+# --> connection default
+drop table t2;
+# --> connection con2
+# Waiting for 'drop table t2' to get blocked...
+# --> connection con1
+drop table t1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+unlock tables;
+# --> connection default
+# Demonstrate that there is no deadlock with FLUSH TABLE,
+# even though it is waiting for the other table to go away
+create table t2 like t1;
+# Sending:
+flush table t2;
+# --> connection con2
+drop table t1;
+# --> connection con1
+unlock tables;
+# --> connection default
+# Reaping 'flush table t2'...
+drop table t2;
+#
+# Bug #46224 HANDLER statements within a transaction might
+# lead to deadlocks
+#
+create table t1 (a int, key using btree (a));
+insert into t1 values (1), (2);
+# --> connection default
+begin;
+select * from t1;
+a
+1
+2
+handler t1 open;
+# --> connection con1
+# Sending:
+lock tables t1 write;
+# --> connection con2
+# Check that 'lock tables t1 write' waits until transaction which
+# has read from the table commits.
+# --> connection default
+# The below 'handler t1 read ...' should not be blocked as
+# 'lock tables t1 write' has not succeeded yet.
+handler t1 read a next;
+a
+1
+# Unblock 'lock tables t1 write'.
+commit;
+# --> connection con1
+# Reap 'lock tables t1 write'.
+# --> connection default
+# Sending:
+handler t1 read a next;
+# --> connection con1
+# Waiting for 'handler t1 read a next' to get blocked...
+# The below 'drop table t1' should be able to proceed without
+# waiting as it will force HANDLER to be closed.
+drop table t1;
+unlock tables;
+# --> connection default
+# Reaping 'handler t1 read a next'...
+ERROR 42S02: Table 'test.t1' doesn't exist
+handler t1 close;
+# --> connection con1
+# --> connection con2
+# --> connection con3
+#
+# A temporary table test.
+# Check that we don't loose positions of HANDLER opened
+# against a temporary table.
+#
+create table t1 (a int, b int, key using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create temporary table t2 (a int, b int, key using btree (a));
+insert into t2 (a) select a from t1;
+handler t1 open;
+handler t1 read a next;
+a b
+1 NULL
+handler t2 open;
+handler t2 read a next;
+a b
+1 NULL
+flush table t1;
+handler t2 read a next;
+a b
+2 NULL
+# Sic: the position is lost
+handler t1 read a next;
+a b
+1 NULL
+select * from t1;
+a b
+1 NULL
+2 NULL
+3 NULL
+4 NULL
+5 NULL
+# Sic: the position is not lost
+handler t2 read a next;
+a b
+3 NULL
+select * from t2;
+ERROR HY000: Can't reopen table: 't2'
+handler t2 read a next;
+a b
+4 NULL
+drop table t1;
+drop temporary table t2;
+#
+# A test for lock_table_names()/unlock_table_names() function.
+# It should work properly in presence of open HANDLER.
+#
+create table t1 (a int, b int, key a (a));
+create table t2 like t1;
+create table t3 like t1;
+create table t4 like t1;
+handler t1 open;
+handler t2 open;
+rename table t4 to t5, t3 to t4, t5 to t3;
+handler t1 read first;
+a b
+handler t2 read first;
+a b
+drop table t1, t2, t3, t4;
+#
+# A test for FLUSH TABLES WITH READ LOCK and HANDLER statements.
+#
+set autocommit=0;
+create table t1 (a int, b int, key a (a));
+insert into t1 (a, b) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 5);
+create table t2 like t1;
+insert into t2 (a, b) select a, b from t1;
+create table t3 like t1;
+insert into t3 (a, b) select a, b from t1;
+commit;
+flush tables with read lock;
+handler t1 open;
+lock table t1 read;
+handler t1 read next;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+# This implicitly leaves LOCK TABLES but doesn't drop the GLR
+lock table not_exists_write read;
+ERROR 42S02: Table 'test.not_exists_write' doesn't exist
+# We still have the read lock.
+drop table t1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+handler t1 open;
+select a from t2;
+a
+1
+2
+3
+4
+5
+handler t1 read next;
+a b
+1 1
+flush tables with read lock;
+handler t2 open;
+flush tables with read lock;
+handler t1 read next;
+a b
+1 1
+select a from t3;
+a
+1
+2
+3
+4
+5
+handler t2 read next;
+a b
+1 1
+handler t1 close;
+rollback;
+handler t2 close;
+drop table t1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+commit;
+flush tables;
+drop table t1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+unlock tables;
+drop table t1;
+set autocommit=default;
+drop table t2, t3;
+#
+# HANDLER statement and operation-type aware metadata locks.
+# Check that when we clone a ticket for HANDLER we downrade
+# the lock.
+#
+# Establish an auxiliary connection con1.
+# -> connection default
+create table t1 (a int, b int, key using btree (a));
+insert into t1 (a, b) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 5);
+begin;
+insert into t1 (a, b) values (6, 6);
+handler t1 open;
+handler t1 read a last;
+a b
+6 6
+insert into t1 (a, b) values (7, 7);
+handler t1 read a last;
+a b
+7 7
+commit;
+# -> connection con1
+# Demonstrate that the HANDLER doesn't hold MDL_SHARED_WRITE.
+lock table t1 write;
+unlock tables;
+# -> connection default
+handler t1 read a prev;
+a b
+6 6
+handler t1 close;
+# Cleanup.
+drop table t1;
+# -> connection con1
+# -> connection default
+#
+# A test for Bug#50555 "handler commands crash server in
+# my_hash_first()".
+#
+handler no_such_table read no_such_index first;
+ERROR 42S02: Unknown table 'no_such_table' in HANDLER
+handler no_such_table close;
+ERROR 42S02: Unknown table 'no_such_table' in HANDLER
+#
+# Bug#50907 Assertion `hash_tables->table->next == __null' on
+# HANDLER OPEN
+#
+DROP TABLE IF EXISTS t1, t2;
+CREATE TEMPORARY TABLE t1 (i INT);
+CREATE TEMPORARY TABLE t2 (i INT);
+HANDLER t2 OPEN;
+HANDLER t2 READ FIRST;
+i
+HANDLER t2 CLOSE;
+DROP TABLE t1, t2;
+#
+# Bug#50912 Assertion `ticket->m_type >= mdl_request->type'
+# failed on HANDLER + I_S
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (id INT);
+HANDLER t1 OPEN;
+SELECT table_name, table_comment FROM information_schema.tables
+WHERE table_schema= 'test' AND table_name= 't1';
+table_name table_comment
+t1
+HANDLER t1 CLOSE;
+DROP TABLE t1;
+#
+# Test for bug #50908 "Assertion `handler_tables_hash.records == 0'
+# failed in enter_locked_tables_mode".
+#
+drop tables if exists t1, t2;
+drop function if exists f1;
+create table t1 (i int);
+insert into t1 values (1), (2);
+create table t2 (j int);
+insert into t2 values (1);
+create function f1() returns int return (select count(*) from t2);
+# Check that open HANDLER survives statement executed in
+# prelocked mode.
+handler t1 open;
+handler t1 read next;
+i
+1
+# The below statement were aborted due to an assertion failure.
+select f1() from t2;
+f1()
+1
+handler t1 read next;
+i
+2
+handler t1 close;
+# Check that the same happens under GLOBAL READ LOCK.
+flush tables with read lock;
+handler t1 open;
+handler t1 read next;
+i
+1
+select f1() from t2;
+f1()
+1
+handler t1 read next;
+i
+2
+unlock tables;
+handler t1 close;
+# Now, check that the same happens if LOCK TABLES is executed.
+handler t1 open;
+handler t1 read next;
+i
+1
+lock table t2 read;
+select * from t2;
+j
+1
+unlock tables;
+handler t1 read next;
+i
+2
+handler t1 close;
+# Finally, check scenario with GRL and LOCK TABLES.
+flush tables with read lock;
+handler t1 open;
+handler t1 read next;
+i
+1
+lock table t2 read;
+select * from t2;
+j
+1
+# This unlocks both tables and GRL.
+unlock tables;
+handler t1 read next;
+i
+2
+handler t1 close;
+# Clean-up.
+drop function f1;
+drop tables t1, t2;
+#
+# Test for bug #51136 "Crash in pthread_rwlock_rdlock on TEMPORARY +
+# HANDLER + LOCK + SP".
+# Also see additional coverage for this bug in flush.test.
+#
+drop tables if exists t1, t2;
+create table t1 (i int);
+create temporary table t2 (j int);
+handler t1 open;
+lock table t2 read;
+# This commit should not release any MDL locks.
+commit;
+unlock tables;
+# The below statement crashed before the bug fix as it
+# has attempted to release metadata lock which was
+# already released by commit.
+handler t1 close;
+drop tables t1, t2;
+#
+# Bug#51355 handler stmt cause assertion in
+# bool MDL_context::try_acquire_lock(MDL_request*)
+#
+DROP TABLE IF EXISTS t1;
+# Connection default
+CREATE TABLE t1(id INT, KEY id(id));
+HANDLER t1 OPEN;
+# Connection con51355
+# Sending:
+DROP TABLE t1;
+# Connection default
+# This I_S query will cause the handler table to be closed and
+# the metadata lock to be released. This will allow DROP TABLE
+# to proceed. Waiting for the table to be removed.
+# Connection con51355
+# Reaping: DROP TABLE t1
+# Connection default
+HANDLER t1 READ id NEXT;
+ERROR 42S02: Table 'test.t1' doesn't exist
+HANDLER t1 READ id NEXT;
+ERROR 42S02: Table 'test.t1' doesn't exist
+HANDLER t1 CLOSE;
+# Connection con51355
+# Connection default
+#
+# Bug#54401 assert in Diagnostics_area::set_eof_status , HANDLER
+#
+DROP TABLE IF EXISTS t1, t2;
+DROP FUNCTION IF EXISTS f1;
+CREATE FUNCTION f1() RETURNS INTEGER
+BEGIN
+SELECT 1 FROM t2 INTO @a;
+RETURN 1;
+END|
+SELECT f1();
+ERROR 42S02: Table 'test.t2' doesn't exist
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES (1);
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST WHERE f1() = 1;
+ERROR 42000: This version of MySQL doesn't yet support 'stored functions in HANDLER ... READ'
+HANDLER t1 CLOSE;
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
+# Bug#54920 Stored functions are allowed in HANDLER statements,
+# but broken.
+#
+DROP TABLE IF EXISTS t1;
+DROP FUNCTION IF EXISTS f1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1), (2);
+CREATE FUNCTION f1() RETURNS INT RETURN 1;
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST WHERE f1() = 1;
+ERROR 42000: This version of MySQL doesn't yet support 'stored functions in HANDLER ... READ'
+HANDLER t1 CLOSE;
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
# BUG#51877 - HANDLER interface causes invalid memory read
#
CREATE TABLE t1(a INT, KEY using btree (a));
diff --git a/mysql-test/suite/handler/heap.test b/mysql-test/suite/handler/heap.test
index d6715144caa..bc070cf743f 100644
--- a/mysql-test/suite/handler/heap.test
+++ b/mysql-test/suite/handler/heap.test
@@ -2,7 +2,6 @@
#
let $engine_type= MEMORY;
-let $key_type=using btree;
--source init.inc
--source handler.inc
diff --git a/mysql-test/suite/handler/init.inc b/mysql-test/suite/handler/init.inc
index 3e63f14a103..ff5b2218ed1 100644
--- a/mysql-test/suite/handler/init.inc
+++ b/mysql-test/suite/handler/init.inc
@@ -2,10 +2,9 @@
#
# Input variables
# $engine_type -- storage engine to be tested
-# $key_type -- set if you want a non standard key type
+# using btree -- set if you want a non standard key type
#
# This scripts sets up default values for:
-# $other_engine_type -- storage engine <> $engine_type
# $other_handler_engine_type -- storage engine <> $engine_type, if possible
# 1. $other_handler_engine_type must support handler
# 2. $other_handler_engine_type must point to an all
@@ -17,7 +16,6 @@
-- source include/not_embedded.inc
eval SET SESSION STORAGE_ENGINE = $engine_type;
-let $other_engine_type= CSV;
let $other_handler_engine_type= MyISAM;
--disable_warnings
@@ -26,7 +24,7 @@ drop table if exists t1,t3,t4,t5;
# Create default test table
-eval create table t1 (a int, b char(10), key a $key_type (a), key b $key_type (a,b));
+create table t1 (a int, b char(10), key a using btree (a), key b using btree (a,b));
insert into t1 values
(17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"),
(14,"aaa"),(16,"ccc"),(16,"xxx"),
diff --git a/mysql-test/suite/handler/innodb.result b/mysql-test/suite/handler/innodb.result
index 3bf3a1f2c70..ab7b8dc8848 100644
--- a/mysql-test/suite/handler/innodb.result
+++ b/mysql-test/suite/handler/innodb.result
@@ -1,6 +1,6 @@
SET SESSION STORAGE_ENGINE = InnoDB;
drop table if exists t1,t3,t4,t5;
-create table t1 (a int, b char(10), key a (a), key b (a,b));
+create table t1 (a int, b char(10), key a using btree (a), key b using btree (a,b));
insert into t1 values
(17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"),
(14,"aaa"),(16,"ccc"),(16,"xxx"),
@@ -362,7 +362,8 @@ prepare stmt from 'handler t1 read a=(?)';
flush tables;
set @a=17;
execute stmt using @a;
-ERROR HY000: Prepared statement needs to be re-prepared
+a b c
+17 ddd NULL
deallocate prepare stmt;
handler t1 close;
handler t1 open as t2;
@@ -372,7 +373,7 @@ insert into t1 values (17);
handler t2 read first;
ERROR 42S02: Unknown table 't2' in HANDLER
handler t1 open as t2;
-alter table t1 engine=CSV;
+alter table t1 engine=csv;
handler t2 read first;
ERROR 42S02: Unknown table 't2' in HANDLER
drop table t1;
@@ -395,7 +396,7 @@ handler t1 read first;
a
6
drop table t1;
-create table t1(a int, index (a));
+create table t1(a int, index using btree (a));
insert into t1 values (1), (2), (3);
handler t1 open;
handler t1 read a=(W);
@@ -421,7 +422,7 @@ Ok
handler t close;
use test;
drop table t1;
-create table t1 ( a int, b int, INDEX a (a) );
+create table t1 ( a int, b int, INDEX a using btree (a) );
insert into t1 values (1,2), (2,1);
handler t1 open;
handler t1 read a=(1) where b=2;
@@ -550,7 +551,7 @@ test.t1 optimize note Table does not support optimize, doing recreate + analyze
test.t1 optimize status OK
proceed with the normal connection
drop table t1;
-CREATE TABLE t1 ( no1 smallint(5) NOT NULL default '0', no2 int(10) NOT NULL default '0', PRIMARY KEY (no1,no2));
+CREATE TABLE t1 ( no1 smallint(5) NOT NULL default '0', no2 int(10) NOT NULL default '0', PRIMARY KEY using btree (no1,no2));
INSERT INTO t1 VALUES (1,274),(1,275),(2,6),(2,8),(4,1),(4,2);
HANDLER t1 OPEN;
HANDLER t1 READ `primary` = (1, 1000);
@@ -583,7 +584,7 @@ ERROR 42S02: Table 'test.t1' doesn't exist
drop table if exists t1;
Warnings:
Note 1051 Unknown table 't1'
-create table t1 (a int not null) ENGINE=CSV;
+create table t1 (a int not null) ENGINE=csv;
--> client 2
handler t1 open;
ERROR HY000: Table storage engine for 't1' doesn't have this option
@@ -601,7 +602,7 @@ handler t1_alias READ a next where inexistent > 0;
ERROR 42S22: Unknown column 'inexistent' in 'field list'
handler t1_alias close;
drop table t1;
-create temporary table t1 (a int, b char(1), key a (a), key b (a,b));
+create temporary table t1 (a int, b char(1), key a using btree (a), key b using btree (a,b));
insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"),
(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"),(9,'k');
select a,b from t1;
@@ -672,7 +673,7 @@ a b
handler a2 close;
drop table t1;
create table t1 (a int);
-create temporary table t2 (a int, key (a));
+create temporary table t2 (a int, key using btree (a));
handler t1 open as a1;
handler t2 open as a2;
handler a2 read a first;
@@ -682,7 +683,7 @@ handler a2 read a next;
ERROR 42S02: Unknown table 'a2' in HANDLER
handler a1 close;
ERROR 42S02: Unknown table 'a1' in HANDLER
-create table t1 (a int, key (a));
+create table t1 (a int, key using btree (a));
create table t2 like t1;
handler t1 open as a1;
handler t2 open as a2;
@@ -695,7 +696,7 @@ handler a1 close;
ERROR 42S02: Unknown table 'a1' in HANDLER
handler a2 close;
drop table t1, t2;
-create table t1 (a int, key (a));
+create table t1 (a int, key using btree (a));
handler t1 open as a1;
handler a1 read a first;
a
@@ -703,7 +704,7 @@ rename table t1 to t2;
handler a1 read a first;
ERROR 42S02: Unknown table 'a1' in HANDLER
drop table t2;
-create table t1 (a int, key (a));
+create table t1 (a int, key using btree (a));
create table t2 like t1;
handler t1 open as a1;
handler t2 open as a2;
@@ -720,9 +721,974 @@ ERROR 42S02: Unknown table 'a1' in HANDLER
handler a2 close;
drop table t1, t2;
#
+# Add test coverage for HANDLER and LOCK TABLES, HANDLER and DDL.
+#
+drop table if exists t1, t2, t3;
+create table t1 (a int, key a (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t2 (a int, key a (a)) select * from t1;
+create temporary table t3 (a int, key a (a)) select * from t2;
+handler t1 open;
+handler t2 open;
+handler t3 open;
+#
+# No HANDLER sql is allowed under LOCK TABLES.
+# But it does not implicitly closes all handlers.
+#
+lock table t1 read;
+handler t1 open;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+handler t1 read next;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+handler t2 close;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+handler t3 open;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+# After UNLOCK TABLES handlers should be around and
+# we should be able to continue reading through them.
+unlock tables;
+handler t1 read next;
+a
+1
+handler t1 close;
+handler t2 read next;
+a
+1
+handler t2 close;
+handler t3 read next;
+a
+1
+handler t3 close;
+drop temporary table t3;
+#
+# Other operations that implicitly close handler:
+#
+# TRUNCATE
+#
+handler t1 open;
+truncate table t1;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler t1 open;
+#
+# CREATE TRIGGER
+#
+create trigger t1_ai after insert on t1 for each row set @a=1;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# DROP TRIGGER
+#
+handler t1 open;
+drop trigger t1_ai;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# ALTER TABLE
+#
+handler t1 open;
+alter table t1 add column b int;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# ANALYZE TABLE
+#
+handler t1 open;
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# OPTIMIZE TABLE
+#
+handler t1 open;
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
+test.t1 optimize status OK
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# REPAIR TABLE
+#
+handler t1 open;
+repair table t1;
+Table Op Msg_type Msg_text
+test.t1 repair note The storage engine for the table doesn't support repair
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# DROP TABLE, naturally.
+#
+handler t1 open;
+drop table t1;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+create table t1 (a int, b int, key a using btree (a)) select a from t2;
+#
+# RENAME TABLE, naturally
+#
+handler t1 open;
+rename table t1 to t3;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# CREATE TABLE (even with IF NOT EXISTS clause,
+# and the table exists).
+#
+handler t2 open;
+create table if not exists t2 (a int);
+Warnings:
+Note 1050 Table 't2' already exists
+handler t2 read next;
+ERROR 42S02: Unknown table 't2' in HANDLER
+rename table t3 to t1;
+drop table t2;
+#
+# FLUSH TABLE doesn't close the table but loses the position
+#
+handler t1 open;
+handler t1 read a prev;
+b a
+NULL 5
+flush table t1;
+handler t1 read a prev;
+b a
+NULL 5
+handler t1 close;
+#
+# FLUSH TABLES WITH READ LOCK behaves like FLUSH TABLE.
+#
+handler t1 open;
+handler t1 read a prev;
+b a
+NULL 5
+flush tables with read lock;
+handler t1 read a prev;
+b a
+NULL 5
+handler t1 close;
+unlock tables;
+#
+# Let us also check that these operations behave in similar
+# way under LOCK TABLES.
+#
+# TRUNCATE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+truncate table t1;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler t1 open;
+#
+# CREATE TRIGGER under LOCK TABLES.
+#
+lock tables t1 write;
+create trigger t1_ai after insert on t1 for each row set @a=1;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# DROP TRIGGER under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+drop trigger t1_ai;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# ALTER TABLE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+alter table t1 drop column b;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# ANALYZE TABLE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# OPTIMIZE TABLE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
+test.t1 optimize status OK
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# REPAIR TABLE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+repair table t1;
+Table Op Msg_type Msg_text
+test.t1 repair note The storage engine for the table doesn't support repair
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# DROP TABLE under LOCK TABLES, naturally.
+#
+handler t1 open;
+lock tables t1 write;
+drop table t1;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+create table t1 (a int, b int, key a using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+#
+# FLUSH TABLE doesn't close the table but loses the position
+#
+handler t1 open;
+handler t1 read a prev;
+a b
+5 NULL
+lock tables t1 write;
+flush table t1;
+unlock tables;
+handler t1 read a prev;
+a b
+5 NULL
+handler t1 close;
+#
+# Explore the effect of HANDLER locks on concurrent DDL
+#
+handler t1 open;
+# Establishing auxiliary connections con1, con2, con3
+# --> connection con1;
+# Sending:
+drop table t1 ;
+# We can't use connection 'default' as wait_condition will
+# autoclose handlers.
+# --> connection con2
+# Waitng for 'drop table t1' to get blocked...
+# --> connection default
+handler t1 read a prev;
+a b
+5 NULL
+handler t1 read a prev;
+a b
+4 NULL
+handler t1 close;
+# --> connection con1
+# Reaping 'drop table t1'...
+# --> connection default
+#
+# Explore the effect of HANDLER locks in parallel with SELECT
+#
+create table t1 (a int, key a using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+begin;
+select * from t1;
+a
+1
+2
+3
+4
+5
+handler t1 open;
+handler t1 read a prev;
+a
+5
+handler t1 read a prev;
+a
+4
+handler t1 close;
+# --> connection con1;
+# Sending:
+drop table t1 ;
+# --> connection con2
+# Waiting for 'drop table t1' to get blocked...
+# --> connection default
+# We can still use the table, it's part of the transaction
+select * from t1;
+a
+1
+2
+3
+4
+5
+# Such are the circumstances that t1 is a part of transaction,
+# thus we can reopen it in the handler
+handler t1 open;
+# We can commit the transaction, it doesn't close the handler
+# and doesn't let DROP to proceed.
+commit;
+handler t1 read a prev;
+a
+5
+handler t1 read a prev;
+a
+4
+handler t1 read a prev;
+a
+3
+handler t1 close;
+# --> connection con1
+# Now drop can proceed
+# Reaping 'drop table t1'...
+# --> connection default
+#
+# Demonstrate that HANDLER locks and transaction locks
+# reside in the same context, and we don't back-off
+# when have transaction or handler locks.
+#
+create table t1 (a int, key a (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t0 (a int, key a using btree (a));
+insert into t0 (a) values (1), (2), (3), (4), (5);
+begin;
+select * from t1;
+a
+1
+2
+3
+4
+5
+# --> connection con2
+# Sending:
+rename table t0 to t3, t1 to t0, t3 to t1;
+# --> connection con1
+# Waiting for 'rename table ...' to get blocked...
+# --> connection default
+handler t0 open;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+select * from t0;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+handler t1 open;
+commit;
+handler t1 close;
+# --> connection con2
+# Reaping 'rename table ...'...
+# --> connection default
+handler t1 open;
+handler t1 read a prev;
+a
+5
+handler t1 close;
+drop table t0;
+#
+# Originally there was a deadlock error in this test.
+# With implementation of deadlock detector
+# we no longer deadlock, but block and wait on a lock.
+# The HANDLER is auto-closed as soon as the connection
+# sees a pending conflicting lock against it.
+#
+create table t2 (a int, key a (a));
+handler t1 open;
+# --> connection con1
+lock tables t2 read;
+# --> connection con2
+# Sending 'drop table t2'...
+drop table t2;
+# --> connection con1
+# Waiting for 'drop table t2' to get blocked...
+# --> connection default
+# Sending 'select * from t2'
+select * from t2;
+# --> connection con1
+# Waiting for 'select * from t2' to get blocked...
+unlock tables;
+# --> connection con2
+# Reaping 'drop table t2'...
+# --> connection default
+# Reaping 'select * from t2'
+ERROR 42S02: Table 'test.t2' doesn't exist
+handler t1 close;
+#
+# ROLLBACK TO SAVEPOINT releases transactional locks,
+# but has no effect on open HANDLERs
+#
+create table t2 like t1;
+create table t3 like t1;
+begin;
+# Have something before the savepoint
+select * from t3;
+a
+savepoint sv;
+handler t1 open;
+handler t1 read a first;
+a
+1
+handler t1 read a next;
+a
+2
+select * from t2;
+a
+# --> connection con1
+# Sending:
+drop table t1;
+# --> connection con2
+# Sending:
+drop table t2;
+# --> connection default
+# Let DROP TABLE statements sync in. We must use
+# a separate connection for that, because otherwise SELECT
+# will auto-close the HANDLERs, becaues there are pending
+# exclusive locks against them.
+# --> connection con3
+# Waiting for 'drop table t1' to get blocked...
+# Waiting for 'drop table t2' to get blocked...
+# Demonstrate that t2 lock was released and t2 was dropped
+# after ROLLBACK TO SAVEPOINT
+# --> connection default
+rollback to savepoint sv;
+# --> connection con2
+# Reaping 'drop table t2'...
+# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
+# lock.
+# --> connection default
+handler t1 read a next;
+a
+3
+handler t1 read a next;
+a
+4
+# Demonstrate that the drop will go through as soon as we close the
+# HANDLER
+handler t1 close;
+# connection con1
+# Reaping 'drop table t1'...
+# --> connection default
+commit;
+drop table t3;
+#
+# A few special cases when using SAVEPOINT/ROLLBACK TO
+# SAVEPOINT and HANDLER.
+#
+# Show that rollback to the savepoint taken in the beginning
+# of the transaction doesn't release mdl lock on
+# the HANDLER that was opened later.
+#
+create table t1 (a int, key using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t2 like t1;
+begin;
+savepoint sv;
+handler t1 open;
+handler t1 read a first;
+a
+1
+handler t1 read a next;
+a
+2
+select * from t2;
+a
+# --> connection con1
+# Sending:
+drop table t1;
+# --> connection con2
+# Sending:
+drop table t2;
+# --> connection default
+# Let DROP TABLE statements sync in. We must use
+# a separate connection for that, because otherwise SELECT
+# will auto-close the HANDLERs, becaues there are pending
+# exclusive locks against them.
+# --> connection con3
+# Waiting for 'drop table t1' to get blocked...
+# Waiting for 'drop table t2' to get blocked...
+# Demonstrate that t2 lock was released and t2 was dropped
+# after ROLLBACK TO SAVEPOINT
+# --> connection default
+rollback to savepoint sv;
+# --> connection con2
+# Reaping 'drop table t2'...
+# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
+# lock.
+# --> connection default
+handler t1 read a next;
+a
+3
+handler t1 read a next;
+a
+4
+# Demonstrate that the drop will go through as soon as we close the
+# HANDLER
+handler t1 close;
+# connection con1
+# Reaping 'drop table t1'...
+# --> connection default
+commit;
+#
+# Show that rollback to the savepoint taken in the beginning
+# of the transaction works properly (no valgrind warnins, etc),
+# even though it's done after the HANDLER mdl lock that was there
+# at the beginning is released and added again.
+#
+create table t1 (a int, key using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t2 like t1;
+create table t3 like t1;
+insert into t3 (a) select a from t1;
+begin;
+handler t1 open;
+savepoint sv;
+handler t1 read a first;
+a
+1
+select * from t2;
+a
+handler t1 close;
+handler t3 open;
+handler t3 read a first;
+a
+1
+rollback to savepoint sv;
+# --> connection con1
+drop table t1, t2;
+# Sending:
+drop table t3;
+# Let DROP TABLE statement sync in.
+# --> connection con2
+# Waiting for 'drop table t3' to get blocked...
+# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
+# lock.
+# --> connection default
+handler t3 read a next;
+a
+2
+# Demonstrate that the drop will go through as soon as we close the
+# HANDLER
+handler t3 close;
+# connection con1
+# Reaping 'drop table t3'...
+# --> connection default
+commit;
+#
+# If we have to wait on an exclusive locks while having
+# an open HANDLER, ER_LOCK_DEADLOCK is reported.
+#
+create table t1 (a int, key a(a));
+create table t2 like t1;
+handler t1 open;
+# --> connection con1
+lock table t1 write, t2 write;
+# --> connection default
+drop table t2;
+# --> connection con2
+# Waiting for 'drop table t2' to get blocked...
+# --> connection con1
+drop table t1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+unlock tables;
+# --> connection default
+# Demonstrate that there is no deadlock with FLUSH TABLE,
+# even though it is waiting for the other table to go away
+create table t2 like t1;
+# Sending:
+flush table t2;
+# --> connection con2
+drop table t1;
+# --> connection con1
+unlock tables;
+# --> connection default
+# Reaping 'flush table t2'...
+drop table t2;
+#
+# Bug #46224 HANDLER statements within a transaction might
+# lead to deadlocks
+#
+create table t1 (a int, key using btree (a));
+insert into t1 values (1), (2);
+# --> connection default
+begin;
+select * from t1;
+a
+1
+2
+handler t1 open;
+# --> connection con1
+# Sending:
+lock tables t1 write;
+# --> connection con2
+# Check that 'lock tables t1 write' waits until transaction which
+# has read from the table commits.
+# --> connection default
+# The below 'handler t1 read ...' should not be blocked as
+# 'lock tables t1 write' has not succeeded yet.
+handler t1 read a next;
+a
+1
+# Unblock 'lock tables t1 write'.
+commit;
+# --> connection con1
+# Reap 'lock tables t1 write'.
+# --> connection default
+# Sending:
+handler t1 read a next;
+# --> connection con1
+# Waiting for 'handler t1 read a next' to get blocked...
+# The below 'drop table t1' should be able to proceed without
+# waiting as it will force HANDLER to be closed.
+drop table t1;
+unlock tables;
+# --> connection default
+# Reaping 'handler t1 read a next'...
+ERROR 42S02: Table 'test.t1' doesn't exist
+handler t1 close;
+# --> connection con1
+# --> connection con2
+# --> connection con3
+#
+# A temporary table test.
+# Check that we don't loose positions of HANDLER opened
+# against a temporary table.
+#
+create table t1 (a int, b int, key using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create temporary table t2 (a int, b int, key using btree (a));
+insert into t2 (a) select a from t1;
+handler t1 open;
+handler t1 read a next;
+a b
+1 NULL
+handler t2 open;
+handler t2 read a next;
+a b
+1 NULL
+flush table t1;
+handler t2 read a next;
+a b
+2 NULL
+# Sic: the position is lost
+handler t1 read a next;
+a b
+1 NULL
+select * from t1;
+a b
+1 NULL
+2 NULL
+3 NULL
+4 NULL
+5 NULL
+# Sic: the position is not lost
+handler t2 read a next;
+a b
+3 NULL
+select * from t2;
+ERROR HY000: Can't reopen table: 't2'
+handler t2 read a next;
+a b
+4 NULL
+drop table t1;
+drop temporary table t2;
+#
+# A test for lock_table_names()/unlock_table_names() function.
+# It should work properly in presence of open HANDLER.
+#
+create table t1 (a int, b int, key a (a));
+create table t2 like t1;
+create table t3 like t1;
+create table t4 like t1;
+handler t1 open;
+handler t2 open;
+rename table t4 to t5, t3 to t4, t5 to t3;
+handler t1 read first;
+a b
+handler t2 read first;
+a b
+drop table t1, t2, t3, t4;
+#
+# A test for FLUSH TABLES WITH READ LOCK and HANDLER statements.
+#
+set autocommit=0;
+create table t1 (a int, b int, key a (a));
+insert into t1 (a, b) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 5);
+create table t2 like t1;
+insert into t2 (a, b) select a, b from t1;
+create table t3 like t1;
+insert into t3 (a, b) select a, b from t1;
+commit;
+flush tables with read lock;
+handler t1 open;
+lock table t1 read;
+handler t1 read next;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+# This implicitly leaves LOCK TABLES but doesn't drop the GLR
+lock table not_exists_write read;
+ERROR 42S02: Table 'test.not_exists_write' doesn't exist
+# We still have the read lock.
+drop table t1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+handler t1 open;
+select a from t2;
+a
+1
+2
+3
+4
+5
+handler t1 read next;
+a b
+1 1
+flush tables with read lock;
+handler t2 open;
+flush tables with read lock;
+handler t1 read next;
+a b
+1 1
+select a from t3;
+a
+1
+2
+3
+4
+5
+handler t2 read next;
+a b
+1 1
+handler t1 close;
+rollback;
+handler t2 close;
+drop table t1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+commit;
+flush tables;
+drop table t1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+unlock tables;
+drop table t1;
+set autocommit=default;
+drop table t2, t3;
+#
+# HANDLER statement and operation-type aware metadata locks.
+# Check that when we clone a ticket for HANDLER we downrade
+# the lock.
+#
+# Establish an auxiliary connection con1.
+# -> connection default
+create table t1 (a int, b int, key using btree (a));
+insert into t1 (a, b) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 5);
+begin;
+insert into t1 (a, b) values (6, 6);
+handler t1 open;
+handler t1 read a last;
+a b
+6 6
+insert into t1 (a, b) values (7, 7);
+handler t1 read a last;
+a b
+7 7
+commit;
+# -> connection con1
+# Demonstrate that the HANDLER doesn't hold MDL_SHARED_WRITE.
+lock table t1 write;
+unlock tables;
+# -> connection default
+handler t1 read a prev;
+a b
+6 6
+handler t1 close;
+# Cleanup.
+drop table t1;
+# -> connection con1
+# -> connection default
+#
+# A test for Bug#50555 "handler commands crash server in
+# my_hash_first()".
+#
+handler no_such_table read no_such_index first;
+ERROR 42S02: Unknown table 'no_such_table' in HANDLER
+handler no_such_table close;
+ERROR 42S02: Unknown table 'no_such_table' in HANDLER
+#
+# Bug#50907 Assertion `hash_tables->table->next == __null' on
+# HANDLER OPEN
+#
+DROP TABLE IF EXISTS t1, t2;
+CREATE TEMPORARY TABLE t1 (i INT);
+CREATE TEMPORARY TABLE t2 (i INT);
+HANDLER t2 OPEN;
+HANDLER t2 READ FIRST;
+i
+HANDLER t2 CLOSE;
+DROP TABLE t1, t2;
+#
+# Bug#50912 Assertion `ticket->m_type >= mdl_request->type'
+# failed on HANDLER + I_S
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (id INT);
+HANDLER t1 OPEN;
+SELECT table_name, table_comment FROM information_schema.tables
+WHERE table_schema= 'test' AND table_name= 't1';
+table_name table_comment
+t1
+HANDLER t1 CLOSE;
+DROP TABLE t1;
+#
+# Test for bug #50908 "Assertion `handler_tables_hash.records == 0'
+# failed in enter_locked_tables_mode".
+#
+drop tables if exists t1, t2;
+drop function if exists f1;
+create table t1 (i int);
+insert into t1 values (1), (2);
+create table t2 (j int);
+insert into t2 values (1);
+create function f1() returns int return (select count(*) from t2);
+# Check that open HANDLER survives statement executed in
+# prelocked mode.
+handler t1 open;
+handler t1 read next;
+i
+1
+# The below statement were aborted due to an assertion failure.
+select f1() from t2;
+f1()
+1
+handler t1 read next;
+i
+2
+handler t1 close;
+# Check that the same happens under GLOBAL READ LOCK.
+flush tables with read lock;
+handler t1 open;
+handler t1 read next;
+i
+1
+select f1() from t2;
+f1()
+1
+handler t1 read next;
+i
+2
+unlock tables;
+handler t1 close;
+# Now, check that the same happens if LOCK TABLES is executed.
+handler t1 open;
+handler t1 read next;
+i
+1
+lock table t2 read;
+select * from t2;
+j
+1
+unlock tables;
+handler t1 read next;
+i
+2
+handler t1 close;
+# Finally, check scenario with GRL and LOCK TABLES.
+flush tables with read lock;
+handler t1 open;
+handler t1 read next;
+i
+1
+lock table t2 read;
+select * from t2;
+j
+1
+# This unlocks both tables and GRL.
+unlock tables;
+handler t1 read next;
+i
+2
+handler t1 close;
+# Clean-up.
+drop function f1;
+drop tables t1, t2;
+#
+# Test for bug #51136 "Crash in pthread_rwlock_rdlock on TEMPORARY +
+# HANDLER + LOCK + SP".
+# Also see additional coverage for this bug in flush.test.
+#
+drop tables if exists t1, t2;
+create table t1 (i int);
+create temporary table t2 (j int);
+handler t1 open;
+lock table t2 read;
+# This commit should not release any MDL locks.
+commit;
+unlock tables;
+# The below statement crashed before the bug fix as it
+# has attempted to release metadata lock which was
+# already released by commit.
+handler t1 close;
+drop tables t1, t2;
+#
+# Bug#51355 handler stmt cause assertion in
+# bool MDL_context::try_acquire_lock(MDL_request*)
+#
+DROP TABLE IF EXISTS t1;
+# Connection default
+CREATE TABLE t1(id INT, KEY id(id));
+HANDLER t1 OPEN;
+# Connection con51355
+# Sending:
+DROP TABLE t1;
+# Connection default
+# This I_S query will cause the handler table to be closed and
+# the metadata lock to be released. This will allow DROP TABLE
+# to proceed. Waiting for the table to be removed.
+# Connection con51355
+# Reaping: DROP TABLE t1
+# Connection default
+HANDLER t1 READ id NEXT;
+ERROR 42S02: Table 'test.t1' doesn't exist
+HANDLER t1 READ id NEXT;
+ERROR 42S02: Table 'test.t1' doesn't exist
+HANDLER t1 CLOSE;
+# Connection con51355
+# Connection default
+#
+# Bug#54401 assert in Diagnostics_area::set_eof_status , HANDLER
+#
+DROP TABLE IF EXISTS t1, t2;
+DROP FUNCTION IF EXISTS f1;
+CREATE FUNCTION f1() RETURNS INTEGER
+BEGIN
+SELECT 1 FROM t2 INTO @a;
+RETURN 1;
+END|
+SELECT f1();
+ERROR 42S02: Table 'test.t2' doesn't exist
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES (1);
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST WHERE f1() = 1;
+ERROR 42000: This version of MySQL doesn't yet support 'stored functions in HANDLER ... READ'
+HANDLER t1 CLOSE;
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
+# Bug#54920 Stored functions are allowed in HANDLER statements,
+# but broken.
+#
+DROP TABLE IF EXISTS t1;
+DROP FUNCTION IF EXISTS f1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1), (2);
+CREATE FUNCTION f1() RETURNS INT RETURN 1;
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST WHERE f1() = 1;
+ERROR 42000: This version of MySQL doesn't yet support 'stored functions in HANDLER ... READ'
+HANDLER t1 CLOSE;
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
# BUG#51877 - HANDLER interface causes invalid memory read
#
-CREATE TABLE t1(a INT, KEY (a));
+CREATE TABLE t1(a INT, KEY using btree (a));
HANDLER t1 OPEN;
HANDLER t1 READ a FIRST;
a
diff --git a/mysql-test/suite/handler/interface.result b/mysql-test/suite/handler/interface.result
index 04fcb1b9002..923277914bd 100644
--- a/mysql-test/suite/handler/interface.result
+++ b/mysql-test/suite/handler/interface.result
@@ -2,7 +2,7 @@ drop table if exists t1,t3,t4,t5;
drop database if exists test_test;
SET SESSION STORAGE_ENGINE = MyISAM;
drop table if exists t1,t3,t4,t5;
-create table t1 (a int, b char(10), key a (a), key b (a,b));
+create table t1 (a int, b char(10), key a using btree (a), key b using btree (a,b));
insert into t1 values
(17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"),
(14,"aaa"),(16,"ccc"),(16,"xxx"),
@@ -174,7 +174,8 @@ handler t1 read first;
c1
1
connection: flush
-flush tables;;
+flush tables;
+connection: waiter
connection: default
handler t2 open;
handler t2 read first;
@@ -186,6 +187,36 @@ c1
handler t1 close;
handler t2 close;
drop table t1,t2;
+drop table if exists t1, t0;
+create table t1 (c1 int);
+connection: default
+handler t1 open;
+handler t1 read first;
+c1
+connection: flush
+rename table t1 to t0;
+connection: waiter
+connection: default
+#
+# RENAME placed two pending locks and waits.
+# When HANDLER t0 OPEN does open_tables(), it calls
+# mysql_ha_flush(), which in turn closes the open HANDLER for t1.
+# RENAME TABLE gets unblocked. If it gets scheduled quickly
+# and manages to complete before open_tables()
+# of HANDLER t0 OPEN, open_tables() and therefore the whole
+# HANDLER t0 OPEN succeeds. Otherwise open_tables()
+# notices a pending or active exclusive metadata lock on t2
+# and the whole HANDLER t0 OPEN fails with ER_LOCK_DEADLOCK
+# error.
+#
+handler t0 open;
+handler t0 close;
+connection: flush
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler t1 close;
+ERROR 42S02: Unknown table 't1' in HANDLER
+drop table t0;
create table t1 (a int);
handler t1 open as t1_alias;
drop table t1;
@@ -204,23 +235,7 @@ a
drop table t1;
handler t1_alias read next;
ERROR 42S02: Unknown table 't1_alias' in HANDLER
-create table t1 (c1 int);
-connection: default
-handler t1 open;
-handler t1 read first;
-c1
-connection: flush
-rename table t1 to t2;;
-connection: default
-handler t2 open;
-handler t2 read first;
-c1
-handler t1 read next;
-ERROR 42S02: Table 'test.t1' doesn't exist
-handler t1 close;
-handler t2 close;
-drop table t2;
-create table t1 (a int, b char(1), key a (a), key b (a,b));
+create table t1 (a int, b char(1), key a (a), key b (a,b));
insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"),
(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j");
handler t1 open;
@@ -246,16 +261,36 @@ drop table t1;
handler t1 read a next;
ERROR 42S02: Unknown table 't1' in HANDLER
drop table if exists t1;
+# First test case which is supposed trigger the execution
+# path on which problem was discovered.
create table t1 (a int not null);
insert into t1 values (1);
handler t1 open;
+lock table t1 write;
alter table t1 engine=csv;
handler t1 read a next;
ERROR HY000: Table storage engine for 't1' doesn't have this option
handler t1 close;
+unlock tables;
+drop table t1;
+# Now test case which was reported originally but which no longer
+# triggers execution path which has caused the problem.
+create table t1 (a int not null);
+insert into t1 values (1);
+handler t1 open;
+alter table t1 engine=csv;
+# Since S metadata lock was already acquired at HANDLER OPEN time
+# and TL_READ lock requested by HANDLER READ is compatible with
+# ALTER's TL_WRITE_ALLOW_READ the below statement should succeed
+# without waiting. The old version of table should be used in it.
+handler t1 read next;
+a
+1
+handler t1 close;
drop table t1;
USE information_schema;
HANDLER COLUMNS OPEN;
ERROR HY000: Incorrect usage of HANDLER OPEN and information_schema
+USE test;
PREPARE h_r FROM 'HANDLER t1 READ `PRIMARY` LAST';
ERROR 42S02: Unknown table 't1' in HANDLER
diff --git a/mysql-test/suite/handler/interface.test b/mysql-test/suite/handler/interface.test
index e03f2ed777c..e4e854b2515 100644
--- a/mysql-test/suite/handler/interface.test
+++ b/mysql-test/suite/handler/interface.test
@@ -181,13 +181,16 @@ handler t1 read first;
connect (flush,localhost,root,,);
connection flush;
--echo connection: flush
---send flush tables;
-connection default;
---echo connection: default
+send flush tables;
+connect (waiter,localhost,root,,);
+connection waiter;
+--echo connection: waiter
let $wait_condition=
select count(*) = 1 from information_schema.processlist
- where state = "Flushing tables";
+ where state = "Waiting for table flush";
--source include/wait_condition.inc
+connection default;
+--echo connection: default
handler t2 open;
handler t2 read first;
handler t1 read next;
@@ -200,6 +203,63 @@ drop table t1,t2;
disconnect flush;
#
+# Bug#31409 RENAME TABLE causes server crash or deadlock when used with HANDLER statements
+#
+
+--disable_warnings
+drop table if exists t1, t0;
+--enable_warnings
+create table t1 (c1 int);
+--echo connection: default
+handler t1 open;
+handler t1 read first;
+connect (flush,localhost,root,,);
+connection flush;
+--echo connection: flush
+send rename table t1 to t0;
+connection waiter;
+--echo connection: waiter
+let $wait_condition=
+ select count(*) = 1 from information_schema.processlist
+ where state = "Waiting for table metadata lock" and
+ info = "rename table t1 to t0";
+--source include/wait_condition.inc
+connection default;
+--echo connection: default
+--echo #
+--echo # RENAME placed two pending locks and waits.
+--echo # When HANDLER t0 OPEN does open_tables(), it calls
+--echo # mysql_ha_flush(), which in turn closes the open HANDLER for t1.
+--echo # RENAME TABLE gets unblocked. If it gets scheduled quickly
+--echo # and manages to complete before open_tables()
+--echo # of HANDLER t0 OPEN, open_tables() and therefore the whole
+--echo # HANDLER t0 OPEN succeeds. Otherwise open_tables()
+--echo # notices a pending or active exclusive metadata lock on t2
+--echo # and the whole HANDLER t0 OPEN fails with ER_LOCK_DEADLOCK
+--echo # error.
+--echo #
+--error 0, ER_LOCK_DEADLOCK
+handler t0 open;
+--error 0, ER_UNKNOWN_TABLE
+handler t0 close;
+--echo connection: flush
+connection flush;
+reap;
+--error ER_UNKNOWN_TABLE
+handler t1 read next;
+--error ER_UNKNOWN_TABLE
+handler t1 close;
+connection default;
+drop table t0;
+connection flush;
+disconnect flush;
+--source include/wait_until_disconnected.inc
+connection waiter;
+disconnect waiter;
+--source include/wait_until_disconnected.inc
+connection default;
+
+#
# Bug#31397 Inconsistent drop table behavior of handler tables.
#
@@ -221,40 +281,9 @@ drop table t1;
--error ER_UNKNOWN_TABLE
handler t1_alias read next;
-#
-# Bug#31409 RENAME TABLE causes server crash or deadlock when used with
-# HANDLER statements
-#
-
-create table t1 (c1 int);
---echo connection: default
-handler t1 open;
-handler t1 read first;
-connect (flush,localhost,root,,);
-connection flush;
---echo connection: flush
---send rename table t1 to t2;
-connection default;
---echo connection: default
-let $wait_condition=
- select count(*) = 1 from information_schema.processlist
- where state = "Waiting for table" and info = "rename table t1 to t2";
---source include/wait_condition.inc
-handler t2 open;
-handler t2 read first;
---error ER_NO_SUCH_TABLE
-handler t1 read next;
-handler t1 close;
-handler t2 close;
-connection flush;
-reap;
-connection default;
-drop table t2;
-disconnect flush;
-
# Flush tables causes handlers reopen
-eval create table t1 (a int, b char(1), key a $key_type (a), key b $key_type (a,b));
+create table t1 (a int, b char(1), key a (a), key b (a,b));
insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"),
(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j");
handler t1 open;
@@ -275,39 +304,76 @@ handler t1 read a next;
# Bug#41112: crash in mysql_ha_close_table/get_lock_data with alter table
#
+connect(con1,localhost,root,,);
+connect(con2,localhost,root,,);
+
+connection default;
--disable_warnings
drop table if exists t1;
--enable_warnings
+--echo # First test case which is supposed trigger the execution
+--echo # path on which problem was discovered.
create table t1 (a int not null);
insert into t1 values (1);
handler t1 open;
-connect(con1,localhost,root,,);
+connection con1;
+lock table t1 write;
send alter table t1 engine=csv;
-connection default;
+connection con2;
let $wait_condition=
select count(*) = 1 from information_schema.processlist
- where state = "rename result table" and info = "alter table t1 engine=csv";
+ where state = "Waiting for table metadata lock" and
+ info = "alter table t1 engine=csv";
--source include/wait_condition.inc
+connection default;
--error ER_ILLEGAL_HA
handler t1 read a next;
handler t1 close;
connection con1;
--reap
+unlock tables;
+drop table t1;
+--echo # Now test case which was reported originally but which no longer
+--echo # triggers execution path which has caused the problem.
+connection default;
+create table t1 (a int not null);
+insert into t1 values (1);
+handler t1 open;
+connection con1;
+send alter table t1 engine=csv;
+connection con2;
+let $wait_condition=
+ select count(*) = 1 from information_schema.processlist
+ where state = "Waiting for table metadata lock" and
+ info = "alter table t1 engine=csv";
+--source include/wait_condition.inc
+connection default;
+--echo # Since S metadata lock was already acquired at HANDLER OPEN time
+--echo # and TL_READ lock requested by HANDLER READ is compatible with
+--echo # ALTER's TL_WRITE_ALLOW_READ the below statement should succeed
+--echo # without waiting. The old version of table should be used in it.
+handler t1 read next;
+handler t1 close;
+connection con1;
+--reap # Since last in this connection was a send
drop table t1;
disconnect con1;
--source include/wait_until_disconnected.inc
+connection con2;
+disconnect con2;
+--source include/wait_until_disconnected.inc
connection default;
#
# Bug#44151 using handler commands on information_schema tables crashes server
#
-
USE information_schema;
--error ER_WRONG_USAGE
HANDLER COLUMNS OPEN;
+USE test;
#
-# LP#697622 Assertion `! is_set()' failed when preparing a HANDLER statement
+# lp:697622 Assertion `! is_set()' failed when preparing a HANDLER statement
#
--error ER_UNKNOWN_TABLE
PREPARE h_r FROM 'HANDLER t1 READ `PRIMARY` LAST';
diff --git a/mysql-test/suite/handler/myisam.result b/mysql-test/suite/handler/myisam.result
index 321811d7339..96e67038db5 100644
--- a/mysql-test/suite/handler/myisam.result
+++ b/mysql-test/suite/handler/myisam.result
@@ -1,6 +1,6 @@
SET SESSION STORAGE_ENGINE = MyISAM;
drop table if exists t1,t3,t4,t5;
-create table t1 (a int, b char(10), key a (a), key b (a,b));
+create table t1 (a int, b char(10), key a using btree (a), key b using btree (a,b));
insert into t1 values
(17,"ddd"),(18,"eee"),(19,"fff"),(19,"yyy"),
(14,"aaa"),(16,"ccc"),(16,"xxx"),
@@ -362,7 +362,8 @@ prepare stmt from 'handler t1 read a=(?)';
flush tables;
set @a=17;
execute stmt using @a;
-ERROR HY000: Prepared statement needs to be re-prepared
+a b c
+17 ddd NULL
deallocate prepare stmt;
handler t1 close;
handler t1 open as t2;
@@ -372,7 +373,7 @@ insert into t1 values (17);
handler t2 read first;
ERROR 42S02: Unknown table 't2' in HANDLER
handler t1 open as t2;
-alter table t1 engine=CSV;
+alter table t1 engine=csv;
handler t2 read first;
ERROR 42S02: Unknown table 't2' in HANDLER
drop table t1;
@@ -395,7 +396,7 @@ handler t1 read first;
a
6
drop table t1;
-create table t1(a int, index (a));
+create table t1(a int, index using btree (a));
insert into t1 values (1), (2), (3);
handler t1 open;
handler t1 read a=(W);
@@ -421,7 +422,7 @@ Ok
handler t close;
use test;
drop table t1;
-create table t1 ( a int, b int, INDEX a (a) );
+create table t1 ( a int, b int, INDEX a using btree (a) );
insert into t1 values (1,2), (2,1);
handler t1 open;
handler t1 read a=(1) where b=2;
@@ -549,7 +550,7 @@ Table Op Msg_type Msg_text
test.t1 optimize status OK
proceed with the normal connection
drop table t1;
-CREATE TABLE t1 ( no1 smallint(5) NOT NULL default '0', no2 int(10) NOT NULL default '0', PRIMARY KEY (no1,no2));
+CREATE TABLE t1 ( no1 smallint(5) NOT NULL default '0', no2 int(10) NOT NULL default '0', PRIMARY KEY using btree (no1,no2));
INSERT INTO t1 VALUES (1,274),(1,275),(2,6),(2,8),(4,1),(4,2);
HANDLER t1 OPEN;
HANDLER t1 READ `primary` = (1, 1000);
@@ -582,7 +583,7 @@ ERROR 42S02: Table 'test.t1' doesn't exist
drop table if exists t1;
Warnings:
Note 1051 Unknown table 't1'
-create table t1 (a int not null) ENGINE=CSV;
+create table t1 (a int not null) ENGINE=csv;
--> client 2
handler t1 open;
ERROR HY000: Table storage engine for 't1' doesn't have this option
@@ -600,7 +601,7 @@ handler t1_alias READ a next where inexistent > 0;
ERROR 42S22: Unknown column 'inexistent' in 'field list'
handler t1_alias close;
drop table t1;
-create temporary table t1 (a int, b char(1), key a (a), key b (a,b));
+create temporary table t1 (a int, b char(1), key a using btree (a), key b using btree (a,b));
insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"),
(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"),(9,'k');
select a,b from t1;
@@ -671,7 +672,7 @@ a b
handler a2 close;
drop table t1;
create table t1 (a int);
-create temporary table t2 (a int, key (a));
+create temporary table t2 (a int, key using btree (a));
handler t1 open as a1;
handler t2 open as a2;
handler a2 read a first;
@@ -681,7 +682,7 @@ handler a2 read a next;
ERROR 42S02: Unknown table 'a2' in HANDLER
handler a1 close;
ERROR 42S02: Unknown table 'a1' in HANDLER
-create table t1 (a int, key (a));
+create table t1 (a int, key using btree (a));
create table t2 like t1;
handler t1 open as a1;
handler t2 open as a2;
@@ -694,7 +695,7 @@ handler a1 close;
ERROR 42S02: Unknown table 'a1' in HANDLER
handler a2 close;
drop table t1, t2;
-create table t1 (a int, key (a));
+create table t1 (a int, key using btree (a));
handler t1 open as a1;
handler a1 read a first;
a
@@ -702,7 +703,7 @@ rename table t1 to t2;
handler a1 read a first;
ERROR 42S02: Unknown table 'a1' in HANDLER
drop table t2;
-create table t1 (a int, key (a));
+create table t1 (a int, key using btree (a));
create table t2 like t1;
handler t1 open as a1;
handler t2 open as a2;
@@ -718,9 +719,972 @@ ERROR 42S02: Unknown table 'a1' in HANDLER
handler a2 close;
drop table t1, t2;
#
+# Add test coverage for HANDLER and LOCK TABLES, HANDLER and DDL.
+#
+drop table if exists t1, t2, t3;
+create table t1 (a int, key a (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t2 (a int, key a (a)) select * from t1;
+create temporary table t3 (a int, key a (a)) select * from t2;
+handler t1 open;
+handler t2 open;
+handler t3 open;
+#
+# No HANDLER sql is allowed under LOCK TABLES.
+# But it does not implicitly closes all handlers.
+#
+lock table t1 read;
+handler t1 open;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+handler t1 read next;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+handler t2 close;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+handler t3 open;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+# After UNLOCK TABLES handlers should be around and
+# we should be able to continue reading through them.
+unlock tables;
+handler t1 read next;
+a
+1
+handler t1 close;
+handler t2 read next;
+a
+1
+handler t2 close;
+handler t3 read next;
+a
+1
+handler t3 close;
+drop temporary table t3;
+#
+# Other operations that implicitly close handler:
+#
+# TRUNCATE
+#
+handler t1 open;
+truncate table t1;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler t1 open;
+#
+# CREATE TRIGGER
+#
+create trigger t1_ai after insert on t1 for each row set @a=1;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# DROP TRIGGER
+#
+handler t1 open;
+drop trigger t1_ai;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# ALTER TABLE
+#
+handler t1 open;
+alter table t1 add column b int;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# ANALYZE TABLE
+#
+handler t1 open;
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status Table is already up to date
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# OPTIMIZE TABLE
+#
+handler t1 open;
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# REPAIR TABLE
+#
+handler t1 open;
+repair table t1;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# DROP TABLE, naturally.
+#
+handler t1 open;
+drop table t1;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+create table t1 (a int, b int, key a using btree (a)) select a from t2;
+#
+# RENAME TABLE, naturally
+#
+handler t1 open;
+rename table t1 to t3;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# CREATE TABLE (even with IF NOT EXISTS clause,
+# and the table exists).
+#
+handler t2 open;
+create table if not exists t2 (a int);
+Warnings:
+Note 1050 Table 't2' already exists
+handler t2 read next;
+ERROR 42S02: Unknown table 't2' in HANDLER
+rename table t3 to t1;
+drop table t2;
+#
+# FLUSH TABLE doesn't close the table but loses the position
+#
+handler t1 open;
+handler t1 read a prev;
+b a
+NULL 5
+flush table t1;
+handler t1 read a prev;
+b a
+NULL 5
+handler t1 close;
+#
+# FLUSH TABLES WITH READ LOCK behaves like FLUSH TABLE.
+#
+handler t1 open;
+handler t1 read a prev;
+b a
+NULL 5
+flush tables with read lock;
+handler t1 read a prev;
+b a
+NULL 5
+handler t1 close;
+unlock tables;
+#
+# Let us also check that these operations behave in similar
+# way under LOCK TABLES.
+#
+# TRUNCATE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+truncate table t1;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler t1 open;
+#
+# CREATE TRIGGER under LOCK TABLES.
+#
+lock tables t1 write;
+create trigger t1_ai after insert on t1 for each row set @a=1;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# DROP TRIGGER under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+drop trigger t1_ai;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# ALTER TABLE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+alter table t1 drop column b;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# ANALYZE TABLE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status Table is already up to date
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# OPTIMIZE TABLE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# REPAIR TABLE under LOCK TABLES.
+#
+handler t1 open;
+lock tables t1 write;
+repair table t1;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+#
+# DROP TABLE under LOCK TABLES, naturally.
+#
+handler t1 open;
+lock tables t1 write;
+drop table t1;
+unlock tables;
+handler t1 read next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+create table t1 (a int, b int, key a using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+#
+# FLUSH TABLE doesn't close the table but loses the position
+#
+handler t1 open;
+handler t1 read a prev;
+a b
+5 NULL
+lock tables t1 write;
+flush table t1;
+unlock tables;
+handler t1 read a prev;
+a b
+5 NULL
+handler t1 close;
+#
+# Explore the effect of HANDLER locks on concurrent DDL
+#
+handler t1 open;
+# Establishing auxiliary connections con1, con2, con3
+# --> connection con1;
+# Sending:
+drop table t1 ;
+# We can't use connection 'default' as wait_condition will
+# autoclose handlers.
+# --> connection con2
+# Waitng for 'drop table t1' to get blocked...
+# --> connection default
+handler t1 read a prev;
+a b
+5 NULL
+handler t1 read a prev;
+a b
+4 NULL
+handler t1 close;
+# --> connection con1
+# Reaping 'drop table t1'...
+# --> connection default
+#
+# Explore the effect of HANDLER locks in parallel with SELECT
+#
+create table t1 (a int, key a using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+begin;
+select * from t1;
+a
+1
+2
+3
+4
+5
+handler t1 open;
+handler t1 read a prev;
+a
+5
+handler t1 read a prev;
+a
+4
+handler t1 close;
+# --> connection con1;
+# Sending:
+drop table t1 ;
+# --> connection con2
+# Waiting for 'drop table t1' to get blocked...
+# --> connection default
+# We can still use the table, it's part of the transaction
+select * from t1;
+a
+1
+2
+3
+4
+5
+# Such are the circumstances that t1 is a part of transaction,
+# thus we can reopen it in the handler
+handler t1 open;
+# We can commit the transaction, it doesn't close the handler
+# and doesn't let DROP to proceed.
+commit;
+handler t1 read a prev;
+a
+5
+handler t1 read a prev;
+a
+4
+handler t1 read a prev;
+a
+3
+handler t1 close;
+# --> connection con1
+# Now drop can proceed
+# Reaping 'drop table t1'...
+# --> connection default
+#
+# Demonstrate that HANDLER locks and transaction locks
+# reside in the same context, and we don't back-off
+# when have transaction or handler locks.
+#
+create table t1 (a int, key a (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t0 (a int, key a using btree (a));
+insert into t0 (a) values (1), (2), (3), (4), (5);
+begin;
+select * from t1;
+a
+1
+2
+3
+4
+5
+# --> connection con2
+# Sending:
+rename table t0 to t3, t1 to t0, t3 to t1;
+# --> connection con1
+# Waiting for 'rename table ...' to get blocked...
+# --> connection default
+handler t0 open;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+select * from t0;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+handler t1 open;
+commit;
+handler t1 close;
+# --> connection con2
+# Reaping 'rename table ...'...
+# --> connection default
+handler t1 open;
+handler t1 read a prev;
+a
+5
+handler t1 close;
+drop table t0;
+#
+# Originally there was a deadlock error in this test.
+# With implementation of deadlock detector
+# we no longer deadlock, but block and wait on a lock.
+# The HANDLER is auto-closed as soon as the connection
+# sees a pending conflicting lock against it.
+#
+create table t2 (a int, key a (a));
+handler t1 open;
+# --> connection con1
+lock tables t2 read;
+# --> connection con2
+# Sending 'drop table t2'...
+drop table t2;
+# --> connection con1
+# Waiting for 'drop table t2' to get blocked...
+# --> connection default
+# Sending 'select * from t2'
+select * from t2;
+# --> connection con1
+# Waiting for 'select * from t2' to get blocked...
+unlock tables;
+# --> connection con2
+# Reaping 'drop table t2'...
+# --> connection default
+# Reaping 'select * from t2'
+ERROR 42S02: Table 'test.t2' doesn't exist
+handler t1 close;
+#
+# ROLLBACK TO SAVEPOINT releases transactional locks,
+# but has no effect on open HANDLERs
+#
+create table t2 like t1;
+create table t3 like t1;
+begin;
+# Have something before the savepoint
+select * from t3;
+a
+savepoint sv;
+handler t1 open;
+handler t1 read a first;
+a
+1
+handler t1 read a next;
+a
+2
+select * from t2;
+a
+# --> connection con1
+# Sending:
+drop table t1;
+# --> connection con2
+# Sending:
+drop table t2;
+# --> connection default
+# Let DROP TABLE statements sync in. We must use
+# a separate connection for that, because otherwise SELECT
+# will auto-close the HANDLERs, becaues there are pending
+# exclusive locks against them.
+# --> connection con3
+# Waiting for 'drop table t1' to get blocked...
+# Waiting for 'drop table t2' to get blocked...
+# Demonstrate that t2 lock was released and t2 was dropped
+# after ROLLBACK TO SAVEPOINT
+# --> connection default
+rollback to savepoint sv;
+# --> connection con2
+# Reaping 'drop table t2'...
+# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
+# lock.
+# --> connection default
+handler t1 read a next;
+a
+3
+handler t1 read a next;
+a
+4
+# Demonstrate that the drop will go through as soon as we close the
+# HANDLER
+handler t1 close;
+# connection con1
+# Reaping 'drop table t1'...
+# --> connection default
+commit;
+drop table t3;
+#
+# A few special cases when using SAVEPOINT/ROLLBACK TO
+# SAVEPOINT and HANDLER.
+#
+# Show that rollback to the savepoint taken in the beginning
+# of the transaction doesn't release mdl lock on
+# the HANDLER that was opened later.
+#
+create table t1 (a int, key using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t2 like t1;
+begin;
+savepoint sv;
+handler t1 open;
+handler t1 read a first;
+a
+1
+handler t1 read a next;
+a
+2
+select * from t2;
+a
+# --> connection con1
+# Sending:
+drop table t1;
+# --> connection con2
+# Sending:
+drop table t2;
+# --> connection default
+# Let DROP TABLE statements sync in. We must use
+# a separate connection for that, because otherwise SELECT
+# will auto-close the HANDLERs, becaues there are pending
+# exclusive locks against them.
+# --> connection con3
+# Waiting for 'drop table t1' to get blocked...
+# Waiting for 'drop table t2' to get blocked...
+# Demonstrate that t2 lock was released and t2 was dropped
+# after ROLLBACK TO SAVEPOINT
+# --> connection default
+rollback to savepoint sv;
+# --> connection con2
+# Reaping 'drop table t2'...
+# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
+# lock.
+# --> connection default
+handler t1 read a next;
+a
+3
+handler t1 read a next;
+a
+4
+# Demonstrate that the drop will go through as soon as we close the
+# HANDLER
+handler t1 close;
+# connection con1
+# Reaping 'drop table t1'...
+# --> connection default
+commit;
+#
+# Show that rollback to the savepoint taken in the beginning
+# of the transaction works properly (no valgrind warnins, etc),
+# even though it's done after the HANDLER mdl lock that was there
+# at the beginning is released and added again.
+#
+create table t1 (a int, key using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create table t2 like t1;
+create table t3 like t1;
+insert into t3 (a) select a from t1;
+begin;
+handler t1 open;
+savepoint sv;
+handler t1 read a first;
+a
+1
+select * from t2;
+a
+handler t1 close;
+handler t3 open;
+handler t3 read a first;
+a
+1
+rollback to savepoint sv;
+# --> connection con1
+drop table t1, t2;
+# Sending:
+drop table t3;
+# Let DROP TABLE statement sync in.
+# --> connection con2
+# Waiting for 'drop table t3' to get blocked...
+# Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
+# lock.
+# --> connection default
+handler t3 read a next;
+a
+2
+# Demonstrate that the drop will go through as soon as we close the
+# HANDLER
+handler t3 close;
+# connection con1
+# Reaping 'drop table t3'...
+# --> connection default
+commit;
+#
+# If we have to wait on an exclusive locks while having
+# an open HANDLER, ER_LOCK_DEADLOCK is reported.
+#
+create table t1 (a int, key a(a));
+create table t2 like t1;
+handler t1 open;
+# --> connection con1
+lock table t1 write, t2 write;
+# --> connection default
+drop table t2;
+# --> connection con2
+# Waiting for 'drop table t2' to get blocked...
+# --> connection con1
+drop table t1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+unlock tables;
+# --> connection default
+# Demonstrate that there is no deadlock with FLUSH TABLE,
+# even though it is waiting for the other table to go away
+create table t2 like t1;
+# Sending:
+flush table t2;
+# --> connection con2
+drop table t1;
+# --> connection con1
+unlock tables;
+# --> connection default
+# Reaping 'flush table t2'...
+drop table t2;
+#
+# Bug #46224 HANDLER statements within a transaction might
+# lead to deadlocks
+#
+create table t1 (a int, key using btree (a));
+insert into t1 values (1), (2);
+# --> connection default
+begin;
+select * from t1;
+a
+1
+2
+handler t1 open;
+# --> connection con1
+# Sending:
+lock tables t1 write;
+# --> connection con2
+# Check that 'lock tables t1 write' waits until transaction which
+# has read from the table commits.
+# --> connection default
+# The below 'handler t1 read ...' should not be blocked as
+# 'lock tables t1 write' has not succeeded yet.
+handler t1 read a next;
+a
+1
+# Unblock 'lock tables t1 write'.
+commit;
+# --> connection con1
+# Reap 'lock tables t1 write'.
+# --> connection default
+# Sending:
+handler t1 read a next;
+# --> connection con1
+# Waiting for 'handler t1 read a next' to get blocked...
+# The below 'drop table t1' should be able to proceed without
+# waiting as it will force HANDLER to be closed.
+drop table t1;
+unlock tables;
+# --> connection default
+# Reaping 'handler t1 read a next'...
+ERROR 42S02: Table 'test.t1' doesn't exist
+handler t1 close;
+# --> connection con1
+# --> connection con2
+# --> connection con3
+#
+# A temporary table test.
+# Check that we don't loose positions of HANDLER opened
+# against a temporary table.
+#
+create table t1 (a int, b int, key using btree (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+create temporary table t2 (a int, b int, key using btree (a));
+insert into t2 (a) select a from t1;
+handler t1 open;
+handler t1 read a next;
+a b
+1 NULL
+handler t2 open;
+handler t2 read a next;
+a b
+1 NULL
+flush table t1;
+handler t2 read a next;
+a b
+2 NULL
+# Sic: the position is lost
+handler t1 read a next;
+a b
+1 NULL
+select * from t1;
+a b
+1 NULL
+2 NULL
+3 NULL
+4 NULL
+5 NULL
+# Sic: the position is not lost
+handler t2 read a next;
+a b
+3 NULL
+select * from t2;
+ERROR HY000: Can't reopen table: 't2'
+handler t2 read a next;
+a b
+4 NULL
+drop table t1;
+drop temporary table t2;
+#
+# A test for lock_table_names()/unlock_table_names() function.
+# It should work properly in presence of open HANDLER.
+#
+create table t1 (a int, b int, key a (a));
+create table t2 like t1;
+create table t3 like t1;
+create table t4 like t1;
+handler t1 open;
+handler t2 open;
+rename table t4 to t5, t3 to t4, t5 to t3;
+handler t1 read first;
+a b
+handler t2 read first;
+a b
+drop table t1, t2, t3, t4;
+#
+# A test for FLUSH TABLES WITH READ LOCK and HANDLER statements.
+#
+set autocommit=0;
+create table t1 (a int, b int, key a (a));
+insert into t1 (a, b) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 5);
+create table t2 like t1;
+insert into t2 (a, b) select a, b from t1;
+create table t3 like t1;
+insert into t3 (a, b) select a, b from t1;
+commit;
+flush tables with read lock;
+handler t1 open;
+lock table t1 read;
+handler t1 read next;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+# This implicitly leaves LOCK TABLES but doesn't drop the GLR
+lock table not_exists_write read;
+ERROR 42S02: Table 'test.not_exists_write' doesn't exist
+# We still have the read lock.
+drop table t1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+handler t1 open;
+select a from t2;
+a
+1
+2
+3
+4
+5
+handler t1 read next;
+a b
+1 1
+flush tables with read lock;
+handler t2 open;
+flush tables with read lock;
+handler t1 read next;
+a b
+1 1
+select a from t3;
+a
+1
+2
+3
+4
+5
+handler t2 read next;
+a b
+1 1
+handler t1 close;
+rollback;
+handler t2 close;
+drop table t1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+commit;
+flush tables;
+drop table t1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+unlock tables;
+drop table t1;
+set autocommit=default;
+drop table t2, t3;
+#
+# HANDLER statement and operation-type aware metadata locks.
+# Check that when we clone a ticket for HANDLER we downrade
+# the lock.
+#
+# Establish an auxiliary connection con1.
+# -> connection default
+create table t1 (a int, b int, key using btree (a));
+insert into t1 (a, b) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 5);
+begin;
+insert into t1 (a, b) values (6, 6);
+handler t1 open;
+handler t1 read a last;
+a b
+6 6
+insert into t1 (a, b) values (7, 7);
+handler t1 read a last;
+a b
+7 7
+commit;
+# -> connection con1
+# Demonstrate that the HANDLER doesn't hold MDL_SHARED_WRITE.
+lock table t1 write;
+unlock tables;
+# -> connection default
+handler t1 read a prev;
+a b
+6 6
+handler t1 close;
+# Cleanup.
+drop table t1;
+# -> connection con1
+# -> connection default
+#
+# A test for Bug#50555 "handler commands crash server in
+# my_hash_first()".
+#
+handler no_such_table read no_such_index first;
+ERROR 42S02: Unknown table 'no_such_table' in HANDLER
+handler no_such_table close;
+ERROR 42S02: Unknown table 'no_such_table' in HANDLER
+#
+# Bug#50907 Assertion `hash_tables->table->next == __null' on
+# HANDLER OPEN
+#
+DROP TABLE IF EXISTS t1, t2;
+CREATE TEMPORARY TABLE t1 (i INT);
+CREATE TEMPORARY TABLE t2 (i INT);
+HANDLER t2 OPEN;
+HANDLER t2 READ FIRST;
+i
+HANDLER t2 CLOSE;
+DROP TABLE t1, t2;
+#
+# Bug#50912 Assertion `ticket->m_type >= mdl_request->type'
+# failed on HANDLER + I_S
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (id INT);
+HANDLER t1 OPEN;
+SELECT table_name, table_comment FROM information_schema.tables
+WHERE table_schema= 'test' AND table_name= 't1';
+table_name table_comment
+t1
+HANDLER t1 CLOSE;
+DROP TABLE t1;
+#
+# Test for bug #50908 "Assertion `handler_tables_hash.records == 0'
+# failed in enter_locked_tables_mode".
+#
+drop tables if exists t1, t2;
+drop function if exists f1;
+create table t1 (i int);
+insert into t1 values (1), (2);
+create table t2 (j int);
+insert into t2 values (1);
+create function f1() returns int return (select count(*) from t2);
+# Check that open HANDLER survives statement executed in
+# prelocked mode.
+handler t1 open;
+handler t1 read next;
+i
+1
+# The below statement were aborted due to an assertion failure.
+select f1() from t2;
+f1()
+1
+handler t1 read next;
+i
+2
+handler t1 close;
+# Check that the same happens under GLOBAL READ LOCK.
+flush tables with read lock;
+handler t1 open;
+handler t1 read next;
+i
+1
+select f1() from t2;
+f1()
+1
+handler t1 read next;
+i
+2
+unlock tables;
+handler t1 close;
+# Now, check that the same happens if LOCK TABLES is executed.
+handler t1 open;
+handler t1 read next;
+i
+1
+lock table t2 read;
+select * from t2;
+j
+1
+unlock tables;
+handler t1 read next;
+i
+2
+handler t1 close;
+# Finally, check scenario with GRL and LOCK TABLES.
+flush tables with read lock;
+handler t1 open;
+handler t1 read next;
+i
+1
+lock table t2 read;
+select * from t2;
+j
+1
+# This unlocks both tables and GRL.
+unlock tables;
+handler t1 read next;
+i
+2
+handler t1 close;
+# Clean-up.
+drop function f1;
+drop tables t1, t2;
+#
+# Test for bug #51136 "Crash in pthread_rwlock_rdlock on TEMPORARY +
+# HANDLER + LOCK + SP".
+# Also see additional coverage for this bug in flush.test.
+#
+drop tables if exists t1, t2;
+create table t1 (i int);
+create temporary table t2 (j int);
+handler t1 open;
+lock table t2 read;
+# This commit should not release any MDL locks.
+commit;
+unlock tables;
+# The below statement crashed before the bug fix as it
+# has attempted to release metadata lock which was
+# already released by commit.
+handler t1 close;
+drop tables t1, t2;
+#
+# Bug#51355 handler stmt cause assertion in
+# bool MDL_context::try_acquire_lock(MDL_request*)
+#
+DROP TABLE IF EXISTS t1;
+# Connection default
+CREATE TABLE t1(id INT, KEY id(id));
+HANDLER t1 OPEN;
+# Connection con51355
+# Sending:
+DROP TABLE t1;
+# Connection default
+# This I_S query will cause the handler table to be closed and
+# the metadata lock to be released. This will allow DROP TABLE
+# to proceed. Waiting for the table to be removed.
+# Connection con51355
+# Reaping: DROP TABLE t1
+# Connection default
+HANDLER t1 READ id NEXT;
+ERROR 42S02: Table 'test.t1' doesn't exist
+HANDLER t1 READ id NEXT;
+ERROR 42S02: Table 'test.t1' doesn't exist
+HANDLER t1 CLOSE;
+# Connection con51355
+# Connection default
+#
+# Bug#54401 assert in Diagnostics_area::set_eof_status , HANDLER
+#
+DROP TABLE IF EXISTS t1, t2;
+DROP FUNCTION IF EXISTS f1;
+CREATE FUNCTION f1() RETURNS INTEGER
+BEGIN
+SELECT 1 FROM t2 INTO @a;
+RETURN 1;
+END|
+SELECT f1();
+ERROR 42S02: Table 'test.t2' doesn't exist
+CREATE TABLE t1(a INT);
+INSERT INTO t1 VALUES (1);
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST WHERE f1() = 1;
+ERROR 42000: This version of MySQL doesn't yet support 'stored functions in HANDLER ... READ'
+HANDLER t1 CLOSE;
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
+# Bug#54920 Stored functions are allowed in HANDLER statements,
+# but broken.
+#
+DROP TABLE IF EXISTS t1;
+DROP FUNCTION IF EXISTS f1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1), (2);
+CREATE FUNCTION f1() RETURNS INT RETURN 1;
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST WHERE f1() = 1;
+ERROR 42000: This version of MySQL doesn't yet support 'stored functions in HANDLER ... READ'
+HANDLER t1 CLOSE;
+DROP FUNCTION f1;
+DROP TABLE t1;
+#
# BUG#51877 - HANDLER interface causes invalid memory read
#
-CREATE TABLE t1(a INT, KEY (a));
+CREATE TABLE t1(a INT, KEY using btree (a));
HANDLER t1 OPEN;
HANDLER t1 READ a FIRST;
a