Below is the list of changes that have just been committed into a local
5.1 repository of patg. When patg does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.2220 06/07/02 22:19:04 patg@stripped +4 -0
BUG #19773
This is a hand-coded patch that has already been applied to 5.0. Reason
for hand coding is my concern that merging from 5.0 may not work correctly
federated.result:
BUG #19773
New results for multi-table delete and update tests
federated.test:
BUG# 19773
Added multi-table delete and update
ha_federated.h:
removed ref_length declaration, added funciton defs for read_next and
index_read_rewith_result
ha_federated.cc:
BUG #19773
This is a hand-coded patch that has already been applied to 5.0. Reason
for hand coding is my concern that merging from 5.0 may not work correctly
Post-review changes, per Monty. 3rd patch, OK'd for push.
- Added index_read_idx_with_result_set, which uses the result set passed to it
- Hash by entire connection scheme
- Protected store_result result set for table scan by adding a method result set
to index_read_idx and index_read which is passed to index_read_with_result,
which
in turn iterates over the single record via read_next.
This is a change from having two result sets in the first two patches.
This keeps the code clean and avoids the need for yet another result set.
- Rewrote ::position and ::rnd_pos to store position - if primary key use
primary key, if not, use record buffer.
- Rewrote get_share to store hash with connect string vs. table name
- delete_row added subtration of "records" by affected->rows
- Added read_next to handle what rnd_next used to do (converting raw record
to query and vice versa)
- Removed many DBUG_PRINT lines
- Removed memset initialisation since subsequent loop accomplishes
- Removed un-necessary mysql_free_result lines
mysql-test/r/federated.result
1.31 06/07/02 22:16:46 patg@stripped +86 -0
BUG #19773
New results for multi-table delete and update tests
mysql-test/t/federated.test
1.27 06/07/02 22:16:13 patg@stripped +8 -6
BUG# 19773
Added multi-table delete and update
sql/ha_federated.h
1.31 06/07/02 22:12:26 patg@stripped +11 -5
removed ref_length declaration, added funciton defs for read_next and
index_read_rewith_result
sql/ha_federated.cc
1.63 06/07/02 22:09:05 patg@stripped +189 -165
BUG #19773
Post-review changes, per Monty. 3rd patch, OK'd for push.
- Added index_read_idx_with_result_set, which uses the result set passed to it
- Hash by entire connection scheme
- Protected store_result result set for table scan by adding a method result set
to index_read_idx and index_read which is passed to index_read_with_result,
which
in turn iterates over the single record via read_next.
This is a change from having two result sets in the first two patches.
This keeps the code clean and avoids the need for yet another result set.
- Rewrote ::position and ::rnd_pos to store position - if primary key use
primary key, if not, use record buffer.
- Rewrote get_share to store hash with connect string vs. table name
- delete_row added subtration of "records" by affected->rows
- Added read_next to handle what rnd_next used to do (converting raw record
to query and vice versa)
- Removed many DBUG_PRINT lines
- Removed memset initialisation since subsequent loop accomplishes
- Removed un-necessary mysql_free_result lines
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: patg
# Host: govinda.patg.net
# Root: /home/patg/mysql-build/mysql-5.1-engines
--- 1.30/mysql-test/r/federated.result 2006-06-15 15:49:35 -07:00
+++ 1.31/mysql-test/r/federated.result 2006-07-02 22:16:46 -07:00
@@ -1602,6 +1602,92 @@
DROP TABLE federated.t1;
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@stripped:SLAVE_PORT/federated/t1';
+create table federated.t2 (id int, c1 varchar(20), c2 varchar(20)) ENGINE=FEDERATED
CONNECTION='mysql://root@stripped: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@stripped: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@stripped: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 DATABASE IF EXISTS federated;
DROP TABLE IF EXISTS federated.t1;
--- 1.26/mysql-test/t/federated.test 2006-06-15 15:49:45 -07:00
+++ 1.27/mysql-test/t/federated.test 2006-07-02 22:16:13 -07:00
@@ -1317,12 +1317,13 @@
#
# The following can be enabled when bug #19773 has been fixed
---disable_parsing
connection slave;
create table federated.t1 (i1 int, i2 int, i3 int);
create table federated.t2 (id int, c1 varchar(20), c2 varchar(20));
connection master;
+--replace_result $SLAVE_MYPORT SLAVE_PORT
eval create table federated.t1 (i1 int, i2 int, i3 int) ENGINE=FEDERATED
CONNECTION='mysql://root@stripped:$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@stripped:$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.t2 values (9,"abc","def"),(5,"opq","lmn"),(2,"test t","t test");
@@ -1331,7 +1332,7 @@
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.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.t2 order by id;
drop table federated.t1, federated.t2;
@@ -1345,8 +1346,10 @@
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));
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@stripped:$SLAVE_MYPORT/federated/t1';
-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@stripped:$SLAVE_MYPORT/federated/t2';
+--replace_result $SLAVE_MYPORT SLAVE_PORT
+eval create table federated.t1 (i1 int auto_increment not null, i2 int, i3 int, primary
key (i1)) ENGINE=FEDERATED
CONNECTION='mysql://root@stripped:$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@stripped:$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.t2 values (9,"abc","def"),(5,"opq","lmn"),(2,"test t","t test");
select * from federated.t1 order by i1;
@@ -1354,13 +1357,12 @@
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.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.t2 order by id;
drop table federated.t1, federated.t2;
connection slave;
drop table federated.t1, federated.t2;
connection master;
---enable_parsing
--source include/federated_cleanup.inc
--- 1.62/sql/ha_federated.cc 2006-06-04 09:23:39 -07:00
+++ 1.63/sql/ha_federated.cc 2006-07-02 22:09:05 -07:00
@@ -385,8 +385,8 @@
static byte *federated_get_key(FEDERATED_SHARE *share, uint *length,
my_bool not_used __attribute__ ((unused)))
{
- *length= share->table_name_length;
- return (byte*) share->table_name;
+ *length= share->connect_string_length;
+ return (byte*) share->scheme;
}
/*
@@ -510,6 +510,7 @@
}
else
{
+ int escaped_table_name_length= 0;
/*
Since we do not support transactions at this version, we can let the
client API silently reconnect. For future versions, we will need more
@@ -528,17 +529,16 @@
query.append(FEDERATED_STAR);
query.append(FEDERATED_FROM);
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),
share->table_name,
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_WHERE);
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()))
{
error_code= table_create_flag ?
@@ -634,8 +634,7 @@
table->s->connect_string.length,
MYF(0));
- // Add a null for later termination of table name
- share->scheme[table->s->connect_string.length]= 0;
+ share->connect_string_length= table->s->connect_string.length;
DBUG_PRINT("info",("parse_url alloced share->scheme %lx", share->scheme));
/*
@@ -653,7 +652,7 @@
if (!(share->hostname= strchr(share->username, '@')))
goto error;
-
+
share->username[share->hostname - share->username]= '\0';
share->hostname++;
@@ -701,7 +700,7 @@
share->table_name++;
share->table_name_length= strlen(share->table_name);
-
+
/* make sure there's not an extra / */
if ((strchr(share->table_name, '/')))
goto error;
@@ -737,8 +736,7 @@
ha_federated::ha_federated(TABLE_SHARE *table_arg)
:handler(&federated_hton, table_arg),
- mysql(0), stored_result(0),
- ref_length(sizeof(MYSQL_ROW_OFFSET)), current_position(0)
+ mysql(0), stored_result(0)
{
trx_next= 0;
}
@@ -763,15 +761,16 @@
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;
Field **field;
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
DBUG_ENTER("ha_federated::convert_row_to_internal_format");
- lengths= mysql_fetch_lengths(stored_result);
- memset(record, 0, table->s->null_bytes);
+ lengths= mysql_fetch_lengths(result);
for (field= table->field; *field; field++, row++, lengths++)
{
@@ -1316,12 +1315,11 @@
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];
- uint tmp_table_name_length;
Field **field;
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,
or it will contain garbage
@@ -1329,12 +1327,14 @@
query.length(0);
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;
if (!(share= (FEDERATED_SHARE *) hash_search(&federated_open_tables,
- (byte*) table_name,
- tmp_table_name_length)))
+ (byte*) tmp_share.scheme,
+ tmp_share.
+ connect_string_length)))
{
query.set_charset(system_charset_info);
query.append(FEDERATED_SELECT);
@@ -1352,18 +1352,15 @@
if (!(share= (FEDERATED_SHARE *)
my_multi_malloc(MYF(MY_WME),
&share, sizeof(*share),
- &tmp_table_name, tmp_table_name_length+ 1,
&select_query,
query.length()+table->s->connect_string.length+1,
NullS)))
- {
- pthread_mutex_unlock(&federated_mutex);
- return NULL;
- }
-
- if (parse_url(share, table, 0))
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(FEDERATED_BTICK);
share->select_query= select_query;
@@ -1384,11 +1381,8 @@
error:
pthread_mutex_unlock(&federated_mutex);
- if (share->scheme)
- {
- my_free((gptr) share->scheme, MYF(0));
- share->scheme= 0;
- }
+ my_free((gptr) tmp_share.scheme, MYF(MY_ALLOW_ZERO_PTR));
+ my_free((gptr) share, MYF(MY_ALLOW_ZERO_PTR));
return NULL;
}
@@ -1408,13 +1402,7 @@
{
hash_delete(&federated_open_tables, (byte*) share);
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));
- share->socket= 0;
- }
-
+ my_free((gptr) share->socket, MYF(MY_ALLOW_ZERO_PTR));
thr_lock_delete(&share->lock);
VOID(pthread_mutex_destroy(&share->mutex));
my_free((gptr) share, MYF(0));
@@ -1476,14 +1464,15 @@
/* Connect to foreign database mysql_real_connect() */
mysql= mysql_init(0);
- if (!mysql_real_connect(mysql,
- share->hostname,
- share->username,
- share->password,
- share->database,
- share->port,
- share->socket, 0))
+ if (!mysql || !mysql_real_connect(mysql,
+ share->hostname,
+ share->username,
+ share->password,
+ share->database,
+ share->port,
+ share->socket, 0))
{
+ free_share(share);
DBUG_RETURN(stash_remote_error());
}
/*
@@ -1493,6 +1482,11 @@
*/
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);
}
@@ -1516,13 +1510,12 @@
/* free the result set */
if (stored_result)
{
- DBUG_PRINT("info",
- ("mysql_free_result result at address %lx", stored_result));
mysql_free_result(stored_result);
stored_result= 0;
}
/* Disconnect from mysql */
- mysql_close(mysql);
+ if (mysql)
+ mysql_close(mysql);
retval= free_share(share);
DBUG_RETURN(retval);
@@ -1810,18 +1803,12 @@
/*
buffers for following strings
*/
- char old_field_value_buffer[STRING_BUFFER_USUAL_SIZE];
- char new_field_value_buffer[STRING_BUFFER_USUAL_SIZE];
+ char field_value_buffer[STRING_BUFFER_USUAL_SIZE];
char update_buffer[FEDERATED_QUERY_BUFFER_SIZE];
char where_buffer[FEDERATED_QUERY_BUFFER_SIZE];
- /* stores the value to be replaced of the field were are updating */
- String old_field_value(old_field_value_buffer,
- sizeof(old_field_value_buffer),
- &my_charset_bin);
- /* stores the new value of the field */
- String new_field_value(new_field_value_buffer,
- sizeof(new_field_value_buffer),
+ /* Work area for field values */
+ String field_value(field_value_buffer, sizeof(field_value_buffer),
&my_charset_bin);
/* stores the update query */
String update_string(update_buffer,
@@ -1835,8 +1822,7 @@
/*
set string lengths to 0 to avoid misc chars in string
*/
- old_field_value.length(0);
- new_field_value.length(0);
+ field_value.length(0);
update_string.length(0);
where_string.length(0);
@@ -1861,20 +1847,20 @@
if (bitmap_is_set(table->write_set, (*field)->field_index))
{
if ((*field)->is_null())
- new_field_value.append(FEDERATED_NULL);
+ field_value.append(FEDERATED_NULL);
else
{
my_bitmap_map *old_map= tmp_use_all_columns(table, table->read_set);
/* otherwise = */
- (*field)->val_str(&new_field_value);
- (*field)->quote_data(&new_field_value);
+ (*field)->val_str(&field_value);
+ (*field)->quote_data(&field_value);
tmp_restore_column_map(table->read_set, old_map);
}
update_string.append((*field)->field_name);
update_string.append(FEDERATED_EQ);
- update_string.append(new_field_value);
+ update_string.append(field_value);
+ field_value.length(0);
update_string.append(FEDERATED_COMMA);
- new_field_value.length(0);
}
if (bitmap_is_set(table->read_set, (*field)->field_index))
@@ -1885,11 +1871,11 @@
else
{
where_string.append(FEDERATED_EQ);
- (*field)->val_str(&old_field_value,
+ (*field)->val_str(&field_value,
(char*) (old_data + (*field)->offset()));
- (*field)->quote_data(&old_field_value);
- where_string.append(old_field_value);
- old_field_value.length(0);
+ (*field)->quote_data(&field_value);
+ where_string.append(field_value);
+ field_value.length(0);
}
where_string.append(FEDERATED_AND);
}
@@ -1987,9 +1973,10 @@
DBUG_RETURN(stash_remote_error());
}
stats.deleted+= mysql->affected_rows;
+ stats.records-= mysql->affected_rows;
DBUG_PRINT("info",
- ("rows deleted %d rows deleted for all time %d",
- int(mysql->affected_rows), stats.deleted));
+ ("records %d rows deleted %d rows deleted for all time %d",
+ stats.records, int(mysql->affected_rows), stats.deleted));
DBUG_RETURN(0);
}
@@ -2007,8 +1994,11 @@
{
int retval;
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));
}
@@ -2025,18 +2015,47 @@
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;
char error_buffer[FEDERATED_QUERY_BUFFER_SIZE];
char index_value[STRING_BUFFER_USUAL_SIZE];
char sql_query_buffer[FEDERATED_QUERY_BUFFER_SIZE];
- String index_string(index_value,
+ String index_string(index_value,
sizeof(index_value),
&my_charset_bin);
String sql_query(sql_query_buffer,
sizeof(sql_query_buffer),
&my_charset_bin);
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);
sql_query.length(0);
statistic_increment(table->in_use->status_var.ha_read_key_count,
@@ -2053,20 +2072,6 @@
NULL, 0, 0);
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()))
{
my_sprintf(error_buffer, (error_buffer, "error: %d '%s'",
@@ -2074,40 +2079,31 @@
retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
goto error;
}
- stored_result= mysql_store_result(mysql);
-
- if (!stored_result)
+ if (!(*result= mysql_store_result(mysql)))
{
retval= HA_ERR_END_OF_FILE;
goto error;
}
- /*
- This basically says that the record in table->record[0] is legal,
- 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;
+ if (!(retval= read_next(buf, *result)))
+ DBUG_RETURN(retval);
- retval= rnd_next(buf);
+ mysql_free_result(*result);
+ *result= 0;
+ table->status= STATUS_NOT_FOUND;
DBUG_RETURN(retval);
error:
- if (stored_result)
- {
- mysql_free_result(stored_result);
- stored_result= 0;
- }
table->status= STATUS_NOT_FOUND;
my_error(retval, MYF(0), error_buffer);
DBUG_RETURN(retval);
}
/* Initialized at each key walk (called multiple times unlike rnd_init()) */
+
int ha_federated::index_init(uint keynr, bool sorted)
{
DBUG_ENTER("ha_federated::index_init");
- DBUG_PRINT("info",
- ("table: '%s' key: %d", table->s->table_name.str, keynr));
+ DBUG_PRINT("info", ("table: '%s' key: %u", table->s->table_name, keynr));
active_index= keynr;
DBUG_RETURN(0);
}
@@ -2124,8 +2120,7 @@
&my_charset_bin);
DBUG_ENTER("ha_federated::read_range_first");
- if (start_key == NULL && end_key == NULL)
- DBUG_RETURN(0);
+ DBUG_ASSERT(!(start_key == NULL && end_key == NULL));
sql_query.length(0);
sql_query.append(share->select_query);
@@ -2133,6 +2128,11 @@
&table->key_info[active_index],
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()))
{
retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE;
@@ -2140,35 +2140,20 @@
}
sql_query.length(0);
- if (stored_result)
- {
- 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)
+ if (!(stored_result= mysql_store_result(mysql)))
{
retval= HA_ERR_END_OF_FILE;
goto error;
}
-
+
/* This was successful, please let it be known! */
table->status= 0;
- retval= rnd_next(table->record[0]);
+ retval= read_next(table->record[0], stored_result);
DBUG_RETURN(retval);
error:
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);
}
@@ -2184,12 +2169,10 @@
/* Used to read forward through the index. */
int ha_federated::index_next(byte *buf)
{
- int retval;
DBUG_ENTER("ha_federated::index_next");
statistic_increment(table->in_use->status_var.ha_read_next_count,
&LOCK_status);
- retval= rnd_next(buf);
- DBUG_RETURN(retval);
+ DBUG_RETURN(read_next(buf, stored_result));
}
/*
rnd_init() is called when the system wants the storage engine to do a table
@@ -2244,11 +2227,8 @@
if (scan)
{
- DBUG_PRINT("info", ("share->select_query %s", share->select_query));
if (stored_result)
{
- DBUG_PRINT("info",
- ("mysql_free_result address %lx", stored_result));
mysql_free_result(stored_result);
stored_result= 0;
}
@@ -2270,23 +2250,19 @@
int ha_federated::rnd_end()
{
- int retval;
DBUG_ENTER("ha_federated::rnd_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);
+ DBUG_RETURN(index_end());
}
int ha_federated::index_end(void)
{
DBUG_ENTER("ha_federated::index_end");
+ if (stored_result)
+ {
+ mysql_free_result(stored_result);
+ stored_result= 0;
+ }
active_index= MAX_KEY;
DBUG_RETURN(0);
}
@@ -2304,8 +2280,6 @@
int ha_federated::rnd_next(byte *buf)
{
- int retval;
- MYSQL_ROW row;
DBUG_ENTER("ha_federated::rnd_next");
if (stored_result == 0)
@@ -2317,28 +2291,60 @@
*/
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. */
- current_position= stored_result->data_cursor;
- DBUG_PRINT("info", ("current position %d", current_position));
- if (!(row= mysql_fetch_row(stored_result)))
+ if (!(row= mysql_fetch_row(result)))
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);
}
+
/*
- 'position()' is called after each call to rnd_next() if the data needs to be
- ordered. You can do something like the following to store the position:
- my_store_ptr(ref, ref_length, current_position);
+ store reference to current row so that we can later find it for
+ a re-read, update or delete.
- The server uses ref to store data. ref_length in the above case is the size
- needed to store current_position. ref is just a byte array that the server
- 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.
+ In case of federated, a reference is either a primary key or
+ the whole record.
+
+ 'position()' is called after each call to rnd_next() if the data needs to be
+ ordered.
Called from filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc.
*/
@@ -2346,8 +2352,11 @@
void ha_federated::position(const byte *record)
{
DBUG_ENTER("ha_federated::position");
- /* my_store_ptr Add seek storage */
- *(MYSQL_ROW_OFFSET *) ref= current_position; // ref is always aligned
+ if (table->s->primary_key != MAX_KEY)
+ key_copy(ref, (byte *)record, table->key_info + table->s->primary_key,
+ ref_length);
+ else
+ memcpy(ref, record, ref_length);
DBUG_VOID_RETURN;
}
@@ -2364,14 +2373,25 @@
*/
int ha_federated::rnd_pos(byte *buf, byte *pos)
{
+ int result;
DBUG_ENTER("ha_federated::rnd_pos");
statistic_increment(table->in_use->status_var.ha_read_rnd_count,
&LOCK_status);
- memcpy_fixed(¤t_position, pos, sizeof(MYSQL_ROW_OFFSET));
- stored_result->current_row= 0;
- stored_result->data_cursor= current_position;
- DBUG_RETURN(rnd_next(buf));
+ if (table->s->primary_key != MAX_KEY)
+ {
+ /* We have a primary key, so use index_read_idx to find row */
+ 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);
}
@@ -2488,6 +2508,10 @@
stats.check_time= (ha_rows) my_strtoll10(row[13], (char**) 0,
&error);
}
+ /*
+ size of IO operations (This is based on a good guess, no high science
+ involved)
+ */
if (flag & HA_STATUS_CONST)
stats.block_size= 4096;
}
--- 1.30/sql/ha_federated.h 2006-06-04 09:23:39 -07:00
+++ 1.31/sql/ha_federated.h 2006-07-02 22:12:26 -07:00
@@ -130,6 +130,7 @@
remote host info, parse_url supplies
*/
char *scheme;
+ char *connect_string;
char *hostname;
char *username;
char *password;
@@ -139,7 +140,7 @@
char *socket;
char *sport;
ushort port;
- uint table_name_length, use_count;
+ uint table_name_length, connect_string_length, use_count;
pthread_mutex_t mutex;
THR_LOCK lock;
} FEDERATED_SHARE;
@@ -153,9 +154,7 @@
FEDERATED_SHARE *share; /* Shared lock info */
MYSQL *mysql; /* MySQL connection */
MYSQL_RES *stored_result;
- uint ref_length;
uint fetch_num; // stores the fetch num
- MYSQL_ROW_OFFSET current_position; // Current position used by ::position()
int remote_error_number;
char remote_error_buf[FEDERATED_QUERY_BUFFER_SIZE];
@@ -164,8 +163,9 @@
return 0 on success
return errorcode otherwise
*/
- uint convert_row_to_internal_format(byte *buf, MYSQL_ROW row);
- bool create_where_from_key(String *to, KEY *key_info,
+ uint convert_row_to_internal_format(byte *buf, MYSQL_ROW row,
+ MYSQL_RES *result);
+ bool create_where_from_key(String *to, KEY *key_info,
const key_range *start_key,
const key_range *end_key,
bool records_in_range, bool eq_range);
@@ -299,6 +299,12 @@
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type); //required
virtual bool get_error_message(int error, String *buf);
+ 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 external_lock(THD *thd, int lock_type);
int connection_commit();
int connection_rollback();
| Thread |
|---|
| • bk commit into 5.1 tree (patg:1.2220) BUG#19773 | Patrick Galbraith | 3 Jul |