Commit 0d01dd20 authored by Michael Widenius's avatar Michael Widenius

Added HANDLER support for MEMORY tables

Added key and file version numbers to MEMORY tables so that we can detect if someone has changed them between HANDLER calls.


mysql-test/suite/handler/aria.result:
  Fixed result after test changes
mysql-test/suite/handler/handler.inc:
  Changed test to use combined key to ensure rows are returned in a pre-determinated order.
mysql-test/suite/handler/heap.result:
  New result
mysql-test/suite/handler/heap.test:
  Added test for HANDLER + HEAP
mysql-test/suite/handler/innodb.result:
  Fixed result after test changes
mysql-test/suite/handler/myisam.result:
  Fixed result after test changes
sql/sql_handler.cc:
  Fixed wrong parameter to ha_index_next_same()
storage/heap/ha_heap.cc:
  Abort key scan if table has changed.
  Abort table scan if table has been recreated.
storage/heap/ha_heap.h:
  Added support for HANDLER
storage/heap/hp_clear.c:
  Increase version number so that we can notice changes if using HANDLER
storage/heap/hp_delete.c:
  Increase key data version number on key changes.
storage/heap/hp_rfirst.c:
  Remember version of key data
  Give error if using read-first on hash key.
storage/heap/hp_rkey.c:
  Remember version of key data
storage/heap/hp_rlast.c:
  Remember version of key data
  Give error if using read-last on hash key.
storage/heap/hp_rnext.c:
  Fixed that we get next key from last search.
storage/heap/hp_rprev.c:
  Fixed that we get previous key from last search.
storage/heap/hp_scan.c:
  Remember version of key and file data
storage/heap/hp_update.c:
  Increase key data version number on key changes.
storage/heap/hp_write.c:
  Increase key data version number on key changes.
parent 050c004f
......@@ -136,6 +136,8 @@ typedef struct st_heap_share
ulong min_records,max_records; /* Params to open */
ulonglong data_length,index_length,max_table_size;
uint key_stat_version; /* version to indicate insert/delete */
uint key_version; /* Updated on key change */
uint file_version; /* Update on clear */
uint records; /* records */
uint blength; /* records rounded up to 2^n */
uint deleted; /* Deleted records in database */
......@@ -173,6 +175,8 @@ typedef struct st_heap_info
enum ha_rkey_function last_find_flag;
TREE_ELEMENT *parents[MAX_TREE_HEIGHT+1];
TREE_ELEMENT **last_pos;
uint key_version; /* Version at last read */
uint file_version; /* Version at scan */
uint lastkey_len;
my_bool implicit_emptied;
#ifdef THREAD
......
......@@ -6,42 +6,42 @@ insert into t1 values
(14,"aaa"),(16,"ccc"),(16,"xxx"),
(20,"ggg"),(21,"hhh"),(22,"iii");
handler t1 open as t2;
handler t2 read a first;
handler t2 read b first;
a b
14 aaa
handler t2 read a next;
handler t2 read b next;
a b
16 ccc
handler t2 read a next;
handler t2 read b next;
a b
16 xxx
handler t2 read a prev;
handler t2 read b prev;
a b
16 ccc
handler t2 read a last;
handler t2 read b last;
a b
22 iii
handler t2 read a prev;
handler t2 read b prev;
a b
21 hhh
handler t2 read a prev;
handler t2 read b prev;
a b
20 ggg
handler t2 read a first;
handler t2 read b first;
a b
14 aaa
handler t2 read a prev;
handler t2 read b prev;
a b
handler t2 read a last;
handler t2 read b last;
a b
22 iii
handler t2 read a prev;
handler t2 read b prev;
a b
21 hhh
handler t2 read a next;
handler t2 read b next;
a b
22 iii
handler t2 read a next;
handler t2 read b next;
a b
handler t2 read a=(15);
a b
......@@ -66,19 +66,19 @@ a b
handler t2 read a>=(11);
a b
14 aaa
handler t2 read a=(18);
handler t2 read b=(18);
a b
18 eee
handler t2 read a>=(18);
handler t2 read b>=(18);
a b
18 eee
handler t2 read a>(18);
handler t2 read b>(18);
a b
19 fff
handler t2 read a<=(18);
handler t2 read b<=(18);
a b
18 eee
handler t2 read a<(18);
handler t2 read b<(18);
a b
17 ddd
handler t2 read a=(15);
......@@ -119,19 +119,19 @@ handler t2 read a<=(1);
a b
handler t2 read a<(1);
a b
handler t2 read a first limit 5;
handler t2 read b first limit 5;
a b
14 aaa
16 ccc
16 xxx
17 ddd
18 eee
handler t2 read a next limit 3;
handler t2 read b next limit 3;
a b
19 fff
19 yyy
20 ggg
handler t2 read a prev limit 10;
handler t2 read b prev limit 10;
a b
19 yyy
19 fff
......@@ -162,10 +162,10 @@ a b
handler t2 read a=(16) limit 1,3;
a b
16 xxx
handler t2 read a=(19);
handler t2 read b=(19);
a b
19 fff
handler t2 read a=(19) where b="yyy";
handler t2 read b=(19) where b="yyy";
a b
19 yyy
handler t2 read first;
......@@ -557,7 +557,7 @@ handler t1_alias READ a next where inexistent > 0;
ERROR 42S22: Unknown column 'inexistent' in 'field list'
handler t1_alias close;
drop table t1;
create temporary table t1 (a int, b char(1), key a (a), key b(a,b));
create temporary table t1 (a int, b char(1), key a (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"),(9,'k');
select a,b from t1;
......@@ -609,20 +609,20 @@ a b
9 j
9 k
handler t1 open as a2;
handler a2 read a=(9);
handler a2 read b=(9);
a b
9 j
handler a2 read a next;
handler a2 read b next;
a b
9 k
handler a2 read a prev limit 2;
handler a2 read b prev limit 2;
a b
9 j
8 i
handler a2 read a last;
handler a2 read b last;
a b
9 k
handler a2 read a prev;
handler a2 read b prev;
a b
9 j
handler a2 close;
......
......@@ -23,21 +23,21 @@
# Start testing the table created in init.inc
#
handler t1 open as t2;
handler t2 read a first;
handler t2 read a next;
handler t2 read a next;
handler t2 read a prev;
handler t2 read a last;
handler t2 read a prev;
handler t2 read a prev;
handler t2 read a first;
handler t2 read a prev;
handler t2 read a last;
handler t2 read a prev;
handler t2 read a next;
handler t2 read a next;
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=(16);
......@@ -55,16 +55,19 @@ handler t1 read a last;
handler t2 read a=(11);
handler t2 read a>=(11);
# Search on something we ca nfind
handler t2 read a=(18);
handler t2 read a>=(18);
handler t2 read a>(18);
handler t2 read a<=(18);
handler t2 read a<(18);
# 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);
--sorted_result
handler t2 read a>(15);
handler t2 read a<=(15);
handler t2 read a<(15);
......@@ -83,17 +86,17 @@ handler t2 read a>(1);
handler t2 read a<=(1);
handler t2 read a<(1);
handler t2 read a first limit 5;
handler t2 read a next limit 3;
handler t2 read a prev limit 10;
handler t2 read b first limit 5;
handler t2 read b next limit 3;
handler t2 read b prev limit 10;
handler t2 read a>=(16) limit 4;
handler t2 read a>=(16) limit 2,2;
select * from t1 where a>=16 limit 2,2;
handler t2 read a last limit 3;
handler t2 read a=(16) limit 1,3;
handler t2 read a=(19);
handler t2 read a=(19) where b="yyy";
handler t2 read b=(19);
handler t2 read b=(19) where b="yyy";
handler t2 read first;
handler t2 read next;
......@@ -450,7 +453,7 @@ drop table t1;
# is open by a HANDLER, no other statement can access it.
#
eval create temporary table t1 (a int, b char(1), key a $key_type (a), key b(a,b));
eval create temporary table t1 (a int, b char(1), key a $key_type (a), key b $key_type (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;
......@@ -466,12 +469,12 @@ handler a1 read a=(6) where b="g";
handler a1 close;
select a,b from t1;
handler t1 open as a2;
handler a2 read a=(9);
handler a2 read a next;
handler a2 read a prev limit 2;
handler a2 read b=(9);
handler a2 read b next;
handler a2 read b prev limit 2;
--error 0,1031
handler a2 read a last;
handler a2 read a prev;
handler a2 read b last;
handler a2 read b prev;
handler a2 close;
drop table t1;
......
SET SESSION 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");
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
22 iii
handler t2 read b prev;
a b
21 hhh
handler t2 read b prev;
a b
20 ggg
handler t2 read b first;
a b
14 aaa
handler t2 read b prev;
a b
handler t2 read b last;
a b
22 iii
handler t2 read b prev;
a b
21 hhh
handler t2 read b next;
a b
22 iii
handler t2 read b next;
a b
handler t2 read a=(15);
a b
handler t2 read a=(16);
a b
16 ccc
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);
a b
16 ccc
handler t2 read a>(15);
a b
16 ccc
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
22 iii
handler t2 read a<(54);
a b
22 iii
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 a>=(16) limit 4;
a b
16 ccc
16 xxx
17 ddd
18 eee
handler t2 read a>=(16) limit 2,2;
a b
17 ddd
18 eee
select * from t1 where a>=16 limit 2,2;
a b
17 ddd
18 eee
handler t2 read a last limit 3;
a b
22 iii
21 hhh
20 ggg
handler t2 read a=(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 a next;
a b
14 aaa
handler t1 read a next;
a b
16 ccc
handler t1 close;
handler t1 open;
handler t1 read a prev;
a b
22 iii
handler t1 read a prev;
a b
21 hhh
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=(16) limit 1,3;
a b
16 xxx
flush tables;
handler t1 read a=(16) limit 1,3;
a b
16 xxx
handler t1 close;
handler t1 open;
prepare stmt from 'handler t1 read a=(?) limit ?,?';
set @a=16,@b=1,@c=100;
execute stmt using @a,@b,@c;
a b
16 xxx
set @a=16,@b=2,@c=1;
execute stmt using @a,@b,@c;
a b
set @a=16,@b=0,@c=2;
execute stmt using @a,@b,@c;
a b
16 ccc
16 xxx
deallocate prepare stmt;
prepare stmt from 'handler t1 read a next limit ?';
handler t1 read a>=(11);
a b
14 aaa
set @a=3;
execute stmt using @a;
a b
16 ccc
16 xxx
17 ddd
execute stmt using @a;
a b
18 eee
19 fff
19 yyy
execute stmt using @a;
a b
20 ggg
21 hhh
22 iii
deallocate prepare stmt;
prepare stmt from 'handler t1 read b prev limit ?';
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
execute stmt using @a;
a b
14 aaa
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 a>=(?) where a < ? limit 5';
set @a=15, @b=20;
execute stmt using @a,@b;
a b
16 ccc
16 xxx
17 ddd
18 eee
19 fff
execute stmt using @a,@b;
a b
16 ccc
16 xxx
17 ddd
18 eee
19 fff
deallocate prepare stmt;
prepare stmt from 'handler t1 read a=(?)';
set @a=16;
execute stmt using @a;
a b
16 ccc
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=16;
execute stmt using @a;
ERROR HY000: Prepared statement needs to be re-prepared
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
send the below to another connection, do not wait for the result
optimize table t1;
proceed with the normal connection
handler t1 read next;
c1
1
handler t1 close;
read the result from the other connection
Table Op Msg_type Msg_text
test.t1 optimize note The storage engine for the table doesn't support optimize
proceed with the normal connection
drop table t1;
CREATE TABLE t1 ( no1 smallint(5) NOT NULL default '0', no2 int(10) NOT NULL default '0', PRIMARY KEY 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
send the below to another connection, do not wait for the result
drop table t1;
proceed with the normal connection
select * from t1;
c1
14397
unlock tables;
read the result from the other connection
proceed with the normal connection
select * from t1;
ERROR 42S02: Table 'test.t1' doesn't exist
drop table if exists t1;
Warnings:
Note 1051 Unknown table 't1'
create table t1 (a int not null) ENGINE=CSV;
--> client 2
handler t1 open;
ERROR HY000: Table storage engine for 't1' doesn't have this option
--> client 1
drop table t1;
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;
ERROR HY000: Can't reopen table: 'a1'
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;
#
# 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;
CREATE TABLE t1(a INT, b INT, KEY(a), KEY b using btree (b), KEY ab using btree(a, b));
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: Table storage engine for 't1' doesn't have this option
HANDLER t1 READ a LAST;
ERROR HY000: Table storage engine for 't1' doesn't have this option
HANDLER t1 READ b FIRST LIMIT 2;
a b
1 10
2 20
HANDLER t1 READ b 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
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 FIRST;
a b
2 20
insert into t1 values (8,50);
HANDLER t1 READ NEXT;
a b
2 20
delete from t1 where a=3;
HANDLER t1 READ NEXT LIMIT 2;
a b
1 10
4 40
delete from t1;
HANDLER t1 READ NEXT LIMIT 2;
ERROR HY000: Record has changed since last read in table 't1'
HANDLER t1 CLOSE;
DROP TABLE t1;
End of 5.1 tests
# test of HANDLER with HEAP tables
#
let $engine_type= MEMORY;
let $key_type=using btree;
--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));
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 b 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;
--echo End of 5.1 tests
......@@ -6,42 +6,42 @@ insert into t1 values
(14,"aaa"),(16,"ccc"),(16,"xxx"),
(20,"ggg"),(21,"hhh"),(22,"iii");
handler t1 open as t2;
handler t2 read a first;
handler t2 read b first;
a b
14 aaa
handler t2 read a next;
handler t2 read b next;
a b
16 ccc
handler t2 read a next;
handler t2 read b next;
a b
16 xxx
handler t2 read a prev;
handler t2 read b prev;
a b
16 ccc
handler t2 read a last;
handler t2 read b last;
a b
22 iii
handler t2 read a prev;
handler t2 read b prev;
a b
21 hhh
handler t2 read a prev;
handler t2 read b prev;
a b
20 ggg
handler t2 read a first;
handler t2 read b first;
a b
14 aaa
handler t2 read a prev;
handler t2 read b prev;
a b
handler t2 read a last;
handler t2 read b last;
a b
22 iii
handler t2 read a prev;
handler t2 read b prev;
a b
21 hhh
handler t2 read a next;
handler t2 read b next;
a b
22 iii
handler t2 read a next;
handler t2 read b next;
a b
handler t2 read a=(15);
a b
......@@ -66,19 +66,19 @@ a b
handler t2 read a>=(11);
a b
14 aaa
handler t2 read a=(18);
handler t2 read b=(18);
a b
18 eee
handler t2 read a>=(18);
handler t2 read b>=(18);
a b
18 eee
handler t2 read a>(18);
handler t2 read b>(18);
a b
19 fff
handler t2 read a<=(18);
handler t2 read b<=(18);
a b
18 eee
handler t2 read a<(18);
handler t2 read b<(18);
a b
17 ddd
handler t2 read a=(15);
......@@ -119,19 +119,19 @@ handler t2 read a<=(1);
a b
handler t2 read a<(1);
a b
handler t2 read a first limit 5;
handler t2 read b first limit 5;
a b
14 aaa
16 ccc
16 xxx
17 ddd
18 eee
handler t2 read a next limit 3;
handler t2 read b next limit 3;
a b
19 fff
19 yyy
20 ggg
handler t2 read a prev limit 10;
handler t2 read b prev limit 10;
a b
19 yyy
19 fff
......@@ -162,10 +162,10 @@ a b
handler t2 read a=(16) limit 1,3;
a b
16 xxx
handler t2 read a=(19);
handler t2 read b=(19);
a b
19 fff
handler t2 read a=(19) where b="yyy";
handler t2 read b=(19) where b="yyy";
a b
19 yyy
handler t2 read first;
......@@ -558,7 +558,7 @@ handler t1_alias READ a next where inexistent > 0;
ERROR 42S22: Unknown column 'inexistent' in 'field list'
handler t1_alias close;
drop table t1;
create temporary table t1 (a int, b char(1), key a (a), key b(a,b));
create temporary table t1 (a int, b char(1), key a (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"),(9,'k');
select a,b from t1;
......@@ -610,20 +610,20 @@ a b
9 j
9 k
handler t1 open as a2;
handler a2 read a=(9);
handler a2 read b=(9);
a b
9 j
handler a2 read a next;
handler a2 read b next;
a b
9 k
handler a2 read a prev limit 2;
handler a2 read b prev limit 2;
a b
9 j
8 i
handler a2 read a last;
handler a2 read b last;
a b
9 k
handler a2 read a prev;
handler a2 read b prev;
a b
9 j
handler a2 close;
......
......@@ -6,42 +6,42 @@ insert into t1 values
(14,"aaa"),(16,"ccc"),(16,"xxx"),
(20,"ggg"),(21,"hhh"),(22,"iii");
handler t1 open as t2;
handler t2 read a first;
handler t2 read b first;
a b
14 aaa
handler t2 read a next;
handler t2 read b next;
a b
16 ccc
handler t2 read a next;
handler t2 read b next;
a b
16 xxx
handler t2 read a prev;
handler t2 read b prev;
a b
16 ccc
handler t2 read a last;
handler t2 read b last;
a b
22 iii
handler t2 read a prev;
handler t2 read b prev;
a b
21 hhh
handler t2 read a prev;
handler t2 read b prev;
a b
20 ggg
handler t2 read a first;
handler t2 read b first;
a b
14 aaa
handler t2 read a prev;
handler t2 read b prev;
a b
handler t2 read a last;
handler t2 read b last;
a b
22 iii
handler t2 read a prev;
handler t2 read b prev;
a b
21 hhh
handler t2 read a next;
handler t2 read b next;
a b
22 iii
handler t2 read a next;
handler t2 read b next;
a b
handler t2 read a=(15);
a b
......@@ -66,19 +66,19 @@ a b
handler t2 read a>=(11);
a b
14 aaa
handler t2 read a=(18);
handler t2 read b=(18);
a b
18 eee
handler t2 read a>=(18);
handler t2 read b>=(18);
a b
18 eee
handler t2 read a>(18);
handler t2 read b>(18);
a b
19 fff
handler t2 read a<=(18);
handler t2 read b<=(18);
a b
18 eee
handler t2 read a<(18);
handler t2 read b<(18);
a b
17 ddd
handler t2 read a=(15);
......@@ -119,19 +119,19 @@ handler t2 read a<=(1);
a b
handler t2 read a<(1);
a b
handler t2 read a first limit 5;
handler t2 read b first limit 5;
a b
14 aaa
16 ccc
16 xxx
17 ddd
18 eee
handler t2 read a next limit 3;
handler t2 read b next limit 3;
a b
19 fff
19 yyy
20 ggg
handler t2 read a prev limit 10;
handler t2 read b prev limit 10;
a b
19 yyy
19 fff
......@@ -162,10 +162,10 @@ a b
handler t2 read a=(16) limit 1,3;
a b
16 xxx
handler t2 read a=(19);
handler t2 read b=(19);
a b
19 fff
handler t2 read a=(19) where b="yyy";
handler t2 read b=(19) where b="yyy";
a b
19 yyy
handler t2 read first;
......@@ -557,7 +557,7 @@ handler t1_alias READ a next where inexistent > 0;
ERROR 42S22: Unknown column 'inexistent' in 'field list'
handler t1_alias close;
drop table t1;
create temporary table t1 (a int, b char(1), key a (a), key b(a,b));
create temporary table t1 (a int, b char(1), key a (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"),(9,'k');
select a,b from t1;
......@@ -609,20 +609,20 @@ a b
9 j
9 k
handler t1 open as a2;
handler a2 read a=(9);
handler a2 read b=(9);
a b
9 j
handler a2 read a next;
handler a2 read b next;
a b
9 k
handler a2 read a prev limit 2;
handler a2 read b prev limit 2;
a b
9 j
8 i
handler a2 read a last;
handler a2 read b last;
a b
9 k
handler a2 read a prev;
handler a2 read b prev;
a b
9 j
handler a2 close;
......
......@@ -657,7 +657,6 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
int error, keyno;
uint num_rows;
uchar *UNINIT_VAR(key);
uint UNINIT_VAR(key_len);
bool need_reopen;
List_iterator<Item> it;
DBUG_ENTER("mysql_ha_read");
......@@ -784,7 +783,8 @@ retry:
case RNEXT_SAME:
/* Continue scan on "(keypart1,keypart2,...)=(c1, c2, ...) */
DBUG_ASSERT(keyname != 0);
error= table->file->ha_index_next_same(table->record[0], key, key_len);
error= table->file->ha_index_next_same(table->record[0], key,
handler->key_len);
break;
case RKEY:
{
......
......@@ -183,6 +183,19 @@ void ha_heap::set_keys_for_scanning(void)
}
int ha_heap::can_continue_handler_scan()
{
int error= 0;
if ((file->key_version != file->s->key_version && inited == INDEX) ||
(file->file_version != file->s->file_version && inited == RND))
{
/* Data changed, not safe to do index or rnd scan */
error= HA_ERR_RECORD_CHANGED;
}
return error;
}
void ha_heap::update_key_stats()
{
for (uint i= 0; i < table->s->keys; i++)
......
/* Copyright (C) 2000-2006 MySQL AB
/* Copyright (C) 2000-2006 MySQL AB, 2009-2011 Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -52,6 +52,7 @@ public:
{
return (HA_FAST_KEY_READ | HA_NO_BLOBS | HA_NULL_IN_KEY |
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
HA_CAN_SQL_HANDLER |
HA_REC_NOT_IN_SEQ | HA_CAN_INSERT_DELAYED | HA_NO_TRANSACTIONS |
HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT);
}
......@@ -93,6 +94,7 @@ public:
int rnd_next(uchar *buf);
int rnd_pos(uchar * buf, uchar *pos);
void position(const uchar *record);
int can_continue_handler_scan();
int info(uint);
int extra(enum ha_extra_function operation);
int reset();
......
......@@ -40,6 +40,8 @@ void hp_clear(HP_SHARE *info)
info->blength=1;
info->changed=0;
info->del_link=0;
info->key_version++;
info->file_version++;
DBUG_VOID_RETURN;
}
......
......@@ -47,6 +47,7 @@ int heap_delete(HP_INFO *info, const uchar *record)
share->del_link=pos;
pos[share->reclength]=0; /* Record deleted */
share->deleted++;
share->key_version++;
info->current_hash_ptr=0;
#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG)
DBUG_EXECUTE("check_heap",heap_check_heap(info, 0););
......
......@@ -24,6 +24,8 @@ int heap_rfirst(HP_INFO *info, uchar *record, int inx)
DBUG_ENTER("heap_rfirst");
info->lastinx= inx;
info->key_version= info->s->key_version;
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
{
uchar *pos;
......@@ -57,15 +59,8 @@ int heap_rfirst(HP_INFO *info, uchar *record, int inx)
}
else
{
if (!(info->s->records))
{
my_errno=HA_ERR_END_OF_FILE;
/* We can't scan a non existing key value with hash index */
my_errno= HA_ERR_WRONG_COMMAND;
DBUG_RETURN(my_errno);
}
DBUG_ASSERT(0); /* TODO fix it */
info->current_record=0;
info->current_hash_ptr=0;
info->update=HA_STATE_PREV_FOUND;
DBUG_RETURN(heap_rnext(info,record));
}
}
......@@ -30,6 +30,7 @@ int heap_rkey(HP_INFO *info, uchar *record, int inx, const uchar *key,
}
info->lastinx= inx;
info->current_record= (ulong) ~0L; /* For heap_rrnd() */
info->key_version= info->s->key_version;
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
{
......
......@@ -25,6 +25,7 @@ int heap_rlast(HP_INFO *info, uchar *record, int inx)
DBUG_ENTER("heap_rlast");
info->lastinx= inx;
info->key_version= info->s->key_version;
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
{
uchar *pos;
......@@ -47,9 +48,8 @@ int heap_rlast(HP_INFO *info, uchar *record, int inx)
}
else
{
info->current_ptr=0;
info->current_hash_ptr=0;
info->update=HA_STATE_NEXT_FOUND;
DBUG_RETURN(heap_rprev(info,record));
/* We can't scan a non existing key value with hash index */
my_errno= HA_ERR_WRONG_COMMAND;
DBUG_RETURN(my_errno);
}
}
......@@ -70,6 +70,7 @@ int heap_rnext(HP_INFO *info, uchar *record)
custom_arg.keyseg = keyinfo->seg;
custom_arg.key_length = info->lastkey_len;
custom_arg.search_flag = SEARCH_SAME | SEARCH_FIND;
info->last_find_flag= HA_READ_KEY_OR_NEXT;
pos = tree_search_key(&keyinfo->rb_tree, info->lastkey, info->parents,
&info->last_pos, info->last_find_flag, &custom_arg);
}
......
......@@ -41,6 +41,7 @@ int heap_rprev(HP_INFO *info, uchar *record)
custom_arg.keyseg = keyinfo->seg;
custom_arg.key_length = keyinfo->length;
custom_arg.search_flag = SEARCH_SAME;
info->last_find_flag= HA_READ_KEY_OR_PREV;
pos = tree_search_key(&keyinfo->rb_tree, info->lastkey, info->parents,
&info->last_pos, info->last_find_flag, &custom_arg);
}
......
......@@ -31,6 +31,8 @@ int heap_scan_init(register HP_INFO *info)
info->current_record= (ulong) ~0L; /* No current record */
info->update=0;
info->next_block=0;
info->key_version= info->s->key_version;
info->file_version= info->s->file_version;
DBUG_RETURN(0);
}
......
......@@ -21,7 +21,7 @@ int heap_update(HP_INFO *info, const uchar *old, const uchar *heap_new)
{
HP_KEYDEF *keydef, *end, *p_lastinx;
uchar *pos;
my_bool auto_key_changed= 0;
my_bool auto_key_changed= 0, key_changed= 0;
HP_SHARE *share= info->s;
DBUG_ENTER("heap_update");
......@@ -54,6 +54,8 @@ int heap_update(HP_INFO *info, const uchar *old, const uchar *heap_new)
#endif
if (auto_key_changed)
heap_update_auto_increment(info, heap_new);
if (key_changed)
share->key_version++;
DBUG_RETURN(0);
err:
......
......@@ -56,6 +56,7 @@ int heap_write(HP_INFO *info, const uchar *record)
pos[share->reclength]=1; /* Mark record as not deleted */
if (++share->records == share->blength)
share->blength+= share->blength;
info->s->key_version++;
info->current_ptr=pos;
info->current_hash_ptr=0;
info->update|=HA_STATE_AKTIV;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment