mirror of
https://github.com/MariaDB/server.git
synced 2025-01-30 10:31:54 +01:00
Merge marko@build.mysql.com:/home/bk/mysql-4.0
into hundin.mysql.fi:/home/marko/k/mysql-4.0
This commit is contained in:
commit
c36a75a809
14 changed files with 1021 additions and 326 deletions
|
@ -218,7 +218,13 @@ inline double ulonglong2double(ulonglong value)
|
||||||
((uint32) (uchar) (A)[0])))
|
((uint32) (uchar) (A)[0])))
|
||||||
#define sint4korr(A) (*((long *) (A)))
|
#define sint4korr(A) (*((long *) (A)))
|
||||||
#define uint2korr(A) (*((uint16 *) (A)))
|
#define uint2korr(A) (*((uint16 *) (A)))
|
||||||
#define uint3korr(A) (long) (*((unsigned long *) (A)) & 0xFFFFFF)
|
/*
|
||||||
|
ATTENTION !
|
||||||
|
|
||||||
|
Please, note, uint3korr reads 4 bytes (not 3) !
|
||||||
|
It means, that you have to provide enough allocated space !
|
||||||
|
*/
|
||||||
|
#define uint3korr(A) (long) (*((unsigned int *) (A)) & 0xFFFFFF)
|
||||||
#define uint4korr(A) (*((unsigned long *) (A)))
|
#define uint4korr(A) (*((unsigned long *) (A)))
|
||||||
#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
|
#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
|
||||||
(((uint32) ((uchar) (A)[1])) << 8) +\
|
(((uint32) ((uchar) (A)[1])) << 8) +\
|
||||||
|
|
|
@ -898,7 +898,13 @@ typedef char bool; /* Ordinary boolean values 0 1 */
|
||||||
(((uint32) ((uchar) (A)[1])) << 8) +\
|
(((uint32) ((uchar) (A)[1])) << 8) +\
|
||||||
(((uint32) ((uchar) (A)[2])) << 16))
|
(((uint32) ((uchar) (A)[2])) << 16))
|
||||||
#else
|
#else
|
||||||
#define uint3korr(A) (long) (*((unsigned long *) (A)) & 0xFFFFFF)
|
/*
|
||||||
|
ATTENTION !
|
||||||
|
|
||||||
|
Please, note, uint3korr reads 4 bytes (not 3) !
|
||||||
|
It means, that you have to provide enough allocated space !
|
||||||
|
*/
|
||||||
|
#define uint3korr(A) (long) (*((unsigned int *) (A)) & 0xFFFFFF)
|
||||||
#endif
|
#endif
|
||||||
#define uint4korr(A) (*((unsigned long *) (A)))
|
#define uint4korr(A) (*((unsigned long *) (A)))
|
||||||
#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
|
#define uint5korr(A) ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
|
||||||
|
|
|
@ -7,58 +7,6 @@ check table t1;
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 check status OK
|
test.t1 check status OK
|
||||||
drop table t1;
|
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 t1;
|
||||||
drop table if exists t2;
|
drop table if exists t2;
|
||||||
create table t1(table_id char(20) primary key);
|
create table t1(table_id char(20) primary key);
|
||||||
|
@ -84,14 +32,23 @@ test.t2
|
||||||
|
|
||||||
flush tables;
|
flush tables;
|
||||||
handler a1 read first limit 9;
|
handler a1 read first limit 9;
|
||||||
Unknown table 'a1' in HANDLER
|
table_id
|
||||||
|
test.t1
|
||||||
|
|
||||||
handler a2 read first limit 9;
|
handler a2 read first limit 9;
|
||||||
Unknown table 'a2' in HANDLER
|
table_id
|
||||||
|
test.t1
|
||||||
|
|
||||||
handler t2 read first limit 9;
|
handler t2 read first limit 9;
|
||||||
Unknown table 't2' in HANDLER
|
table_id
|
||||||
|
test.t2
|
||||||
|
|
||||||
handler t1 open as a1;
|
handler t1 open as a1;
|
||||||
|
Not unique table/alias: 'a1'
|
||||||
handler t1 open as a2;
|
handler t1 open as a2;
|
||||||
|
Not unique table/alias: 'a2'
|
||||||
handler t2 open;
|
handler t2 open;
|
||||||
|
Not unique table/alias: 't2'
|
||||||
handler a1 read first limit 9;
|
handler a1 read first limit 9;
|
||||||
table_id
|
table_id
|
||||||
test.t1
|
test.t1
|
||||||
|
@ -106,15 +63,43 @@ test.t2
|
||||||
|
|
||||||
flush table t1;
|
flush table t1;
|
||||||
handler a1 read first limit 9;
|
handler a1 read first limit 9;
|
||||||
Unknown table 'a1' in HANDLER
|
table_id
|
||||||
|
test.t1
|
||||||
|
|
||||||
handler a2 read first limit 9;
|
handler a2 read first limit 9;
|
||||||
Unknown table 'a2' in HANDLER
|
table_id
|
||||||
|
test.t1
|
||||||
|
|
||||||
handler t2 read first limit 9;
|
handler t2 read first limit 9;
|
||||||
table_id
|
table_id
|
||||||
test.t2
|
test.t2
|
||||||
|
|
||||||
flush table t2;
|
flush table t2;
|
||||||
handler t2 close;
|
handler t2 close;
|
||||||
Unknown table 't2' in HANDLER
|
|
||||||
drop table t1;
|
drop table t1;
|
||||||
drop table t2;
|
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
|
a b
|
||||||
handler t1 close;
|
handler t1 close;
|
||||||
drop table t1;
|
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;
|
check table t1;
|
||||||
drop 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
|
# 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
|
--disable_warnings
|
||||||
drop table if exists t1;
|
drop table if exists t1;
|
||||||
|
@ -87,28 +34,43 @@ handler a1 read first limit 9;
|
||||||
handler a2 read first limit 9;
|
handler a2 read first limit 9;
|
||||||
handler t2 read first limit 9;
|
handler t2 read first limit 9;
|
||||||
flush tables;
|
flush tables;
|
||||||
--error 1109;
|
|
||||||
handler a1 read first limit 9;
|
handler a1 read first limit 9;
|
||||||
--error 1109;
|
|
||||||
handler a2 read first limit 9;
|
handler a2 read first limit 9;
|
||||||
--error 1109;
|
|
||||||
handler t2 read first limit 9;
|
handler t2 read first limit 9;
|
||||||
#
|
#
|
||||||
|
--error 1066
|
||||||
handler t1 open as a1;
|
handler t1 open as a1;
|
||||||
|
--error 1066
|
||||||
handler t1 open as a2;
|
handler t1 open as a2;
|
||||||
|
--error 1066
|
||||||
handler t2 open;
|
handler t2 open;
|
||||||
handler a1 read first limit 9;
|
handler a1 read first limit 9;
|
||||||
handler a2 read first limit 9;
|
handler a2 read first limit 9;
|
||||||
handler t2 read first limit 9;
|
handler t2 read first limit 9;
|
||||||
flush table t1;
|
flush table t1;
|
||||||
--error 1109;
|
|
||||||
handler a1 read first limit 9;
|
handler a1 read first limit 9;
|
||||||
--error 1109;
|
|
||||||
handler a2 read first limit 9;
|
handler a2 read first limit 9;
|
||||||
handler t2 read first limit 9;
|
handler t2 read first limit 9;
|
||||||
flush table t2;
|
flush table t2;
|
||||||
--error 1109;
|
|
||||||
handler t2 close;
|
handler t2 close;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
drop table t2;
|
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;
|
handler t1 close;
|
||||||
drop 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 ('');
|
||||||
|
--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);
|
const char *path, const char *wild, bool dir);
|
||||||
|
|
||||||
/* sql_handler.cc */
|
/* sql_handler.cc */
|
||||||
int mysql_ha_open(THD *thd, TABLE_LIST *tables);
|
int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen= 0);
|
||||||
int mysql_ha_close(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_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
|
int mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
|
||||||
List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows);
|
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 */
|
/* sql_base.cc */
|
||||||
void set_item_name(Item *item,char *pos,uint length);
|
void set_item_name(Item *item,char *pos,uint length);
|
||||||
|
|
|
@ -1114,14 +1114,14 @@ static void set_effective_user(struct passwd *user_info)
|
||||||
{
|
{
|
||||||
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
|
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
|
||||||
DBUG_ASSERT(user_info);
|
DBUG_ASSERT(user_info);
|
||||||
if (setegid(user_info->pw_gid) == -1)
|
if (setregid((gid_t)-1,user_info->pw_gid) == -1)
|
||||||
{
|
{
|
||||||
sql_perror("setegid");
|
sql_perror("setregid");
|
||||||
unireg_abort(1);
|
unireg_abort(1);
|
||||||
}
|
}
|
||||||
if (seteuid(user_info->pw_uid) == -1)
|
if (setreuid((uid_t)-1,user_info->pw_uid) == -1)
|
||||||
{
|
{
|
||||||
sql_perror("seteuid");
|
sql_perror("setreuid");
|
||||||
unireg_abort(1);
|
unireg_abort(1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2510,9 +2510,9 @@ You should consider changing lower_case_table_names to 1 or 2",
|
||||||
#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
|
#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
|
||||||
if (locked_in_memory && !getuid())
|
if (locked_in_memory && !getuid())
|
||||||
{
|
{
|
||||||
if (seteuid(0) == -1)
|
if (setreuid((uid_t)-1,0) == -1)
|
||||||
{ // this should never happen
|
{ // this should never happen
|
||||||
sql_perror("seteuid");
|
sql_perror("setreuid");
|
||||||
unireg_abort(1);
|
unireg_abort(1);
|
||||||
}
|
}
|
||||||
if (mlockall(MCL_CURRENT))
|
if (mlockall(MCL_CURRENT))
|
||||||
|
|
|
@ -249,9 +249,10 @@ static int init_rr_cache(READ_RECORD *info)
|
||||||
rec_cache_size=info->cache_records*info->reclength;
|
rec_cache_size=info->cache_records*info->reclength;
|
||||||
info->rec_cache_size=info->cache_records*info->ref_length;
|
info->rec_cache_size=info->cache_records*info->ref_length;
|
||||||
|
|
||||||
|
// We have to allocate one more byte to use uint3korr (see comments for it)
|
||||||
if (info->cache_records <= 2 ||
|
if (info->cache_records <= 2 ||
|
||||||
!(info->cache=(byte*) my_malloc_lock(rec_cache_size+info->cache_records*
|
!(info->cache=(byte*) my_malloc_lock(rec_cache_size+info->cache_records*
|
||||||
info->struct_length,
|
info->struct_length+1,
|
||||||
MYF(0))))
|
MYF(0))))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
#ifdef HAVE_purify
|
#ifdef HAVE_purify
|
||||||
|
|
|
@ -389,7 +389,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
|
||||||
thd->proc_info="Flushing tables";
|
thd->proc_info="Flushing tables";
|
||||||
|
|
||||||
close_old_data_files(thd,thd->open_tables,1,1);
|
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;
|
bool found=1;
|
||||||
/* Wait until all threads has closed all the tables we had locked */
|
/* Wait until all threads has closed all the tables we had locked */
|
||||||
DBUG_PRINT("info", ("Waiting for others threads to close their open tables"));
|
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 */
|
/* 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) ;
|
for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ;
|
||||||
table && table->in_use ;
|
table && table->in_use ;
|
||||||
|
@ -1251,7 +1251,7 @@ bool wait_for_tables(THD *thd)
|
||||||
{
|
{
|
||||||
thd->some_tables_deleted=0;
|
thd->some_tables_deleted=0;
|
||||||
close_old_data_files(thd,thd->open_tables,0,dropping_tables != 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))
|
if (!table_is_used(thd->open_tables,1))
|
||||||
break;
|
break;
|
||||||
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
|
(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
|
** Thread specific functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
|
THD::THD():user_time(0),global_read_lock(0),fatal_error(0),
|
||||||
insert_id_used(0),rand_used(0),in_lock_tables(0),
|
last_insert_id_used(0),insert_id_used(0),rand_used(0),
|
||||||
global_read_lock(0),bootstrap(0)
|
in_lock_tables(0),bootstrap(0)
|
||||||
{
|
{
|
||||||
host=user=priv_user=db=query=ip=0;
|
host=user=priv_user=db=query=ip=0;
|
||||||
host_or_ip= "connecting host";
|
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;
|
query_error=0;
|
||||||
next_insert_id=last_insert_id=0;
|
next_insert_id=last_insert_id=0;
|
||||||
open_tables=temporary_tables=handler_tables=0;
|
open_tables=temporary_tables=handler_tables=0;
|
||||||
|
hash_clear(&handler_tables_hash);
|
||||||
current_tablenr=0;
|
current_tablenr=0;
|
||||||
handler_items=0;
|
handler_items=0;
|
||||||
tmp_table=0;
|
tmp_table=0;
|
||||||
|
@ -215,11 +216,9 @@ void THD::cleanup(void)
|
||||||
lock=locked_tables; locked_tables=0;
|
lock=locked_tables; locked_tables=0;
|
||||||
close_thread_tables(this);
|
close_thread_tables(this);
|
||||||
}
|
}
|
||||||
if (handler_tables)
|
mysql_ha_flush(this, (TABLE_LIST*) 0,
|
||||||
{
|
MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL);
|
||||||
open_tables=handler_tables; handler_tables=0;
|
hash_free(&handler_tables_hash);
|
||||||
close_thread_tables(this);
|
|
||||||
}
|
|
||||||
close_temporary_tables(this);
|
close_temporary_tables(this);
|
||||||
hash_free(&user_vars);
|
hash_free(&user_vars);
|
||||||
if (global_read_lock)
|
if (global_read_lock)
|
||||||
|
|
|
@ -421,6 +421,7 @@ public:
|
||||||
and are still in use by this thread
|
and are still in use by this thread
|
||||||
*/
|
*/
|
||||||
TABLE *open_tables,*temporary_tables, *handler_tables;
|
TABLE *open_tables,*temporary_tables, *handler_tables;
|
||||||
|
HASH handler_tables_hash;
|
||||||
// TODO: document the variables below
|
// TODO: document the variables below
|
||||||
MYSQL_LOCK *lock,*locked_tables;
|
MYSQL_LOCK *lock,*locked_tables;
|
||||||
ULL *ull;
|
ULL *ull;
|
||||||
|
|
|
@ -17,10 +17,6 @@
|
||||||
|
|
||||||
/* HANDLER ... commands - direct access to ISAM */
|
/* HANDLER ... commands - direct access to ISAM */
|
||||||
|
|
||||||
#include "mysql_priv.h"
|
|
||||||
#include "sql_select.h"
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
HANDLER blabla OPEN [ AS foobar ] [ (column-list) ]
|
HANDLER blabla OPEN [ AS foobar ] [ (column-list) ]
|
||||||
|
|
||||||
|
@ -38,34 +34,215 @@
|
||||||
all the sql_alloc'ed memory. It's harder to work around...
|
all the sql_alloc'ed memory. It's harder to work around...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
There are two containers holding information about open handler tables.
|
||||||
|
The first is 'thd->handler_tables'. It is a linked list of TABLE objects.
|
||||||
|
It is used like 'thd->open_tables' in the table cache. The trick is to
|
||||||
|
exchange these two lists during open and lock of tables. Thus the normal
|
||||||
|
table cache code can be used.
|
||||||
|
The second container is a HASH. It holds objects of the type TABLE_LIST.
|
||||||
|
Despite its name, no lists of tables but only single structs are hashed
|
||||||
|
(the 'next' pointer is always NULL). The reason for theis second container
|
||||||
|
is, that we want handler tables to survive FLUSH TABLE commands. A table
|
||||||
|
affected by FLUSH TABLE must be closed so that other threads are not
|
||||||
|
blocked by handler tables still in use. Since we use the normal table cache
|
||||||
|
functions with 'thd->handler_tables', the closed tables are removed from
|
||||||
|
this list. Hence we need the original open information for the handler
|
||||||
|
table in the case that it is used again. This information is handed over
|
||||||
|
to mysql_ha_open() as a TABLE_LIST. So we store this information in the
|
||||||
|
second container, where it is not affected by FLUSH TABLE. The second
|
||||||
|
container is implemented as a hash for performance reasons. Consequently,
|
||||||
|
we use it not only for re-opening a handler table, but also for the
|
||||||
|
HANDLER ... READ commands. For this purpose, we store a pointer to the
|
||||||
|
TABLE structure (in the first container) in the TBALE_LIST object in the
|
||||||
|
second container. When the table is flushed, the pointer is cleared.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mysql_priv.h"
|
||||||
|
#include "sql_select.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#define HANDLER_TABLES_HASH_SIZE 120
|
||||||
|
|
||||||
|
static enum enum_ha_read_modes rkey_to_rnext[]=
|
||||||
|
{ RNEXT_SAME, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV };
|
||||||
|
|
||||||
#define HANDLER_TABLES_HACK(thd) { \
|
#define HANDLER_TABLES_HACK(thd) { \
|
||||||
TABLE *tmp=thd->open_tables; \
|
TABLE *tmp=thd->open_tables; \
|
||||||
thd->open_tables=thd->handler_tables; \
|
thd->open_tables=thd->handler_tables; \
|
||||||
thd->handler_tables=tmp; }
|
thd->handler_tables=tmp; }
|
||||||
|
|
||||||
static TABLE **find_table_ptr_by_name(THD *thd,const char *db,
|
static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, int mode_flags);
|
||||||
const char *table_name,
|
|
||||||
bool is_alias, bool dont_lock,
|
|
||||||
bool *was_flushed);
|
|
||||||
|
|
||||||
int mysql_ha_open(THD *thd, TABLE_LIST *tables)
|
|
||||||
|
/*
|
||||||
|
Get hash key and hash key length.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
mysql_ha_hash_get_key()
|
||||||
|
tables Pointer to the hash object.
|
||||||
|
key_len_p (out) Pointer to the result for key length.
|
||||||
|
first Unused.
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
The hash object is an TABLE_LIST struct.
|
||||||
|
The hash key is the alias name.
|
||||||
|
The hash key length is the alias name length plus one for the
|
||||||
|
terminateing NUL character.
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
Pointer to the TABLE_LIST struct.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static char *mysql_ha_hash_get_key(TABLE_LIST *tables, uint *key_len_p,
|
||||||
|
my_bool first __attribute__((unused)))
|
||||||
{
|
{
|
||||||
HANDLER_TABLES_HACK(thd);
|
*key_len_p= strlen(tables->alias) + 1 ; /* include '\0' in comparisons */
|
||||||
int err=open_tables(thd,tables);
|
return tables->alias;
|
||||||
HANDLER_TABLES_HACK(thd);
|
}
|
||||||
if (err)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
// there can be only one table in *tables
|
|
||||||
if (!(tables->table->file->table_flags() & HA_CAN_SQL_HANDLER))
|
/*
|
||||||
|
Free an hash object.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
mysql_ha_hash_free()
|
||||||
|
tables Pointer to the hash object.
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
The hash object is an TABLE_LIST struct.
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
Nothing
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void mysql_ha_hash_free(TABLE_LIST *tables)
|
||||||
|
{
|
||||||
|
my_free((char*) tables, MYF(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Open a HANDLER table.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
mysql_ha_open()
|
||||||
|
thd Thread identifier.
|
||||||
|
tables A list of tables with the first entry to open.
|
||||||
|
reopen Re-open a previously opened handler table.
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
Though this function takes a list of tables, only the first list entry
|
||||||
|
will be opened.
|
||||||
|
'reopen' is set when a handler table is to be re-opened. In this case,
|
||||||
|
'tables' is the pointer to the hashed TABLE_LIST object which has been
|
||||||
|
saved on the original open.
|
||||||
|
'reopen' is also used to suppress the sending of an 'ok' message or
|
||||||
|
error messages.
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 ok
|
||||||
|
!= 0 error
|
||||||
|
*/
|
||||||
|
|
||||||
|
int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
|
||||||
|
{
|
||||||
|
TABLE_LIST *hash_tables;
|
||||||
|
char *db;
|
||||||
|
char *name;
|
||||||
|
char *alias;
|
||||||
|
uint dblen;
|
||||||
|
uint namelen;
|
||||||
|
uint aliaslen;
|
||||||
|
int err;
|
||||||
|
DBUG_ENTER("mysql_ha_open");
|
||||||
|
DBUG_PRINT("enter",("mysql_ha_open: '%s'.'%s' as '%s' reopen %d",
|
||||||
|
tables->db, tables->real_name, tables->alias, reopen));
|
||||||
|
|
||||||
|
if (! hash_inited(&thd->handler_tables_hash))
|
||||||
{
|
{
|
||||||
my_printf_error(ER_ILLEGAL_HA,ER(ER_ILLEGAL_HA),MYF(0), tables->alias);
|
/*
|
||||||
mysql_ha_close(thd, tables,1);
|
HASH entries are of type TABLE_LIST.
|
||||||
return -1;
|
*/
|
||||||
|
if (hash_init(&thd->handler_tables_hash, HANDLER_TABLES_HASH_SIZE, 0, 0,
|
||||||
|
(hash_get_key) mysql_ha_hash_get_key,
|
||||||
|
(hash_free_key) mysql_ha_hash_free, 0))
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
else if (! reopen) /* Otherwise we have 'tables' already. */
|
||||||
|
{
|
||||||
|
if (hash_search(&thd->handler_tables_hash, (byte*) tables->alias,
|
||||||
|
strlen(tables->alias) + 1))
|
||||||
|
{
|
||||||
|
DBUG_PRINT("info",("mysql_ha_open: duplicate '%s'", tables->alias));
|
||||||
|
if (! reopen)
|
||||||
|
my_printf_error(ER_NONUNIQ_TABLE, ER(ER_NONUNIQ_TABLE),
|
||||||
|
MYF(0), tables->alias);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
send_ok(&thd->net);
|
/*
|
||||||
return 0;
|
open_tables() will set 'tables->table' if successful.
|
||||||
|
It must be NULL for a real open when calling open_tables().
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(! tables->table);
|
||||||
|
HANDLER_TABLES_HACK(thd);
|
||||||
|
err=open_tables(thd,tables);
|
||||||
|
HANDLER_TABLES_HACK(thd);
|
||||||
|
if (err)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* There can be only one table in '*tables'. */
|
||||||
|
if (! (tables->table->file->table_flags() & HA_CAN_SQL_HANDLER))
|
||||||
|
{
|
||||||
|
if (! reopen)
|
||||||
|
my_printf_error(ER_ILLEGAL_HA,ER(ER_ILLEGAL_HA),MYF(0), tables->alias);
|
||||||
|
mysql_ha_close(thd, tables);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! reopen)
|
||||||
|
{
|
||||||
|
/* copy the TABLE_LIST struct */
|
||||||
|
dblen= strlen(tables->db) + 1;
|
||||||
|
namelen= strlen(tables->real_name) + 1;
|
||||||
|
aliaslen= strlen(tables->alias) + 1;
|
||||||
|
if (!(my_multi_malloc(MYF(MY_WME),
|
||||||
|
&hash_tables, sizeof(*hash_tables),
|
||||||
|
&db, dblen,
|
||||||
|
&name, namelen,
|
||||||
|
&alias, aliaslen,
|
||||||
|
NullS)))
|
||||||
|
{
|
||||||
|
DBUG_PRINT("exit",("mysql_ha_open: malloc ERROR"));
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
/* structure copy */
|
||||||
|
*hash_tables= *tables;
|
||||||
|
hash_tables->db= db;
|
||||||
|
hash_tables->real_name= name;
|
||||||
|
hash_tables->alias= alias;
|
||||||
|
memcpy(hash_tables->db, tables->db, dblen);
|
||||||
|
memcpy(hash_tables->real_name, tables->real_name, namelen);
|
||||||
|
memcpy(hash_tables->alias, tables->alias, aliaslen);
|
||||||
|
|
||||||
|
/* add to hash */
|
||||||
|
if (hash_insert(&thd->handler_tables_hash, (byte*) hash_tables))
|
||||||
|
{
|
||||||
|
mysql_ha_close(thd, tables);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! reopen)
|
||||||
|
send_ok(&thd->net);
|
||||||
|
DBUG_PRINT("exit",("mysql_ha_open: OK"));
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
|
err:
|
||||||
|
DBUG_PRINT("exit",("mysql_ha_open: ERROR"));
|
||||||
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,145 +253,185 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables)
|
||||||
mysql_ha_close()
|
mysql_ha_close()
|
||||||
thd Thread identifier.
|
thd Thread identifier.
|
||||||
tables A list of tables with the first entry to close.
|
tables A list of tables with the first entry to close.
|
||||||
dont_send_ok Suppresses the commands' ok message and
|
|
||||||
error message and error return.
|
|
||||||
dont_lock Suppresses the normal locking of LOCK_open.
|
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
Though this function takes a list of tables, only the first list entry
|
Though this function takes a list of tables, only the first list entry
|
||||||
will be closed. Broadcasts a COND_refresh condition.
|
will be closed. Broadcasts a COND_refresh condition.
|
||||||
If mysql_ha_close() is not called from the parser, 'dont_send_ok'
|
|
||||||
must be set.
|
|
||||||
If the caller did already lock LOCK_open, it must set 'dont_lock'.
|
|
||||||
|
|
||||||
IMPLEMENTATION
|
|
||||||
find_table_ptr_by_name() closes the table, if a FLUSH TABLE is outstanding.
|
|
||||||
It returns a NULL pointer in this case, but flags the situation in
|
|
||||||
'was_flushed'. In that case the normal ER_UNKNOWN_TABLE error messages
|
|
||||||
is suppressed.
|
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
0 ok
|
0 ok
|
||||||
-1 error
|
!= 0 error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int mysql_ha_close(THD *thd, TABLE_LIST *tables,
|
int mysql_ha_close(THD *thd, TABLE_LIST *tables)
|
||||||
bool dont_send_ok, bool dont_lock, bool no_alias)
|
|
||||||
{
|
{
|
||||||
|
TABLE_LIST *hash_tables;
|
||||||
TABLE **table_ptr;
|
TABLE **table_ptr;
|
||||||
bool was_flushed;
|
bool was_flushed= FALSE;
|
||||||
|
bool not_opened;
|
||||||
|
DBUG_ENTER("mysql_ha_close");
|
||||||
|
DBUG_PRINT("enter",("mysql_ha_close: '%s'.'%s' as '%s'",
|
||||||
|
tables->db, tables->real_name, tables->alias));
|
||||||
|
|
||||||
table_ptr= find_table_ptr_by_name(thd, tables->db, tables->alias,
|
if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
|
||||||
!no_alias, dont_lock, &was_flushed);
|
(byte*) tables->alias,
|
||||||
if (*table_ptr)
|
strlen(tables->alias) + 1)))
|
||||||
{
|
{
|
||||||
if (!dont_lock)
|
/*
|
||||||
VOID(pthread_mutex_lock(&LOCK_open));
|
Though we could take the table pointer from hash_tables->table,
|
||||||
if (close_thread_table(thd, table_ptr))
|
we must follow the thd->handler_tables chain anyway, as we need the
|
||||||
|
address of the 'next' pointer referencing this table
|
||||||
|
for close_thread_table().
|
||||||
|
*/
|
||||||
|
for (table_ptr= &(thd->handler_tables);
|
||||||
|
*table_ptr && (*table_ptr != hash_tables->table);
|
||||||
|
table_ptr= &(*table_ptr)->next);
|
||||||
|
|
||||||
|
#if MYSQL_VERSION_ID < 40100
|
||||||
|
if (*tables->db && strcmp(hash_tables->db, tables->db))
|
||||||
{
|
{
|
||||||
/* Tell threads waiting for refresh that something has happened */
|
DBUG_PRINT("info",("mysql_ha_close: wrong db"));
|
||||||
VOID(pthread_cond_broadcast(&COND_refresh));
|
hash_tables= NULL;
|
||||||
}
|
}
|
||||||
if (!dont_lock)
|
else
|
||||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
#endif
|
||||||
}
|
|
||||||
else if (!was_flushed && !dont_send_ok)
|
|
||||||
{
|
|
||||||
my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
|
|
||||||
tables->alias, "HANDLER");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (!dont_send_ok)
|
|
||||||
send_ok(&thd->net);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Close a list of HANDLER tables.
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
mysql_ha_close_list()
|
|
||||||
thd Thread identifier.
|
|
||||||
tables The list of tables to close. If NULL,
|
|
||||||
close all HANDLER tables.
|
|
||||||
flushed Close only tables which are marked flushed.
|
|
||||||
Used only if tables is NULL.
|
|
||||||
|
|
||||||
DESCRIPTION
|
|
||||||
The list of HANDLER tables may be NULL, in which case all HANDLER
|
|
||||||
tables are closed. Broadcasts a COND_refresh condition, for
|
|
||||||
every table closed. If 'tables' is NULL and 'flushed' is set,
|
|
||||||
all HANDLER tables marked for flush are closed.
|
|
||||||
The caller must lock LOCK_open.
|
|
||||||
|
|
||||||
IMPLEMENTATION
|
|
||||||
find_table_ptr_by_name() closes the table, if it is marked for flush.
|
|
||||||
It returns a NULL pointer in this case, but flags the situation in
|
|
||||||
'was_flushed'. In that case the normal ER_UNKNOWN_TABLE error messages
|
|
||||||
is suppressed.
|
|
||||||
|
|
||||||
RETURN
|
|
||||||
0 ok
|
|
||||||
*/
|
|
||||||
|
|
||||||
int mysql_ha_close_list(THD *thd, TABLE_LIST *tables, bool flushed)
|
|
||||||
{
|
|
||||||
TABLE_LIST *tl_item;
|
|
||||||
TABLE **table_ptr;
|
|
||||||
|
|
||||||
if (tables)
|
|
||||||
{
|
|
||||||
for (tl_item= tables ; tl_item; tl_item= tl_item->next)
|
|
||||||
{
|
{
|
||||||
mysql_ha_close(thd, tl_item, /*dont_send_ok*/ 1,
|
if (*table_ptr)
|
||||||
/*dont_lock*/ 1, /*no_alias*/ 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
table_ptr= &(thd->handler_tables);
|
|
||||||
while (*table_ptr)
|
|
||||||
{
|
|
||||||
if (! flushed || ((*table_ptr)->version != refresh_version))
|
|
||||||
{
|
{
|
||||||
|
VOID(pthread_mutex_lock(&LOCK_open));
|
||||||
if (close_thread_table(thd, table_ptr))
|
if (close_thread_table(thd, table_ptr))
|
||||||
{
|
{
|
||||||
/* Tell threads waiting for refresh that something has happened */
|
/* Tell threads waiting for refresh that something has happened */
|
||||||
VOID(pthread_cond_broadcast(&COND_refresh));
|
VOID(pthread_cond_broadcast(&COND_refresh));
|
||||||
}
|
}
|
||||||
continue;
|
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||||
}
|
}
|
||||||
table_ptr= &((*table_ptr)->next);
|
|
||||||
|
hash_delete(&thd->handler_tables_hash, (byte*) hash_tables);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
if (! hash_tables)
|
||||||
|
{
|
||||||
|
#if MYSQL_VERSION_ID < 40100
|
||||||
|
char buff[MAX_DBKEY_LENGTH];
|
||||||
|
if (*tables->db)
|
||||||
|
strxnmov(buff, sizeof(buff), tables->db, ".", tables->real_name, NullS);
|
||||||
|
else
|
||||||
|
strncpy(buff, tables->alias, sizeof(buff));
|
||||||
|
my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
|
||||||
|
buff, "HANDLER");
|
||||||
|
#else
|
||||||
|
my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
|
||||||
|
tables->alias, "HANDLER");
|
||||||
|
#endif
|
||||||
|
DBUG_PRINT("exit",("mysql_ha_close: ERROR"));
|
||||||
|
DBUG_RETURN(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
send_ok(&thd->net);
|
||||||
|
DBUG_PRINT("exit",("mysql_ha_close: OK"));
|
||||||
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum enum_ha_read_modes rkey_to_rnext[]=
|
|
||||||
{ RNEXT_SAME, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV };
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Read from a HANDLER table.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
mysql_ha_read()
|
||||||
|
thd Thread identifier.
|
||||||
|
tables A list of tables with the first entry to read.
|
||||||
|
mode
|
||||||
|
keyname
|
||||||
|
key_expr
|
||||||
|
ha_rkey_mode
|
||||||
|
cond
|
||||||
|
select_limit
|
||||||
|
offset_limit
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 ok
|
||||||
|
!= 0 error
|
||||||
|
*/
|
||||||
|
|
||||||
int mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
int mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
||||||
enum enum_ha_read_modes mode, char *keyname, List<Item> *key_expr,
|
enum enum_ha_read_modes mode, char *keyname, List<Item> *key_expr,
|
||||||
enum ha_rkey_function ha_rkey_mode, Item *cond,
|
enum ha_rkey_function ha_rkey_mode, Item *cond,
|
||||||
ha_rows select_limit,ha_rows offset_limit)
|
ha_rows select_limit,ha_rows offset_limit)
|
||||||
{
|
{
|
||||||
int err, keyno=-1;
|
TABLE_LIST *hash_tables;
|
||||||
bool was_flushed;
|
TABLE *table;
|
||||||
TABLE *table= *find_table_ptr_by_name(thd, tables->db, tables->alias,
|
int err;
|
||||||
/*is_alias*/ 1, /*dont_lock*/ 0,
|
int keyno=-1;
|
||||||
&was_flushed);
|
uint num_rows;
|
||||||
|
bool was_flushed;
|
||||||
|
MYSQL_LOCK *lock;
|
||||||
|
DBUG_ENTER("mysql_ha_read");
|
||||||
|
DBUG_PRINT("enter",("mysql_ha_read: '%s'.'%s' as '%s'",
|
||||||
|
tables->db, tables->real_name, tables->alias));
|
||||||
|
|
||||||
|
List<Item> list;
|
||||||
|
list.push_front(new Item_field(NULL,NULL,"*"));
|
||||||
|
List_iterator<Item> it(list);
|
||||||
|
it++;
|
||||||
|
|
||||||
|
if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
|
||||||
|
(byte*) tables->alias,
|
||||||
|
strlen(tables->alias) + 1)))
|
||||||
|
{
|
||||||
|
table= hash_tables->table;
|
||||||
|
DBUG_PRINT("info",("mysql_ha_read: found in hash '%s'.'%s' as '%s' tab %p",
|
||||||
|
hash_tables->db, hash_tables->real_name,
|
||||||
|
hash_tables->alias, table));
|
||||||
|
if (!table)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
The handler table has been closed. Re-open it.
|
||||||
|
*/
|
||||||
|
if (mysql_ha_open(thd, hash_tables, 1))
|
||||||
|
{
|
||||||
|
DBUG_PRINT("exit",("mysql_ha_read: reopen failed"));
|
||||||
|
goto err0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table= hash_tables->table;
|
||||||
|
DBUG_PRINT("info",("mysql_ha_read: re-opened '%s'.'%s' as '%s' tab %p",
|
||||||
|
hash_tables->db, hash_tables->real_name,
|
||||||
|
hash_tables->alias, table));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MYSQL_VERSION_ID < 40100
|
||||||
|
if (*tables->db && strcmp(table->table_cache_key, tables->db))
|
||||||
|
{
|
||||||
|
DBUG_PRINT("info",("mysql_ha_read: wrong db"));
|
||||||
|
table= NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
table= NULL;
|
||||||
|
|
||||||
if (!table)
|
if (!table)
|
||||||
{
|
{
|
||||||
my_printf_error(ER_UNKNOWN_TABLE,ER(ER_UNKNOWN_TABLE),MYF(0),
|
#if MYSQL_VERSION_ID < 40100
|
||||||
tables->alias,"HANDLER");
|
char buff[MAX_DBKEY_LENGTH];
|
||||||
return -1;
|
if (*tables->db)
|
||||||
|
strxnmov(buff, sizeof(buff), tables->db, ".", tables->real_name, NullS);
|
||||||
|
else
|
||||||
|
strncpy(buff, tables->alias, sizeof(buff));
|
||||||
|
my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
|
||||||
|
buff, "HANDLER");
|
||||||
|
#else
|
||||||
|
my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
|
||||||
|
tables->alias, "HANDLER");
|
||||||
|
#endif
|
||||||
|
goto err0;
|
||||||
}
|
}
|
||||||
tables->table=table;
|
tables->table=table;
|
||||||
|
|
||||||
if (cond && cond->fix_fields(thd,tables))
|
if (cond && cond->fix_fields(thd,tables))
|
||||||
return -1;
|
goto err0;
|
||||||
|
|
||||||
table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it
|
table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it
|
||||||
|
|
||||||
|
@ -224,24 +441,19 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
||||||
{
|
{
|
||||||
my_printf_error(ER_KEY_DOES_NOT_EXITS,ER(ER_KEY_DOES_NOT_EXITS),MYF(0),
|
my_printf_error(ER_KEY_DOES_NOT_EXITS,ER(ER_KEY_DOES_NOT_EXITS),MYF(0),
|
||||||
keyname,tables->alias);
|
keyname,tables->alias);
|
||||||
return -1;
|
goto err0;
|
||||||
}
|
}
|
||||||
table->file->index_init(keyno);
|
table->file->index_init(keyno);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Item> list;
|
if (insert_fields(thd,tables,tables->db,tables->alias,&it))
|
||||||
list.push_front(new Item_field(NULL,NULL,"*"));
|
goto err0;
|
||||||
List_iterator<Item> it(list);
|
|
||||||
uint num_rows;
|
|
||||||
it++;
|
|
||||||
|
|
||||||
insert_fields(thd,tables,tables->db,tables->alias,&it);
|
|
||||||
|
|
||||||
select_limit+=offset_limit;
|
select_limit+=offset_limit;
|
||||||
send_fields(thd,list,1);
|
send_fields(thd,list,1);
|
||||||
|
|
||||||
HANDLER_TABLES_HACK(thd);
|
HANDLER_TABLES_HACK(thd);
|
||||||
MYSQL_LOCK *lock=mysql_lock_tables(thd,&tables->table,1);
|
lock= mysql_lock_tables(thd, &tables->table, 1);
|
||||||
HANDLER_TABLES_HACK(thd);
|
HANDLER_TABLES_HACK(thd);
|
||||||
|
|
||||||
byte *key;
|
byte *key;
|
||||||
|
@ -363,83 +575,155 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
||||||
ok:
|
ok:
|
||||||
mysql_unlock_tables(thd,lock);
|
mysql_unlock_tables(thd,lock);
|
||||||
send_eof(&thd->net);
|
send_eof(&thd->net);
|
||||||
return 0;
|
DBUG_PRINT("exit",("mysql_ha_read: OK"));
|
||||||
|
DBUG_RETURN(0);
|
||||||
err:
|
err:
|
||||||
mysql_unlock_tables(thd,lock);
|
mysql_unlock_tables(thd,lock);
|
||||||
err0:
|
err0:
|
||||||
return -1;
|
DBUG_PRINT("exit",("mysql_ha_read: ERROR"));
|
||||||
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Find a HANDLER table by name.
|
Flush (close) a list of HANDLER tables.
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
find_table_ptr_by_name()
|
mysql_ha_flush()
|
||||||
thd Thread identifier.
|
thd Thread identifier.
|
||||||
db Database (schema) name.
|
tables The list of tables to close. If NULL,
|
||||||
table_name Table name ;-).
|
close all HANDLER tables [marked as flushed].
|
||||||
is_alias Table name may be an alias name.
|
mode_flags MYSQL_HA_CLOSE_FINAL finally close the table.
|
||||||
dont_lock Suppresses the normal locking of LOCK_open.
|
MYSQL_HA_REOPEN_ON_USAGE mark for reopen.
|
||||||
|
MYSQL_HA_FLUSH_ALL flush all tables, not only
|
||||||
|
those marked for flush.
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
Find the table 'db'.'table_name' in the list of HANDLER tables of the
|
The list of HANDLER tables may be NULL, in which case all HANDLER
|
||||||
thread 'thd'. If the table has been marked by FLUSH TABLE(S), close it,
|
tables are closed (if MYSQL_HA_FLUSH_ALL) is set.
|
||||||
flag this situation in '*was_flushed' and broadcast a COND_refresh
|
If 'tables' is NULL and MYSQL_HA_FLUSH_ALL is not set,
|
||||||
condition.
|
all HANDLER tables marked for flush are closed.
|
||||||
An empty database (schema) name matches all database (schema) names.
|
Broadcasts a COND_refresh condition, for every table closed.
|
||||||
If the caller did already lock LOCK_open, it must set 'dont_lock'.
|
The caller must lock LOCK_open.
|
||||||
|
|
||||||
IMPLEMENTATION
|
NOTE
|
||||||
Just in case that the table is twice in 'thd->handler_tables' (!?!),
|
Since mysql_ha_flush() is called when the base table has to be closed,
|
||||||
the loop does not break when the table was flushed. If another table
|
we compare real table names, not aliases. Hence, database names matter.
|
||||||
by that name was found and not flushed, '*was_flushed' is cleared again,
|
|
||||||
since a pointer to an open HANDLER table is returned.
|
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
*was_flushed Table has been closed due to FLUSH TABLE.
|
0 ok
|
||||||
NULL A HANDLER Table by that name does not exist (any more).
|
|
||||||
!= NULL Pointer to the TABLE structure.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static TABLE **find_table_ptr_by_name(THD *thd, const char *db,
|
int mysql_ha_flush(THD *thd, TABLE_LIST *tables, int mode_flags)
|
||||||
const char *table_name,
|
|
||||||
bool is_alias, bool dont_lock,
|
|
||||||
bool *was_flushed)
|
|
||||||
{
|
{
|
||||||
int dblen;
|
TABLE_LIST **tmp_tables_p;
|
||||||
TABLE **table_ptr;
|
TABLE_LIST *tmp_tables;
|
||||||
|
TABLE **table_ptr;
|
||||||
|
bool was_flushed;
|
||||||
|
DBUG_ENTER("mysql_ha_flush");
|
||||||
|
DBUG_PRINT("enter",("mysql_ha_flush: tables %p mode_flags 0x%02x",
|
||||||
|
tables, mode_flags));
|
||||||
|
|
||||||
DBUG_ASSERT(db);
|
if (tables)
|
||||||
dblen= *db ? strlen(db)+1 : 0;
|
|
||||||
table_ptr= &(thd->handler_tables);
|
|
||||||
*was_flushed= FALSE;
|
|
||||||
|
|
||||||
for (TABLE *table=*table_ptr; table ; table=*table_ptr)
|
|
||||||
{
|
{
|
||||||
if ((!dblen || !memcmp(table->table_cache_key, db, dblen)) &&
|
/* Close all tables in the list. */
|
||||||
!my_strcasecmp((is_alias ? table->table_name : table->real_name),
|
for (tmp_tables= tables ; tmp_tables; tmp_tables= tmp_tables->next)
|
||||||
table_name))
|
|
||||||
{
|
{
|
||||||
if (table->version != refresh_version)
|
DBUG_PRINT("info",("mysql_ha_flush: in tables list '%s'.'%s' as '%s'",
|
||||||
|
tmp_tables->db, tmp_tables->real_name,
|
||||||
|
tmp_tables->alias));
|
||||||
|
/* Close all currently open handler tables with the same base table. */
|
||||||
|
table_ptr= &(thd->handler_tables);
|
||||||
|
while (*table_ptr)
|
||||||
{
|
{
|
||||||
if (!dont_lock)
|
if ((! *tmp_tables->db ||
|
||||||
VOID(pthread_mutex_lock(&LOCK_open));
|
! my_strcasecmp((*table_ptr)->table_cache_key, tmp_tables->db)) &&
|
||||||
if (close_thread_table(thd, table_ptr))
|
! my_strcasecmp((*table_ptr)->real_name, tmp_tables->real_name))
|
||||||
{
|
{
|
||||||
/* Tell threads waiting for refresh that something has happened */
|
DBUG_PRINT("info",("mysql_ha_flush: *table_ptr '%s'.'%s' as '%s'",
|
||||||
VOID(pthread_cond_broadcast(&COND_refresh));
|
(*table_ptr)->table_cache_key,
|
||||||
|
(*table_ptr)->real_name,
|
||||||
|
(*table_ptr)->table_name));
|
||||||
|
mysql_ha_flush_table(thd, table_ptr, mode_flags);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (!dont_lock)
|
table_ptr= &(*table_ptr)->next;
|
||||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
}
|
||||||
*was_flushed= TRUE;
|
/* end of handler_tables list */
|
||||||
|
}
|
||||||
|
/* end of flush tables list */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Close all currently open tables [which are marked for flush]. */
|
||||||
|
table_ptr= &(thd->handler_tables);
|
||||||
|
while (*table_ptr)
|
||||||
|
{
|
||||||
|
if ((mode_flags & MYSQL_HA_FLUSH_ALL) ||
|
||||||
|
((*table_ptr)->version != refresh_version))
|
||||||
|
{
|
||||||
|
mysql_ha_flush_table(thd, table_ptr, mode_flags);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
*was_flushed= FALSE;
|
table_ptr= &(*table_ptr)->next;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
table_ptr=&(table->next);
|
|
||||||
}
|
}
|
||||||
return table_ptr;
|
|
||||||
|
DBUG_PRINT("exit",("mysql_ha_flush: OK"));
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Flush (close) a table.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
mysql_ha_flush_table()
|
||||||
|
thd Thread identifier.
|
||||||
|
table The table to close.
|
||||||
|
mode_flags MYSQL_HA_CLOSE_FINAL finally close the table.
|
||||||
|
MYSQL_HA_REOPEN_ON_USAGE mark for reopen.
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
Broadcasts a COND_refresh condition, for every table closed.
|
||||||
|
The caller must lock LOCK_open.
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 ok
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, int mode_flags)
|
||||||
|
{
|
||||||
|
TABLE_LIST *hash_tables;
|
||||||
|
TABLE *table= *table_ptr;
|
||||||
|
bool was_flushed;
|
||||||
|
DBUG_ENTER("mysql_ha_flush_table");
|
||||||
|
DBUG_PRINT("info",("mysql_ha_flush_table: '%s'.'%s' as '%s' flags 0x%02x",
|
||||||
|
table->table_cache_key, table->real_name,
|
||||||
|
table->table_name, mode_flags));
|
||||||
|
|
||||||
|
if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
|
||||||
|
(*table_ptr)->table_name,
|
||||||
|
strlen((*table_ptr)->table_name) + 1)))
|
||||||
|
{
|
||||||
|
if (! (mode_flags & MYSQL_HA_REOPEN_ON_USAGE))
|
||||||
|
{
|
||||||
|
/* This is a final close. Remove from hash. */
|
||||||
|
hash_delete(&thd->handler_tables_hash, (byte*) hash_tables);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Mark table as closed, ready for re-open. */
|
||||||
|
hash_tables->table= NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (close_thread_table(thd, table_ptr))
|
||||||
|
{
|
||||||
|
/* Tell threads waiting for refresh that something has happened */
|
||||||
|
VOID(pthread_cond_broadcast(&COND_refresh));
|
||||||
|
}
|
||||||
|
|
||||||
|
DBUG_PRINT("exit",("mysql_ha_flush_table: OK"));
|
||||||
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,7 +186,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||||
for (table=tables ; table ; table=table->next)
|
for (table=tables ; table ; table=table->next)
|
||||||
{
|
{
|
||||||
char *db=table->db;
|
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))
|
if (!close_temporary_table(thd, db, table->real_name))
|
||||||
{
|
{
|
||||||
tmp_table_deleted=1;
|
tmp_table_deleted=1;
|
||||||
|
@ -1253,7 +1253,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
|
||||||
if (send_fields(thd, field_list, 1))
|
if (send_fields(thd, field_list, 1))
|
||||||
DBUG_RETURN(-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)
|
for (table = tables; table; table = table->next)
|
||||||
{
|
{
|
||||||
char table_name[NAME_LEN*2+2];
|
char table_name[NAME_LEN*2+2];
|
||||||
|
@ -1514,7 +1514,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
||||||
}
|
}
|
||||||
used_fields=create_info->used_fields;
|
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)))
|
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue