Commit 69bf342a authored by ingo/mydev@chilla.local's avatar ingo/mydev@chilla.local

Merge chilla.local:/home/mydev/mysql-5.1-amerge

into  chilla.local:/home/mydev/mysql-5.1-aid
parents 4cdb1469 99a2489e
...@@ -1558,6 +1558,8 @@ id ...@@ -1558,6 +1558,8 @@ id
3 3
4 4
5 5
DROP TABLE federated.t1;
DROP TABLE federated.t1;
DROP TABLE IF EXISTS federated.bug_17377_table; DROP TABLE IF EXISTS federated.bug_17377_table;
CREATE TABLE federated.bug_17377_table ( CREATE TABLE federated.bug_17377_table (
`fld_cid` bigint(20) NOT NULL auto_increment, `fld_cid` bigint(20) NOT NULL auto_increment,
...@@ -1601,7 +1603,92 @@ fld_cid fld_name fld_parentid fld_delt ...@@ -1601,7 +1603,92 @@ fld_cid fld_name fld_parentid fld_delt
5 Torkel 0 0 5 Torkel 0 0
DROP TABLE federated.t1; DROP TABLE federated.t1;
DROP TABLE federated.bug_17377_table; DROP TABLE federated.bug_17377_table;
DROP TABLE federated.t1; create table federated.t1 (i1 int, i2 int, i3 int);
create table federated.t2 (id int, c1 varchar(20), c2 varchar(20));
create table federated.t1 (i1 int, i2 int, i3 int) ENGINE=FEDERATED CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
create table federated.t2 (id int, c1 varchar(20), c2 varchar(20)) ENGINE=FEDERATED CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t2';
insert into federated.t1 values (1,5,10),(3,7,12),(4,5,2),(9,10,15),(2,2,2);
insert into federated.t2 values (9,"abc","def"),(5,"opq","lmn"),(2,"test t","t test");
select * from federated.t1 order by i1;
i1 i2 i3
1 5 10
2 2 2
3 7 12
4 5 2
9 10 15
select * from federated.t2;
id c1 c2
9 abc def
5 opq lmn
2 test t t test
update federated.t1,federated.t2 set t1.i2=15, t2.c2="ppc" where t1.i1=t2.id;
select * from federated.t1 order by i1;
i1 i2 i3
1 5 10
2 15 2
3 7 12
4 5 2
9 15 15
select * from federated.t2 order by id;
id c1 c2
2 test t ppc
5 opq lmn
9 abc ppc
delete federated.t1.*,federated.t2.* from federated.t1,federated.t2 where t1.i2=t2.id;
select * from federated.t1 order by i1;
i1 i2 i3
2 15 2
3 7 12
9 15 15
select * from federated.t2 order by id;
id c1 c2
2 test t ppc
9 abc ppc
drop table federated.t1, federated.t2;
drop table federated.t1, federated.t2;
create table federated.t1 (i1 int, i2 int, i3 int, primary key (i1));
create table federated.t2 (id int, c1 varchar(20), c2 varchar(20), primary key (id));
create table federated.t1 (i1 int auto_increment not null, i2 int, i3 int, primary key (i1)) ENGINE=FEDERATED CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1';
create table federated.t2 (id int auto_increment not null, c1 varchar(20), c2 varchar(20), primary key(id)) ENGINE=FEDERATED CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t2';
insert into federated.t1 values (1,5,10),(3,7,12),(4,5,2),(9,10,15),(2,2,2);
insert into federated.t2 values (9,"abc","def"),(5,"opq","lmn"),(2,"test t","t test");
select * from federated.t1 order by i1;
i1 i2 i3
1 5 10
2 2 2
3 7 12
4 5 2
9 10 15
select * from federated.t2 order by id;
id c1 c2
2 test t t test
5 opq lmn
9 abc def
update federated.t1,federated.t2 set t1.i2=15, t2.c2="ppc" where t1.i1=t2.id;
select * from federated.t1 order by i1;
i1 i2 i3
1 5 10
2 15 2
3 7 12
4 5 2
9 15 15
select * from federated.t2 order by id;
id c1 c2
2 test t ppc
5 opq lmn
9 abc ppc
delete federated.t1.*,federated.t2.* from federated.t1,federated.t2 where t1.i2=t2.id;
select * from federated.t1 order by i1;
i1 i2 i3
2 15 2
3 7 12
9 15 15
select * from federated.t2 order by id;
id c1 c2
2 test t ppc
9 abc ppc
drop table federated.t1, federated.t2;
drop table federated.t1, federated.t2;
DROP TABLE IF EXISTS federated.t1; DROP TABLE IF EXISTS federated.t1;
DROP DATABASE IF EXISTS federated; DROP DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1; DROP TABLE IF EXISTS federated.t1;
......
...@@ -1256,6 +1256,10 @@ SELECT LAST_INSERT_ID(); ...@@ -1256,6 +1256,10 @@ SELECT LAST_INSERT_ID();
INSERT INTO federated.t1 VALUES (); INSERT INTO federated.t1 VALUES ();
SELECT LAST_INSERT_ID(); SELECT LAST_INSERT_ID();
SELECT * FROM federated.t1; SELECT * FROM federated.t1;
DROP TABLE federated.t1;
connection slave;
DROP TABLE federated.t1;
# #
# Bug#17377 Federated Engine returns wrong Data, always the rows # Bug#17377 Federated Engine returns wrong Data, always the rows
...@@ -1310,19 +1314,19 @@ select * from federated.t1 where fld_parentid=0 and fld_delt=0; ...@@ -1310,19 +1314,19 @@ select * from federated.t1 where fld_parentid=0 and fld_delt=0;
DROP TABLE federated.t1; DROP TABLE federated.t1;
connection slave; connection slave;
DROP TABLE federated.bug_17377_table; DROP TABLE federated.bug_17377_table;
DROP TABLE federated.t1;
# #
# Test multi updates and deletes without keys # BUG 19773 Crash when using multi-table updates, deletes
# with federated tables
# #
# The following can be enabled when bug #19773 has been fixed
--disable_parsing
connection slave; connection slave;
create table federated.t1 (i1 int, i2 int, i3 int); create table federated.t1 (i1 int, i2 int, i3 int);
create table federated.t2 (id int, c1 varchar(20), c2 varchar(20)); create table federated.t2 (id int, c1 varchar(20), c2 varchar(20));
connection master; connection master;
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval create table federated.t1 (i1 int, i2 int, i3 int) ENGINE=FEDERATED CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; eval create table federated.t1 (i1 int, i2 int, i3 int) ENGINE=FEDERATED CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval create table federated.t2 (id int, c1 varchar(20), c2 varchar(20)) ENGINE=FEDERATED CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t2'; eval create table federated.t2 (id int, c1 varchar(20), c2 varchar(20)) ENGINE=FEDERATED CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t2';
insert into federated.t1 values (1,5,10),(3,7,12),(4,5,2),(9,10,15),(2,2,2); insert into federated.t1 values (1,5,10),(3,7,12),(4,5,2),(9,10,15),(2,2,2);
insert into federated.t2 values (9,"abc","def"),(5,"opq","lmn"),(2,"test t","t test"); insert into federated.t2 values (9,"abc","def"),(5,"opq","lmn"),(2,"test t","t test");
...@@ -1331,22 +1335,23 @@ select * from federated.t2; ...@@ -1331,22 +1335,23 @@ select * from federated.t2;
update federated.t1,federated.t2 set t1.i2=15, t2.c2="ppc" where t1.i1=t2.id; update federated.t1,federated.t2 set t1.i2=15, t2.c2="ppc" where t1.i1=t2.id;
select * from federated.t1 order by i1; select * from federated.t1 order by i1;
select * from federated.t2 order by id; select * from federated.t2 order by id;
delete t1.*,t2.* from federated.t1,federated.t2 where t1.i2=t2.id; delete federated.t1.*,federated.t2.* from federated.t1,federated.t2 where t1.i2=t2.id;
select * from federated.t1 order by i1; select * from federated.t1 order by i1;
select * from federated.t2 order by id; select * from federated.t2 order by id;
drop table federated.t1, federated.t2; drop table federated.t1, federated.t2;
connection slave; connection slave;
drop table federated.t1, federated.t2; drop table federated.t1, federated.t2;
connection master;
# Test multi updates and deletes with keys # Test multi updates and deletes with keys
connection slave; connection slave;
create table federated.t1 (i1 int, i2 int, i3 int, primary key (i1)); create table federated.t1 (i1 int, i2 int, i3 int, primary key (i1));
create table federated.t2 (id int, c1 varchar(20), c2 varchar(20), primary key (id)); create table federated.t2 (id int, c1 varchar(20), c2 varchar(20), primary key (id));
connection master; connection master;
eval create table federated.t1 (i1 int auto_increment not null, i2 int, i3 int, primary key (i1)) ENGINE=FEDERATED ENGINE=FEDERATED CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1'; --replace_result $SLAVE_MYPORT SLAVE_PORT
eval create table federated.t2 (id int auto_increment not null, c1 varchar(20), c2 varchar(20), primary key(id)) ENGINE=FEDERATED ENGINE=FEDERATED CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t2'; eval create table federated.t1 (i1 int auto_increment not null, i2 int, i3 int, primary key (i1)) ENGINE=FEDERATED CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t1';
--replace_result $SLAVE_MYPORT SLAVE_PORT
eval create table federated.t2 (id int auto_increment not null, c1 varchar(20), c2 varchar(20), primary key(id)) ENGINE=FEDERATED CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t2';
insert into federated.t1 values (1,5,10),(3,7,12),(4,5,2),(9,10,15),(2,2,2); insert into federated.t1 values (1,5,10),(3,7,12),(4,5,2),(9,10,15),(2,2,2);
insert into federated.t2 values (9,"abc","def"),(5,"opq","lmn"),(2,"test t","t test"); insert into federated.t2 values (9,"abc","def"),(5,"opq","lmn"),(2,"test t","t test");
select * from federated.t1 order by i1; select * from federated.t1 order by i1;
...@@ -1354,13 +1359,12 @@ select * from federated.t2 order by id; ...@@ -1354,13 +1359,12 @@ select * from federated.t2 order by id;
update federated.t1,federated.t2 set t1.i2=15, t2.c2="ppc" where t1.i1=t2.id; update federated.t1,federated.t2 set t1.i2=15, t2.c2="ppc" where t1.i1=t2.id;
select * from federated.t1 order by i1; select * from federated.t1 order by i1;
select * from federated.t2 order by id; select * from federated.t2 order by id;
delete t1.*,t2.* from federated.t1,federated.t2 where t1.i2=t2.id; delete federated.t1.*,federated.t2.* from federated.t1,federated.t2 where t1.i2=t2.id;
select * from federated.t1 order by i1; select * from federated.t1 order by i1;
select * from federated.t2 order by id; select * from federated.t2 order by id;
drop table federated.t1, federated.t2; drop table federated.t1, federated.t2;
connection slave; connection slave;
drop table federated.t1, federated.t2; drop table federated.t1, federated.t2;
connection master;
--enable_parsing
--source include/federated_cleanup.inc source include/federated_cleanup.inc;
...@@ -32,13 +32,14 @@ ...@@ -32,13 +32,14 @@
so to read, that data has to be parsed into fields, to write, fields have to so to read, that data has to be parsed into fields, to write, fields have to
be stored in this format to write to this data file. be stored in this format to write to this data file.
With MySQL Federated storage engine, there will be no local files for each With MySQL Federated storage engine, there will be no local files
table's data (such as .MYD). A foreign database will store the data that would for each table's data (such as .MYD). A foreign database will store
normally be in this file. This will necessitate the use of MySQL client API the data that would normally be in this file. This will necessitate
to read, delete, update, insert this data. The data will have to be retrieve the use of MySQL client API to read, delete, update, insert this
via an SQL call "SELECT * FROM users". Then, to read this data, it will have data. The data will have to be retrieve via an SQL call "SELECT *
to be retrieved via mysql_fetch_row one row at a time, then converted from FROM users". Then, to read this data, it will have to be retrieved
the column in this select into the format that the handler expects. via mysql_fetch_row one row at a time, then converted from the
column in this select into the format that the handler expects.
The create table will simply create the .frm file, and within the The create table will simply create the .frm file, and within the
"CREATE TABLE" SQL, there SHALL be any of the following : "CREATE TABLE" SQL, there SHALL be any of the following :
...@@ -385,8 +386,8 @@ static handler *federated_create_handler(TABLE_SHARE *table, ...@@ -385,8 +386,8 @@ static handler *federated_create_handler(TABLE_SHARE *table,
static byte *federated_get_key(FEDERATED_SHARE *share, uint *length, static byte *federated_get_key(FEDERATED_SHARE *share, uint *length,
my_bool not_used __attribute__ ((unused))) my_bool not_used __attribute__ ((unused)))
{ {
*length= share->table_name_length; *length= share->connect_string_length;
return (byte*) share->table_name; return (byte*) share->scheme;
} }
/* /*
...@@ -415,7 +416,7 @@ int federated_db_init() ...@@ -415,7 +416,7 @@ int federated_db_init()
if (pthread_mutex_init(&federated_mutex, MY_MUTEX_INIT_FAST)) if (pthread_mutex_init(&federated_mutex, MY_MUTEX_INIT_FAST))
goto error; goto error;
if (!hash_init(&federated_open_tables, system_charset_info, 32, 0, 0, if (!hash_init(&federated_open_tables, &my_charset_bin, 32, 0, 0,
(hash_get_key) federated_get_key, 0, 0)) (hash_get_key) federated_get_key, 0, 0))
{ {
federated_init= TRUE; federated_init= TRUE;
...@@ -510,6 +511,7 @@ static int check_foreign_data_source(FEDERATED_SHARE *share, ...@@ -510,6 +511,7 @@ static int check_foreign_data_source(FEDERATED_SHARE *share,
} }
else else
{ {
int escaped_table_name_length= 0;
/* /*
Since we do not support transactions at this version, we can let the Since we do not support transactions at this version, we can let the
client API silently reconnect. For future versions, we will need more client API silently reconnect. For future versions, we will need more
...@@ -528,17 +530,16 @@ static int check_foreign_data_source(FEDERATED_SHARE *share, ...@@ -528,17 +530,16 @@ static int check_foreign_data_source(FEDERATED_SHARE *share,
query.append(FEDERATED_STAR); query.append(FEDERATED_STAR);
query.append(FEDERATED_FROM); query.append(FEDERATED_FROM);
query.append(FEDERATED_BTICK); query.append(FEDERATED_BTICK);
escape_string_for_mysql(&my_charset_bin, (char *)escaped_table_name, escaped_table_name_length=
escape_string_for_mysql(&my_charset_bin, (char*)escaped_table_name,
sizeof(escaped_table_name), sizeof(escaped_table_name),
share->table_name, share->table_name,
share->table_name_length); share->table_name_length);
query.append(escaped_table_name); query.append(escaped_table_name, escaped_table_name_length);
query.append(FEDERATED_BTICK); query.append(FEDERATED_BTICK);
query.append(FEDERATED_WHERE); query.append(FEDERATED_WHERE);
query.append(FEDERATED_FALSE); query.append(FEDERATED_FALSE);
DBUG_PRINT("info", ("check_foreign_data_source query %s",
query.c_ptr_quick()));
if (mysql_real_query(mysql, query.ptr(), query.length())) if (mysql_real_query(mysql, query.ptr(), query.length()))
{ {
error_code= table_create_flag ? error_code= table_create_flag ?
...@@ -632,8 +633,7 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, ...@@ -632,8 +633,7 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
share->scheme= my_strndup(table->s->connect_string.str, share->scheme= my_strndup(table->s->connect_string.str,
table->s->connect_string.length, MYF(0)); table->s->connect_string.length, MYF(0));
// Add a null for later termination of table name share->connect_string_length= table->s->connect_string.length;
share->scheme[table->s->connect_string.length]= 0;
DBUG_PRINT("info",("parse_url alloced share->scheme %lx", share->scheme)); DBUG_PRINT("info",("parse_url alloced share->scheme %lx", share->scheme));
/* /*
...@@ -735,8 +735,7 @@ error: ...@@ -735,8 +735,7 @@ error:
ha_federated::ha_federated(TABLE_SHARE *table_arg) ha_federated::ha_federated(TABLE_SHARE *table_arg)
:handler(&federated_hton, table_arg), :handler(&federated_hton, table_arg),
mysql(0), stored_result(0), mysql(0), stored_result(0)
ref_length(sizeof(MYSQL_ROW_OFFSET)), current_position(0)
{ {
trx_next= 0; trx_next= 0;
} }
...@@ -749,6 +748,7 @@ ha_federated::ha_federated(TABLE_SHARE *table_arg) ...@@ -749,6 +748,7 @@ ha_federated::ha_federated(TABLE_SHARE *table_arg)
convert_row_to_internal_format() convert_row_to_internal_format()
record Byte pointer to record record Byte pointer to record
row MySQL result set row from fetchrow() row MySQL result set row from fetchrow()
result Result set to use
DESCRIPTION DESCRIPTION
This method simply iterates through a row returned via fetchrow with This method simply iterates through a row returned via fetchrow with
...@@ -761,15 +761,16 @@ ha_federated::ha_federated(TABLE_SHARE *table_arg) ...@@ -761,15 +761,16 @@ ha_federated::ha_federated(TABLE_SHARE *table_arg)
0 After fields have had field values stored from record 0 After fields have had field values stored from record
*/ */
uint ha_federated::convert_row_to_internal_format(byte *record, MYSQL_ROW row) uint ha_federated::convert_row_to_internal_format(byte *record,
MYSQL_ROW row,
MYSQL_RES *result)
{ {
ulong *lengths; ulong *lengths;
Field **field; Field **field;
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set); my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
DBUG_ENTER("ha_federated::convert_row_to_internal_format"); DBUG_ENTER("ha_federated::convert_row_to_internal_format");
lengths= mysql_fetch_lengths(stored_result); lengths= mysql_fetch_lengths(result);
memset(record, 0, table->s->null_bytes);
for (field= table->field; *field; field++, row++, lengths++) for (field= table->field; *field; field++, row++, lengths++)
{ {
...@@ -1314,12 +1315,11 @@ err: ...@@ -1314,12 +1315,11 @@ err:
static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
{ {
char *select_query, *tmp_table_name; char *select_query;
char query_buffer[FEDERATED_QUERY_BUFFER_SIZE]; char query_buffer[FEDERATED_QUERY_BUFFER_SIZE];
uint tmp_table_name_length;
Field **field; Field **field;
String query(query_buffer, sizeof(query_buffer), &my_charset_bin); String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
FEDERATED_SHARE *share; FEDERATED_SHARE *share= NULL, tmp_share;
/* /*
In order to use this string, we must first zero it's length, In order to use this string, we must first zero it's length,
or it will contain garbage or it will contain garbage
...@@ -1327,12 +1327,15 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) ...@@ -1327,12 +1327,15 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
query.length(0); query.length(0);
pthread_mutex_lock(&federated_mutex); pthread_mutex_lock(&federated_mutex);
tmp_table_name= table->s->table_name.str;
tmp_table_name_length= table->s->table_name.length;
if (parse_url(&tmp_share, table, 0))
goto error;
/* TODO: change tmp_share.scheme to LEX_STRING object */
if (!(share= (FEDERATED_SHARE *) hash_search(&federated_open_tables, if (!(share= (FEDERATED_SHARE *) hash_search(&federated_open_tables,
(byte*) table_name, (byte*) tmp_share.scheme,
tmp_table_name_length))) tmp_share.
connect_string_length)))
{ {
query.set_charset(system_charset_info); query.set_charset(system_charset_info);
query.append(FEDERATED_SELECT); query.append(FEDERATED_SELECT);
...@@ -1350,18 +1353,15 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) ...@@ -1350,18 +1353,15 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
if (!(share= (FEDERATED_SHARE *) if (!(share= (FEDERATED_SHARE *)
my_multi_malloc(MYF(MY_WME), my_multi_malloc(MYF(MY_WME),
&share, sizeof(*share), &share, sizeof(*share),
&tmp_table_name, tmp_table_name_length+ 1,
&select_query, &select_query,
query.length()+table->s->connect_string.length+1, query.length()+table->s->connect_string.length+1,
NullS))) NullS)))
{
pthread_mutex_unlock(&federated_mutex);
return NULL;
}
if (parse_url(share, table, 0))
goto error; goto error;
memcpy(share, &tmp_share, sizeof(tmp_share));
share->table_name_length= strlen(share->table_name);
/* TODO: share->table_name to LEX_STRING object */
query.append(share->table_name, share->table_name_length); query.append(share->table_name, share->table_name_length);
query.append(FEDERATED_BTICK); query.append(FEDERATED_BTICK);
share->select_query= select_query; share->select_query= select_query;
...@@ -1382,11 +1382,8 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table) ...@@ -1382,11 +1382,8 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
error: error:
pthread_mutex_unlock(&federated_mutex); pthread_mutex_unlock(&federated_mutex);
if (share->scheme) my_free((gptr) tmp_share.scheme, MYF(MY_ALLOW_ZERO_PTR));
{ my_free((gptr) share, MYF(MY_ALLOW_ZERO_PTR));
my_free((gptr) share->scheme, MYF(0));
share->scheme= 0;
}
return NULL; return NULL;
} }
...@@ -1406,13 +1403,7 @@ static int free_share(FEDERATED_SHARE *share) ...@@ -1406,13 +1403,7 @@ static int free_share(FEDERATED_SHARE *share)
{ {
hash_delete(&federated_open_tables, (byte*) share); hash_delete(&federated_open_tables, (byte*) share);
my_free((gptr) share->scheme, MYF(MY_ALLOW_ZERO_PTR)); my_free((gptr) share->scheme, MYF(MY_ALLOW_ZERO_PTR));
share->scheme= 0;
if (share->socket)
{
my_free((gptr) share->socket, MYF(MY_ALLOW_ZERO_PTR)); my_free((gptr) share->socket, MYF(MY_ALLOW_ZERO_PTR));
share->socket= 0;
}
thr_lock_delete(&share->lock); thr_lock_delete(&share->lock);
VOID(pthread_mutex_destroy(&share->mutex)); VOID(pthread_mutex_destroy(&share->mutex));
my_free((gptr) share, MYF(0)); my_free((gptr) share, MYF(0));
...@@ -1474,7 +1465,7 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked) ...@@ -1474,7 +1465,7 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked)
/* Connect to foreign database mysql_real_connect() */ /* Connect to foreign database mysql_real_connect() */
mysql= mysql_init(0); mysql= mysql_init(0);
if (!mysql_real_connect(mysql, if (!mysql || !mysql_real_connect(mysql,
share->hostname, share->hostname,
share->username, share->username,
share->password, share->password,
...@@ -1482,6 +1473,7 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked) ...@@ -1482,6 +1473,7 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked)
share->port, share->port,
share->socket, 0)) share->socket, 0))
{ {
free_share(share);
DBUG_RETURN(stash_remote_error()); DBUG_RETURN(stash_remote_error());
} }
/* /*
...@@ -1491,6 +1483,11 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked) ...@@ -1491,6 +1483,11 @@ int ha_federated::open(const char *name, int mode, uint test_if_locked)
*/ */
mysql->reconnect= 1; mysql->reconnect= 1;
ref_length= (table->s->primary_key != MAX_KEY ?
table->key_info[table->s->primary_key].key_length :
table->s->reclength);
DBUG_PRINT("info", ("ref_length: %u", ref_length));
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -1514,12 +1511,11 @@ int ha_federated::close(void) ...@@ -1514,12 +1511,11 @@ int ha_federated::close(void)
/* free the result set */ /* free the result set */
if (stored_result) if (stored_result)
{ {
DBUG_PRINT("info",
("mysql_free_result result at address %lx", stored_result));
mysql_free_result(stored_result); mysql_free_result(stored_result);
stored_result= 0; stored_result= 0;
} }
/* Disconnect from mysql */ /* Disconnect from mysql */
if (mysql) // QQ is this really needed
mysql_close(mysql); mysql_close(mysql);
retval= free_share(share); retval= free_share(share);
DBUG_RETURN(retval); DBUG_RETURN(retval);
...@@ -1686,8 +1682,6 @@ int ha_federated::write_row(byte *buf) ...@@ -1686,8 +1682,6 @@ int ha_federated::write_row(byte *buf)
/* add the values */ /* add the values */
insert_string.append(values_string); insert_string.append(values_string);
DBUG_PRINT("info", ("insert query %s", insert_string.c_ptr_quick()));
if (mysql_real_query(mysql, insert_string.ptr(), insert_string.length())) if (mysql_real_query(mysql, insert_string.ptr(), insert_string.length()))
{ {
DBUG_RETURN(stash_remote_error()); DBUG_RETURN(stash_remote_error());
...@@ -1919,7 +1913,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data) ...@@ -1919,7 +1913,7 @@ int ha_federated::update_row(const byte *old_data, byte *new_data)
/* /*
This will delete a row. 'buf' will contain a copy of the row to be =deleted. This will delete a row. 'buf' will contain a copy of the row to be =deleted.
The server will call this right after the current row has been called (from The server will call this right after the current row has been called (from
either a previous rnd_nexT() or index call). either a previous rnd_next() or index call).
If you keep a pointer to the last row or can access a primary key it will If you keep a pointer to the last row or can access a primary key it will
make doing the deletion quite a bit easier. make doing the deletion quite a bit easier.
Keep in mind that the server does no guarentee consecutive deletions. Keep in mind that the server does no guarentee consecutive deletions.
...@@ -1985,6 +1979,7 @@ int ha_federated::delete_row(const byte *buf) ...@@ -1985,6 +1979,7 @@ int ha_federated::delete_row(const byte *buf)
DBUG_RETURN(stash_remote_error()); DBUG_RETURN(stash_remote_error());
} }
stats.deleted+= mysql->affected_rows; stats.deleted+= mysql->affected_rows;
stats.records-= mysql->affected_rows;
DBUG_PRINT("info", DBUG_PRINT("info",
("rows deleted %d rows deleted for all time %d", ("rows deleted %d rows deleted for all time %d",
int(mysql->affected_rows), stats.deleted)); int(mysql->affected_rows), stats.deleted));
...@@ -2001,12 +1996,15 @@ int ha_federated::delete_row(const byte *buf) ...@@ -2001,12 +1996,15 @@ int ha_federated::delete_row(const byte *buf)
*/ */
int ha_federated::index_read(byte *buf, const byte *key, int ha_federated::index_read(byte *buf, const byte *key,
uint key_len, enum ha_rkey_function find_flag) uint key_len, ha_rkey_function find_flag)
{ {
int retval;
DBUG_ENTER("ha_federated::index_read"); DBUG_ENTER("ha_federated::index_read");
retval= index_read_idx(buf, active_index, key, key_len, find_flag);
DBUG_RETURN(retval); if (stored_result)
mysql_free_result(stored_result);
DBUG_RETURN(index_read_idx_with_result_set(buf, active_index, key,
key_len, find_flag,
&stored_result));
} }
...@@ -2015,12 +2013,45 @@ int ha_federated::index_read(byte *buf, const byte *key, ...@@ -2015,12 +2013,45 @@ int ha_federated::index_read(byte *buf, const byte *key,
row if any. This is only used to read whole keys. row if any. This is only used to read whole keys.
This method is called via index_read in the case of a WHERE clause using This method is called via index_read in the case of a WHERE clause using
a regular non-primary key index, OR is called DIRECTLY when the WHERE clause a primary key index OR is called DIRECTLY when the WHERE clause
uses a PRIMARY KEY index. uses a PRIMARY KEY index.
NOTES
This uses an internal result set that is deleted before function
returns. We need to be able to be calable from ha_rnd_pos()
*/ */
int ha_federated::index_read_idx(byte *buf, uint index, const byte *key, int ha_federated::index_read_idx(byte *buf, uint index, const byte *key,
uint key_len, enum ha_rkey_function find_flag) uint key_len, enum ha_rkey_function find_flag)
{
int retval;
MYSQL_RES *mysql_result;
DBUG_ENTER("ha_federated::index_read_idx");
if ((retval= index_read_idx_with_result_set(buf, index, key,
key_len, find_flag,
&mysql_result)))
DBUG_RETURN(retval);
mysql_free_result(mysql_result);
DBUG_RETURN(retval);
}
/*
Create result set for rows matching query and return first row
RESULT
0 ok In this case *result will contain the result set
table->status == 0
# error In this case *result will contain 0
table->status == STATUS_NOT_FOUND
*/
int ha_federated::index_read_idx_with_result_set(byte *buf, uint index,
const byte *key,
uint key_len,
ha_rkey_function find_flag,
MYSQL_RES **result)
{ {
int retval; int retval;
char error_buffer[FEDERATED_QUERY_BUFFER_SIZE]; char error_buffer[FEDERATED_QUERY_BUFFER_SIZE];
...@@ -2033,8 +2064,9 @@ int ha_federated::index_read_idx(byte *buf, uint index, const byte *key, ...@@ -2033,8 +2064,9 @@ int ha_federated::index_read_idx(byte *buf, uint index, const byte *key,
sizeof(sql_query_buffer), sizeof(sql_query_buffer),
&my_charset_bin); &my_charset_bin);
key_range range; key_range range;
DBUG_ENTER("ha_federated::index_read_idx"); DBUG_ENTER("ha_federated::index_read_idx_with_result_set");
*result= 0; // In case of errors
index_string.length(0); index_string.length(0);
sql_query.length(0); sql_query.length(0);
statistic_increment(table->in_use->status_var.ha_read_key_count, statistic_increment(table->in_use->status_var.ha_read_key_count,
...@@ -2051,20 +2083,6 @@ int ha_federated::index_read_idx(byte *buf, uint index, const byte *key, ...@@ -2051,20 +2083,6 @@ int ha_federated::index_read_idx(byte *buf, uint index, const byte *key,
NULL, 0, 0); NULL, 0, 0);
sql_query.append(index_string); sql_query.append(index_string);
DBUG_PRINT("info",
("current key %d key value %s index_string value %s length %d",
index, (char*) key, index_string.c_ptr_quick(),
index_string.length()));
DBUG_PRINT("info",
("current position %d sql_query %s", current_position,
sql_query.c_ptr_quick()));
if (stored_result)
{
mysql_free_result(stored_result);
stored_result= 0;
}
if (mysql_real_query(mysql, sql_query.ptr(), sql_query.length())) if (mysql_real_query(mysql, sql_query.ptr(), sql_query.length()))
{ {
my_sprintf(error_buffer, (error_buffer, "error: %d '%s'", my_sprintf(error_buffer, (error_buffer, "error: %d '%s'",
...@@ -2072,45 +2090,41 @@ int ha_federated::index_read_idx(byte *buf, uint index, const byte *key, ...@@ -2072,45 +2090,41 @@ int ha_federated::index_read_idx(byte *buf, uint index, const byte *key,
retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE; retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
goto error; goto error;
} }
stored_result= mysql_store_result(mysql); if (!(*result= mysql_store_result(mysql)))
if (!stored_result)
{ {
retval= HA_ERR_END_OF_FILE; retval= HA_ERR_END_OF_FILE;
goto error; goto error;
} }
/* if (!(retval= read_next(buf, *result)))
This basically says that the record in table->record[0] is legal, DBUG_RETURN(retval);
and that it is ok to use this record, for whatever reason, such
as with a join (without it, joins will not work)
*/
table->status= 0;
retval= rnd_next(buf); mysql_free_result(*result);
*result= 0;
table->status= STATUS_NOT_FOUND;
DBUG_RETURN(retval); DBUG_RETURN(retval);
error: error:
if (stored_result)
{
mysql_free_result(stored_result);
stored_result= 0;
}
table->status= STATUS_NOT_FOUND; table->status= STATUS_NOT_FOUND;
my_error(retval, MYF(0), error_buffer); my_error(retval, MYF(0), error_buffer);
DBUG_RETURN(retval); DBUG_RETURN(retval);
} }
/* Initialized at each key walk (called multiple times unlike rnd_init()) */ /* Initialized at each key walk (called multiple times unlike rnd_init()) */
int ha_federated::index_init(uint keynr, bool sorted) int ha_federated::index_init(uint keynr, bool sorted)
{ {
DBUG_ENTER("ha_federated::index_init"); DBUG_ENTER("ha_federated::index_init");
DBUG_PRINT("info", DBUG_PRINT("info", ("table: '%s' key: %u", table->s->table_name, keynr));
("table: '%s' key: %d", table->s->table_name.str, keynr));
active_index= keynr; active_index= keynr;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/*
Read first range
*/
int ha_federated::read_range_first(const key_range *start_key, int ha_federated::read_range_first(const key_range *start_key,
const key_range *end_key, const key_range *end_key,
bool eq_range, bool sorted) bool eq_range, bool sorted)
...@@ -2122,8 +2136,7 @@ int ha_federated::read_range_first(const key_range *start_key, ...@@ -2122,8 +2136,7 @@ int ha_federated::read_range_first(const key_range *start_key,
&my_charset_bin); &my_charset_bin);
DBUG_ENTER("ha_federated::read_range_first"); DBUG_ENTER("ha_federated::read_range_first");
if (start_key == NULL && end_key == NULL) DBUG_ASSERT(!(start_key == NULL && end_key == NULL));
DBUG_RETURN(0);
sql_query.length(0); sql_query.length(0);
sql_query.append(share->select_query); sql_query.append(share->select_query);
...@@ -2131,6 +2144,11 @@ int ha_federated::read_range_first(const key_range *start_key, ...@@ -2131,6 +2144,11 @@ int ha_federated::read_range_first(const key_range *start_key,
&table->key_info[active_index], &table->key_info[active_index],
start_key, end_key, 0, eq_range); start_key, end_key, 0, eq_range);
if (stored_result)
{
mysql_free_result(stored_result);
stored_result= 0;
}
if (mysql_real_query(mysql, sql_query.ptr(), sql_query.length())) if (mysql_real_query(mysql, sql_query.ptr(), sql_query.length()))
{ {
retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE; retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
...@@ -2138,38 +2156,21 @@ int ha_federated::read_range_first(const key_range *start_key, ...@@ -2138,38 +2156,21 @@ int ha_federated::read_range_first(const key_range *start_key,
} }
sql_query.length(0); sql_query.length(0);
if (stored_result) if (!(stored_result= mysql_store_result(mysql)))
{
DBUG_PRINT("info",
("mysql_free_result address %lx", stored_result));
mysql_free_result(stored_result);
stored_result= 0;
}
stored_result= mysql_store_result(mysql);
if (!stored_result)
{ {
retval= HA_ERR_END_OF_FILE; retval= HA_ERR_END_OF_FILE;
goto error; goto error;
} }
/* This was successful, please let it be known! */ retval= read_next(table->record[0], stored_result);
table->status= 0;
retval= rnd_next(table->record[0]);
DBUG_RETURN(retval); DBUG_RETURN(retval);
error: error:
table->status= STATUS_NOT_FOUND; table->status= STATUS_NOT_FOUND;
if (stored_result)
{
DBUG_PRINT("info", ("mysql_free_result address %lx", stored_result));
mysql_free_result(stored_result);
stored_result= 0;
}
DBUG_RETURN(retval); DBUG_RETURN(retval);
} }
int ha_federated::read_range_next() int ha_federated::read_range_next()
{ {
int retval; int retval;
...@@ -2182,13 +2183,13 @@ int ha_federated::read_range_next() ...@@ -2182,13 +2183,13 @@ int ha_federated::read_range_next()
/* Used to read forward through the index. */ /* Used to read forward through the index. */
int ha_federated::index_next(byte *buf) int ha_federated::index_next(byte *buf)
{ {
int retval;
DBUG_ENTER("ha_federated::index_next"); DBUG_ENTER("ha_federated::index_next");
statistic_increment(table->in_use->status_var.ha_read_next_count, statistic_increment(table->in_use->status_var.ha_read_next_count,
&LOCK_status); &LOCK_status);
retval= rnd_next(buf); DBUG_RETURN(read_next(buf, stored_result));
DBUG_RETURN(retval);
} }
/* /*
rnd_init() is called when the system wants the storage engine to do a table rnd_init() is called when the system wants the storage engine to do a table
scan. scan.
...@@ -2242,11 +2243,8 @@ int ha_federated::rnd_init(bool scan) ...@@ -2242,11 +2243,8 @@ int ha_federated::rnd_init(bool scan)
if (scan) if (scan)
{ {
DBUG_PRINT("info", ("share->select_query %s", share->select_query));
if (stored_result) if (stored_result)
{ {
DBUG_PRINT("info",
("mysql_free_result address %lx", stored_result));
mysql_free_result(stored_result); mysql_free_result(stored_result);
stored_result= 0; stored_result= 0;
} }
...@@ -2266,25 +2264,22 @@ error: ...@@ -2266,25 +2264,22 @@ error:
DBUG_RETURN(stash_remote_error()); DBUG_RETURN(stash_remote_error());
} }
int ha_federated::rnd_end() int ha_federated::rnd_end()
{ {
int retval;
DBUG_ENTER("ha_federated::rnd_end"); DBUG_ENTER("ha_federated::rnd_end");
DBUG_RETURN(index_end());
if (stored_result)
{
DBUG_PRINT("info", ("mysql_free_result address %lx", stored_result));
mysql_free_result(stored_result);
stored_result= 0;
}
retval= index_end();
DBUG_RETURN(retval);
} }
int ha_federated::index_end(void) int ha_federated::index_end(void)
{ {
DBUG_ENTER("ha_federated::index_end"); DBUG_ENTER("ha_federated::index_end");
if (stored_result)
{
mysql_free_result(stored_result);
stored_result= 0;
}
active_index= MAX_KEY; active_index= MAX_KEY;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -2302,8 +2297,6 @@ int ha_federated::index_end(void) ...@@ -2302,8 +2297,6 @@ int ha_federated::index_end(void)
int ha_federated::rnd_next(byte *buf) int ha_federated::rnd_next(byte *buf)
{ {
int retval;
MYSQL_ROW row;
DBUG_ENTER("ha_federated::rnd_next"); DBUG_ENTER("ha_federated::rnd_next");
if (stored_result == 0) if (stored_result == 0)
...@@ -2311,32 +2304,60 @@ int ha_federated::rnd_next(byte *buf) ...@@ -2311,32 +2304,60 @@ int ha_federated::rnd_next(byte *buf)
/* /*
Return value of rnd_init is not always checked (see records.cc), Return value of rnd_init is not always checked (see records.cc),
so we can get here _even_ if there is _no_ pre-fetched result-set! so we can get here _even_ if there is _no_ pre-fetched result-set!
TODO: fix it. TODO: fix it. We can delete this in 5.1 when rnd_init() is checked.
*/ */
DBUG_RETURN(1); DBUG_RETURN(1);
} }
DBUG_RETURN(read_next(buf, stored_result));
}
/*
ha_federated::read_next
reads from a result set and converts to mysql internal
format
SYNOPSIS
field_in_record_is_null()
buf byte pointer to record
result mysql result set
DESCRIPTION
This method is a wrapper method that reads one record from a result
set and converts it to the internal table format
RETURN VALUE
1 error
0 no error
*/
int ha_federated::read_next(byte *buf, MYSQL_RES *result)
{
int retval;
my_ulonglong num_rows;
MYSQL_ROW row;
DBUG_ENTER("ha_federated::read_next");
table->status= STATUS_NOT_FOUND; // For easier return
/* Fetch a row, insert it back in a row format. */ /* Fetch a row, insert it back in a row format. */
current_position= stored_result->data_cursor; if (!(row= mysql_fetch_row(result)))
DBUG_PRINT("info", ("current position %d", current_position));
if (!(row= mysql_fetch_row(stored_result)))
DBUG_RETURN(HA_ERR_END_OF_FILE); DBUG_RETURN(HA_ERR_END_OF_FILE);
retval= convert_row_to_internal_format(buf, row); if (!(retval= convert_row_to_internal_format(buf, row, result)))
table->status= 0;
DBUG_RETURN(retval); DBUG_RETURN(retval);
} }
/* /*
'position()' is called after each call to rnd_next() if the data needs to be store reference to current row so that we can later find it for
ordered. You can do something like the following to store the position: a re-read, update or delete.
my_store_ptr(ref, ref_length, current_position);
The server uses ref to store data. ref_length in the above case is the size In case of federated, a reference is either a primary key or
needed to store current_position. ref is just a byte array that the server the whole record.
will maintain. If you are using offsets to mark rows, then current_position
should be the offset. If it is a primary key like in BDB, then it needs to
be a primary key.
Called from filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc. Called from filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc.
*/ */
...@@ -2344,32 +2365,44 @@ int ha_federated::rnd_next(byte *buf) ...@@ -2344,32 +2365,44 @@ int ha_federated::rnd_next(byte *buf)
void ha_federated::position(const byte *record) void ha_federated::position(const byte *record)
{ {
DBUG_ENTER("ha_federated::position"); DBUG_ENTER("ha_federated::position");
/* my_store_ptr Add seek storage */ if (table->s->primary_key != MAX_KEY)
*(MYSQL_ROW_OFFSET *) ref= current_position; // ref is always aligned key_copy(ref, (byte *)record, table->key_info + table->s->primary_key,
ref_length);
else
memcpy(ref, record, ref_length);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/* /*
This is like rnd_next, but you are given a position to use to determine the This is like rnd_next, but you are given a position to use to determine the
row. The position will be of the type that you stored in ref. You can use row. The position will be of the type that you stored in ref.
ha_get_ptr(pos,ref_length) to retrieve whatever key or position you saved
when position() was called.
This method is required for an ORDER BY. This method is required for an ORDER BY
Called from filesort.cc records.cc sql_insert.cc sql_select.cc sql_update.cc. Called from filesort.cc records.cc sql_insert.cc sql_select.cc sql_update.cc.
*/ */
int ha_federated::rnd_pos(byte *buf, byte *pos) int ha_federated::rnd_pos(byte *buf, byte *pos)
{ {
int result;
DBUG_ENTER("ha_federated::rnd_pos"); DBUG_ENTER("ha_federated::rnd_pos");
statistic_increment(table->in_use->status_var.ha_read_rnd_count, statistic_increment(table->in_use->status_var.ha_read_rnd_count,
&LOCK_status); &LOCK_status);
memcpy_fixed(&current_position, pos, sizeof(MYSQL_ROW_OFFSET)); if (table->s->primary_key != MAX_KEY)
stored_result->current_row= 0; {
stored_result->data_cursor= current_position; /* We have a primary key, so use index_read_idx to find row */
DBUG_RETURN(rnd_next(buf)); result= index_read_idx(buf, table->s->primary_key, pos,
ref_length, HA_READ_KEY_EXACT);
}
else
{
/* otherwise, get the old record ref as obtained in ::position */
memcpy(buf, pos, ref_length);
result= 0;
}
table->status= result ? STATUS_NOT_FOUND : 0;
DBUG_RETURN(result);
} }
...@@ -2477,8 +2510,10 @@ void ha_federated::info(uint flag) ...@@ -2477,8 +2510,10 @@ void ha_federated::info(uint flag)
stats.records= (ha_rows) my_strtoll10(row[4], (char**) 0, stats.records= (ha_rows) my_strtoll10(row[4], (char**) 0,
&error); &error);
if (row[5] != NULL) if (row[5] != NULL)
stats.mean_rec_length= (ha_rows) my_strtoll10(row[5], (char**) 0, stats.mean_rec_length= (ha_rows) my_strtoll10(row[5], (char**) 0, &error);
&error);
stats.data_file_length= stats.records * stats.mean_rec_length;
if (row[12] != NULL) if (row[12] != NULL)
stats.update_time= (ha_rows) my_strtoll10(row[12], (char**) 0, stats.update_time= (ha_rows) my_strtoll10(row[12], (char**) 0,
&error); &error);
...@@ -2486,8 +2521,13 @@ void ha_federated::info(uint flag) ...@@ -2486,8 +2521,13 @@ void ha_federated::info(uint flag)
stats.check_time= (ha_rows) my_strtoll10(row[13], (char**) 0, stats.check_time= (ha_rows) my_strtoll10(row[13], (char**) 0,
&error); &error);
} }
/*
size of IO operations (This is based on a good guess, no high science
involved)
*/
if (flag & HA_STATUS_CONST) if (flag & HA_STATUS_CONST)
stats.block_size= 4096; stats.block_size= 4096;
} }
if (result) if (result)
...@@ -2498,6 +2538,7 @@ void ha_federated::info(uint flag) ...@@ -2498,6 +2538,7 @@ void ha_federated::info(uint flag)
error: error:
if (result) if (result)
mysql_free_result(result); mysql_free_result(result);
my_sprintf(error_buffer, (error_buffer, ": %d : %s", my_sprintf(error_buffer, (error_buffer, ": %d : %s",
mysql_errno(mysql), mysql_error(mysql))); mysql_errno(mysql), mysql_error(mysql)));
my_error(error_code, MYF(0), error_buffer); my_error(error_code, MYF(0), error_buffer);
...@@ -2578,6 +2619,7 @@ THR_LOCK_DATA **ha_federated::store_lock(THD *thd, ...@@ -2578,6 +2619,7 @@ THR_LOCK_DATA **ha_federated::store_lock(THD *thd,
THR_LOCK_DATA **to, THR_LOCK_DATA **to,
enum thr_lock_type lock_type) enum thr_lock_type lock_type)
{ {
DBUG_ENTER("ha_federated::store_lock");
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
{ {
/* /*
...@@ -2607,7 +2649,7 @@ THR_LOCK_DATA **ha_federated::store_lock(THD *thd, ...@@ -2607,7 +2649,7 @@ THR_LOCK_DATA **ha_federated::store_lock(THD *thd,
*to++= &lock; *to++= &lock;
return to; DBUG_RETURN(to);
} }
/* /*
......
...@@ -130,6 +130,7 @@ typedef struct st_federated_share { ...@@ -130,6 +130,7 @@ typedef struct st_federated_share {
remote host info, parse_url supplies remote host info, parse_url supplies
*/ */
char *scheme; char *scheme;
char *connect_string;
char *hostname; char *hostname;
char *username; char *username;
char *password; char *password;
...@@ -139,7 +140,7 @@ typedef struct st_federated_share { ...@@ -139,7 +140,7 @@ typedef struct st_federated_share {
char *socket; char *socket;
char *sport; char *sport;
ushort port; ushort port;
uint table_name_length, use_count; uint table_name_length, connect_string_length, use_count;
pthread_mutex_t mutex; pthread_mutex_t mutex;
THR_LOCK lock; THR_LOCK lock;
} FEDERATED_SHARE; } FEDERATED_SHARE;
...@@ -153,7 +154,6 @@ class ha_federated: public handler ...@@ -153,7 +154,6 @@ class ha_federated: public handler
FEDERATED_SHARE *share; /* Shared lock info */ FEDERATED_SHARE *share; /* Shared lock info */
MYSQL *mysql; /* MySQL connection */ MYSQL *mysql; /* MySQL connection */
MYSQL_RES *stored_result; MYSQL_RES *stored_result;
uint ref_length;
uint fetch_num; // stores the fetch num uint fetch_num; // stores the fetch num
MYSQL_ROW_OFFSET current_position; // Current position used by ::position() MYSQL_ROW_OFFSET current_position; // Current position used by ::position()
int remote_error_number; int remote_error_number;
...@@ -164,7 +164,8 @@ private: ...@@ -164,7 +164,8 @@ private:
return 0 on success return 0 on success
return errorcode otherwise return errorcode otherwise
*/ */
uint convert_row_to_internal_format(byte *buf, MYSQL_ROW row); uint convert_row_to_internal_format(byte *buf, MYSQL_ROW row,
MYSQL_RES *row);
bool create_where_from_key(String *to, KEY *key_info, bool create_where_from_key(String *to, KEY *key_info,
const key_range *start_key, const key_range *start_key,
const key_range *end_key, const key_range *end_key,
...@@ -304,6 +305,13 @@ public: ...@@ -304,6 +305,13 @@ public:
int connection_rollback(); int connection_rollback();
int connection_autocommit(bool state); int connection_autocommit(bool state);
int execute_simple_query(const char *query, int len); int execute_simple_query(const char *query, int len);
int read_next(byte *buf, MYSQL_RES *result);
int index_read_idx_with_result_set(byte *buf, uint index,
const byte *key,
uint key_len,
ha_rkey_function find_flag,
MYSQL_RES **result);
}; };
int federated_db_init(void); int federated_db_init(void);
......
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