Commit e47decfa authored by ingo@mysql.com's avatar ingo@mysql.com

BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S).

BUG#4335 - one name can be handler open'ed many times.
Reworked the HANDLER functions and interface.
Using a HASH to store information on open tables that
survives FLUSH TABLE.
HANDLER tables alias names must now be unique, though it
is allowed in 4.0 to qualify them with the database name
of the base table.
parent 38f462ae
......@@ -7,58 +7,6 @@ check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
drop database if exists test_test;
create database test_test;
use test_test;
create table t1(table_id char(20) primary key);
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);
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;
drop table if exists t1;
create table t1(table_id char(20) primary key);
insert into t1 values ('test.t1');
insert into t1 values ('');
handler t1 open;
handler t1 read first limit 9;
table_id
test.t1
use test;
handler test.t1 read first limit 9;
table_id
test.t1
handler test.t2 read first limit 9;
Unknown table 't2' in HANDLER
handler test_test.t1 read first limit 9;
table_id
test_test.t1
handler test_test.t2 read first limit 9;
table_id
test_test.t2
handler test_test.t1 close;
drop table test_test.t1;
handler test_test.t2 close;
drop table test_test.t2;
drop database test_test;
use test;
handler test.t1 close;
drop table test.t1;
drop table if exists t1;
drop table if exists t2;
create table t1(table_id char(20) primary key);
......@@ -84,14 +32,23 @@ test.t2
flush tables;
handler a1 read first limit 9;
Unknown table 'a1' in HANDLER
table_id
test.t1
handler a2 read first limit 9;
Unknown table 'a2' in HANDLER
table_id
test.t1
handler t2 read first limit 9;
Unknown table 't2' in HANDLER
table_id
test.t2
handler t1 open as a1;
Not unique table/alias: 'a1'
handler t1 open as a2;
Not unique table/alias: 'a2'
handler t2 open;
Not unique table/alias: 't2'
handler a1 read first limit 9;
table_id
test.t1
......@@ -106,15 +63,43 @@ test.t2
flush table t1;
handler a1 read first limit 9;
Unknown table 'a1' in HANDLER
table_id
test.t1
handler a2 read first limit 9;
Unknown table 'a2' in HANDLER
table_id
test.t1
handler t2 read first limit 9;
table_id
test.t2
flush table t2;
handler t2 close;
Unknown table 't2' in HANDLER
drop table t1;
drop table t2;
create table t1(table_id char(20) primary key);
insert into t1 values ('Record-01');
insert into t1 values ('Record-02');
insert into t1 values ('Record-03');
insert into t1 values ('Record-04');
insert into t1 values ('Record-05');
handler t1 open;
handler t1 read first limit 1;
table_id
Record-01
handler t1 read next limit 1;
table_id
Record-02
handler t1 read next limit 1;
table_id
Record-03
flush table t1;
handler t1 read next limit 1;
table_id
Record-01
handler t1 read next limit 1;
table_id
Record-02
handler t1 close;
drop table t1;
......@@ -203,3 +203,247 @@ handler t1 read a=(1) where b=1;
a b
handler t1 close;
drop table t1;
drop database if exists test_test;
create database test_test;
use test_test;
create table t1(table_id char(20) primary key);
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);
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;
drop table if exists t1;
create table t1(table_id char(20) primary key);
insert into t1 values ('test.t1');
insert into t1 values ('');
handler t1 open;
Not unique table/alias: 't1'
use test;
handler test.t1 read first limit 9;
Unknown table 'test.t1' in HANDLER
handler test_test.t1 read first limit 9;
table_id
test_test.t1
handler t1 read first limit 9;
table_id
test_test.t1
handler test_test.t2 read first limit 9;
table_id
test_test.t2
handler t2 read first limit 9;
table_id
test_test.t2
handler test_test.t1 close;
handler t1 close;
Unknown table 't1' in HANDLER
drop table test_test.t1;
handler test_test.t2 close;
handler t2 close;
Unknown table 't2' in HANDLER
drop table test_test.t2;
drop database test_test;
use test;
handler test.t1 close;
Unknown table 'test.t1' in HANDLER
handler t1 close;
Unknown table 't1' in HANDLER
drop table test.t1;
drop database if exists test_test;
drop table if exists t1;
drop table if exists t2;
drop table if exists t3;
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;
Not unique table/alias: 't1'
handler t2 open t1;
Not unique table/alias: 't1'
handler t3 open t1;
Not unique table/alias: 't1'
handler t1 read first limit 9;
c1
test_test.t1
handler test.t1 close;
Unknown table 'test.t1' in HANDLER
handler test.t1 open h1;
Not unique table/alias: 'h1'
handler test_test.t1 open h1;
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 test.h2 read first limit 9;
c1
t1
handler test.h1 close;
Unknown table 'test.h1' in HANDLER
handler test_test.t1 close;
handler test_test.h1 close;
handler h2 close;
handler t1 read first limit 9;
Unknown table 't1' in HANDLER
handler h1 read first limit 9;
Unknown table 'h1' in HANDLER
handler h2 read first limit 9;
Unknown table 'h2' in HANDLER
handler h3 read first limit 9;
c1
test_test.t3
handler test_test.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;
Unknown table 'test.h3' in HANDLER
handler test_test.h3 close;
use test;
drop table t3;
drop table t2;
drop table t1;
drop database test_test;
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;
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;
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;
Unknown table 'h5' in HANDLER
alter table t3 engine=MyISAM;
handler h1 read first limit 9;
Unknown table 'h1' in HANDLER
handler h2 read first limit 9;
c1
t2
handler h3 read first limit 9;
Unknown table 'h3' in HANDLER
handler h4 read first limit 9;
c1
t4
handler h5 read first limit 9;
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;
Unknown table 'h1_1' in HANDLER
handler h1_2 read first limit 9;
Unknown table 'h1_2' in HANDLER
handler h1_3 read first limit 9;
Unknown table 'h1_3' in HANDLER
drop table t1;
drop table t2;
drop table t3;
drop table t4;
drop table t5;
......@@ -12,63 +12,10 @@ flush table t1;
check table t1;
drop table t1;
#
# Check if two database names beginning the same are seen as different.
#
# This database begins like the usual 'test' database.
#
--disable_warnings
drop database if exists test_test;
--enable_warnings
create database test_test;
use test_test;
create table t1(table_id char(20) primary key);
insert into t1 values ('test_test.t1');
insert into t1 values ('');
handler t1 open;
handler t1 read first limit 9;
create table t2(table_id char(20) primary key);
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;
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1(table_id char(20) primary key);
insert into t1 values ('test.t1');
insert into t1 values ('');
handler t1 open;
handler t1 read first limit 9;
#
# Check accesibility of all the tables.
#
use test;
handler test.t1 read first limit 9;
--error 1109;
handler test.t2 read first limit 9;
handler test_test.t1 read first limit 9;
handler test_test.t2 read first limit 9;
#
# Cleanup.
#
handler test_test.t1 close;
drop table test_test.t1;
handler test_test.t2 close;
drop table test_test.t2;
drop database test_test;
#
use test;
handler test.t1 close;
drop table test.t1;
#
# In the following test FLUSH TABLES produces a deadlock
# (hang forever) if the fix for bug#3565 is missing.
# (hang forever) if the fix for BUG #3565 is missing.
# And it shows that handler tables are re-opened after flush (BUG #4286).
#
--disable_warnings
drop table if exists t1;
......@@ -87,28 +34,43 @@ handler a1 read first limit 9;
handler a2 read first limit 9;
handler t2 read first limit 9;
flush tables;
--error 1109;
handler a1 read first limit 9;
--error 1109;
handler a2 read first limit 9;
--error 1109;
handler t2 read first limit 9;
#
--error 1066
handler t1 open as a1;
--error 1066
handler t1 open as a2;
--error 1066
handler t2 open;
handler a1 read first limit 9;
handler a2 read first limit 9;
handler t2 read first limit 9;
flush table t1;
--error 1109;
handler a1 read first limit 9;
--error 1109;
handler a2 read first limit 9;
handler t2 read first limit 9;
flush table t2;
--error 1109;
handler t2 close;
drop table t1;
drop table t2;
#
# The fix for BUG #4286 cannot restore the position after a flush.
#
create table t1(table_id char(20) primary key);
insert into t1 values ('Record-01');
insert into t1 values ('Record-02');
insert into t1 values ('Record-03');
insert into t1 values ('Record-04');
insert into t1 values ('Record-05');
handler t1 open;
handler t1 read first limit 1;
handler t1 read next limit 1;
handler t1 read next limit 1;
flush table t1;
handler t1 read next limit 1;
handler t1 read next limit 1;
handler t1 close;
drop table t1;
......@@ -135,3 +135,207 @@ handler t1 read a=(1) where b=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.
#
--disable_warnings
drop database if exists test_test;
--enable_warnings
create database test_test;
use test_test;
create table t1(table_id char(20) primary key);
insert into t1 values ('test_test.t1');
insert into t1 values ('');
handler t1 open;
handler t1 read first limit 9;
create table t2(table_id char(20) primary key);
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;
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1(table_id char(20) primary key);
insert into t1 values ('test.t1');
insert into t1 values ('');
--error 1066
handler t1 open;
#
# Check accesibility of all the tables.
#
use test;
--error 1109;
handler test.t1 read first limit 9;
handler test_test.t1 read first limit 9;
handler t1 read first limit 9;
handler test_test.t2 read first limit 9;
handler t2 read first limit 9;
#
# Cleanup.
#
handler test_test.t1 close;
--error 1109;
handler t1 close;
drop table test_test.t1;
handler test_test.t2 close;
--error 1109;
handler t2 close;
drop table test_test.t2;
drop database test_test;
#
use test;
--error 1109;
handler test.t1 close;
--error 1109;
handler t1 close;
drop table test.t1;
#
# BUG#4335
#
--disable_warnings
drop database if exists test_test;
drop table if exists t1;
drop table if exists t2;
drop table if exists t3;
--enable_warnings
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 1109
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 test.h2 read first limit 9;
--error 1109
handler test.h1 close;
handler test_test.t1 close;
handler test_test.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 test_test.h3 read first limit 9;
use test_test;
handler h3 read first limit 9;
--error 1109
handler test.h3 read first limit 9;
handler test_test.h3 close;
use test;
drop table t3;
drop table t2;
drop table t1;
drop database test_test;
#
# 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
alter table t1 engine=MyISAM;
--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
alter table t5 engine=MyISAM;
--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
alter table t3 engine=MyISAM;
--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;
alter table t1 engine=MyISAM;
--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;
......@@ -540,12 +540,15 @@ int mysql_find_files(THD *thd,List<char> *files, const char *db,
const char *path, const char *wild, bool dir);
/* sql_handler.cc */
int mysql_ha_open(THD *thd, TABLE_LIST *tables);
int mysql_ha_close(THD *thd, TABLE_LIST *tables,
bool dont_send_ok=0, bool dont_lock=0, bool no_alias=0);
int mysql_ha_close_list(THD *thd, TABLE_LIST *tables, bool flushed=0);
int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen= 0);
int mysql_ha_close(THD *thd, TABLE_LIST *tables);
int mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows);
int mysql_ha_flush(THD *thd, TABLE_LIST *tables, int mode_flags);
/* mysql_ha_flush mode_flags bits */
#define MYSQL_HA_CLOSE_FINAL 0x00
#define MYSQL_HA_REOPEN_ON_USAGE 0x01
#define MYSQL_HA_FLUSH_ALL 0x02
/* sql_base.cc */
void set_item_name(Item *item,char *pos,uint length);
......
......@@ -389,7 +389,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
thd->proc_info="Flushing tables";
close_old_data_files(thd,thd->open_tables,1,1);
mysql_ha_close_list(thd, tables);
mysql_ha_flush(thd, tables, MYSQL_HA_REOPEN_ON_USAGE | MYSQL_HA_FLUSH_ALL);
bool found=1;
/* Wait until all threads has closed all the tables we had locked */
DBUG_PRINT("info", ("Waiting for others threads to close their open tables"));
......@@ -859,7 +859,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
}
/* close handler tables which are marked for flush */
mysql_ha_close_list(thd, (TABLE_LIST*) NULL, /*flushed*/ 1);
mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE);
for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ;
table && table->in_use ;
......@@ -1226,7 +1226,7 @@ bool wait_for_tables(THD *thd)
{
thd->some_tables_deleted=0;
close_old_data_files(thd,thd->open_tables,0,dropping_tables != 0);
mysql_ha_close_list(thd, (TABLE_LIST*) NULL, /*flushed*/ 1);
mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE);
if (!table_is_used(thd->open_tables,1))
break;
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
......
......@@ -78,9 +78,9 @@ extern "C" void free_user_var(user_var_entry *entry)
** Thread specific functions
****************************************************************************/
THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
insert_id_used(0),rand_used(0),in_lock_tables(0),
global_read_lock(0),bootstrap(0)
THD::THD():user_time(0),global_read_lock(0),fatal_error(0),
last_insert_id_used(0),insert_id_used(0),rand_used(0),
in_lock_tables(0),bootstrap(0)
{
host=user=priv_user=db=query=ip=0;
host_or_ip= "connecting host";
......@@ -90,6 +90,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
query_error=0;
next_insert_id=last_insert_id=0;
open_tables=temporary_tables=handler_tables=0;
hash_clear(&handler_tables_hash);
current_tablenr=0;
handler_items=0;
tmp_table=0;
......@@ -215,11 +216,9 @@ void THD::cleanup(void)
lock=locked_tables; locked_tables=0;
close_thread_tables(this);
}
if (handler_tables)
{
open_tables=handler_tables; handler_tables=0;
close_thread_tables(this);
}
mysql_ha_flush(this, (TABLE_LIST*) 0,
MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL);
hash_free(&handler_tables_hash);
close_temporary_tables(this);
hash_free(&user_vars);
if (global_read_lock)
......
......@@ -421,6 +421,7 @@ class THD :public ilink
and are still in use by this thread
*/
TABLE *open_tables,*temporary_tables, *handler_tables;
HASH handler_tables_hash;
// TODO: document the variables below
MYSQL_LOCK *lock,*locked_tables;
ULL *ull;
......
This diff is collapsed.
......@@ -176,7 +176,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
for (table=tables ; table ; table=table->next)
{
char *db=table->db;
mysql_ha_close(thd, table, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL);
if (!close_temporary_table(thd, db, table->real_name))
{
tmp_table_deleted=1;
......@@ -1242,7 +1242,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (send_fields(thd, field_list, 1))
DBUG_RETURN(-1);
mysql_ha_close(thd, tables, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL);
for (table = tables; table; table = table->next)
{
char table_name[NAME_LEN*2+2];
......@@ -1503,7 +1503,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
used_fields=create_info->used_fields;
mysql_ha_close(thd, table_list, /*dont_send_ok*/ 1, /*dont_lock*/ 1);
mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL);
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
DBUG_RETURN(-1);
......
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