summaryrefslogtreecommitdiffstats
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.result1708
-rw-r--r--mysql-test/suite/handler/aria.test102
-rw-r--r--mysql-test/suite/handler/disconnect_4480.result7
-rw-r--r--mysql-test/suite/handler/disconnect_4480.test10
-rw-r--r--mysql-test/suite/handler/handler.inc1355
-rw-r--r--mysql-test/suite/handler/heap.result1706
-rw-r--r--mysql-test/suite/handler/heap.test105
-rw-r--r--mysql-test/suite/handler/init.inc31
-rw-r--r--mysql-test/suite/handler/innodb.result1790
-rw-r--r--mysql-test/suite/handler/innodb.test49
-rw-r--r--mysql-test/suite/handler/interface.result354
-rw-r--r--mysql-test/suite/handler/interface.test403
-rw-r--r--mysql-test/suite/handler/myisam.result1792
-rw-r--r--mysql-test/suite/handler/myisam.test191
-rw-r--r--mysql-test/suite/handler/ps.result9
-rw-r--r--mysql-test/suite/handler/ps.test13
-rw-r--r--mysql-test/suite/handler/savepoint.inc182
17 files changed, 9807 insertions, 0 deletions
diff --git a/mysql-test/suite/handler/aria.result b/mysql-test/suite/handler/aria.result
new file mode 100644
index 00000000..b0a4a173
--- /dev/null
+++ b/mysql-test/suite/handler/aria.result
@@ -0,0 +1,1708 @@
+SET SESSION DEFAULT_STORAGE_ENGINE = Aria;
+drop table if exists t1,t3,t4,t5;
+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"),
+(20,"ggg"),(21,"hhh"),(22,"iii"),(23,"xxx"),(24,"xxx"),(25,"xxx");
+handler t1 open as t2;
+handler t2 read b first;
+a b
+14 aaa
+handler t2 read b next;
+a b
+16 ccc
+handler t2 read b next;
+a b
+16 xxx
+handler t2 read b prev;
+a b
+16 ccc
+handler t2 read b last;
+a b
+25 xxx
+handler t2 read b prev;
+a b
+24 xxx
+handler t2 read b prev;
+a b
+23 xxx
+handler t2 read b first;
+a b
+14 aaa
+handler t2 read b prev;
+a b
+handler t2 read b last;
+a b
+25 xxx
+handler t2 read b prev;
+a b
+24 xxx
+handler t2 read b next;
+a b
+25 xxx
+handler t2 read b next;
+a b
+handler t2 read a=(15);
+a b
+handler t2 read a=(21);
+a b
+21 hhh
+handler t2 read a=(19,"fff");
+ERROR 42000: Too many key parts specified; max 1 parts allowed
+handler t2 read b=(19,"fff");
+a b
+19 fff
+handler t2 read b=(19,"yyy");
+a b
+19 yyy
+handler t2 read b=(19);
+a b
+19 fff
+handler t1 read a last;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler t2 read a=(11);
+a b
+handler t2 read a>=(11);
+a b
+14 aaa
+handler t2 read b=(18);
+a b
+18 eee
+handler t2 read b>=(18);
+a b
+18 eee
+handler t2 read b>(18);
+a b
+19 fff
+handler t2 read b<=(18);
+a b
+18 eee
+handler t2 read b<(18);
+a b
+17 ddd
+handler t2 read a=(15);
+a b
+handler t2 read a>=(15) limit 2;
+a b
+16 ccc
+16 xxx
+handler t2 read a>(15) limit 2;
+a b
+16 ccc
+16 xxx
+handler t2 read a<=(15);
+a b
+14 aaa
+handler t2 read a<(15);
+a b
+14 aaa
+handler t2 read a=(54);
+a b
+handler t2 read a>=(54);
+a b
+handler t2 read a>(54);
+a b
+handler t2 read a<=(54);
+a b
+25 xxx
+handler t2 read a<(54);
+a b
+25 xxx
+handler t2 read a=(1);
+a b
+handler t2 read a>=(1);
+a b
+14 aaa
+handler t2 read a>(1);
+a b
+14 aaa
+handler t2 read a<=(1);
+a b
+handler t2 read a<(1);
+a b
+handler t2 read b first limit 5;
+a b
+14 aaa
+16 ccc
+16 xxx
+17 ddd
+18 eee
+handler t2 read b next limit 3;
+a b
+19 fff
+19 yyy
+20 ggg
+handler t2 read b prev limit 10;
+a b
+19 yyy
+19 fff
+18 eee
+17 ddd
+16 xxx
+16 ccc
+14 aaa
+handler t2 read b>=(16) limit 4;
+a b
+16 ccc
+16 xxx
+17 ddd
+18 eee
+handler t2 read b>=(16) limit 2,2;
+a b
+17 ddd
+18 eee
+select * from t1 where a>=16 order by a,b limit 2,2;
+a b
+17 ddd
+18 eee
+handler t2 read a last limit 3;
+a b
+25 xxx
+24 xxx
+23 xxx
+handler t2 read b=(16) limit 1,3;
+a b
+16 xxx
+handler t2 read b=(19);
+a b
+19 fff
+handler t2 read b=(19) where b="yyy";
+a b
+19 yyy
+handler t2 read first;
+a b
+17 ddd
+handler t2 read next;
+a b
+18 eee
+handler t2 read next;
+a b
+19 fff
+handler t2 close;
+handler t1 open;
+handler t1 read b next;
+a b
+14 aaa
+handler t1 read b next;
+a b
+16 ccc
+handler t1 close;
+handler t1 open;
+handler t1 read a prev;
+a b
+25 xxx
+handler t1 read a prev;
+a b
+24 xxx
+handler t1 close;
+handler t1 open as t2;
+handler t2 read first;
+a b
+17 ddd
+alter table t1 engine = Aria;
+handler t2 read first;
+ERROR 42S02: Unknown table 't2' in HANDLER
+handler t1 open;
+handler t1 read a=(20) limit 1,3;
+a b
+flush tables;
+handler t1 read a=(20) limit 1,3;
+a b
+handler t1 close;
+handler t1 open;
+handler t1 read a=(25);
+a b
+25 xxx
+handler t1 read a next;
+a b
+handler t1 read a next;
+a b
+handler t1 read a next;
+a b
+handler t1 read a prev;
+a b
+25 xxx
+handler t1 read a=(1000);
+a b
+handler t1 read a next;
+a b
+handler t1 read a prev;
+a b
+25 xxx
+handler t1 read a=(1000);
+a b
+handler t1 read a prev;
+a b
+25 xxx
+handler t1 read a=(14);
+a b
+14 aaa
+handler t1 read a prev;
+a b
+handler t1 read a prev;
+a b
+handler t1 read a next;
+a b
+14 aaa
+handler t1 read a=(1);
+a b
+handler t1 read a prev;
+a b
+handler t1 read a next;
+a b
+14 aaa
+handler t1 read a=(1);
+a b
+handler t1 read a next;
+a b
+14 aaa
+handler t1 close;
+handler t1 open;
+prepare stmt from 'handler t1 read a=(?) limit ?,?';
+set @a=20,@b=1,@c=100;
+execute stmt using @a,@b,@c;
+a b
+set @a=20,@b=2,@c=1;
+execute stmt using @a,@b,@c;
+a b
+set @a=20,@b=0,@c=2;
+execute stmt using @a,@b,@c;
+a b
+20 ggg
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read a next limit ?';
+handler t1 read a>=(21);
+a b
+21 hhh
+set @a=3;
+execute stmt using @a;
+a b
+22 iii
+23 xxx
+24 xxx
+execute stmt using @a;
+a b
+25 xxx
+execute stmt using @a;
+a b
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read b prev limit ?';
+execute stmt using @a;
+a b
+25 xxx
+24 xxx
+23 xxx
+execute stmt using @a;
+a b
+22 iii
+21 hhh
+20 ggg
+execute stmt using @a;
+a b
+19 yyy
+19 fff
+18 eee
+execute stmt using @a;
+a b
+17 ddd
+16 xxx
+16 ccc
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read b=(?,?)';
+set @a=14, @b='aaa';
+execute stmt using @a,@b;
+a b
+14 aaa
+set @a=14, @b='not found';
+execute stmt using @a,@b;
+a b
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read b=(1+?) limit 10';
+set @a=15;
+execute stmt using @a;
+a b
+16 ccc
+16 xxx
+execute stmt using @a;
+a b
+16 ccc
+16 xxx
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read b>=(?) where a < ? limit 5';
+set @a=17, @b=24;
+execute stmt using @a,@b;
+a b
+17 ddd
+18 eee
+19 fff
+19 yyy
+20 ggg
+execute stmt using @a,@b;
+a b
+17 ddd
+18 eee
+19 fff
+19 yyy
+20 ggg
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read a=(?)';
+set @a=17;
+execute stmt using @a;
+a b
+17 ddd
+alter table t1 add c int;
+execute stmt using @a;
+ERROR 42S02: Unknown table 't1' in HANDLER
+deallocate prepare stmt;
+handler t1 close;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler t1 open;
+prepare stmt from 'handler t1 read a=(?)';
+flush tables;
+set @a=17;
+execute stmt using @a;
+a b c
+17 ddd NULL
+deallocate prepare stmt;
+handler t1 close;
+handler t1 open as t2;
+drop table t1;
+create table t1 (a int not null);
+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;
+handler t2 read first;
+ERROR 42S02: Unknown table 't2' in HANDLER
+drop table t1;
+create table t1 (a int);
+insert into t1 values (1),(2),(3),(4),(5),(6);
+delete from t1 limit 2;
+handler t1 open;
+handler t1 read first;
+a
+3
+handler t1 read first limit 1,1;
+a
+4
+handler t1 read first limit 2,2;
+a
+5
+6
+delete from t1 limit 3;
+handler t1 read first;
+a
+6
+drop table t1;
+create table t1(a int, index using btree (a));
+insert into t1 values (1), (2), (3);
+handler t1 open;
+handler t1 read a=(W);
+ERROR 42S22: Unknown column 'W' in 'field list'
+handler t1 read a=(a);
+ERROR HY000: Incorrect arguments to HANDLER ... READ
+drop table t1;
+create table t1 (a char(5));
+insert into t1 values ("Ok");
+handler t1 open as t;
+handler t read first;
+a
+Ok
+use mysql;
+handler t read first;
+a
+Ok
+handler t close;
+handler test.t1 open as t;
+handler t read first;
+a
+Ok
+handler t close;
+use test;
+drop table t1;
+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;
+a b
+1 2
+handler t1 read a=(1) where b=3;
+a b
+handler t1 read a=(1) where b=1;
+a b
+handler t1 close;
+drop table t1;
+create table t1 (c1 char(20));
+insert into t1 values ("t1");
+handler t1 open as h1;
+handler h1 read first limit 9;
+c1
+t1
+create table t2 (c1 char(20));
+insert into t2 values ("t2");
+handler t2 open as h2;
+handler h2 read first limit 9;
+c1
+t2
+create table t3 (c1 char(20));
+insert into t3 values ("t3");
+handler t3 open as h3;
+handler h3 read first limit 9;
+c1
+t3
+create table t4 (c1 char(20));
+insert into t4 values ("t4");
+handler t4 open as h4;
+handler h4 read first limit 9;
+c1
+t4
+create table t5 (c1 char(20));
+insert into t5 values ("t5");
+handler t5 open as h5;
+handler h5 read first limit 9;
+c1
+t5
+alter table t1 engine=MyISAM;
+handler h1 read first limit 9;
+ERROR 42S02: Unknown table 'h1' in HANDLER
+handler h2 read first limit 9;
+c1
+t2
+handler h3 read first limit 9;
+c1
+t3
+handler h4 read first limit 9;
+c1
+t4
+handler h5 read first limit 9;
+c1
+t5
+alter table t5 engine=MyISAM;
+handler h1 read first limit 9;
+ERROR 42S02: Unknown table 'h1' in HANDLER
+handler h2 read first limit 9;
+c1
+t2
+handler h3 read first limit 9;
+c1
+t3
+handler h4 read first limit 9;
+c1
+t4
+handler h5 read first limit 9;
+ERROR 42S02: Unknown table 'h5' in HANDLER
+alter table t3 engine=MyISAM;
+handler h1 read first limit 9;
+ERROR 42S02: Unknown table 'h1' in HANDLER
+handler h2 read first limit 9;
+c1
+t2
+handler h3 read first limit 9;
+ERROR 42S02: Unknown table 'h3' in HANDLER
+handler h4 read first limit 9;
+c1
+t4
+handler h5 read first limit 9;
+ERROR 42S02: Unknown table 'h5' in HANDLER
+handler h2 close;
+handler h4 close;
+handler t1 open as h1_1;
+handler t1 open as h1_2;
+handler t1 open as h1_3;
+handler h1_1 read first limit 9;
+c1
+t1
+handler h1_2 read first limit 9;
+c1
+t1
+handler h1_3 read first limit 9;
+c1
+t1
+alter table t1 engine=Aria;
+handler h1_1 read first limit 9;
+ERROR 42S02: Unknown table 'h1_1' in HANDLER
+handler h1_2 read first limit 9;
+ERROR 42S02: Unknown table 'h1_2' in HANDLER
+handler h1_3 read first limit 9;
+ERROR 42S02: Unknown table 'h1_3' in HANDLER
+drop table t1;
+drop table t2;
+drop table t3;
+drop table t4;
+drop table t5;
+create table t1 (c1 int);
+insert into t1 values (1);
+handler t1 open;
+handler t1 read first;
+c1
+1
+connect con2,localhost,root,,;
+connection con2;
+send the below to another connection, do not wait for the result
+optimize table t1;
+connection default;
+handler t1 read next;
+c1
+handler t1 close;
+connection con2;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+connection default;
+drop table t1;
+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);
+no1 no2
+HANDLER t1 READ `primary` PREV;
+no1 no2
+1 275
+HANDLER t1 READ `primary` = (1, 1000);
+no1 no2
+HANDLER t1 READ `primary` NEXT;
+no1 no2
+2 6
+DROP TABLE t1;
+create table t1 (c1 int);
+insert into t1 values (14397);
+flush tables with read lock;
+drop table t1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+connection con2;
+drop table t1;
+connection default;
+select * from t1;
+c1
+14397
+unlock tables;
+connection con2;
+read the result from the other connection
+connection default;
+select * from t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+drop table if exists t1;
+Warnings:
+Note 1051 Unknown table 'test.t1'
+create table t1 (a int not null) ENGINE=csv;
+connection con2;
+handler t1 open;
+ERROR HY000: Storage engine CSV of the table `test`.`t1` doesn't have this option
+connection default;
+drop table t1;
+disconnect con2;
+create table t1 (a int);
+handler t1 open as t1_alias;
+handler t1_alias read a next;
+ERROR 42000: Key 'a' doesn't exist in table 't1_alias'
+handler t1_alias READ a next where inexistent > 0;
+ERROR 42S22: Unknown column 'inexistent' in 'field list'
+handler t1_alias read a next;
+ERROR 42000: Key 'a' doesn't exist in table 't1_alias'
+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 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;
+a b
+0 a
+1 b
+2 c
+3 d
+4 e
+5 f
+6 g
+7 h
+8 i
+9 j
+9 k
+handler t1 open as a1;
+handler a1 read a=(1);
+a b
+1 b
+handler a1 read a next;
+a b
+2 c
+handler a1 read a next;
+a b
+3 d
+select a,b from t1;
+a b
+0 a
+1 b
+2 c
+3 d
+4 e
+5 f
+6 g
+7 h
+8 i
+9 j
+9 k
+handler a1 read a prev;
+a b
+2 c
+handler a1 read a prev;
+a b
+1 b
+handler a1 read a=(6) where b="g";
+a b
+6 g
+handler a1 close;
+select a,b from t1;
+a b
+0 a
+1 b
+2 c
+3 d
+4 e
+5 f
+6 g
+7 h
+8 i
+9 j
+9 k
+handler t1 open as a2;
+handler a2 read b=(9);
+a b
+9 j
+handler a2 read b next;
+a b
+9 k
+handler a2 read b prev limit 2;
+a b
+9 j
+8 i
+handler a2 read b last;
+a b
+9 k
+handler a2 read b prev;
+a b
+9 j
+handler a2 close;
+drop table t1;
+create table t1 (a int);
+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;
+a
+drop table t1, t2;
+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 using btree (a));
+create table t2 like t1;
+handler t1 open as a1;
+handler t2 open as a2;
+handler a1 read a first;
+a
+handler a2 read a first;
+a
+alter table t1 add b int;
+handler a1 close;
+ERROR 42S02: Unknown table 'a1' in HANDLER
+handler a2 close;
+drop table t1, t2;
+create table t1 (a int, key using btree (a));
+handler t1 open as a1;
+handler a1 read a first;
+a
+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 using btree (a));
+create table t2 like t1;
+handler t1 open as a1;
+handler t2 open as a2;
+handler a1 read a first;
+a
+handler a2 read a first;
+a
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status Table is already up to date
+handler a1 close;
+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 Engine-independent statistics collected
+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 Engine-independent statistics collected
+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;
+connect con1, localhost, root,,;
+connect con2, localhost, root,,;
+connect con3, localhost, root,,;
+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.
+#
+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;
+# We back-off on hitting deadlock condition.
+handler t0 open;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+select * from t0;
+a
+1
+2
+3
+4
+5
+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;
+drop table t1;
+#
+# 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));
+handler t1 open;
+connection con1;
+select get_lock('lock1', 10);
+get_lock('lock1', 10)
+1
+connection default;
+select get_lock('lock1', 10);
+connection con2;
+# Waiting for 'select get_lock('lock1', 10)' to get blocked...
+connection con1;
+drop table t1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+select release_lock('lock1');
+release_lock('lock1')
+1
+connection default;
+get_lock('lock1', 10)
+1
+select release_lock('lock1');
+release_lock('lock1')
+1
+# 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'.
+select * from t1;
+a
+1
+2
+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;
+disconnect con1;
+connection con2;
+disconnect con2;
+connection con3;
+disconnect con3;
+connection default;
+#
+# 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;
+a b
+1 NULL
+2 NULL
+3 NULL
+4 NULL
+5 NULL
+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
+2 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.
+#
+connect con1,localhost,root,,;
+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 default;
+handler t1 read a prev;
+a b
+6 6
+handler t1 close;
+# Cleanup.
+drop table t1;
+connection con1;
+disconnect 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;
+connect con51355, localhost, root;
+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;
+disconnect 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|
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
+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 MariaDB 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 MariaDB 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));
+HANDLER t1 OPEN;
+HANDLER t1 READ a FIRST;
+a
+INSERT INTO t1 VALUES(1);
+HANDLER t1 READ a NEXT;
+a
+1
+HANDLER t1 CLOSE;
+DROP TABLE t1;
+#
+# BUG #46456: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash
+#
+CREATE TABLE t1 AS SELECT 1 AS f1;
+HANDLER t1 OPEN;
+TRUNCATE t1;
+HANDLER t1 READ FIRST;
+ERROR 42S02: Unknown table 't1' in HANDLER
+DROP TABLE t1;
+CREATE TEMPORARY TABLE t1 AS SELECT 1 AS f1;
+HANDLER t1 OPEN;
+TRUNCATE t1;
+HANDLER t1 READ FIRST;
+ERROR 42S02: Unknown table 't1' in HANDLER
+DROP TABLE t1;
+#
+# Bug #54007: assert in ha_myisam::index_next , HANDLER
+#
+CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a), KEY b(b), KEY ab(a, b));
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST;
+a b
+HANDLER t1 READ `PRIMARY` NEXT;
+a b
+HANDLER t1 READ ab NEXT;
+a b
+HANDLER t1 READ b NEXT;
+a b
+HANDLER t1 READ NEXT;
+a b
+HANDLER t1 CLOSE;
+INSERT INTO t1 VALUES (2, 20), (1, 10), (4, 40), (3, 30);
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST;
+a b
+2 20
+HANDLER t1 READ NEXT;
+a b
+1 10
+HANDLER t1 READ `PRIMARY` NEXT;
+a b
+1 10
+HANDLER t1 READ `PRIMARY` NEXT;
+a b
+2 20
+HANDLER t1 READ ab NEXT;
+a b
+1 10
+HANDLER t1 READ ab NEXT;
+a b
+2 20
+HANDLER t1 READ b NEXT;
+a b
+1 10
+HANDLER t1 READ b NEXT;
+a b
+2 20
+HANDLER t1 READ b NEXT;
+a b
+3 30
+HANDLER t1 READ b NEXT;
+a b
+4 40
+HANDLER t1 READ b NEXT;
+a b
+HANDLER t1 READ NEXT;
+a b
+2 20
+HANDLER t1 READ NEXT;
+a b
+1 10
+HANDLER t1 READ NEXT;
+a b
+4 40
+HANDLER t1 CLOSE;
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST;
+a b
+2 20
+HANDLER t1 READ `PRIMARY` PREV;
+a b
+4 40
+HANDLER t1 READ `PRIMARY` PREV;
+a b
+3 30
+HANDLER t1 READ b PREV;
+a b
+4 40
+HANDLER t1 READ b PREV;
+a b
+3 30
+HANDLER t1 CLOSE;
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST;
+a b
+2 20
+HANDLER t1 READ `PRIMARY` PREV LIMIT 3;
+a b
+4 40
+3 30
+2 20
+HANDLER t1 READ b NEXT LIMIT 5;
+a b
+1 10
+2 20
+3 30
+4 40
+HANDLER t1 CLOSE;
+DROP TABLE t1;
+End of 5.1 tests
+#
+# 10.2 Test
+#
+# MDEV-20207: Assertion `! is_set()' failed in
+# Diagnostics_area::set_eof_status upon HANDLER READ
+#
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note 1051 Unknown table 'test.t1'
+CREATE TABLE t1 (a POINT, KEY(a));
+HANDLER t1 OPEN h;
+HANDLER h READ a = (0);
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
+HANDLER h CLOSE;
+DROP TABLE t1;
+# End of 10.2 Test
diff --git a/mysql-test/suite/handler/aria.test b/mysql-test/suite/handler/aria.test
new file mode 100644
index 00000000..912a9e89
--- /dev/null
+++ b/mysql-test/suite/handler/aria.test
@@ -0,0 +1,102 @@
+# t/handler_innodb.test
+#
+# test of HANDLER ...
+#
+# Last update:
+# 2006-07-31 ML test refactored (MySQL 5.1)
+# code of t/handler.test and t/innodb_handler.test united
+# main testing code put into handler.inc
+# rename t/innodb_handler.test to t/handler_innodb.test
+#
+
+--source include/have_maria.inc
+let $engine_type= Aria;
+
+--source init.inc
+--source handler.inc
+
+--echo #
+--echo # BUG #46456: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash
+--echo #
+CREATE TABLE t1 AS SELECT 1 AS f1;
+HANDLER t1 OPEN;
+TRUNCATE t1;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+DROP TABLE t1;
+
+CREATE TEMPORARY TABLE t1 AS SELECT 1 AS f1;
+HANDLER t1 OPEN;
+TRUNCATE t1;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+DROP TABLE t1;
+
+--echo #
+--echo # Bug #54007: assert in ha_myisam::index_next , HANDLER
+--echo #
+CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a), KEY b(b), KEY ab(a, b));
+
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST;
+HANDLER t1 READ `PRIMARY` NEXT;
+HANDLER t1 READ ab NEXT;
+HANDLER t1 READ b NEXT;
+HANDLER t1 READ NEXT;
+HANDLER t1 CLOSE;
+
+INSERT INTO t1 VALUES (2, 20), (1, 10), (4, 40), (3, 30);
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST;
+HANDLER t1 READ NEXT;
+HANDLER t1 READ `PRIMARY` NEXT;
+HANDLER t1 READ `PRIMARY` NEXT;
+HANDLER t1 READ ab NEXT;
+HANDLER t1 READ ab NEXT;
+HANDLER t1 READ b NEXT;
+HANDLER t1 READ b NEXT;
+HANDLER t1 READ b NEXT;
+HANDLER t1 READ b NEXT;
+HANDLER t1 READ b NEXT;
+HANDLER t1 READ NEXT;
+HANDLER t1 READ NEXT;
+HANDLER t1 READ NEXT;
+HANDLER t1 CLOSE;
+
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST;
+HANDLER t1 READ `PRIMARY` PREV;
+HANDLER t1 READ `PRIMARY` PREV;
+HANDLER t1 READ b PREV;
+HANDLER t1 READ b PREV;
+HANDLER t1 CLOSE;
+
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST;
+HANDLER t1 READ `PRIMARY` PREV LIMIT 3;
+HANDLER t1 READ b NEXT LIMIT 5;
+HANDLER t1 CLOSE;
+
+DROP TABLE t1;
+
+--echo End of 5.1 tests
+
+--echo #
+--echo # 10.2 Test
+--echo #
+--echo # MDEV-20207: Assertion `! is_set()' failed in
+--echo # Diagnostics_area::set_eof_status upon HANDLER READ
+--echo #
+
+DROP TABLE IF EXISTS t1;
+
+CREATE TABLE t1 (a POINT, KEY(a));
+HANDLER t1 OPEN h;
+
+--error ER_CANT_CREATE_GEOMETRY_OBJECT
+HANDLER h READ a = (0);
+
+HANDLER h CLOSE;
+DROP TABLE t1;
+
+--echo # End of 10.2 Test
diff --git a/mysql-test/suite/handler/disconnect_4480.result b/mysql-test/suite/handler/disconnect_4480.result
new file mode 100644
index 00000000..3e21a9ac
--- /dev/null
+++ b/mysql-test/suite/handler/disconnect_4480.result
@@ -0,0 +1,7 @@
+connect con1,localhost,root,,;
+create temporary table t1 as select 1;
+handler t1 open;
+handler t1 read next;
+1
+1
+disconnect con1;
diff --git a/mysql-test/suite/handler/disconnect_4480.test b/mysql-test/suite/handler/disconnect_4480.test
new file mode 100644
index 00000000..507249bd
--- /dev/null
+++ b/mysql-test/suite/handler/disconnect_4480.test
@@ -0,0 +1,10 @@
+#
+# MDEV-4480 Assertion `inited == NONE' fails on closing a connection with open handler on temporary table
+#
+
+--connect (con1,localhost,root,,)
+create temporary table t1 as select 1;
+handler t1 open;
+handler t1 read next;
+--disconnect con1
+
diff --git a/mysql-test/suite/handler/handler.inc b/mysql-test/suite/handler/handler.inc
new file mode 100644
index 00000000..9ad9e8d9
--- /dev/null
+++ b/mysql-test/suite/handler/handler.inc
@@ -0,0 +1,1355 @@
+# handler.inc
+#
+# See init.inc for setup of variables for this script
+#
+# The variables
+# $engine_type -- storage engine to be tested
+# $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
+# time available storage engine
+# 2006-08 MySQL 5.1 MyISAM and MEMORY only
+#
+# test of HANDLER ...
+#
+# Last update:
+# 2006-07-31 ML test refactored (MySQL 5.1)
+# code of t/handler.test and t/innodb_handler.test united
+# main testing code put into handler.inc
+#
+
+source include/have_csv.inc;
+
+#
+# Start testing the table created in init.inc
+#
+handler t1 open as t2;
+handler t2 read b first;
+handler t2 read b next;
+handler t2 read b next;
+handler t2 read b prev;
+handler t2 read b last;
+handler t2 read b prev;
+handler t2 read b prev;
+
+handler t2 read b first;
+handler t2 read b prev;
+
+handler t2 read b last;
+handler t2 read b prev;
+handler t2 read b next;
+handler t2 read b next;
+
+handler t2 read a=(15);
+handler t2 read a=(21);
+
+--error 1070
+handler t2 read a=(19,"fff");
+
+handler t2 read b=(19,"fff");
+handler t2 read b=(19,"yyy");
+handler t2 read b=(19);
+
+--error 1109
+handler t1 read a last;
+
+handler t2 read a=(11);
+handler t2 read a>=(11);
+
+# Search on something we can find
+handler t2 read b=(18);
+handler t2 read b>=(18);
+handler t2 read b>(18);
+handler t2 read b<=(18);
+handler t2 read b<(18);
+
+# Search on something we can't find
+--sorted_result
+handler t2 read a=(15);
+--sorted_result
+handler t2 read a>=(15) limit 2;
+--sorted_result
+handler t2 read a>(15) limit 2;
+handler t2 read a<=(15);
+handler t2 read a<(15);
+
+# Search from upper end
+handler t2 read a=(54);
+handler t2 read a>=(54);
+handler t2 read a>(54);
+handler t2 read a<=(54);
+handler t2 read a<(54);
+
+# Search from lower end
+handler t2 read a=(1);
+handler t2 read a>=(1);
+handler t2 read a>(1);
+handler t2 read a<=(1);
+handler t2 read a<(1);
+
+handler t2 read b first limit 5;
+handler t2 read b next limit 3;
+handler t2 read b prev limit 10;
+
+handler t2 read b>=(16) limit 4;
+handler t2 read b>=(16) limit 2,2;
+select * from t1 where a>=16 order by a,b limit 2,2;
+handler t2 read a last limit 3;
+handler t2 read b=(16) limit 1,3;
+handler t2 read b=(19);
+handler t2 read b=(19) where b="yyy";
+
+handler t2 read first;
+handler t2 read next;
+handler t2 read next;
+handler t2 close;
+
+handler t1 open;
+handler t1 read b next; # this used to crash as a bug#5373
+handler t1 read b next;
+handler t1 close;
+
+handler t1 open;
+handler t1 read a prev; # this used to crash as a bug#5373
+handler t1 read a prev;
+handler t1 close;
+
+handler t1 open as t2;
+handler t2 read first;
+eval alter table t1 engine = $engine_type;
+--error 1109
+handler t2 read first;
+
+handler t1 open;
+handler t1 read a=(20) limit 1,3;
+flush tables;
+handler t1 read a=(20) limit 1,3;
+handler t1 close;
+
+#
+# Search after end and before start of index
+#
+
+handler t1 open;
+handler t1 read a=(25);
+handler t1 read a next;
+handler t1 read a next;
+handler t1 read a next;
+handler t1 read a prev;
+handler t1 read a=(1000);
+handler t1 read a next;
+handler t1 read a prev;
+handler t1 read a=(1000);
+handler t1 read a prev;
+
+handler t1 read a=(14);
+handler t1 read a prev;
+handler t1 read a prev;
+handler t1 read a next;
+handler t1 read a=(1);
+handler t1 read a prev;
+handler t1 read a next;
+handler t1 read a=(1);
+handler t1 read a next;
+
+handler t1 close;
+
+#
+# Test with prepared statements
+#
+
+handler t1 open;
+prepare stmt from 'handler t1 read a=(?) limit ?,?';
+set @a=20,@b=1,@c=100;
+execute stmt using @a,@b,@c;
+set @a=20,@b=2,@c=1;
+execute stmt using @a,@b,@c;
+set @a=20,@b=0,@c=2;
+execute stmt using @a,@b,@c;
+deallocate prepare stmt;
+
+prepare stmt from 'handler t1 read a next limit ?';
+handler t1 read a>=(21);
+set @a=3;
+execute stmt using @a;
+execute stmt using @a;
+execute stmt using @a;
+deallocate prepare stmt;
+
+prepare stmt from 'handler t1 read b prev limit ?';
+execute stmt using @a;
+execute stmt using @a;
+execute stmt using @a;
+execute stmt using @a;
+deallocate prepare stmt;
+
+prepare stmt from 'handler t1 read b=(?,?)';
+set @a=14, @b='aaa';
+execute stmt using @a,@b;
+set @a=14, @b='not found';
+execute stmt using @a,@b;
+deallocate prepare stmt;
+
+prepare stmt from 'handler t1 read b=(1+?) limit 10';
+set @a=15;
+execute stmt using @a;
+execute stmt using @a;
+deallocate prepare stmt;
+
+prepare stmt from 'handler t1 read b>=(?) where a < ? limit 5';
+set @a=17, @b=24;
+execute stmt using @a,@b;
+execute stmt using @a,@b;
+deallocate prepare stmt;
+
+prepare stmt from 'handler t1 read a=(?)';
+set @a=17;
+execute stmt using @a;
+alter table t1 add c int;
+--error 1109
+execute stmt using @a;
+deallocate prepare stmt;
+--error 1109
+handler t1 close;
+
+handler t1 open;
+prepare stmt from 'handler t1 read a=(?)';
+flush tables;
+set @a=17;
+execute stmt using @a;
+deallocate prepare stmt;
+handler t1 close;
+
+#
+# DROP TABLE / ALTER TABLE
+#
+handler t1 open as t2;
+drop table t1;
+create table t1 (a int not null);
+insert into t1 values (17);
+--error 1109
+handler t2 read first;
+handler t1 open as t2;
+alter table t1 engine=csv;
+--error 1109
+handler t2 read first;
+drop table t1;
+
+#
+# Test case for the bug #787
+#
+create table t1 (a int);
+insert into t1 values (1),(2),(3),(4),(5),(6);
+delete from t1 limit 2;
+handler t1 open;
+handler t1 read first;
+handler t1 read first limit 1,1;
+handler t1 read first limit 2,2;
+delete from t1 limit 3;
+handler t1 read first;
+drop table t1;
+
+#
+# Test for #751
+#
+create table t1(a int, index using btree (a));
+insert into t1 values (1), (2), (3);
+handler t1 open;
+--error 1054
+handler t1 read a=(W);
+--error 1210
+handler t1 read a=(a);
+drop table t1;
+#
+# BUG#2304
+#
+create table t1 (a char(5));
+insert into t1 values ("Ok");
+handler t1 open as t;
+handler t read first;
+use mysql;
+handler t read first;
+handler t close;
+handler test.t1 open as t;
+handler t read first;
+handler t close;
+use test;
+drop table t1;
+
+#
+# BUG#3649
+#
+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;
+handler t1 read a=(1) where b=3;
+handler t1 read a=(1) where b=1;
+handler t1 close;
+drop table t1;
+
+#
+# Test if fix for BUG#4286 correctly closes handler tables.
+#
+create table t1 (c1 char(20));
+insert into t1 values ("t1");
+handler t1 open as h1;
+handler h1 read first limit 9;
+create table t2 (c1 char(20));
+insert into t2 values ("t2");
+handler t2 open as h2;
+handler h2 read first limit 9;
+create table t3 (c1 char(20));
+insert into t3 values ("t3");
+handler t3 open as h3;
+handler h3 read first limit 9;
+create table t4 (c1 char(20));
+insert into t4 values ("t4");
+handler t4 open as h4;
+handler h4 read first limit 9;
+create table t5 (c1 char(20));
+insert into t5 values ("t5");
+handler t5 open as h5;
+handler h5 read first limit 9;
+# close first
+eval alter table t1 engine=$other_handler_engine_type;
+--error 1109
+handler h1 read first limit 9;
+handler h2 read first limit 9;
+handler h3 read first limit 9;
+handler h4 read first limit 9;
+handler h5 read first limit 9;
+# close last
+eval alter table t5 engine=$other_handler_engine_type;
+--error 1109
+handler h1 read first limit 9;
+handler h2 read first limit 9;
+handler h3 read first limit 9;
+handler h4 read first limit 9;
+--error 1109
+handler h5 read first limit 9;
+# close middle
+eval alter table t3 engine=$other_handler_engine_type;
+--error 1109
+handler h1 read first limit 9;
+handler h2 read first limit 9;
+--error 1109
+handler h3 read first limit 9;
+handler h4 read first limit 9;
+--error 1109
+handler h5 read first limit 9;
+handler h2 close;
+handler h4 close;
+# close all depending handler tables
+handler t1 open as h1_1;
+handler t1 open as h1_2;
+handler t1 open as h1_3;
+handler h1_1 read first limit 9;
+handler h1_2 read first limit 9;
+handler h1_3 read first limit 9;
+eval alter table t1 engine=$engine_type;
+--error 1109
+handler h1_1 read first limit 9;
+--error 1109
+handler h1_2 read first limit 9;
+--error 1109
+handler h1_3 read first limit 9;
+drop table t1;
+drop table t2;
+drop table t3;
+drop table t4;
+drop table t5;
+
+#
+# Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash
+#
+create table t1 (c1 int);
+insert into t1 values (1);
+handler t1 open;
+handler t1 read first;
+connect (con2,localhost,root,,);
+connection con2;
+--echo send the below to another connection, do not wait for the result
+send optimize table t1;
+--sleep 1
+connection default;
+--disable_ps_protocol
+handler t1 read next;
+--enable_ps_protocol
+handler t1 close;
+connection con2;
+reap;
+connection default;
+drop table t1;
+
+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);
+HANDLER t1 READ `primary` PREV;
+HANDLER t1 READ `primary` = (1, 1000);
+HANDLER t1 READ `primary` NEXT;
+DROP TABLE t1;
+
+# End of 4.1 tests
+
+#
+# Addendum to Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash
+# Show that DROP TABLE can no longer deadlock against
+# FLUSH TABLES WITH READ LOCK. This is a 5.0 issue.
+#
+create table t1 (c1 int);
+insert into t1 values (14397);
+flush tables with read lock;
+# The thread with the global read lock cannot drop the table itself:
+--error 1223
+drop table t1;
+#
+# We need a second connection to try the drop.
+# The drop waits for the global read lock to go away.
+# Without the addendum fix it locked LOCK_open before entering the wait loop.
+connection con2;
+send drop table t1;
+--sleep 1
+#
+# Now we need something that wants LOCK_open. A simple table access which
+# opens the table does the trick.
+connection default;
+# This would hang on LOCK_open without the 5.0 addendum fix.
+select * from t1;
+# Release the read lock. This should make the DROP go through.
+unlock tables;
+#
+# Read the result of the drop command.
+connection con2;
+--echo read the result from the other connection
+reap;
+#
+# Now back to normal operation. The table should not exist any more.
+connection default;
+--error 1146
+select * from t1;
+# Just to be sure and not confuse the next test case writer.
+drop table if exists t1;
+
+#
+# Bug#25856 - HANDLER table OPEN in one connection lock DROP TABLE in another one
+#
+create table t1 (a int not null) ENGINE=csv;
+connection con2;
+--error 1031
+handler t1 open;
+connection default;
+drop table t1;
+disconnect con2;
+
+#
+# Bug#30632 HANDLER read failure causes hang
+#
+create table t1 (a int);
+handler t1 open as t1_alias;
+--error 1176
+handler t1_alias read a next;
+--error 1054
+handler t1_alias READ a next where inexistent > 0;
+--error 1176
+handler t1_alias read a next;
+--error 1054
+handler t1_alias READ a next where inexistent > 0;
+handler t1_alias close;
+drop table t1;
+
+#
+# Bug#30882 Dropping a temporary table inside a stored function may cause a server crash
+#
+
+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;
+handler t1 open as a1;
+handler a1 read a=(1);
+handler a1 read a next;
+handler a1 read a next;
+select a,b from t1;
+handler a1 read a prev;
+handler a1 read a prev;
+handler a1 read a=(6) where b="g";
+handler a1 close;
+select a,b from t1;
+handler t1 open as a2;
+handler a2 read b=(9);
+handler a2 read b next;
+handler a2 read b prev limit 2;
+--error 0,1031
+handler a2 read b last;
+handler a2 read b prev;
+handler a2 close;
+drop table t1;
+
+# Test that temporary tables associated with handlers are properly dropped.
+
+create table t1 (a int);
+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;
+drop table t1, t2;
+--error ER_UNKNOWN_TABLE
+handler a2 read a next;
+--error ER_UNKNOWN_TABLE
+handler a1 close;
+
+# Alter table drop handlers
+
+create table t1 (a int, key using btree (a));
+create table t2 like t1;
+handler t1 open as a1;
+handler t2 open as a2;
+handler a1 read a first;
+handler a2 read a first;
+alter table t1 add b int;
+--error ER_UNKNOWN_TABLE
+handler a1 close;
+handler a2 close;
+drop table t1, t2;
+
+# Rename table drop handlers
+
+create table t1 (a int, key using btree (a));
+handler t1 open as a1;
+handler a1 read a first;
+rename table t1 to t2;
+--error ER_UNKNOWN_TABLE
+handler a1 read a first;
+drop table t2;
+
+# Optimize table drop handlers
+
+create table t1 (a int, key using btree (a));
+create table t2 like t1;
+handler t1 open as a1;
+handler t2 open as a2;
+handler a1 read a first;
+handler a2 read a first;
+optimize table t1;
+--error ER_UNKNOWN_TABLE
+handler a1 close;
+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;
+connect(con1, localhost, root,,);
+connect(con2, localhost, root,,);
+connect(con3, localhost, root,,);
+connection con1;
+--echo # Sending:
+--send drop table t1
+--echo # We can't use connection 'default' as wait_condition will
+--echo # autoclose handlers.
+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
+connection default;
+handler t1 read a prev;
+handler t1 read a prev;
+handler t1 close;
+connection con1;
+--echo # Reaping 'drop table t1'...
+--reap
+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;
+connection con1;
+--echo # Sending:
+--send drop table t1
+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
+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;
+connection con1;
+--echo # Now drop can proceed
+--echo # Reaping 'drop table t1'...
+--reap
+connection default;
+--echo #
+--echo # Demonstrate that HANDLER locks and transaction locks
+--echo # reside in the same context.
+--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;
+connection con2;
+--echo # Sending:
+send rename table t0 to t3, t1 to t0, t3 to t1;
+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
+connection default;
+--echo # We back-off on hitting deadlock condition.
+--error ER_LOCK_DEADLOCK
+handler t0 open;
+select * from t0;
+handler t1 open;
+commit;
+handler t1 close;
+connection con2;
+--echo # Reaping 'rename table ...'...
+--reap
+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;
+connection con1;
+lock tables t2 read;
+connection con2;
+--echo # Sending 'drop table t2'...
+--send drop table t2
+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
+connection default;
+--echo # Sending 'select * from t2'
+send select * from t2;
+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;
+connection con2;
+--echo # Reaping 'drop table t2'...
+--reap
+connection default;
+--echo # Reaping 'select * from t2'
+--error ER_NO_SUCH_TABLE
+reap;
+handler t1 close;
+drop table t1;
+
+--echo #
+--echo # If we have to wait on an exclusive locks while having
+--echo # an open HANDLER, ER_LOCK_DEADLOCK is reported.
+--echo #
+--disable_ps2_protocol
+create table t1 (a int, key a(a));
+handler t1 open;
+connection con1;
+select get_lock('lock1', 10);
+connection default;
+send select get_lock('lock1', 10);
+connection con2;
+--echo # Waiting for 'select get_lock('lock1', 10)' to get blocked...
+let $wait_condition=select count(*)=1 from information_schema.processlist
+ where state='User lock' and
+ info='select get_lock(\'lock1\', 10)';
+--source include/wait_condition.inc
+connection con1;
+--error ER_LOCK_DEADLOCK
+drop table t1;
+select release_lock('lock1');
+connection default;
+reap;
+select release_lock('lock1');
+--enable_ps2_protocol
+
+--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
+connection con2;
+drop table t1;
+connection con1;
+unlock tables;
+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);
+
+connection default;
+begin;
+select * from t1;
+handler t1 open;
+
+connection con1;
+--echo # Sending:
+--send lock tables t1 write
+
+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
+
+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'.
+select * from t1; # Release MDL_SHARED_READ held by HANDLER
+commit;
+
+connection con1;
+--echo # Reap 'lock tables t1 write'.
+--reap
+
+connection default;
+--echo # Sending:
+--send handler t1 read a next
+
+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 metadata 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;
+
+connection default;
+--echo # Reaping 'handler t1 read a next'...
+--error ER_NO_SUCH_TABLE
+--reap
+handler t1 close;
+
+connection con1;
+disconnect con1;
+--source include/wait_until_disconnected.inc
+connection con2;
+disconnect con2;
+--source include/wait_until_disconnected.inc
+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;
+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 #
+connect (con1,localhost,root,,);
+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;
+connection default;
+handler t1 read a prev;
+handler t1 close;
+--echo # Cleanup.
+drop table t1;
+connection con1;
+disconnect con1;
+--source include/wait_until_disconnected.inc
+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);
+
+connection default;
+CREATE TABLE t1(id INT, KEY id(id));
+HANDLER t1 OPEN;
+
+connection con51355;
+--echo # Sending:
+--send DROP TABLE t1
+
+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
+
+connection con51355;
+--echo # Reaping: DROP TABLE t1
+--reap
+
+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;
+connection con51355;
+disconnect con51355;
+--source include/wait_until_disconnected.inc
+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
+
+--enable_prepare_warnings
+delimiter |;
+CREATE FUNCTION f1() RETURNS INTEGER
+BEGIN
+ SELECT 1 FROM t2 INTO @a;
+ RETURN 1;
+END|
+delimiter ;|
+--disable_prepare_warnings
+
+# 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 #
+CREATE TABLE t1(a INT, KEY using btree (a));
+HANDLER t1 OPEN;
+HANDLER t1 READ a FIRST;
+INSERT INTO t1 VALUES(1);
+--error 0,ER_CHECKREAD
+HANDLER t1 READ a NEXT;
+HANDLER t1 CLOSE;
+DROP TABLE t1;
diff --git a/mysql-test/suite/handler/heap.result b/mysql-test/suite/handler/heap.result
new file mode 100644
index 00000000..e66bccb1
--- /dev/null
+++ b/mysql-test/suite/handler/heap.result
@@ -0,0 +1,1706 @@
+SET SESSION DEFAULT_STORAGE_ENGINE = MEMORY;
+drop table if exists t1,t3,t4,t5;
+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"),
+(20,"ggg"),(21,"hhh"),(22,"iii"),(23,"xxx"),(24,"xxx"),(25,"xxx");
+handler t1 open as t2;
+handler t2 read b first;
+a b
+14 aaa
+handler t2 read b next;
+a b
+16 ccc
+handler t2 read b next;
+a b
+16 xxx
+handler t2 read b prev;
+a b
+16 ccc
+handler t2 read b last;
+a b
+25 xxx
+handler t2 read b prev;
+a b
+24 xxx
+handler t2 read b prev;
+a b
+23 xxx
+handler t2 read b first;
+a b
+14 aaa
+handler t2 read b prev;
+a b
+handler t2 read b last;
+a b
+25 xxx
+handler t2 read b prev;
+a b
+24 xxx
+handler t2 read b next;
+a b
+25 xxx
+handler t2 read b next;
+a b
+handler t2 read a=(15);
+a b
+handler t2 read a=(21);
+a b
+21 hhh
+handler t2 read a=(19,"fff");
+ERROR 42000: Too many key parts specified; max 1 parts allowed
+handler t2 read b=(19,"fff");
+a b
+19 fff
+handler t2 read b=(19,"yyy");
+a b
+19 yyy
+handler t2 read b=(19);
+a b
+19 fff
+handler t1 read a last;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler t2 read a=(11);
+a b
+handler t2 read a>=(11);
+a b
+14 aaa
+handler t2 read b=(18);
+a b
+18 eee
+handler t2 read b>=(18);
+a b
+18 eee
+handler t2 read b>(18);
+a b
+19 fff
+handler t2 read b<=(18);
+a b
+18 eee
+handler t2 read b<(18);
+a b
+17 ddd
+handler t2 read a=(15);
+a b
+handler t2 read a>=(15) limit 2;
+a b
+16 ccc
+16 xxx
+handler t2 read a>(15) limit 2;
+a b
+16 ccc
+16 xxx
+handler t2 read a<=(15);
+a b
+14 aaa
+handler t2 read a<(15);
+a b
+14 aaa
+handler t2 read a=(54);
+a b
+handler t2 read a>=(54);
+a b
+handler t2 read a>(54);
+a b
+handler t2 read a<=(54);
+a b
+25 xxx
+handler t2 read a<(54);
+a b
+25 xxx
+handler t2 read a=(1);
+a b
+handler t2 read a>=(1);
+a b
+14 aaa
+handler t2 read a>(1);
+a b
+14 aaa
+handler t2 read a<=(1);
+a b
+handler t2 read a<(1);
+a b
+handler t2 read b first limit 5;
+a b
+14 aaa
+16 ccc
+16 xxx
+17 ddd
+18 eee
+handler t2 read b next limit 3;
+a b
+19 fff
+19 yyy
+20 ggg
+handler t2 read b prev limit 10;
+a b
+19 yyy
+19 fff
+18 eee
+17 ddd
+16 xxx
+16 ccc
+14 aaa
+handler t2 read b>=(16) limit 4;
+a b
+16 ccc
+16 xxx
+17 ddd
+18 eee
+handler t2 read b>=(16) limit 2,2;
+a b
+17 ddd
+18 eee
+select * from t1 where a>=16 order by a,b limit 2,2;
+a b
+17 ddd
+18 eee
+handler t2 read a last limit 3;
+a b
+25 xxx
+24 xxx
+23 xxx
+handler t2 read b=(16) limit 1,3;
+a b
+16 xxx
+handler t2 read b=(19);
+a b
+19 fff
+handler t2 read b=(19) where b="yyy";
+a b
+19 yyy
+handler t2 read first;
+a b
+17 ddd
+handler t2 read next;
+a b
+18 eee
+handler t2 read next;
+a b
+19 fff
+handler t2 close;
+handler t1 open;
+handler t1 read b next;
+a b
+14 aaa
+handler t1 read b next;
+a b
+16 ccc
+handler t1 close;
+handler t1 open;
+handler t1 read a prev;
+a b
+25 xxx
+handler t1 read a prev;
+a b
+24 xxx
+handler t1 close;
+handler t1 open as t2;
+handler t2 read first;
+a b
+17 ddd
+alter table t1 engine = MEMORY;
+handler t2 read first;
+ERROR 42S02: Unknown table 't2' in HANDLER
+handler t1 open;
+handler t1 read a=(20) limit 1,3;
+a b
+flush tables;
+handler t1 read a=(20) limit 1,3;
+a b
+handler t1 close;
+handler t1 open;
+handler t1 read a=(25);
+a b
+25 xxx
+handler t1 read a next;
+a b
+handler t1 read a next;
+a b
+handler t1 read a next;
+a b
+handler t1 read a prev;
+a b
+25 xxx
+handler t1 read a=(1000);
+a b
+handler t1 read a next;
+a b
+handler t1 read a prev;
+a b
+25 xxx
+handler t1 read a=(1000);
+a b
+handler t1 read a prev;
+a b
+25 xxx
+handler t1 read a=(14);
+a b
+14 aaa
+handler t1 read a prev;
+a b
+handler t1 read a prev;
+a b
+handler t1 read a next;
+a b
+14 aaa
+handler t1 read a=(1);
+a b
+handler t1 read a prev;
+a b
+handler t1 read a next;
+a b
+14 aaa
+handler t1 read a=(1);
+a b
+handler t1 read a next;
+a b
+14 aaa
+handler t1 close;
+handler t1 open;
+prepare stmt from 'handler t1 read a=(?) limit ?,?';
+set @a=20,@b=1,@c=100;
+execute stmt using @a,@b,@c;
+a b
+set @a=20,@b=2,@c=1;
+execute stmt using @a,@b,@c;
+a b
+set @a=20,@b=0,@c=2;
+execute stmt using @a,@b,@c;
+a b
+20 ggg
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read a next limit ?';
+handler t1 read a>=(21);
+a b
+21 hhh
+set @a=3;
+execute stmt using @a;
+a b
+22 iii
+23 xxx
+24 xxx
+execute stmt using @a;
+a b
+25 xxx
+execute stmt using @a;
+a b
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read b prev limit ?';
+execute stmt using @a;
+a b
+25 xxx
+24 xxx
+23 xxx
+execute stmt using @a;
+a b
+22 iii
+21 hhh
+20 ggg
+execute stmt using @a;
+a b
+19 yyy
+19 fff
+18 eee
+execute stmt using @a;
+a b
+17 ddd
+16 xxx
+16 ccc
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read b=(?,?)';
+set @a=14, @b='aaa';
+execute stmt using @a,@b;
+a b
+14 aaa
+set @a=14, @b='not found';
+execute stmt using @a,@b;
+a b
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read b=(1+?) limit 10';
+set @a=15;
+execute stmt using @a;
+a b
+16 ccc
+16 xxx
+execute stmt using @a;
+a b
+16 ccc
+16 xxx
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read b>=(?) where a < ? limit 5';
+set @a=17, @b=24;
+execute stmt using @a,@b;
+a b
+17 ddd
+18 eee
+19 fff
+19 yyy
+20 ggg
+execute stmt using @a,@b;
+a b
+17 ddd
+18 eee
+19 fff
+19 yyy
+20 ggg
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read a=(?)';
+set @a=17;
+execute stmt using @a;
+a b
+17 ddd
+alter table t1 add c int;
+execute stmt using @a;
+ERROR 42S02: Unknown table 't1' in HANDLER
+deallocate prepare stmt;
+handler t1 close;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler t1 open;
+prepare stmt from 'handler t1 read a=(?)';
+flush tables;
+set @a=17;
+execute stmt using @a;
+a b c
+17 ddd NULL
+deallocate prepare stmt;
+handler t1 close;
+handler t1 open as t2;
+drop table t1;
+create table t1 (a int not null);
+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;
+handler t2 read first;
+ERROR 42S02: Unknown table 't2' in HANDLER
+drop table t1;
+create table t1 (a int);
+insert into t1 values (1),(2),(3),(4),(5),(6);
+delete from t1 limit 2;
+handler t1 open;
+handler t1 read first;
+a
+3
+handler t1 read first limit 1,1;
+a
+4
+handler t1 read first limit 2,2;
+a
+5
+6
+delete from t1 limit 3;
+handler t1 read first;
+a
+6
+drop table t1;
+create table t1(a int, index using btree (a));
+insert into t1 values (1), (2), (3);
+handler t1 open;
+handler t1 read a=(W);
+ERROR 42S22: Unknown column 'W' in 'field list'
+handler t1 read a=(a);
+ERROR HY000: Incorrect arguments to HANDLER ... READ
+drop table t1;
+create table t1 (a char(5));
+insert into t1 values ("Ok");
+handler t1 open as t;
+handler t read first;
+a
+Ok
+use mysql;
+handler t read first;
+a
+Ok
+handler t close;
+handler test.t1 open as t;
+handler t read first;
+a
+Ok
+handler t close;
+use test;
+drop table t1;
+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;
+a b
+1 2
+handler t1 read a=(1) where b=3;
+a b
+handler t1 read a=(1) where b=1;
+a b
+handler t1 close;
+drop table t1;
+create table t1 (c1 char(20));
+insert into t1 values ("t1");
+handler t1 open as h1;
+handler h1 read first limit 9;
+c1
+t1
+create table t2 (c1 char(20));
+insert into t2 values ("t2");
+handler t2 open as h2;
+handler h2 read first limit 9;
+c1
+t2
+create table t3 (c1 char(20));
+insert into t3 values ("t3");
+handler t3 open as h3;
+handler h3 read first limit 9;
+c1
+t3
+create table t4 (c1 char(20));
+insert into t4 values ("t4");
+handler t4 open as h4;
+handler h4 read first limit 9;
+c1
+t4
+create table t5 (c1 char(20));
+insert into t5 values ("t5");
+handler t5 open as h5;
+handler h5 read first limit 9;
+c1
+t5
+alter table t1 engine=MyISAM;
+handler h1 read first limit 9;
+ERROR 42S02: Unknown table 'h1' in HANDLER
+handler h2 read first limit 9;
+c1
+t2
+handler h3 read first limit 9;
+c1
+t3
+handler h4 read first limit 9;
+c1
+t4
+handler h5 read first limit 9;
+c1
+t5
+alter table t5 engine=MyISAM;
+handler h1 read first limit 9;
+ERROR 42S02: Unknown table 'h1' in HANDLER
+handler h2 read first limit 9;
+c1
+t2
+handler h3 read first limit 9;
+c1
+t3
+handler h4 read first limit 9;
+c1
+t4
+handler h5 read first limit 9;
+ERROR 42S02: Unknown table 'h5' in HANDLER
+alter table t3 engine=MyISAM;
+handler h1 read first limit 9;
+ERROR 42S02: Unknown table 'h1' in HANDLER
+handler h2 read first limit 9;
+c1
+t2
+handler h3 read first limit 9;
+ERROR 42S02: Unknown table 'h3' in HANDLER
+handler h4 read first limit 9;
+c1
+t4
+handler h5 read first limit 9;
+ERROR 42S02: Unknown table 'h5' in HANDLER
+handler h2 close;
+handler h4 close;
+handler t1 open as h1_1;
+handler t1 open as h1_2;
+handler t1 open as h1_3;
+handler h1_1 read first limit 9;
+c1
+t1
+handler h1_2 read first limit 9;
+c1
+t1
+handler h1_3 read first limit 9;
+c1
+t1
+alter table t1 engine=MEMORY;
+handler h1_1 read first limit 9;
+ERROR 42S02: Unknown table 'h1_1' in HANDLER
+handler h1_2 read first limit 9;
+ERROR 42S02: Unknown table 'h1_2' in HANDLER
+handler h1_3 read first limit 9;
+ERROR 42S02: Unknown table 'h1_3' in HANDLER
+drop table t1;
+drop table t2;
+drop table t3;
+drop table t4;
+drop table t5;
+create table t1 (c1 int);
+insert into t1 values (1);
+handler t1 open;
+handler t1 read first;
+c1
+1
+connect con2,localhost,root,,;
+connection con2;
+send the below to another connection, do not wait for the result
+optimize table t1;
+connection default;
+handler t1 read next;
+c1
+handler t1 close;
+connection con2;
+Table Op Msg_type Msg_text
+test.t1 optimize note The storage engine for the table doesn't support optimize
+connection default;
+drop table t1;
+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);
+no1 no2
+HANDLER t1 READ `primary` PREV;
+no1 no2
+1 275
+HANDLER t1 READ `primary` = (1, 1000);
+no1 no2
+HANDLER t1 READ `primary` NEXT;
+no1 no2
+2 6
+DROP TABLE t1;
+create table t1 (c1 int);
+insert into t1 values (14397);
+flush tables with read lock;
+drop table t1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+connection con2;
+drop table t1;
+connection default;
+select * from t1;
+c1
+14397
+unlock tables;
+connection con2;
+read the result from the other connection
+connection default;
+select * from t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+drop table if exists t1;
+Warnings:
+Note 1051 Unknown table 'test.t1'
+create table t1 (a int not null) ENGINE=csv;
+connection con2;
+handler t1 open;
+ERROR HY000: Storage engine CSV of the table `test`.`t1` doesn't have this option
+connection default;
+drop table t1;
+disconnect con2;
+create table t1 (a int);
+handler t1 open as t1_alias;
+handler t1_alias read a next;
+ERROR 42000: Key 'a' doesn't exist in table 't1_alias'
+handler t1_alias READ a next where inexistent > 0;
+ERROR 42S22: Unknown column 'inexistent' in 'field list'
+handler t1_alias read a next;
+ERROR 42000: Key 'a' doesn't exist in table 't1_alias'
+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 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;
+a b
+0 a
+1 b
+2 c
+3 d
+4 e
+5 f
+6 g
+7 h
+8 i
+9 j
+9 k
+handler t1 open as a1;
+handler a1 read a=(1);
+a b
+1 b
+handler a1 read a next;
+a b
+2 c
+handler a1 read a next;
+a b
+3 d
+select a,b from t1;
+a b
+0 a
+1 b
+2 c
+3 d
+4 e
+5 f
+6 g
+7 h
+8 i
+9 j
+9 k
+handler a1 read a prev;
+a b
+2 c
+handler a1 read a prev;
+a b
+1 b
+handler a1 read a=(6) where b="g";
+a b
+6 g
+handler a1 close;
+select a,b from t1;
+a b
+0 a
+1 b
+2 c
+3 d
+4 e
+5 f
+6 g
+7 h
+8 i
+9 j
+9 k
+handler t1 open as a2;
+handler a2 read b=(9);
+a b
+9 j
+handler a2 read b next;
+a b
+9 k
+handler a2 read b prev limit 2;
+a b
+9 j
+8 i
+handler a2 read b last;
+a b
+9 k
+handler a2 read b prev;
+a b
+9 j
+handler a2 close;
+drop table t1;
+create table t1 (a int);
+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;
+a
+drop table t1, t2;
+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 using btree (a));
+create table t2 like t1;
+handler t1 open as a1;
+handler t2 open as a2;
+handler a1 read a first;
+a
+handler a2 read a first;
+a
+alter table t1 add b int;
+handler a1 close;
+ERROR 42S02: Unknown table 'a1' in HANDLER
+handler a2 close;
+drop table t1, t2;
+create table t1 (a int, key using btree (a));
+handler t1 open as a1;
+handler a1 read a first;
+a
+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 using btree (a));
+create table t2 like t1;
+handler t1 open as a1;
+handler t2 open as a2;
+handler a1 read a first;
+a
+handler a2 read a first;
+a
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize note The storage engine for the table doesn't support optimize
+handler a1 close;
+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 Operation failed
+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 status Engine-independent statistics collected
+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;
+connect con1, localhost, root,,;
+connect con2, localhost, root,,;
+connect con3, localhost, root,,;
+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.
+#
+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;
+# We back-off on hitting deadlock condition.
+handler t0 open;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+select * from t0;
+a
+1
+2
+3
+4
+5
+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;
+drop table t1;
+#
+# 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));
+handler t1 open;
+connection con1;
+select get_lock('lock1', 10);
+get_lock('lock1', 10)
+1
+connection default;
+select get_lock('lock1', 10);
+connection con2;
+# Waiting for 'select get_lock('lock1', 10)' to get blocked...
+connection con1;
+drop table t1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+select release_lock('lock1');
+release_lock('lock1')
+1
+connection default;
+get_lock('lock1', 10)
+1
+select release_lock('lock1');
+release_lock('lock1')
+1
+# 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'.
+select * from t1;
+a
+1
+2
+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;
+disconnect con1;
+connection con2;
+disconnect con2;
+connection con3;
+disconnect con3;
+connection default;
+#
+# 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;
+a b
+1 NULL
+2 NULL
+3 NULL
+4 NULL
+5 NULL
+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
+2 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.
+#
+connect con1,localhost,root,,;
+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 default;
+handler t1 read a prev;
+a b
+6 6
+handler t1 close;
+# Cleanup.
+drop table t1;
+connection con1;
+disconnect 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;
+connect con51355, localhost, root;
+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;
+disconnect 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|
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
+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 MariaDB 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 MariaDB 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));
+HANDLER t1 OPEN;
+HANDLER t1 READ a FIRST;
+a
+INSERT INTO t1 VALUES(1);
+HANDLER t1 READ a NEXT;
+HANDLER t1 CLOSE;
+DROP TABLE t1;
+connect con1,localhost,root,,;
+connection default;
+CREATE TABLE t1(a INT, b INT, KEY(a), KEY b using btree (b), KEY ab using btree(a, b)) engine=memory;
+INSERT INTO t1 VALUES (2, 20), (2,20), (1, 10), (4, 40), (3, 30), (5,50), (6,50);
+HANDLER t1 OPEN;
+HANDLER t1 READ a=(2) limit 3;
+a b
+2 20
+2 20
+HANDLER t1 READ a PREV;
+a b
+2 20
+HANDLER t1 READ a PREV;
+a b
+2 20
+HANDLER t1 READ a PREV;
+a b
+HANDLER t1 READ b>=(20) limit 3;
+a b
+2 20
+2 20
+3 30
+HANDLER t1 READ b PREV;
+a b
+2 20
+HANDLER t1 READ b PREV LIMIT 2;
+a b
+2 20
+1 10
+HANDLER t1 READ ab=(3,30) limit 3;
+a b
+3 30
+HANDLER t1 READ ab>=(3,30) limit 3;
+a b
+3 30
+4 40
+5 50
+HANDLER t1 READ a FIRST;
+ERROR HY000: Storage engine MEMORY of the table `test`.`t1` doesn't have this option
+HANDLER t1 READ a LAST;
+ERROR HY000: Storage engine MEMORY of the table `test`.`t1` doesn't have this option
+HANDLER t1 READ b FIRST LIMIT 2;
+a b
+1 10
+2 20
+HANDLER t1 READ ab LAST LIMIT 2;
+a b
+6 50
+5 50
+HANDLER t1 READ FIRST LIMIT 10;
+a b
+2 20
+2 20
+1 10
+4 40
+3 30
+5 50
+6 50
+HANDLER t1 READ b FIRST;
+a b
+1 10
+insert into t1 values (7,50);
+HANDLER t1 READ b NEXT;
+ERROR HY000: Record has changed since last read in table 't1'
+HANDLER t1 READ b FIRST;
+a b
+1 10
+connection con1;
+insert into t1 values (7,50);
+connection default;
+HANDLER t1 READ b NEXT;
+ERROR HY000: Record has changed since last read in table 't1'
+HANDLER t1 READ FIRST;
+a b
+2 20
+connection con1;
+insert into t1 values (8,50);
+connection default;
+HANDLER t1 READ NEXT;
+a b
+2 20
+connection con1;
+delete from t1 where a=3;
+connection default;
+HANDLER t1 READ NEXT LIMIT 2;
+a b
+1 10
+4 40
+connection con1;
+delete from t1;
+connection default;
+HANDLER t1 READ NEXT LIMIT 2;
+ERROR HY000: Record has changed since last read in table 't1'
+HANDLER t1 CLOSE;
+DROP TABLE t1;
+disconnect con1;
+create table t1 (f1 integer not null, key (f1)) engine=Memory;
+insert into t1 values (1);
+HANDLER t1 OPEN;
+HANDLER t1 READ f1 NEXT;
+ERROR HY000: Storage engine MEMORY of the table `test`.`t1` doesn't have this option
+HANDLER t1 READ f1 NEXT;
+ERROR HY000: Storage engine MEMORY of the table `test`.`t1` doesn't have this option
+HANDLER t1 READ f1 NEXT;
+ERROR HY000: Storage engine MEMORY of the table `test`.`t1` doesn't have this option
+HANDLER t1 CLOSE;
+DROP TABLE t1;
+End of 5.3 tests
+#
+# MDEV-15813 ASAN use-after-poison in hp_hashnr upon
+# HANDLER READ on a versioned HEAP table
+#
+CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL, CONSTRAINT PRIMARY KEY (a, b), UNIQUE ba(b, a) USING HASH) ENGINE=HEAP;
+INSERT INTO t1 VALUES (1, 10), (2, 20), (3,30), (4,40);
+HANDLER t1 OPEN AS m;
+HANDLER m READ `PRIMARY`= (3,30);
+a b
+3 30
+HANDLER m READ `PRIMARY`> (3,30);
+ERROR HY000: HASH index `PRIMARY` does not support this operation
+HANDLER m READ `ba`= (30,3);
+a b
+3 30
+HANDLER m READ `ba`= (30);
+ERROR HY000: HASH index `ba` does not support this operation
+HANDLER m CLOSE;
+DROP TABLE t1;
diff --git a/mysql-test/suite/handler/heap.test b/mysql-test/suite/handler/heap.test
new file mode 100644
index 00000000..d60f92da
--- /dev/null
+++ b/mysql-test/suite/handler/heap.test
@@ -0,0 +1,105 @@
+# test of HANDLER with HEAP tables
+#
+
+let $engine_type= MEMORY;
+
+--source init.inc
+--source handler.inc
+
+#
+# Test what happens if table is changed (Unique test for HEAP)
+#
+
+connect (con1,localhost,root,,);
+connection default;
+
+CREATE TABLE t1(a INT, b INT, KEY(a), KEY b using btree (b), KEY ab using btree(a, b)) engine=memory;
+
+INSERT INTO t1 VALUES (2, 20), (2,20), (1, 10), (4, 40), (3, 30), (5,50), (6,50);
+
+HANDLER t1 OPEN;
+HANDLER t1 READ a=(2) limit 3;
+HANDLER t1 READ a PREV;
+HANDLER t1 READ a PREV;
+HANDLER t1 READ a PREV;
+HANDLER t1 READ b>=(20) limit 3;
+HANDLER t1 READ b PREV;
+HANDLER t1 READ b PREV LIMIT 2;
+HANDLER t1 READ ab=(3,30) limit 3;
+HANDLER t1 READ ab>=(3,30) limit 3;
+
+# Test FIRST/LAST on hash and btree keys
+--error ER_ILLEGAL_HA
+HANDLER t1 READ a FIRST;
+--error ER_ILLEGAL_HA
+HANDLER t1 READ a LAST;
+HANDLER t1 READ b FIRST LIMIT 2;
+HANDLER t1 READ ab LAST LIMIT 2;
+
+# Table scan
+HANDLER t1 READ FIRST LIMIT 10;
+# Index scan
+HANDLER t1 READ b FIRST;
+insert into t1 values (7,50);
+--error ER_CHECKREAD
+HANDLER t1 READ b NEXT;
+
+HANDLER t1 READ b FIRST;
+connection con1;
+insert into t1 values (7,50);
+connection default;
+--error ER_CHECKREAD
+HANDLER t1 READ b NEXT;
+
+HANDLER t1 READ FIRST;
+connection con1;
+insert into t1 values (8,50);
+connection default;
+HANDLER t1 READ NEXT;
+connection con1;
+delete from t1 where a=3;
+connection default;
+HANDLER t1 READ NEXT LIMIT 2;
+connection con1;
+delete from t1;
+connection default;
+--error ER_CHECKREAD
+HANDLER t1 READ NEXT LIMIT 2;
+HANDLER t1 CLOSE;
+DROP TABLE t1;
+disconnect con1;
+
+#
+# LP#702786 Two handler read f1 next gives different errors
+#
+create table t1 (f1 integer not null, key (f1)) engine=Memory;
+insert into t1 values (1);
+HANDLER t1 OPEN;
+--error 1031
+HANDLER t1 READ f1 NEXT;
+--error 1031
+HANDLER t1 READ f1 NEXT;
+--error 1031
+HANDLER t1 READ f1 NEXT;
+HANDLER t1 CLOSE;
+DROP TABLE t1;
+
+--echo End of 5.3 tests
+
+--echo #
+--echo # MDEV-15813 ASAN use-after-poison in hp_hashnr upon
+--echo # HANDLER READ on a versioned HEAP table
+--echo #
+
+CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL, CONSTRAINT PRIMARY KEY (a, b), UNIQUE ba(b, a) USING HASH) ENGINE=HEAP;
+INSERT INTO t1 VALUES (1, 10), (2, 20), (3,30), (4,40);
+HANDLER t1 OPEN AS m;
+HANDLER m READ `PRIMARY`= (3,30);
+--error ER_KEY_DOESNT_SUPPORT
+HANDLER m READ `PRIMARY`> (3,30);
+HANDLER m READ `ba`= (30,3);
+--error ER_KEY_DOESNT_SUPPORT
+HANDLER m READ `ba`= (30);
+HANDLER m CLOSE;
+DROP TABLE t1;
+
diff --git a/mysql-test/suite/handler/init.inc b/mysql-test/suite/handler/init.inc
new file mode 100644
index 00000000..7418bbb1
--- /dev/null
+++ b/mysql-test/suite/handler/init.inc
@@ -0,0 +1,31 @@
+# Setup things for handler.inc
+#
+# Input variables
+# $engine_type -- storage engine to be tested
+# using btree -- set if you want a non standard key type
+#
+# This scripts sets up default values for:
+# $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
+# time available storage engine
+# have to be set before sourcing this script.
+#
+# Handler tests don't work with embedded server
+#
+-- source include/not_embedded.inc
+
+eval SET SESSION DEFAULT_STORAGE_ENGINE = $engine_type;
+let $other_handler_engine_type= MyISAM;
+
+--disable_warnings
+drop table if exists t1,t3,t4,t5;
+--enable_warnings
+
+# Create default test table
+
+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"),
+(20,"ggg"),(21,"hhh"),(22,"iii"),(23,"xxx"),(24,"xxx"),(25,"xxx");
diff --git a/mysql-test/suite/handler/innodb.result b/mysql-test/suite/handler/innodb.result
new file mode 100644
index 00000000..5d44642d
--- /dev/null
+++ b/mysql-test/suite/handler/innodb.result
@@ -0,0 +1,1790 @@
+SET SESSION DEFAULT_STORAGE_ENGINE = InnoDB;
+drop table if exists t1,t3,t4,t5;
+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"),
+(20,"ggg"),(21,"hhh"),(22,"iii"),(23,"xxx"),(24,"xxx"),(25,"xxx");
+handler t1 open as t2;
+handler t2 read b first;
+a b
+14 aaa
+handler t2 read b next;
+a b
+16 ccc
+handler t2 read b next;
+a b
+16 xxx
+handler t2 read b prev;
+a b
+16 ccc
+handler t2 read b last;
+a b
+25 xxx
+handler t2 read b prev;
+a b
+24 xxx
+handler t2 read b prev;
+a b
+23 xxx
+handler t2 read b first;
+a b
+14 aaa
+handler t2 read b prev;
+a b
+handler t2 read b last;
+a b
+25 xxx
+handler t2 read b prev;
+a b
+24 xxx
+handler t2 read b next;
+a b
+25 xxx
+handler t2 read b next;
+a b
+handler t2 read a=(15);
+a b
+handler t2 read a=(21);
+a b
+21 hhh
+handler t2 read a=(19,"fff");
+ERROR 42000: Too many key parts specified; max 1 parts allowed
+handler t2 read b=(19,"fff");
+a b
+19 fff
+handler t2 read b=(19,"yyy");
+a b
+19 yyy
+handler t2 read b=(19);
+a b
+19 fff
+handler t1 read a last;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler t2 read a=(11);
+a b
+handler t2 read a>=(11);
+a b
+14 aaa
+handler t2 read b=(18);
+a b
+18 eee
+handler t2 read b>=(18);
+a b
+18 eee
+handler t2 read b>(18);
+a b
+19 fff
+handler t2 read b<=(18);
+a b
+18 eee
+handler t2 read b<(18);
+a b
+17 ddd
+handler t2 read a=(15);
+a b
+handler t2 read a>=(15) limit 2;
+a b
+16 ccc
+16 xxx
+handler t2 read a>(15) limit 2;
+a b
+16 ccc
+16 xxx
+handler t2 read a<=(15);
+a b
+14 aaa
+handler t2 read a<(15);
+a b
+14 aaa
+handler t2 read a=(54);
+a b
+handler t2 read a>=(54);
+a b
+handler t2 read a>(54);
+a b
+handler t2 read a<=(54);
+a b
+25 xxx
+handler t2 read a<(54);
+a b
+25 xxx
+handler t2 read a=(1);
+a b
+handler t2 read a>=(1);
+a b
+14 aaa
+handler t2 read a>(1);
+a b
+14 aaa
+handler t2 read a<=(1);
+a b
+handler t2 read a<(1);
+a b
+handler t2 read b first limit 5;
+a b
+14 aaa
+16 ccc
+16 xxx
+17 ddd
+18 eee
+handler t2 read b next limit 3;
+a b
+19 fff
+19 yyy
+20 ggg
+handler t2 read b prev limit 10;
+a b
+19 yyy
+19 fff
+18 eee
+17 ddd
+16 xxx
+16 ccc
+14 aaa
+handler t2 read b>=(16) limit 4;
+a b
+16 ccc
+16 xxx
+17 ddd
+18 eee
+handler t2 read b>=(16) limit 2,2;
+a b
+17 ddd
+18 eee
+select * from t1 where a>=16 order by a,b limit 2,2;
+a b
+17 ddd
+18 eee
+handler t2 read a last limit 3;
+a b
+25 xxx
+24 xxx
+23 xxx
+handler t2 read b=(16) limit 1,3;
+a b
+16 xxx
+handler t2 read b=(19);
+a b
+19 fff
+handler t2 read b=(19) where b="yyy";
+a b
+19 yyy
+handler t2 read first;
+a b
+17 ddd
+handler t2 read next;
+a b
+18 eee
+handler t2 read next;
+a b
+19 fff
+handler t2 close;
+handler t1 open;
+handler t1 read b next;
+a b
+14 aaa
+handler t1 read b next;
+a b
+16 ccc
+handler t1 close;
+handler t1 open;
+handler t1 read a prev;
+a b
+25 xxx
+handler t1 read a prev;
+a b
+24 xxx
+handler t1 close;
+handler t1 open as t2;
+handler t2 read first;
+a b
+17 ddd
+alter table t1 engine = InnoDB;
+handler t2 read first;
+ERROR 42S02: Unknown table 't2' in HANDLER
+handler t1 open;
+handler t1 read a=(20) limit 1,3;
+a b
+flush tables;
+handler t1 read a=(20) limit 1,3;
+a b
+handler t1 close;
+handler t1 open;
+handler t1 read a=(25);
+a b
+25 xxx
+handler t1 read a next;
+a b
+handler t1 read a next;
+a b
+handler t1 read a next;
+a b
+handler t1 read a prev;
+a b
+25 xxx
+handler t1 read a=(1000);
+a b
+handler t1 read a next;
+a b
+handler t1 read a prev;
+a b
+25 xxx
+handler t1 read a=(1000);
+a b
+handler t1 read a prev;
+a b
+25 xxx
+handler t1 read a=(14);
+a b
+14 aaa
+handler t1 read a prev;
+a b
+handler t1 read a prev;
+a b
+handler t1 read a next;
+a b
+14 aaa
+handler t1 read a=(1);
+a b
+handler t1 read a prev;
+a b
+handler t1 read a next;
+a b
+14 aaa
+handler t1 read a=(1);
+a b
+handler t1 read a next;
+a b
+14 aaa
+handler t1 close;
+handler t1 open;
+prepare stmt from 'handler t1 read a=(?) limit ?,?';
+set @a=20,@b=1,@c=100;
+execute stmt using @a,@b,@c;
+a b
+set @a=20,@b=2,@c=1;
+execute stmt using @a,@b,@c;
+a b
+set @a=20,@b=0,@c=2;
+execute stmt using @a,@b,@c;
+a b
+20 ggg
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read a next limit ?';
+handler t1 read a>=(21);
+a b
+21 hhh
+set @a=3;
+execute stmt using @a;
+a b
+22 iii
+23 xxx
+24 xxx
+execute stmt using @a;
+a b
+25 xxx
+execute stmt using @a;
+a b
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read b prev limit ?';
+execute stmt using @a;
+a b
+25 xxx
+24 xxx
+23 xxx
+execute stmt using @a;
+a b
+22 iii
+21 hhh
+20 ggg
+execute stmt using @a;
+a b
+19 yyy
+19 fff
+18 eee
+execute stmt using @a;
+a b
+17 ddd
+16 xxx
+16 ccc
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read b=(?,?)';
+set @a=14, @b='aaa';
+execute stmt using @a,@b;
+a b
+14 aaa
+set @a=14, @b='not found';
+execute stmt using @a,@b;
+a b
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read b=(1+?) limit 10';
+set @a=15;
+execute stmt using @a;
+a b
+16 ccc
+16 xxx
+execute stmt using @a;
+a b
+16 ccc
+16 xxx
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read b>=(?) where a < ? limit 5';
+set @a=17, @b=24;
+execute stmt using @a,@b;
+a b
+17 ddd
+18 eee
+19 fff
+19 yyy
+20 ggg
+execute stmt using @a,@b;
+a b
+17 ddd
+18 eee
+19 fff
+19 yyy
+20 ggg
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read a=(?)';
+set @a=17;
+execute stmt using @a;
+a b
+17 ddd
+alter table t1 add c int;
+execute stmt using @a;
+ERROR 42S02: Unknown table 't1' in HANDLER
+deallocate prepare stmt;
+handler t1 close;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler t1 open;
+prepare stmt from 'handler t1 read a=(?)';
+flush tables;
+set @a=17;
+execute stmt using @a;
+a b c
+17 ddd NULL
+deallocate prepare stmt;
+handler t1 close;
+handler t1 open as t2;
+drop table t1;
+create table t1 (a int not null);
+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;
+handler t2 read first;
+ERROR 42S02: Unknown table 't2' in HANDLER
+drop table t1;
+create table t1 (a int);
+insert into t1 values (1),(2),(3),(4),(5),(6);
+delete from t1 limit 2;
+handler t1 open;
+handler t1 read first;
+a
+3
+handler t1 read first limit 1,1;
+a
+4
+handler t1 read first limit 2,2;
+a
+5
+6
+delete from t1 limit 3;
+handler t1 read first;
+a
+6
+drop table t1;
+create table t1(a int, index using btree (a));
+insert into t1 values (1), (2), (3);
+handler t1 open;
+handler t1 read a=(W);
+ERROR 42S22: Unknown column 'W' in 'field list'
+handler t1 read a=(a);
+ERROR HY000: Incorrect arguments to HANDLER ... READ
+drop table t1;
+create table t1 (a char(5));
+insert into t1 values ("Ok");
+handler t1 open as t;
+handler t read first;
+a
+Ok
+use mysql;
+handler t read first;
+a
+Ok
+handler t close;
+handler test.t1 open as t;
+handler t read first;
+a
+Ok
+handler t close;
+use test;
+drop table t1;
+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;
+a b
+1 2
+handler t1 read a=(1) where b=3;
+a b
+handler t1 read a=(1) where b=1;
+a b
+handler t1 close;
+drop table t1;
+create table t1 (c1 char(20));
+insert into t1 values ("t1");
+handler t1 open as h1;
+handler h1 read first limit 9;
+c1
+t1
+create table t2 (c1 char(20));
+insert into t2 values ("t2");
+handler t2 open as h2;
+handler h2 read first limit 9;
+c1
+t2
+create table t3 (c1 char(20));
+insert into t3 values ("t3");
+handler t3 open as h3;
+handler h3 read first limit 9;
+c1
+t3
+create table t4 (c1 char(20));
+insert into t4 values ("t4");
+handler t4 open as h4;
+handler h4 read first limit 9;
+c1
+t4
+create table t5 (c1 char(20));
+insert into t5 values ("t5");
+handler t5 open as h5;
+handler h5 read first limit 9;
+c1
+t5
+alter table t1 engine=MyISAM;
+handler h1 read first limit 9;
+ERROR 42S02: Unknown table 'h1' in HANDLER
+handler h2 read first limit 9;
+c1
+t2
+handler h3 read first limit 9;
+c1
+t3
+handler h4 read first limit 9;
+c1
+t4
+handler h5 read first limit 9;
+c1
+t5
+alter table t5 engine=MyISAM;
+handler h1 read first limit 9;
+ERROR 42S02: Unknown table 'h1' in HANDLER
+handler h2 read first limit 9;
+c1
+t2
+handler h3 read first limit 9;
+c1
+t3
+handler h4 read first limit 9;
+c1
+t4
+handler h5 read first limit 9;
+ERROR 42S02: Unknown table 'h5' in HANDLER
+alter table t3 engine=MyISAM;
+handler h1 read first limit 9;
+ERROR 42S02: Unknown table 'h1' in HANDLER
+handler h2 read first limit 9;
+c1
+t2
+handler h3 read first limit 9;
+ERROR 42S02: Unknown table 'h3' in HANDLER
+handler h4 read first limit 9;
+c1
+t4
+handler h5 read first limit 9;
+ERROR 42S02: Unknown table 'h5' in HANDLER
+handler h2 close;
+handler h4 close;
+handler t1 open as h1_1;
+handler t1 open as h1_2;
+handler t1 open as h1_3;
+handler h1_1 read first limit 9;
+c1
+t1
+handler h1_2 read first limit 9;
+c1
+t1
+handler h1_3 read first limit 9;
+c1
+t1
+alter table t1 engine=InnoDB;
+handler h1_1 read first limit 9;
+ERROR 42S02: Unknown table 'h1_1' in HANDLER
+handler h1_2 read first limit 9;
+ERROR 42S02: Unknown table 'h1_2' in HANDLER
+handler h1_3 read first limit 9;
+ERROR 42S02: Unknown table 'h1_3' in HANDLER
+drop table t1;
+drop table t2;
+drop table t3;
+drop table t4;
+drop table t5;
+create table t1 (c1 int);
+insert into t1 values (1);
+handler t1 open;
+handler t1 read first;
+c1
+1
+connect con2,localhost,root,,;
+connection con2;
+send the below to another connection, do not wait for the result
+optimize table t1;
+connection default;
+handler t1 read next;
+c1
+handler t1 close;
+connection con2;
+Table Op Msg_type Msg_text
+test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
+test.t1 optimize status OK
+connection default;
+drop table t1;
+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);
+no1 no2
+HANDLER t1 READ `primary` PREV;
+no1 no2
+1 275
+HANDLER t1 READ `primary` = (1, 1000);
+no1 no2
+HANDLER t1 READ `primary` NEXT;
+no1 no2
+2 6
+DROP TABLE t1;
+create table t1 (c1 int);
+insert into t1 values (14397);
+flush tables with read lock;
+drop table t1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+connection con2;
+drop table t1;
+connection default;
+select * from t1;
+c1
+14397
+unlock tables;
+connection con2;
+read the result from the other connection
+connection default;
+select * from t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+drop table if exists t1;
+Warnings:
+Note 1051 Unknown table 'test.t1'
+create table t1 (a int not null) ENGINE=csv;
+connection con2;
+handler t1 open;
+ERROR HY000: Storage engine CSV of the table `test`.`t1` doesn't have this option
+connection default;
+drop table t1;
+disconnect con2;
+create table t1 (a int);
+handler t1 open as t1_alias;
+handler t1_alias read a next;
+ERROR 42000: Key 'a' doesn't exist in table 't1_alias'
+handler t1_alias READ a next where inexistent > 0;
+ERROR 42S22: Unknown column 'inexistent' in 'field list'
+handler t1_alias read a next;
+ERROR 42000: Key 'a' doesn't exist in table 't1_alias'
+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 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;
+a b
+0 a
+1 b
+2 c
+3 d
+4 e
+5 f
+6 g
+7 h
+8 i
+9 j
+9 k
+handler t1 open as a1;
+handler a1 read a=(1);
+a b
+1 b
+handler a1 read a next;
+a b
+2 c
+handler a1 read a next;
+a b
+3 d
+select a,b from t1;
+a b
+0 a
+1 b
+2 c
+3 d
+4 e
+5 f
+6 g
+7 h
+8 i
+9 j
+9 k
+handler a1 read a prev;
+a b
+2 c
+handler a1 read a prev;
+a b
+1 b
+handler a1 read a=(6) where b="g";
+a b
+6 g
+handler a1 close;
+select a,b from t1;
+a b
+0 a
+1 b
+2 c
+3 d
+4 e
+5 f
+6 g
+7 h
+8 i
+9 j
+9 k
+handler t1 open as a2;
+handler a2 read b=(9);
+a b
+9 j
+handler a2 read b next;
+a b
+9 k
+handler a2 read b prev limit 2;
+a b
+9 j
+8 i
+handler a2 read b last;
+a b
+9 k
+handler a2 read b prev;
+a b
+9 j
+handler a2 close;
+drop table t1;
+create table t1 (a int);
+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;
+a
+drop table t1, t2;
+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 using btree (a));
+create table t2 like t1;
+handler t1 open as a1;
+handler t2 open as a2;
+handler a1 read a first;
+a
+handler a2 read a first;
+a
+alter table t1 add b int;
+handler a1 close;
+ERROR 42S02: Unknown table 'a1' in HANDLER
+handler a2 close;
+drop table t1, t2;
+create table t1 (a int, key using btree (a));
+handler t1 open as a1;
+handler a1 read a first;
+a
+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 using btree (a));
+create table t2 like t1;
+handler t1 open as a1;
+handler t2 open as a2;
+handler a1 read a first;
+a
+handler a2 read a first;
+a
+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 a1 close;
+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 Engine-independent statistics collected
+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 Engine-independent statistics collected
+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;
+connect con1, localhost, root,,;
+connect con2, localhost, root,,;
+connect con3, localhost, root,,;
+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.
+#
+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;
+# We back-off on hitting deadlock condition.
+handler t0 open;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+select * from t0;
+a
+1
+2
+3
+4
+5
+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;
+drop table t1;
+#
+# 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));
+handler t1 open;
+connection con1;
+select get_lock('lock1', 10);
+get_lock('lock1', 10)
+1
+connection default;
+select get_lock('lock1', 10);
+connection con2;
+# Waiting for 'select get_lock('lock1', 10)' to get blocked...
+connection con1;
+drop table t1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+select release_lock('lock1');
+release_lock('lock1')
+1
+connection default;
+get_lock('lock1', 10)
+1
+select release_lock('lock1');
+release_lock('lock1')
+1
+# 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'.
+select * from t1;
+a
+1
+2
+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;
+disconnect con1;
+connection con2;
+disconnect con2;
+connection con3;
+disconnect con3;
+connection default;
+#
+# 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;
+a b
+1 NULL
+2 NULL
+3 NULL
+4 NULL
+5 NULL
+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
+2 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.
+#
+connect con1,localhost,root,,;
+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 default;
+handler t1 read a prev;
+a b
+6 6
+handler t1 close;
+# Cleanup.
+drop table t1;
+connection con1;
+disconnect 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;
+connect con51355, localhost, root;
+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;
+disconnect 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|
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
+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 MariaDB 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 MariaDB 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));
+HANDLER t1 OPEN;
+HANDLER t1 READ a FIRST;
+a
+INSERT INTO t1 VALUES(1);
+HANDLER t1 READ a NEXT;
+a
+HANDLER t1 CLOSE;
+DROP TABLE t1;
+#
+# Testing savepoints with handlers that supports it
+#
+connect con1, localhost, root,,;
+connect con2, localhost, root,,;
+connect con3, localhost, root,,;
+connection default;
+#
+# ROLLBACK TO SAVEPOINT releases transactional locks,
+# but has no effect on open HANDLERs
+#
+create table t1 (a int, key a (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+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;
+#
+# Cleanup for savepoint.inc
+#
+connection con1;
+disconnect con1;
+connection con2;
+disconnect con2;
+connection con3;
+disconnect con3;
+connection default;
+CREATE TABLE t1 (f1 integer, f2 integer, primary key (f1), key (f2)) engine=innodb;
+INSERT INTO t1 VALUES (1,1),(2,2),(3,3);
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST WHERE f2 <= 1;
+f1 f2
+1 1
+HANDLER t1 READ `PRIMARY` PREV;
+f1 f2
+3 3
+DROP TABLE t1;
+#
+# 10.2 Test
+#
+# MDEV-20207: Assertion `! is_set()' failed in
+# Diagnostics_area::set_eof_status upon HANDLER READ
+#
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note 1051 Unknown table 'test.t1'
+CREATE TABLE t1 (a POINT, KEY(a));
+HANDLER t1 OPEN h;
+HANDLER h READ a = (0);
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
+HANDLER h CLOSE;
+DROP TABLE t1;
+# End of 10.2 Test
diff --git a/mysql-test/suite/handler/innodb.test b/mysql-test/suite/handler/innodb.test
new file mode 100644
index 00000000..8c984474
--- /dev/null
+++ b/mysql-test/suite/handler/innodb.test
@@ -0,0 +1,49 @@
+# t/handler_innodb.test
+#
+# test of HANDLER ...
+#
+# Last update:
+# 2006-07-31 ML test refactored (MySQL 5.1)
+# code of t/handler.test and t/innodb_handler.test united
+# main testing code put into handler.inc
+# rename t/innodb_handler.test to t/handler_innodb.test
+#
+
+--source include/have_innodb.inc
+
+let $engine_type= InnoDB;
+
+--source init.inc
+--source handler.inc
+--source savepoint.inc
+
+#
+# LP#697610 ha_index_prev(uchar*): Assertion `inited==INDEX'
+#
+
+CREATE TABLE t1 (f1 integer, f2 integer, primary key (f1), key (f2)) engine=innodb;
+INSERT INTO t1 VALUES (1,1),(2,2),(3,3);
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST WHERE f2 <= 1;
+HANDLER t1 READ `PRIMARY` PREV;
+DROP TABLE t1;
+
+--echo #
+--echo # 10.2 Test
+--echo #
+--echo # MDEV-20207: Assertion `! is_set()' failed in
+--echo # Diagnostics_area::set_eof_status upon HANDLER READ
+--echo #
+
+DROP TABLE IF EXISTS t1;
+
+CREATE TABLE t1 (a POINT, KEY(a));
+HANDLER t1 OPEN h;
+
+--error ER_CANT_CREATE_GEOMETRY_OBJECT
+HANDLER h READ a = (0);
+
+HANDLER h CLOSE;
+DROP TABLE t1;
+
+--echo # End of 10.2 Test
diff --git a/mysql-test/suite/handler/interface.result b/mysql-test/suite/handler/interface.result
new file mode 100644
index 00000000..37584003
--- /dev/null
+++ b/mysql-test/suite/handler/interface.result
@@ -0,0 +1,354 @@
+drop table if exists t1,t3,t4,t5;
+drop database if exists test_test;
+SET SESSION DEFAULT_STORAGE_ENGINE = MyISAM;
+drop table if exists t1,t3,t4,t5;
+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"),
+(20,"ggg"),(21,"hhh"),(22,"iii"),(23,"xxx"),(24,"xxx"),(25,"xxx");
+handler t1 open;
+handler t1 read a=(SELECT 1);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT 1)' at line 1
+handler t1 read a=(1) FIRST;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'FIRST' at line 1
+handler t1 read a=(1) NEXT;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'NEXT' at line 1
+handler t1 read last;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1
+handler t1 close;
+drop table t1;
+CREATE TABLE t1(a INT, PRIMARY KEY(a));
+insert into t1 values(1),(2);
+handler t1 open;
+handler t1 read primary=(1);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'primary=(1)' at line 1
+handler t1 read `primary`=(1);
+a
+1
+handler t1 close;
+drop table t1;
+create database test_test;
+use test_test;
+create table t1(table_id char(20), primary key (table_id));
+insert into t1 values ('test_test.t1');
+insert into t1 values ('');
+handler t1 open;
+handler t1 read first limit 9;
+table_id
+test_test.t1
+
+create table t2(table_id char(20), primary key (table_id));
+insert into t2 values ('test_test.t2');
+insert into t2 values ('');
+handler t2 open;
+handler t2 read first limit 9;
+table_id
+test_test.t2
+
+use test;
+create table t1(table_id char(20), primary key (table_id));
+insert into t1 values ('test.t1');
+insert into t1 values ('');
+handler t1 open;
+ERROR 42000: Not unique table/alias: 't1'
+use test;
+handler test.t1 read first limit 9;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'read first limit 9' at line 1
+handler test_test.t1 read first limit 9;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'read first limit 9' at line 1
+handler t1 read first limit 9;
+table_id
+test_test.t1
+
+handler test_test.t2 read first limit 9;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'read first limit 9' at line 1
+handler t2 read first limit 9;
+table_id
+test_test.t2
+
+handler test_test.t1 close;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'close' at line 1
+handler t1 close;
+drop table test_test.t1;
+handler test_test.t2 close;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'close' at line 1
+handler t2 close;
+drop table test_test.t2;
+drop database test_test;
+use test;
+handler test.t1 close;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'close' at line 1
+handler t1 close;
+ERROR 42S02: Unknown table 't1' in HANDLER
+drop table test.t1;
+create database test_test;
+use test_test;
+create table t1 (c1 char(20));
+insert into t1 values ('test_test.t1');
+create table t3 (c1 char(20));
+insert into t3 values ('test_test.t3');
+handler t1 open;
+handler t1 read first limit 9;
+c1
+test_test.t1
+handler t1 open h1;
+handler h1 read first limit 9;
+c1
+test_test.t1
+use test;
+create table t1 (c1 char(20));
+create table t2 (c1 char(20));
+create table t3 (c1 char(20));
+insert into t1 values ('t1');
+insert into t2 values ('t2');
+insert into t3 values ('t3');
+handler t1 open;
+ERROR 42000: Not unique table/alias: 't1'
+handler t2 open t1;
+ERROR 42000: Not unique table/alias: 't1'
+handler t3 open t1;
+ERROR 42000: Not unique table/alias: 't1'
+handler t1 read first limit 9;
+c1
+test_test.t1
+handler test.t1 close;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'close' at line 1
+handler test.t1 open h1;
+ERROR 42000: Not unique table/alias: 'h1'
+handler test_test.t1 open h1;
+ERROR 42000: Not unique table/alias: 'h1'
+handler test_test.t3 open h3;
+handler test.t1 open h2;
+handler t1 read first limit 9;
+c1
+test_test.t1
+handler h1 read first limit 9;
+c1
+test_test.t1
+handler h2 read first limit 9;
+c1
+t1
+handler h3 read first limit 9;
+c1
+test_test.t3
+handler h2 read first limit 9;
+c1
+t1
+handler test.h1 close;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'close' at line 1
+handler t1 close;
+handler h1 close;
+handler h2 close;
+handler t1 read first limit 9;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler h1 read first limit 9;
+ERROR 42S02: Unknown table 'h1' in HANDLER
+handler h2 read first limit 9;
+ERROR 42S02: Unknown table 'h2' in HANDLER
+handler h3 read first limit 9;
+c1
+test_test.t3
+handler h3 read first limit 9;
+c1
+test_test.t3
+use test_test;
+handler h3 read first limit 9;
+c1
+test_test.t3
+handler test.h3 read first limit 9;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'read first limit 9' at line 1
+handler h3 close;
+use test;
+drop table t3;
+drop table t2;
+drop table t1;
+drop database test_test;
+create table t1 (c1 int);
+create table t2 (c1 int);
+insert into t1 values (1);
+insert into t2 values (2);
+handler t1 open;
+handler t1 read first;
+c1
+1
+connect flush,localhost,root,,;
+connection flush;
+flush tables;
+flush table t1;
+connect waiter,localhost,root,,;
+connection waiter;
+connection default;
+handler t2 open;
+handler t2 read first;
+c1
+2
+handler t1 read next;
+c1
+1
+handler t1 close;
+handler t2 close;
+connection flush;
+connection default;
+drop table t1,t2;
+disconnect flush;
+drop table if exists t1, t0;
+create table t1 (c1 int);
+handler t1 open;
+handler t1 read first;
+c1
+connect flush,localhost,root,,;
+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
+connection default;
+drop table t0;
+connection flush;
+disconnect flush;
+connection waiter;
+disconnect waiter;
+connection default;
+create table t1 (a int);
+handler t1 open as t1_alias;
+drop table t1;
+create table t1 (a int);
+handler t1 open as t1_alias;
+flush tables;
+drop table t1;
+create table t1 (a int);
+handler t1 open as t1_alias;
+handler t1_alias close;
+drop table t1;
+create table t1 (a int);
+handler t1 open as t1_alias;
+handler t1_alias read first;
+a
+drop table t1;
+handler t1_alias read next;
+ERROR 42S02: Unknown table 't1_alias' in HANDLER
+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;
+handler t1 read a first;
+a b
+0 a
+handler t1 read a next;
+a b
+1 b
+flush tables;
+handler t1 read a next;
+a b
+2 c
+flush tables t1;
+handler t1 read a next;
+a b
+0 a
+flush tables with read lock;
+handler t1 read a next;
+a b
+0 a
+unlock tables;
+drop table t1;
+handler t1 read a next;
+ERROR 42S02: Unknown table 't1' in HANDLER
+connect con1,localhost,root,,;
+connect con2,localhost,root,,;
+# Now test case which was reported originally but which no longer
+# 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;
+alter table t1 engine=csv;
+connection con2;
+connection default;
+# 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;
+connection con1;
+drop table t1;
+disconnect con1;
+connection con2;
+disconnect con2;
+connection default;
+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
+create view v as select 1;
+create temporary table v as select 2;
+handler v open;
+prepare stmt from 'create table if not exists v as select 3';
+execute stmt;
+Warnings:
+Note 1050 Table 'v' already exists
+handler v read next;
+ERROR 42S02: Unknown table 'v' in HANDLER
+drop view v;
+#
+# 10.2 Test
+#
+# MDEV-20207: Assertion `! is_set()' failed in
+# Diagnostics_area::set_eof_status upon HANDLER READ
+#
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note 1051 Unknown table 'test.t1'
+CREATE TABLE t1 (a POINT, KEY(a));
+HANDLER t1 OPEN h;
+HANDLER h READ a = (0);
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
+HANDLER h CLOSE;
+DROP TABLE t1;
+# End of 10.2 Test
+#
+# MDEV-15813 ASAN use-after-poison in hp_hashnr upon
+# HANDLER READ on a versioned HEAP table
+#
+CREATE TABLE t1 (g GEOMETRY NOT NULL, SPATIAL gi(g));
+INSERT INTO t1 VALUES (POINT(0,0));
+HANDLER t1 OPEN AS h;
+HANDLER h READ `gi`= (10);
+ERROR HY000: SPATIAL index `gi` does not support this operation
+HANDLER h READ `gi`> (10);
+ERROR HY000: SPATIAL index `gi` does not support this operation
+HANDLER h CLOSE;
+DROP TABLE t1;
+CREATE TABLE t1 (w VARCHAR(100), FULLTEXT fk(w));
+INSERT INTO t1 VALUES ('one two three');
+HANDLER t1 OPEN AS h;
+HANDLER h READ `fk`= (10);
+ERROR HY000: FULLTEXT index `fk` does not support this operation
+HANDLER h READ `fk`> (10);
+ERROR HY000: FULLTEXT index `fk` does not support this operation
+HANDLER h CLOSE;
+DROP TABLE t1;
diff --git a/mysql-test/suite/handler/interface.test b/mysql-test/suite/handler/interface.test
new file mode 100644
index 00000000..a4ed640d
--- /dev/null
+++ b/mysql-test/suite/handler/interface.test
@@ -0,0 +1,403 @@
+#
+# Tests of handler interface that are system independent
+#
+# Handler tests don't work yet with embedded server
+#
+-- source include/not_embedded.inc
+
+--disable_warnings
+drop table if exists t1,t3,t4,t5;
+drop database if exists test_test;
+--enable_warnings
+
+# Run tests with myisam (any engine should be ok)
+
+let $engine_type= MyISAM;
+
+--source init.inc
+
+#
+# Do some syntax checking
+#
+
+handler t1 open;
+--error ER_PARSE_ERROR
+handler t1 read a=(SELECT 1);
+--error ER_PARSE_ERROR
+handler t1 read a=(1) FIRST;
+--error ER_PARSE_ERROR
+handler t1 read a=(1) NEXT;
+--error ER_PARSE_ERROR
+handler t1 read last;
+handler t1 close;
+drop table t1;
+
+CREATE TABLE t1(a INT, PRIMARY KEY(a));
+insert into t1 values(1),(2);
+handler t1 open;
+--error ER_PARSE_ERROR
+handler t1 read primary=(1);
+handler t1 read `primary`=(1);
+handler t1 close;
+drop table t1;
+
+#
+# Check if two database names beginning the same are seen as different.
+#
+# This database begins like the usual 'test' database.
+#
+create database test_test;
+use test_test;
+eval create table t1(table_id char(20), primary key $key_type (table_id));
+insert into t1 values ('test_test.t1');
+insert into t1 values ('');
+handler t1 open;
+handler t1 read first limit 9;
+eval create table t2(table_id char(20), primary key $key_type (table_id));
+insert into t2 values ('test_test.t2');
+insert into t2 values ('');
+handler t2 open;
+handler t2 read first limit 9;
+#
+# This is the usual 'test' database.
+#
+use test;
+eval create table t1(table_id char(20), primary key $key_type (table_id));
+insert into t1 values ('test.t1');
+insert into t1 values ('');
+--error 1066
+handler t1 open;
+#
+# Check accessibility of all the tables.
+#
+use test;
+--error 1064
+handler test.t1 read first limit 9;
+--error 1064
+handler test_test.t1 read first limit 9;
+handler t1 read first limit 9;
+--error 1064
+handler test_test.t2 read first limit 9;
+handler t2 read first limit 9;
+
+#
+# Cleanup.
+#
+
+--error 1064
+handler test_test.t1 close;
+handler t1 close;
+drop table test_test.t1;
+--error 1064
+handler test_test.t2 close;
+handler t2 close;
+drop table test_test.t2;
+drop database test_test;
+
+#
+use test;
+--error 1064
+handler test.t1 close;
+--error 1109
+handler t1 close;
+drop table test.t1;
+
+#
+# BUG#4335 one name can be handler open'ed many times
+#
+
+create database test_test;
+use test_test;
+create table t1 (c1 char(20));
+insert into t1 values ('test_test.t1');
+create table t3 (c1 char(20));
+insert into t3 values ('test_test.t3');
+handler t1 open;
+handler t1 read first limit 9;
+handler t1 open h1;
+handler h1 read first limit 9;
+use test;
+create table t1 (c1 char(20));
+create table t2 (c1 char(20));
+create table t3 (c1 char(20));
+insert into t1 values ('t1');
+insert into t2 values ('t2');
+insert into t3 values ('t3');
+--error 1066
+handler t1 open;
+--error 1066
+handler t2 open t1;
+--error 1066
+handler t3 open t1;
+handler t1 read first limit 9;
+--error 1064
+handler test.t1 close;
+--error 1066
+handler test.t1 open h1;
+--error 1066
+handler test_test.t1 open h1;
+handler test_test.t3 open h3;
+handler test.t1 open h2;
+handler t1 read first limit 9;
+handler h1 read first limit 9;
+handler h2 read first limit 9;
+handler h3 read first limit 9;
+handler h2 read first limit 9;
+--error 1064
+handler test.h1 close;
+handler t1 close;
+handler h1 close;
+handler h2 close;
+--error 1109
+handler t1 read first limit 9;
+--error 1109
+handler h1 read first limit 9;
+--error 1109
+handler h2 read first limit 9;
+handler h3 read first limit 9;
+handler h3 read first limit 9;
+use test_test;
+handler h3 read first limit 9;
+--error 1064
+handler test.h3 read first limit 9;
+handler h3 close;
+use test;
+drop table t3;
+drop table t2;
+drop table t1;
+drop database test_test;
+
+#
+# Bug#21587 FLUSH TABLES causes server crash when used with HANDLER statements
+#
+
+create table t1 (c1 int);
+create table t2 (c1 int);
+insert into t1 values (1);
+insert into t2 values (2);
+handler t1 open;
+handler t1 read first;
+connect (flush,localhost,root,,);
+connection flush;
+flush tables;
+send flush table t1;
+connect (waiter,localhost,root,,);
+connection waiter;
+let $wait_condition=
+ select count(*) = 1 from information_schema.processlist
+ where state = "Waiting for table metadata lock";
+--source include/wait_condition.inc
+connection default;
+handler t2 open;
+handler t2 read first;
+handler t1 read next;
+handler t1 close;
+handler t2 close;
+connection flush;
+reap;
+connection default;
+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);
+handler t1 open;
+handler t1 read first;
+connect (flush,localhost,root,,);
+connection flush;
+send rename table t1 to t0;
+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 #
+--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;
+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.
+#
+
+create table t1 (a int);
+handler t1 open as t1_alias;
+drop table t1;
+create table t1 (a int);
+handler t1 open as t1_alias;
+flush tables;
+drop table t1;
+create table t1 (a int);
+handler t1 open as t1_alias;
+handler t1_alias close;
+drop table t1;
+create table t1 (a int);
+handler t1 open as t1_alias;
+handler t1_alias read first;
+drop table t1;
+--error ER_UNKNOWN_TABLE
+handler t1_alias read next;
+
+# Flush tables causes handlers reopen
+
+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;
+handler t1 read a first;
+handler t1 read a next;
+flush tables;
+handler t1 read a next;
+flush tables t1;
+handler t1 read a next;
+flush tables with read lock;
+handler t1 read a next;
+unlock tables;
+drop table t1;
+--error ER_UNKNOWN_TABLE
+handler t1 read a next;
+
+#
+# Bug#41110: crash with handler command when used concurrently with alter table
+# Bug#41112: crash in mysql_ha_close_table/get_lock_data with alter table
+#
+
+connect(con1,localhost,root,,);
+connect(con2,localhost,root,,);
+
+--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
+#
+--error ER_UNKNOWN_TABLE
+PREPARE h_r FROM 'HANDLER t1 READ `PRIMARY` LAST';
+
+#
+# MySQL Bug#16385711: HANDLER, CREATE TABLE IF NOT EXISTS, PROBLEM AFTER MYSQL_HA_FIND
+#
+create view v as select 1;
+create temporary table v as select 2;
+handler v open;
+prepare stmt from 'create table if not exists v as select 3';
+execute stmt;
+--error ER_UNKNOWN_TABLE
+handler v read next;
+drop view v;
+
+--echo #
+--echo # 10.2 Test
+--echo #
+--echo # MDEV-20207: Assertion `! is_set()' failed in
+--echo # Diagnostics_area::set_eof_status upon HANDLER READ
+--echo #
+
+DROP TABLE IF EXISTS t1;
+
+CREATE TABLE t1 (a POINT, KEY(a));
+HANDLER t1 OPEN h;
+
+--error ER_CANT_CREATE_GEOMETRY_OBJECT
+HANDLER h READ a = (0);
+
+HANDLER h CLOSE;
+DROP TABLE t1;
+
+--echo # End of 10.2 Test
+
+--echo #
+--echo # MDEV-15813 ASAN use-after-poison in hp_hashnr upon
+--echo # HANDLER READ on a versioned HEAP table
+--echo #
+
+CREATE TABLE t1 (g GEOMETRY NOT NULL, SPATIAL gi(g));
+INSERT INTO t1 VALUES (POINT(0,0));
+HANDLER t1 OPEN AS h;
+--error ER_KEY_DOESNT_SUPPORT
+HANDLER h READ `gi`= (10);
+--error ER_KEY_DOESNT_SUPPORT
+HANDLER h READ `gi`> (10);
+HANDLER h CLOSE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (w VARCHAR(100), FULLTEXT fk(w));
+INSERT INTO t1 VALUES ('one two three');
+HANDLER t1 OPEN AS h;
+--error ER_KEY_DOESNT_SUPPORT
+HANDLER h READ `fk`= (10);
+--error ER_KEY_DOESNT_SUPPORT
+HANDLER h READ `fk`> (10);
+HANDLER h CLOSE;
+DROP TABLE t1;
diff --git a/mysql-test/suite/handler/myisam.result b/mysql-test/suite/handler/myisam.result
new file mode 100644
index 00000000..cc817ccd
--- /dev/null
+++ b/mysql-test/suite/handler/myisam.result
@@ -0,0 +1,1792 @@
+SET SESSION DEFAULT_STORAGE_ENGINE = MyISAM;
+drop table if exists t1,t3,t4,t5;
+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"),
+(20,"ggg"),(21,"hhh"),(22,"iii"),(23,"xxx"),(24,"xxx"),(25,"xxx");
+handler t1 open as t2;
+handler t2 read b first;
+a b
+14 aaa
+handler t2 read b next;
+a b
+16 ccc
+handler t2 read b next;
+a b
+16 xxx
+handler t2 read b prev;
+a b
+16 ccc
+handler t2 read b last;
+a b
+25 xxx
+handler t2 read b prev;
+a b
+24 xxx
+handler t2 read b prev;
+a b
+23 xxx
+handler t2 read b first;
+a b
+14 aaa
+handler t2 read b prev;
+a b
+handler t2 read b last;
+a b
+25 xxx
+handler t2 read b prev;
+a b
+24 xxx
+handler t2 read b next;
+a b
+25 xxx
+handler t2 read b next;
+a b
+handler t2 read a=(15);
+a b
+handler t2 read a=(21);
+a b
+21 hhh
+handler t2 read a=(19,"fff");
+ERROR 42000: Too many key parts specified; max 1 parts allowed
+handler t2 read b=(19,"fff");
+a b
+19 fff
+handler t2 read b=(19,"yyy");
+a b
+19 yyy
+handler t2 read b=(19);
+a b
+19 fff
+handler t1 read a last;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler t2 read a=(11);
+a b
+handler t2 read a>=(11);
+a b
+14 aaa
+handler t2 read b=(18);
+a b
+18 eee
+handler t2 read b>=(18);
+a b
+18 eee
+handler t2 read b>(18);
+a b
+19 fff
+handler t2 read b<=(18);
+a b
+18 eee
+handler t2 read b<(18);
+a b
+17 ddd
+handler t2 read a=(15);
+a b
+handler t2 read a>=(15) limit 2;
+a b
+16 ccc
+16 xxx
+handler t2 read a>(15) limit 2;
+a b
+16 ccc
+16 xxx
+handler t2 read a<=(15);
+a b
+14 aaa
+handler t2 read a<(15);
+a b
+14 aaa
+handler t2 read a=(54);
+a b
+handler t2 read a>=(54);
+a b
+handler t2 read a>(54);
+a b
+handler t2 read a<=(54);
+a b
+25 xxx
+handler t2 read a<(54);
+a b
+25 xxx
+handler t2 read a=(1);
+a b
+handler t2 read a>=(1);
+a b
+14 aaa
+handler t2 read a>(1);
+a b
+14 aaa
+handler t2 read a<=(1);
+a b
+handler t2 read a<(1);
+a b
+handler t2 read b first limit 5;
+a b
+14 aaa
+16 ccc
+16 xxx
+17 ddd
+18 eee
+handler t2 read b next limit 3;
+a b
+19 fff
+19 yyy
+20 ggg
+handler t2 read b prev limit 10;
+a b
+19 yyy
+19 fff
+18 eee
+17 ddd
+16 xxx
+16 ccc
+14 aaa
+handler t2 read b>=(16) limit 4;
+a b
+16 ccc
+16 xxx
+17 ddd
+18 eee
+handler t2 read b>=(16) limit 2,2;
+a b
+17 ddd
+18 eee
+select * from t1 where a>=16 order by a,b limit 2,2;
+a b
+17 ddd
+18 eee
+handler t2 read a last limit 3;
+a b
+25 xxx
+24 xxx
+23 xxx
+handler t2 read b=(16) limit 1,3;
+a b
+16 xxx
+handler t2 read b=(19);
+a b
+19 fff
+handler t2 read b=(19) where b="yyy";
+a b
+19 yyy
+handler t2 read first;
+a b
+17 ddd
+handler t2 read next;
+a b
+18 eee
+handler t2 read next;
+a b
+19 fff
+handler t2 close;
+handler t1 open;
+handler t1 read b next;
+a b
+14 aaa
+handler t1 read b next;
+a b
+16 ccc
+handler t1 close;
+handler t1 open;
+handler t1 read a prev;
+a b
+25 xxx
+handler t1 read a prev;
+a b
+24 xxx
+handler t1 close;
+handler t1 open as t2;
+handler t2 read first;
+a b
+17 ddd
+alter table t1 engine = MyISAM;
+handler t2 read first;
+ERROR 42S02: Unknown table 't2' in HANDLER
+handler t1 open;
+handler t1 read a=(20) limit 1,3;
+a b
+flush tables;
+handler t1 read a=(20) limit 1,3;
+a b
+handler t1 close;
+handler t1 open;
+handler t1 read a=(25);
+a b
+25 xxx
+handler t1 read a next;
+a b
+handler t1 read a next;
+a b
+handler t1 read a next;
+a b
+handler t1 read a prev;
+a b
+25 xxx
+handler t1 read a=(1000);
+a b
+handler t1 read a next;
+a b
+handler t1 read a prev;
+a b
+25 xxx
+handler t1 read a=(1000);
+a b
+handler t1 read a prev;
+a b
+25 xxx
+handler t1 read a=(14);
+a b
+14 aaa
+handler t1 read a prev;
+a b
+handler t1 read a prev;
+a b
+handler t1 read a next;
+a b
+14 aaa
+handler t1 read a=(1);
+a b
+handler t1 read a prev;
+a b
+handler t1 read a next;
+a b
+14 aaa
+handler t1 read a=(1);
+a b
+handler t1 read a next;
+a b
+14 aaa
+handler t1 close;
+handler t1 open;
+prepare stmt from 'handler t1 read a=(?) limit ?,?';
+set @a=20,@b=1,@c=100;
+execute stmt using @a,@b,@c;
+a b
+set @a=20,@b=2,@c=1;
+execute stmt using @a,@b,@c;
+a b
+set @a=20,@b=0,@c=2;
+execute stmt using @a,@b,@c;
+a b
+20 ggg
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read a next limit ?';
+handler t1 read a>=(21);
+a b
+21 hhh
+set @a=3;
+execute stmt using @a;
+a b
+22 iii
+23 xxx
+24 xxx
+execute stmt using @a;
+a b
+25 xxx
+execute stmt using @a;
+a b
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read b prev limit ?';
+execute stmt using @a;
+a b
+25 xxx
+24 xxx
+23 xxx
+execute stmt using @a;
+a b
+22 iii
+21 hhh
+20 ggg
+execute stmt using @a;
+a b
+19 yyy
+19 fff
+18 eee
+execute stmt using @a;
+a b
+17 ddd
+16 xxx
+16 ccc
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read b=(?,?)';
+set @a=14, @b='aaa';
+execute stmt using @a,@b;
+a b
+14 aaa
+set @a=14, @b='not found';
+execute stmt using @a,@b;
+a b
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read b=(1+?) limit 10';
+set @a=15;
+execute stmt using @a;
+a b
+16 ccc
+16 xxx
+execute stmt using @a;
+a b
+16 ccc
+16 xxx
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read b>=(?) where a < ? limit 5';
+set @a=17, @b=24;
+execute stmt using @a,@b;
+a b
+17 ddd
+18 eee
+19 fff
+19 yyy
+20 ggg
+execute stmt using @a,@b;
+a b
+17 ddd
+18 eee
+19 fff
+19 yyy
+20 ggg
+deallocate prepare stmt;
+prepare stmt from 'handler t1 read a=(?)';
+set @a=17;
+execute stmt using @a;
+a b
+17 ddd
+alter table t1 add c int;
+execute stmt using @a;
+ERROR 42S02: Unknown table 't1' in HANDLER
+deallocate prepare stmt;
+handler t1 close;
+ERROR 42S02: Unknown table 't1' in HANDLER
+handler t1 open;
+prepare stmt from 'handler t1 read a=(?)';
+flush tables;
+set @a=17;
+execute stmt using @a;
+a b c
+17 ddd NULL
+deallocate prepare stmt;
+handler t1 close;
+handler t1 open as t2;
+drop table t1;
+create table t1 (a int not null);
+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;
+handler t2 read first;
+ERROR 42S02: Unknown table 't2' in HANDLER
+drop table t1;
+create table t1 (a int);
+insert into t1 values (1),(2),(3),(4),(5),(6);
+delete from t1 limit 2;
+handler t1 open;
+handler t1 read first;
+a
+3
+handler t1 read first limit 1,1;
+a
+4
+handler t1 read first limit 2,2;
+a
+5
+6
+delete from t1 limit 3;
+handler t1 read first;
+a
+6
+drop table t1;
+create table t1(a int, index using btree (a));
+insert into t1 values (1), (2), (3);
+handler t1 open;
+handler t1 read a=(W);
+ERROR 42S22: Unknown column 'W' in 'field list'
+handler t1 read a=(a);
+ERROR HY000: Incorrect arguments to HANDLER ... READ
+drop table t1;
+create table t1 (a char(5));
+insert into t1 values ("Ok");
+handler t1 open as t;
+handler t read first;
+a
+Ok
+use mysql;
+handler t read first;
+a
+Ok
+handler t close;
+handler test.t1 open as t;
+handler t read first;
+a
+Ok
+handler t close;
+use test;
+drop table t1;
+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;
+a b
+1 2
+handler t1 read a=(1) where b=3;
+a b
+handler t1 read a=(1) where b=1;
+a b
+handler t1 close;
+drop table t1;
+create table t1 (c1 char(20));
+insert into t1 values ("t1");
+handler t1 open as h1;
+handler h1 read first limit 9;
+c1
+t1
+create table t2 (c1 char(20));
+insert into t2 values ("t2");
+handler t2 open as h2;
+handler h2 read first limit 9;
+c1
+t2
+create table t3 (c1 char(20));
+insert into t3 values ("t3");
+handler t3 open as h3;
+handler h3 read first limit 9;
+c1
+t3
+create table t4 (c1 char(20));
+insert into t4 values ("t4");
+handler t4 open as h4;
+handler h4 read first limit 9;
+c1
+t4
+create table t5 (c1 char(20));
+insert into t5 values ("t5");
+handler t5 open as h5;
+handler h5 read first limit 9;
+c1
+t5
+alter table t1 engine=MyISAM;
+handler h1 read first limit 9;
+ERROR 42S02: Unknown table 'h1' in HANDLER
+handler h2 read first limit 9;
+c1
+t2
+handler h3 read first limit 9;
+c1
+t3
+handler h4 read first limit 9;
+c1
+t4
+handler h5 read first limit 9;
+c1
+t5
+alter table t5 engine=MyISAM;
+handler h1 read first limit 9;
+ERROR 42S02: Unknown table 'h1' in HANDLER
+handler h2 read first limit 9;
+c1
+t2
+handler h3 read first limit 9;
+c1
+t3
+handler h4 read first limit 9;
+c1
+t4
+handler h5 read first limit 9;
+ERROR 42S02: Unknown table 'h5' in HANDLER
+alter table t3 engine=MyISAM;
+handler h1 read first limit 9;
+ERROR 42S02: Unknown table 'h1' in HANDLER
+handler h2 read first limit 9;
+c1
+t2
+handler h3 read first limit 9;
+ERROR 42S02: Unknown table 'h3' in HANDLER
+handler h4 read first limit 9;
+c1
+t4
+handler h5 read first limit 9;
+ERROR 42S02: Unknown table 'h5' in HANDLER
+handler h2 close;
+handler h4 close;
+handler t1 open as h1_1;
+handler t1 open as h1_2;
+handler t1 open as h1_3;
+handler h1_1 read first limit 9;
+c1
+t1
+handler h1_2 read first limit 9;
+c1
+t1
+handler h1_3 read first limit 9;
+c1
+t1
+alter table t1 engine=MyISAM;
+handler h1_1 read first limit 9;
+ERROR 42S02: Unknown table 'h1_1' in HANDLER
+handler h1_2 read first limit 9;
+ERROR 42S02: Unknown table 'h1_2' in HANDLER
+handler h1_3 read first limit 9;
+ERROR 42S02: Unknown table 'h1_3' in HANDLER
+drop table t1;
+drop table t2;
+drop table t3;
+drop table t4;
+drop table t5;
+create table t1 (c1 int);
+insert into t1 values (1);
+handler t1 open;
+handler t1 read first;
+c1
+1
+connect con2,localhost,root,,;
+connection con2;
+send the below to another connection, do not wait for the result
+optimize table t1;
+connection default;
+handler t1 read next;
+c1
+handler t1 close;
+connection con2;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+connection default;
+drop table t1;
+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);
+no1 no2
+HANDLER t1 READ `primary` PREV;
+no1 no2
+1 275
+HANDLER t1 READ `primary` = (1, 1000);
+no1 no2
+HANDLER t1 READ `primary` NEXT;
+no1 no2
+2 6
+DROP TABLE t1;
+create table t1 (c1 int);
+insert into t1 values (14397);
+flush tables with read lock;
+drop table t1;
+ERROR HY000: Can't execute the query because you have a conflicting read lock
+connection con2;
+drop table t1;
+connection default;
+select * from t1;
+c1
+14397
+unlock tables;
+connection con2;
+read the result from the other connection
+connection default;
+select * from t1;
+ERROR 42S02: Table 'test.t1' doesn't exist
+drop table if exists t1;
+Warnings:
+Note 1051 Unknown table 'test.t1'
+create table t1 (a int not null) ENGINE=csv;
+connection con2;
+handler t1 open;
+ERROR HY000: Storage engine CSV of the table `test`.`t1` doesn't have this option
+connection default;
+drop table t1;
+disconnect con2;
+create table t1 (a int);
+handler t1 open as t1_alias;
+handler t1_alias read a next;
+ERROR 42000: Key 'a' doesn't exist in table 't1_alias'
+handler t1_alias READ a next where inexistent > 0;
+ERROR 42S22: Unknown column 'inexistent' in 'field list'
+handler t1_alias read a next;
+ERROR 42000: Key 'a' doesn't exist in table 't1_alias'
+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 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;
+a b
+0 a
+1 b
+2 c
+3 d
+4 e
+5 f
+6 g
+7 h
+8 i
+9 j
+9 k
+handler t1 open as a1;
+handler a1 read a=(1);
+a b
+1 b
+handler a1 read a next;
+a b
+2 c
+handler a1 read a next;
+a b
+3 d
+select a,b from t1;
+a b
+0 a
+1 b
+2 c
+3 d
+4 e
+5 f
+6 g
+7 h
+8 i
+9 j
+9 k
+handler a1 read a prev;
+a b
+2 c
+handler a1 read a prev;
+a b
+1 b
+handler a1 read a=(6) where b="g";
+a b
+6 g
+handler a1 close;
+select a,b from t1;
+a b
+0 a
+1 b
+2 c
+3 d
+4 e
+5 f
+6 g
+7 h
+8 i
+9 j
+9 k
+handler t1 open as a2;
+handler a2 read b=(9);
+a b
+9 j
+handler a2 read b next;
+a b
+9 k
+handler a2 read b prev limit 2;
+a b
+9 j
+8 i
+handler a2 read b last;
+a b
+9 k
+handler a2 read b prev;
+a b
+9 j
+handler a2 close;
+drop table t1;
+create table t1 (a int);
+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;
+a
+drop table t1, t2;
+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 using btree (a));
+create table t2 like t1;
+handler t1 open as a1;
+handler t2 open as a2;
+handler a1 read a first;
+a
+handler a2 read a first;
+a
+alter table t1 add b int;
+handler a1 close;
+ERROR 42S02: Unknown table 'a1' in HANDLER
+handler a2 close;
+drop table t1, t2;
+create table t1 (a int, key using btree (a));
+handler t1 open as a1;
+handler a1 read a first;
+a
+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 using btree (a));
+create table t2 like t1;
+handler t1 open as a1;
+handler t2 open as a2;
+handler a1 read a first;
+a
+handler a2 read a first;
+a
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status Table is already up to date
+handler a1 close;
+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 Engine-independent statistics collected
+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 Engine-independent statistics collected
+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;
+connect con1, localhost, root,,;
+connect con2, localhost, root,,;
+connect con3, localhost, root,,;
+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.
+#
+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;
+# We back-off on hitting deadlock condition.
+handler t0 open;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+select * from t0;
+a
+1
+2
+3
+4
+5
+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;
+drop table t1;
+#
+# 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));
+handler t1 open;
+connection con1;
+select get_lock('lock1', 10);
+get_lock('lock1', 10)
+1
+connection default;
+select get_lock('lock1', 10);
+connection con2;
+# Waiting for 'select get_lock('lock1', 10)' to get blocked...
+connection con1;
+drop table t1;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+select release_lock('lock1');
+release_lock('lock1')
+1
+connection default;
+get_lock('lock1', 10)
+1
+select release_lock('lock1');
+release_lock('lock1')
+1
+# 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'.
+select * from t1;
+a
+1
+2
+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;
+disconnect con1;
+connection con2;
+disconnect con2;
+connection con3;
+disconnect con3;
+connection default;
+#
+# 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;
+a b
+1 NULL
+2 NULL
+3 NULL
+4 NULL
+5 NULL
+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
+2 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.
+#
+connect con1,localhost,root,,;
+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 default;
+handler t1 read a prev;
+a b
+6 6
+handler t1 close;
+# Cleanup.
+drop table t1;
+connection con1;
+disconnect 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;
+connect con51355, localhost, root;
+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;
+disconnect 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|
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
+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 MariaDB 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 MariaDB 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));
+HANDLER t1 OPEN;
+HANDLER t1 READ a FIRST;
+a
+INSERT INTO t1 VALUES(1);
+HANDLER t1 READ a NEXT;
+a
+1
+HANDLER t1 CLOSE;
+DROP TABLE t1;
+#
+# BUG #46456: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash
+#
+CREATE TABLE t1 AS SELECT 1 AS f1;
+HANDLER t1 OPEN;
+TRUNCATE t1;
+HANDLER t1 READ FIRST;
+ERROR 42S02: Unknown table 't1' in HANDLER
+DROP TABLE t1;
+CREATE TEMPORARY TABLE t1 AS SELECT 1 AS f1;
+HANDLER t1 OPEN;
+TRUNCATE t1;
+HANDLER t1 READ FIRST;
+ERROR 42S02: Unknown table 't1' in HANDLER
+DROP TABLE t1;
+#
+# Bug #54007: assert in ha_myisam::index_next , HANDLER
+#
+CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a), KEY b(b), KEY ab(a, b));
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST;
+a b
+HANDLER t1 READ `PRIMARY` NEXT;
+a b
+HANDLER t1 READ ab NEXT;
+a b
+HANDLER t1 READ b NEXT;
+a b
+HANDLER t1 READ NEXT;
+a b
+HANDLER t1 CLOSE;
+INSERT INTO t1 VALUES (2, 20), (1, 10), (4, 40), (3, 30);
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST;
+a b
+2 20
+HANDLER t1 READ NEXT;
+a b
+1 10
+HANDLER t1 READ `PRIMARY` NEXT;
+a b
+1 10
+HANDLER t1 READ `PRIMARY` NEXT;
+a b
+2 20
+HANDLER t1 READ ab NEXT;
+a b
+1 10
+HANDLER t1 READ ab NEXT;
+a b
+2 20
+HANDLER t1 READ b NEXT;
+a b
+1 10
+HANDLER t1 READ b NEXT;
+a b
+2 20
+HANDLER t1 READ b NEXT;
+a b
+3 30
+HANDLER t1 READ b NEXT;
+a b
+4 40
+HANDLER t1 READ b NEXT;
+a b
+HANDLER t1 READ NEXT;
+a b
+2 20
+HANDLER t1 READ NEXT;
+a b
+1 10
+HANDLER t1 READ NEXT;
+a b
+4 40
+HANDLER t1 CLOSE;
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST;
+a b
+2 20
+HANDLER t1 READ `PRIMARY` PREV;
+a b
+4 40
+HANDLER t1 READ `PRIMARY` PREV;
+a b
+3 30
+HANDLER t1 READ b PREV;
+a b
+4 40
+HANDLER t1 READ b PREV;
+a b
+3 30
+HANDLER t1 CLOSE;
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST;
+a b
+2 20
+HANDLER t1 READ `PRIMARY` PREV LIMIT 3;
+a b
+4 40
+3 30
+2 20
+HANDLER t1 READ b NEXT LIMIT 5;
+a b
+1 10
+2 20
+3 30
+4 40
+HANDLER t1 CLOSE;
+DROP TABLE t1;
+#
+# Additional coverage for refactoring which is made as part
+# of fix for bug #27480 "Extend CREATE TEMPORARY TABLES privilege
+# to allow temp table operations".
+#
+# Check that DDL on temporary table properly closes HANDLER cursors
+# for this table belonging to the same connection.
+CREATE TEMPORARY TABLE t1 AS SELECT 1 AS f1;
+# -- CREATE TABLE
+HANDLER t1 OPEN;
+CREATE TEMPORARY TABLE IF NOT EXISTS t1 SELECT 1 AS f1;
+Warnings:
+Note 1050 Table 't1' already exists
+HANDLER t1 READ FIRST;
+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 FIRST;
+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 FIRST;
+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 FIRST;
+ERROR 42S02: Unknown table 't1' in HANDLER
+# -- CHECK TABLE
+HANDLER t1 OPEN;
+CHECK TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+HANDLER t1 READ FIRST;
+ERROR 42S02: Unknown table 't1' in HANDLER
+# -- ALTER TABLE
+HANDLER t1 OPEN;
+ALTER TABLE t1 ADD COLUMN b INT;
+HANDLER t1 READ FIRST;
+ERROR 42S02: Unknown table 't1' in HANDLER
+# -- CREATE INDEX
+HANDLER t1 OPEN;
+CREATE INDEX b ON t1 (b);
+HANDLER t1 READ FIRST;
+ERROR 42S02: Unknown table 't1' in HANDLER
+# -- DROP INDEX
+HANDLER t1 OPEN;
+DROP INDEX b ON t1;
+HANDLER t1 READ FIRST;
+ERROR 42S02: Unknown table 't1' in HANDLER
+# -- TRUNCATE TABLE
+HANDLER t1 OPEN;
+TRUNCATE TABLE t1;
+HANDLER t1 READ FIRST;
+ERROR 42S02: Unknown table 't1' in HANDLER
+# -- DROP TABLE
+HANDLER t1 OPEN;
+DROP TABLE t1;
+HANDLER t1 READ FIRST;
+ERROR 42S02: Unknown table 't1' in HANDLER
+CREATE TEMPORARY TABLE t1(a INT, b INT, INDEX i(a));
+set global keycache1.key_cache_block_size=2048;
+set global keycache1.key_buffer_size=1*1024*1024;
+set global keycache1.key_buffer_size=1024*1024;
+# -- CACHE INDEX
+HANDLER t1 OPEN;
+CACHE INDEX t1 IN keycache1;
+Table Op Msg_type Msg_text
+test.t1 assign_to_keycache status OK
+HANDLER t1 READ FIRST;
+ERROR 42S02: Unknown table 't1' in HANDLER
+# -- LOAD INDEX
+HANDLER t1 OPEN;
+LOAD INDEX INTO CACHE t1;
+Table Op Msg_type Msg_text
+test.t1 preload_keys status OK
+HANDLER t1 READ FIRST;
+ERROR 42S02: Unknown table 't1' in HANDLER
+End of 5.1 tests
+#
+# 10.2 Test
+#
+# MDEV-20207: Assertion `! is_set()' failed in
+# Diagnostics_area::set_eof_status upon HANDLER READ
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a POINT, KEY(a));
+HANDLER t1 OPEN h;
+HANDLER h READ a = (0);
+ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
+HANDLER h CLOSE;
+DROP TABLE t1;
+# End of 10.2 Test
diff --git a/mysql-test/suite/handler/myisam.test b/mysql-test/suite/handler/myisam.test
new file mode 100644
index 00000000..2fce8548
--- /dev/null
+++ b/mysql-test/suite/handler/myisam.test
@@ -0,0 +1,191 @@
+# t/handler_myisam.test
+#
+# test of HANDLER ...
+#
+# Last update:
+# 2006-07-31 ML test refactored (MySQL 5.1)
+# code of t/handler.test and t/innodb_handler.test united
+# main testing code put into handler.inc
+# rename t/handler.test to t/handler_myisam.test
+#
+
+let $engine_type= MyISAM;
+
+--source init.inc
+--source handler.inc
+
+--echo #
+--echo # BUG #46456: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash
+--echo #
+CREATE TABLE t1 AS SELECT 1 AS f1;
+HANDLER t1 OPEN;
+TRUNCATE t1;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+DROP TABLE t1;
+
+CREATE TEMPORARY TABLE t1 AS SELECT 1 AS f1;
+HANDLER t1 OPEN;
+TRUNCATE t1;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+DROP TABLE t1;
+
+--echo #
+--echo # Bug #54007: assert in ha_myisam::index_next , HANDLER
+--echo #
+CREATE TABLE t1(a INT, b INT, PRIMARY KEY(a), KEY b(b), KEY ab(a, b));
+
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST;
+HANDLER t1 READ `PRIMARY` NEXT;
+HANDLER t1 READ ab NEXT;
+HANDLER t1 READ b NEXT;
+HANDLER t1 READ NEXT;
+HANDLER t1 CLOSE;
+
+INSERT INTO t1 VALUES (2, 20), (1, 10), (4, 40), (3, 30);
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST;
+HANDLER t1 READ NEXT;
+HANDLER t1 READ `PRIMARY` NEXT;
+HANDLER t1 READ `PRIMARY` NEXT;
+HANDLER t1 READ ab NEXT;
+HANDLER t1 READ ab NEXT;
+HANDLER t1 READ b NEXT;
+HANDLER t1 READ b NEXT;
+HANDLER t1 READ b NEXT;
+HANDLER t1 READ b NEXT;
+HANDLER t1 READ b NEXT;
+HANDLER t1 READ NEXT;
+HANDLER t1 READ NEXT;
+HANDLER t1 READ NEXT;
+HANDLER t1 CLOSE;
+
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST;
+HANDLER t1 READ `PRIMARY` PREV;
+HANDLER t1 READ `PRIMARY` PREV;
+HANDLER t1 READ b PREV;
+HANDLER t1 READ b PREV;
+HANDLER t1 CLOSE;
+
+HANDLER t1 OPEN;
+HANDLER t1 READ FIRST;
+HANDLER t1 READ `PRIMARY` PREV LIMIT 3;
+HANDLER t1 READ b NEXT LIMIT 5;
+HANDLER t1 CLOSE;
+
+DROP TABLE t1;
+
+
+--echo #
+--echo # Additional coverage for refactoring which is made as part
+--echo # of fix for bug #27480 "Extend CREATE TEMPORARY TABLES privilege
+--echo # to allow temp table operations".
+--echo #
+--echo # Check that DDL on temporary table properly closes HANDLER cursors
+--echo # for this table belonging to the same connection.
+
+CREATE TEMPORARY TABLE t1 AS SELECT 1 AS f1;
+
+--echo # -- CREATE TABLE
+HANDLER t1 OPEN;
+CREATE TEMPORARY TABLE IF NOT EXISTS t1 SELECT 1 AS f1;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+
+--echo # -- REPAIR TABLE
+HANDLER t1 OPEN;
+REPAIR TABLE t1;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+
+--echo # -- ANALYZE TABLE
+HANDLER t1 OPEN;
+ANALYZE TABLE t1;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+
+--echo # -- OPTIMIZE TABLE
+HANDLER t1 OPEN;
+OPTIMIZE TABLE t1;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+
+--echo # -- CHECK TABLE
+HANDLER t1 OPEN;
+CHECK TABLE t1;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+
+--echo # -- ALTER TABLE
+HANDLER t1 OPEN;
+ALTER TABLE t1 ADD COLUMN b INT;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+
+--echo # -- CREATE INDEX
+HANDLER t1 OPEN;
+CREATE INDEX b ON t1 (b);
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+
+--echo # -- DROP INDEX
+HANDLER t1 OPEN;
+DROP INDEX b ON t1;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+
+--echo # -- TRUNCATE TABLE
+HANDLER t1 OPEN;
+TRUNCATE TABLE t1;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+
+--echo # -- DROP TABLE
+HANDLER t1 OPEN;
+DROP TABLE t1;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+
+CREATE TEMPORARY TABLE t1(a INT, b INT, INDEX i(a));
+
+set global keycache1.key_cache_block_size=2048;
+set global keycache1.key_buffer_size=1*1024*1024;
+set global keycache1.key_buffer_size=1024*1024;
+
+--echo # -- CACHE INDEX
+HANDLER t1 OPEN;
+CACHE INDEX t1 IN keycache1;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+
+--echo # -- LOAD INDEX
+HANDLER t1 OPEN;
+LOAD INDEX INTO CACHE t1;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+
+
+--echo End of 5.1 tests
+
+--echo #
+--echo # 10.2 Test
+--echo #
+--echo # MDEV-20207: Assertion `! is_set()' failed in
+--echo # Diagnostics_area::set_eof_status upon HANDLER READ
+--echo #
+
+DROP TABLE IF EXISTS t1;
+
+CREATE TABLE t1 (a POINT, KEY(a));
+HANDLER t1 OPEN h;
+
+--error ER_CANT_CREATE_GEOMETRY_OBJECT
+HANDLER h READ a = (0);
+
+HANDLER h CLOSE;
+DROP TABLE t1;
+
+--echo # End of 10.2 Test
diff --git a/mysql-test/suite/handler/ps.result b/mysql-test/suite/handler/ps.result
new file mode 100644
index 00000000..54685f91
--- /dev/null
+++ b/mysql-test/suite/handler/ps.result
@@ -0,0 +1,9 @@
+create table t1 (i int);
+handler test.t1 open handler_a;
+flush status;
+handler handler_a read first;
+i
+show status like 'Com_stmt_prepare%';
+Variable_name Value
+Com_stmt_prepare OK
+drop table t1;
diff --git a/mysql-test/suite/handler/ps.test b/mysql-test/suite/handler/ps.test
new file mode 100644
index 00000000..783d8624
--- /dev/null
+++ b/mysql-test/suite/handler/ps.test
@@ -0,0 +1,13 @@
+#
+# MDEV-15729 Server crashes in Field::make_field upon HANDLER READ executed with PS protocol
+#
+create table t1 (i int);
+handler test.t1 open handler_a;
+flush status;
+handler handler_a read first;
+# handler...read must be prepared in --ps-protocol mode
+--replace_result $PS_PROTOCOL OK
+--disable_ps_protocol
+show status like 'Com_stmt_prepare%';
+--enable_ps_protocol
+drop table t1;
diff --git a/mysql-test/suite/handler/savepoint.inc b/mysql-test/suite/handler/savepoint.inc
new file mode 100644
index 00000000..a237183e
--- /dev/null
+++ b/mysql-test/suite/handler/savepoint.inc
@@ -0,0 +1,182 @@
+--echo #
+--echo # Testing savepoints with handlers that supports it
+--echo #
+connect(con1, localhost, root,,);
+connect(con2, localhost, root,,);
+connect(con3, localhost, root,,);
+connection default;
+--echo #
+--echo # ROLLBACK TO SAVEPOINT releases transactional locks,
+--echo # but has no effect on open HANDLERs
+--echo #
+create table t1 (a int, key a (a));
+insert into t1 (a) values (1), (2), (3), (4), (5);
+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;
+connection con1;
+--echo # Sending:
+--send drop table t1
+connection con2;
+--echo # Sending:
+--send drop table t2
+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.
+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
+connection default;
+rollback to savepoint sv;
+connection con2;
+--echo # Reaping 'drop table t2'...
+--reap
+--echo # Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
+--echo # lock.
+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;
+connection con1;
+--echo # Reaping 'drop table t1'...
+--reap
+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;
+connection con1;
+--echo # Sending:
+--send drop table t1
+connection con2;
+--echo # Sending:
+--send drop table t2
+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.
+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
+connection default;
+rollback to savepoint sv;
+connection con2;
+--echo # Reaping 'drop table t2'...
+--reap
+--echo # Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
+--echo # lock.
+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;
+connection con1;
+--echo # Reaping 'drop table t1'...
+--reap
+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;
+connection con1;
+drop table t1, t2;
+--echo # Sending:
+--send drop table t3
+--echo # Let DROP TABLE statement sync in.
+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.
+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;
+connection con1;
+--echo # Reaping 'drop table t3'...
+--reap
+connection default;
+commit;
+
+--echo #
+--echo # Cleanup for savepoint.inc
+--echo #
+connection con1;
+disconnect con1;
+--source include/wait_until_disconnected.inc
+connection con2;
+disconnect con2;
+--source include/wait_until_disconnected.inc
+connection con3;
+disconnect con3;
+--source include/wait_until_disconnected.inc
+connection default;