Below is the list of changes that have just been committed into a local
5.0 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.1935 05/06/07 23:48:27 patg@stripped +2 -0
WL# 2653 Implement records_in_range and read_range_first
ha_federated.h:
added "range_type" to create_where_from_key, and enum range_operation.
Table flags for read_range_first to work.
ha_federated.cc:
Savepoint for work on read_range_first, records_in_range,
create_where_from_key, info, to get ranges working with valid
SQL statements, as opposed to full table scan (select * from)
sql/ha_federated.h
1.13 05/06/07 23:44:40 patg@stripped +40 -12
added "range_type" to create_where_from_key, and enum range_operation.
Table flags for read_range_first to work.
sql/ha_federated.cc
1.29 05/06/07 23:44:39 patg@stripped +401 -51
Savepoint for work on read_range_first, records_in_range,
create_where_from_key, info, to get ranges working with valid
SQL statements, as opposed to full table scan (select * from)
# 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: radha.local
# Root: /Users/patg/mysql-5.0
--- 1.28/sql/ha_federated.cc Sat Jun 4 02:30:36 2005
+++ 1.29/sql/ha_federated.cc Tue Jun 7 23:44:39 2005
@@ -54,6 +54,7 @@
***IMPORTANT***
+ This is a first release, conceptual release
Only 'mysql://' is supported at this release.
@@ -349,11 +350,13 @@
#pragma implementation // gcc: Class implementation
#endif
-#include "mysql_priv.h"
+#include <mysql_priv.h>
#ifdef HAVE_FEDERATED_DB
#include "ha_federated.h"
#define MAX_REMOTE_SIZE IO_SIZE
+
+#include "m_string.h"
/* Variables for federated share methods */
static HASH federated_open_tables; // Hash used to track open
// tables
@@ -442,9 +445,7 @@
/* error out if we can't alloc memory for mysql_init(NULL) (per Georg) */
if (! (mysql= mysql_init(NULL)))
- {
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
- }
/* check if we can connect */
if (!mysql_real_connect(mysql,
share->hostname,
@@ -473,7 +474,6 @@
Note: I am not using INORMATION_SCHEMA because this needs to work with < 5.0
if we can connect, then make sure the table exists
*/
-
query.append("SHOW TABLES LIKE '");
escape_string_for_mysql(&my_charset_bin, (char *)escaped_table_base_name,
sizeof(escaped_table_base_name),
@@ -664,6 +664,54 @@
}
+static int get_foreign_data_source(FEDERATED_SHARE *share)
+{
+ DBUG_ENTER("ha_federated::get_foreign_data_source");
+ THD *thd;
+ TABLE_LIST tables[4];
+ TABLE *table;
+ READ_RECORD read_record_info;
+ /*
+ To be able to run this from boot, we allocate a temporary THD
+ */
+ if (!(thd=new THD))
+ DBUG_RETURN(1);
+ thd->store_globals();
+
+ thd->db= my_strdup("test",MYF(0));
+ thd->db_length=4; // Safety
+ bzero((char*) &tables,sizeof(tables));
+ tables[0].alias=tables[0].table_name=(char*) "foreign_servers";
+ tables[1].alias=tables[1].table_name=(char*) "foreign_server_options";
+ tables[2].alias=tables[2].table_name=(char*) "foreign_databases";
+ tables[3].alias=tables[3].table_name=(char*) "foreign_databases_options";
+ tables[0].next_local= tables[0].next_global= tables+1;
+ tables[1].next_local= tables[1].next_global= tables+2;
+ tables[2].next_local= tables[2].next_global= tables+3;
+ tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=
+ tables[3].lock_type=TL_READ;
+ tables[0].db=tables[1].db=tables[2].db=tables[3].db=thd->db;
+
+ if (simple_open_n_lock_tables(thd, tables))
+ {
+ sql_print_error("Fatal error: Can't open and lock foreign data tables: %s",
+ thd->net.last_error);
+ goto end;
+ }
+ init_read_record(&read_record_info,thd,table= tables[0].table,NULL,1,0);
+ while (!(read_record_info.read_record(&read_record_info)))
+ {
+ DBUG_PRINT("info", ("field1 %s field2 %s field3 %s field4 %s field4 %s",
+ table->field[1], table->field[2], table->field[3],
table->field[4]));
+ }
+ end_read_record(&read_record_info);
+end:
+ close_thread_tables(thd);
+ delete thd;
+
+ DBUG_RETURN(0);
+}
+
/*
Convert MySQL result set row to handler internal format
@@ -699,12 +747,24 @@
for (Field **field= table->field; *field; field++, x++)
{
+ my_ptrdiff_t old_ptr;
+ old_ptr= (my_ptrdiff_t) (record - table->record[0]);
+ (*field)->move_field(old_ptr);
if (!row[x])
+ {
+ DBUG_PRINT("info", ("ha_federated::convert_row_to_internal_format col %d value
NULL", x));
(*field)->set_null();
+ }
else
+ {
+ DBUG_PRINT("info", ("ha_federated::convert_row_to_internal_format col %d value %s",
x, row[x]));
+ (*field)->set_notnull();
(*field)->store(row[x], lengths[x], &my_charset_bin);
+ }
+ (*field)->move_field(-old_ptr);
}
+ DBUG_DUMP("record", record, table->s->reclength);
DBUG_RETURN(0);
}
@@ -718,6 +778,8 @@
key_info KEY struct pointer
key byte pointer containing key
key_length length of key
+ range_type 0 - no range, 1 - min range, 2 - max range
+ (see enum range_operation)
DESCRIPTION
Using iteration through all the keys via a KEY_PART_INFO pointer,
@@ -731,14 +793,26 @@
*/
bool ha_federated::create_where_from_key(String *to, KEY *key_info,
- const byte *key, uint key_length)
+ const key_range *range, int range_type)
{
uint second_loop= 0;
KEY_PART_INFO *key_part;
bool needs_quotes;
String tmp;
+ const byte *key;
+ uint key_length;
DBUG_ENTER("ha_federated::create_where_from_key");
+ if (range == NULL)
+ {
+ if (to->append(" TRUE ", 5))
+ DBUG_RETURN(1);
+ DBUG_RETURN(0);
+ }
+
+ key= range->key;
+ key_length= range->length;
+
for (key_part= key_info->key_part; (int) key_length > 0; key_part++)
{
Field *field= key_part->field;
@@ -765,8 +839,53 @@
}
key_length--;
}
- if (to->append("= "))
- DBUG_RETURN(1);
+
+ DBUG_PRINT("info",
+ ("range->flag %d", range->flag));
+ switch(range->flag) {
+ /*
+ in all cases of my testing, records_in_range has the range->flag
+ set to HA_READ_KEY_EXACT when it should be HA_READ_KEY_OR_NEXT
+ */
+ case(HA_READ_KEY_EXACT):
+ if (to->append(" = "))
+ DBUG_RETURN(1);
+ break;
+ case(HA_READ_KEY_OR_NEXT):
+ if (to->append(" >= "))
+ DBUG_RETURN(1);
+ break;
+ case(HA_READ_KEY_OR_PREV):
+ if (to->append(" <= "))
+ DBUG_RETURN(1);
+ break;
+ /*
+ This is an issue which seems to be problematic in that when it is the
+ max range and should be HA_READ_KEY_OR_PREV, it is wrong and is
+ HA_READ_AFTER_KEY!
+ */
+ case(HA_READ_AFTER_KEY):
+ if (range_type == MAX_RANGE)
+ {
+ if (to->append(" <= "))
+ DBUG_RETURN(1);
+ }
+ else
+ {
+ if (to->append(" > "))
+ DBUG_RETURN(1);
+ }
+ break;
+ case(HA_READ_BEFORE_KEY):
+ if (to->append(" < "))
+ DBUG_RETURN(1);
+ break;
+ default:
+ if (to->append(" = "))
+ DBUG_RETURN(1);
+ break;
+ }
+
if (needs_quotes && to->append("'"))
DBUG_RETURN(1);
if (key_part->type == HA_KEYTYPE_BIT)
@@ -828,12 +947,11 @@
if (needs_quotes && to->append("'"))
DBUG_RETURN(1);
DBUG_PRINT("info",
- ("final value for 'to' %s", to->c_ptr_quick()));
+ ("create_where_from_key WHERE clause: %s", to->c_ptr_quick()));
key+= length;
key_length-= length;
- DBUG_RETURN(0);
}
- DBUG_RETURN(1);
+ DBUG_RETURN(0);
}
/*
@@ -845,6 +963,7 @@
static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
{
FEDERATED_SHARE *share;
+ Field **field;
char query_buffer[IO_SIZE];
String query(query_buffer, sizeof(query_buffer), &my_charset_bin);
query.length(0);
@@ -870,7 +989,16 @@
table_name_length)))
{
query.set_charset(system_charset_info);
- query.append("SELECT * FROM `");
+ query.append("SELECT ");
+ for (field= table->field; *field; field++)
+ {
+ query.append('`');
+ query.append((*field)->field_name);
+ query.append('`');
+ query.append(',');
+ }
+ query.length(query.length()-1);
+ query.append(" FROM `");
if (!(share= (FEDERATED_SHARE *)
my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
@@ -924,6 +1052,7 @@
static int free_share(FEDERATED_SHARE *share)
{
+ DBUG_ENTER("free_share");
pthread_mutex_lock(&federated_mutex);
if (!--share->use_count)
@@ -938,23 +1067,88 @@
}
pthread_mutex_unlock(&federated_mutex);
- return 0;
+ DBUG_RETURN(0);
}
+ha_rows ha_federated::records_in_range(uint inx, key_range *min_key,
+ key_range *max_key)
+{
+ /*
+ const byte *key;
+ uint length;
+ enum ha_rkey_function flag;
+
+ Note:
+
+ records_in_range should sent to the remote an explain
+ 'select * from table where ...' min_key and max_key
+
+ The job of this is to give a reasonable estimate of how many rows
+ a query will produce, not precise, just general to help the optimiser
+ choose an optimal query plan - this function MUST be QUICK!
+
+ USE Explain to get row estimate. Do not use count.
+
+*/
+ char sql_query_buf[IO_SIZE];
+ MYSQL_RES *result=0;
+ MYSQL_ROW row;
+ int error=0;
+ ha_rows return_rows=20;
+ String sql_query(sql_query_buf, sizeof(sql_query_buf), &my_charset_bin);
+ DBUG_ENTER("ha_federated::records_in_range");
+
+ sql_query.length(0);
+ sql_query.append("EXPLAIN ");
+ sql_query.append(share->select_query);
+ sql_query.append(" WHERE ");
+ sql_query.append('(');
+ create_where_from_key(&sql_query, &table->key_info[inx], min_key,
MIN_RANGE);
+ sql_query.append(") AND ( ");
+ create_where_from_key(&sql_query, &table->key_info[inx], max_key,
MAX_RANGE);
+ sql_query.append(')');
+
+ DBUG_PRINT("info",("inx %d sql_query %s", inx, sql_query.c_ptr_quick()));
+ if (mysql_real_query(mysql, sql_query.ptr(), sql_query.length()))
+ goto error;
+ sql_query.length(0);
+
+ result= mysql_store_result(mysql);
+ if (! result)
+ goto error;
+
+ if (! mysql_num_rows(result))
+ goto error;
+ if (!(row= mysql_fetch_row(result)))
+ goto error;
+
+ if (! row[8])
+ return_rows=0;
+ else
+ return_rows= (ha_rows) my_strtoll10(row[8], (char**) 0, &error);
+
+error:
+ if (result)
+ mysql_free_result(result);
+
+ DBUG_PRINT("info", ("return_rows (records) %d", return_rows));
+ DBUG_RETURN(return_rows);
+}
/*
If frm_error() is called then we will use this to to find out
what file extentions exist for the storage engine. This is
also used by the default rename_table and delete_table method
in handler.cc.
*/
-static const char *ha_federated_exts[] = {
- NullS
-};
const char **ha_federated::bas_ext() const
{
- return ha_federated_exts;
+ static const char *ext[]=
+ {
+ NullS
+ };
+ return ext;
}
@@ -1019,6 +1213,7 @@
int ha_federated::close(void)
{
+ int retval;
DBUG_ENTER("ha_federated::close");
/* free the result set */
@@ -1031,7 +1226,8 @@
}
/* Disconnect from mysql */
mysql_close(mysql);
- DBUG_RETURN(free_share(share));
+ retval= free_share(share);
+ DBUG_RETURN(retval);
}
@@ -1385,7 +1581,7 @@
}
/*
- 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
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
@@ -1448,6 +1644,10 @@
my_error(ER_QUERY_ON_MASTER, MYF(0), mysql_error(mysql));
DBUG_RETURN(ER_QUERY_ON_MASTER);
}
+ my_ulonglong(deleted)+= mysql->affected_rows;
+ DBUG_PRINT("info",
+ ("rows deleted %d rows deleted for all time %d",
+ int(mysql->affected_rows), deleted));
DBUG_RETURN(0);
}
@@ -1461,12 +1661,12 @@
*/
int ha_federated::index_read(byte *buf, const byte *key,
- uint key_len __attribute__ ((unused)),
- enum ha_rkey_function find_flag
- __attribute__ ((unused)))
+ uint key_len, enum ha_rkey_function find_flag)
{
+ int retval;
DBUG_ENTER("ha_federated::index_read");
- DBUG_RETURN(index_read_idx(buf, active_index, key, key_len, find_flag));
+ retval= index_read_idx(buf, active_index, key, key_len, find_flag);
+ DBUG_RETURN(retval);
}
@@ -1480,20 +1680,19 @@
*/
int ha_federated::index_read_idx(byte *buf, uint index, const byte *key,
- uint key_len __attribute__ ((unused)),
- enum ha_rkey_function find_flag
- __attribute__ ((unused)))
+ uint key_len, enum ha_rkey_function find_flag)
{
+ int retval;
char index_value[IO_SIZE];
char key_value[IO_SIZE];
char test_value[IO_SIZE];
String index_string(index_value, sizeof(index_value), &my_charset_bin);
index_string.length(0);
- uint keylen;
char sql_query_buffer[IO_SIZE];
String sql_query(sql_query_buffer, sizeof(sql_query_buffer), &my_charset_bin);
sql_query.length(0);
+ key_range range;
DBUG_ENTER("ha_federated::index_read_idx");
@@ -1503,8 +1702,10 @@
sql_query.append(share->select_query);
sql_query.append(" WHERE ");
- keylen= strlen((char*) (key));
- create_where_from_key(&index_string, &table->key_info[index], key, keylen);
+ range.key= key;
+ range.length= key_len;
+ range.flag= find_flag;
+ create_where_from_key(&index_string, &table->key_info[index], &range,
NO_RANGE);
sql_query.append(index_string);
DBUG_PRINT("info",
@@ -1533,20 +1734,21 @@
table->status= STATUS_NOT_FOUND;
DBUG_RETURN(HA_ERR_END_OF_FILE);
}
-
if (mysql_errno(mysql))
{
table->status= STATUS_NOT_FOUND;
- DBUG_RETURN(mysql_errno(mysql));
+ retval= mysql_errno(mysql);
+ DBUG_RETURN(retval);
}
- /*
- 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)
- */
+ /*
+ 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;
- DBUG_RETURN(rnd_next(buf));
+ retval= rnd_next(buf);
+ DBUG_RETURN(retval);
}
/* Initialized at each key walk (called multiple times unlike rnd_init()) */
@@ -1560,14 +1762,73 @@
DBUG_RETURN(0);
}
+int ha_federated::read_range_first(const key_range *start_key,
+ const key_range *end_key,
+ bool eq_range, bool sorted)
+{
+ int retval;
+ char sql_query_buffer[IO_SIZE];
+ String sql_query(sql_query_buffer, sizeof(sql_query_buffer), &my_charset_bin);
+
+ DBUG_ENTER("ha_federated::read_range_first");
+ sql_query.length(0);
+
+ sql_query.append(share->select_query);
+ sql_query.append(" WHERE ");
+ sql_query.append('(');
+ create_where_from_key(&sql_query, &table->key_info[active_index], start_key,
MIN_RANGE);
+ sql_query.append(") AND (");
+ create_where_from_key(&sql_query, &table->key_info[active_index], end_key,
MAX_RANGE);
+ sql_query.append(')');
+
+ DBUG_PRINT("info",("active_index %d sql_query %s", active_index,
sql_query.c_ptr_quick()));
+ if (mysql_real_query(mysql, sql_query.ptr(), sql_query.length()))
+ {
+ table->status= STATUS_NOT_FOUND;
+ retval= mysql_errno(mysql);
+ DBUG_RETURN(retval);
+ }
+ sql_query.length(0);
+
+ result= mysql_store_result(mysql);
+
+ if (!result)
+ {
+ table->status= STATUS_NOT_FOUND;
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ }
+ if (mysql_errno(mysql))
+ {
+ table->status= STATUS_NOT_FOUND;
+ retval= mysql_errno(mysql);
+ DBUG_RETURN(retval);
+ }
+ /* This was successful, please let it be known! */
+ table->status=0;
+
+ retval= rnd_next(table->record[0]);
+ DBUG_RETURN(retval);
+}
+
+int ha_federated::read_range_next()
+{
+ int retval;
+ DBUG_ENTER("ha_federated::read_range_next");
+ retval= rnd_next(table->record[0]);
+ DBUG_RETURN(retval);
+}
+
+
/* Used to read forward through the index. */
int ha_federated::index_next(byte *buf)
{
+ int retval;
DBUG_ENTER("ha_federated::index_next");
- DBUG_RETURN(rnd_next(buf));
+ statistic_increment(table->in_use->status_var.ha_read_next_count,
+ &LOCK_status);
+ retval= rnd_next(buf);
+ DBUG_RETURN(retval);
}
-
-
/*
rnd_init() is called when the system wants the storage engine to do a table
scan.
@@ -1587,9 +1848,9 @@
int num_fields, rows;
/*
- This 'scan' flag is incredibly important for this handler to work
- properly, especially with updates containing WHERE clauses using
- indexed columns.
+ The use of the 'scan' flag is incredibly important for this handler
+ to work properly, especially with updates containing WHERE clauses
+ using indexed columns.
When the initial query contains a WHERE clause of the query using an
indexed column, it's index_read_idx that selects the exact record from
@@ -1623,6 +1884,7 @@
scan_flag= scan;
if (scan)
{
+ int retval;
DBUG_PRINT("info", ("share->select_query %s", share->select_query));
if (result)
{
@@ -1640,15 +1902,17 @@
}
result= mysql_store_result(mysql);
- if (mysql_errno(mysql))
- DBUG_RETURN(mysql_errno(mysql));
+ if ((retval= mysql_errno(mysql)))
+ DBUG_RETURN(retval);
}
DBUG_RETURN(0);
}
int ha_federated::rnd_end()
{
+ int retval;
DBUG_ENTER("ha_federated::rnd_end");
+
if (result)
{
DBUG_PRINT("info", ("mysql_free_result address %lx", result));
@@ -1657,7 +1921,8 @@
}
mysql_free_result(result);
- DBUG_RETURN(index_end());
+ retval= index_end();
+ DBUG_RETURN(retval);
}
int ha_federated::index_end(void)
@@ -1679,6 +1944,7 @@
int ha_federated::rnd_next(byte *buf)
{
+ int retval;
MYSQL_ROW row;
DBUG_ENTER("ha_federated::rnd_next");
@@ -1698,7 +1964,8 @@
if (!(row= mysql_fetch_row(result)))
DBUG_RETURN(HA_ERR_END_OF_FILE);
- DBUG_RETURN(convert_row_to_internal_format(buf, row));
+ retval= convert_row_to_internal_format(buf, row);
+ DBUG_RETURN(retval);
}
@@ -1745,17 +2012,27 @@
*/
if (scan_flag)
{
+ int retval;
statistic_increment(table->in_use->status_var.ha_read_rnd_count,
&LOCK_status);
memcpy_fixed(¤t_position, pos, sizeof(MYSQL_ROW_OFFSET)); // pos
/* is not aligned */
result->current_row= 0;
result->data_cursor= current_position;
- DBUG_RETURN(rnd_next(buf));
+ retval= rnd_next(buf);
+ DBUG_RETURN(retval);
}
DBUG_RETURN(0);
}
+/*
+
+ int read_range_first(const key_range *start_key,
+ const key_range *end_key,
+ bool eq_range, bool sorted);
+ int read_range_next();
+
+*/
/*
::info() is used to return information to the optimizer.
@@ -1801,11 +2078,80 @@
*/
/* FIX: later version provide better information to the optimizer */
+/* This is where we put 'SHOW TABLE STATUS LIKE 'tablename' to work */
void ha_federated::info(uint flag)
{
+ int error;
+ char status_buf[IO_SIZE];
+ char escaped_table_base_name[IO_SIZE];
+ uint error_code=0;
+ MYSQL_RES *result=0;
+ MYSQL_ROW row;
+ String status_query_string(status_buf, sizeof(status_buf), &my_charset_bin);
+
DBUG_ENTER("ha_federated::info");
- records= 10000; // fix later
+ /* we want not to show table status if not needed to do so */
+ if (flag & (HA_STATUS_VARIABLE | HA_STATUS_CONST))
+ {
+ status_query_string.length(0);
+ status_query_string.append("SHOW TABLE STATUS LIKE '");
+
+ escape_string_for_mysql(&my_charset_bin, (char *)escaped_table_base_name,
+ sizeof(escaped_table_base_name),
+ share->table_base_name,
+ share->table_base_name_length);
+ status_query_string.append(escaped_table_base_name);
+ status_query_string.append("'");
+
+ error_code= ER_QUERY_ON_MASTER;
+ if (mysql_real_query(mysql, status_query_string.ptr(), status_query_string.length()))
+ goto error;
+ status_query_string.length(0);
+
+ result= mysql_store_result(mysql);
+ if (! result)
+ goto error;
+
+ if (! mysql_num_rows(result))
+ goto error;
+
+ if (!(row= mysql_fetch_row(result)))
+ goto error;
+
+ if (flag & HA_STATUS_VARIABLE | HA_STATUS_CONST)
+ {
+ /*
+ deleted is set in ha_federated::info
+ */
+ /*
+ need to figure out what this means as far as federated is concerned,
+ since we don't have a "file"
+
+ data_file_length = ?
+ index_file_length = ?
+ delete_length = ?
+ */
+ if (row[4] != NULL)
+ records= (ha_rows) my_strtoll10(row[4], (char**) 0, &error);
+ if (row[5] != NULL)
+ mean_rec_length= (ha_rows) my_strtoll10(row[5], (char**) 0, &error);
+ if (row[12] != NULL)
+ update_time= (ha_rows) my_strtoll10(row[12], (char**) 0, &error);
+ if (row[13] != NULL)
+ check_time= (ha_rows) my_strtoll10(row[13], (char**) 0, &error);
+ }
+ if (flag & HA_STATUS_CONST)
+ {
+ TABLE_SHARE *share= table->s;
+ block_size= 4096;
+ }
+ }
+
+error:
+ if (result)
+ mysql_free_result(result);
+
DBUG_VOID_RETURN;
}
@@ -1840,6 +2186,10 @@
my_error(ER_QUERY_ON_MASTER, MYF(0), mysql_error(mysql));
DBUG_RETURN(ER_QUERY_ON_MASTER);
}
+ /*
+ TRUNCATE won't return anything in mysql_affected_rows
+ */
+ deleted+= records;
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@@ -1889,7 +2239,7 @@
*/
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
- lock_type <= TL_WRITE) && !thd->in_lock_tables &&
!thd->tablespace_op)
+ lock_type <= TL_WRITE) && !thd->in_lock_tables)
lock_type= TL_WRITE_ALLOW_WRITE;
/*
@@ -1933,10 +2283,10 @@
my_error(connection_error, MYF(0), name, 1);
goto error;
}
-
+
my_free((gptr) tmp.scheme, MYF(0));
DBUG_RETURN(0);
-
+
error:
DBUG_PRINT("info", ("errors, returning %d", ER_CANT_CREATE_TABLE));
my_free((gptr) tmp.scheme, MYF(0));
--- 1.12/sql/ha_federated.h Fri Mar 4 22:33:14 2005
+++ 1.13/sql/ha_federated.h Tue Jun 7 23:44:40 2005
@@ -69,6 +69,18 @@
uint ref_length;
uint fetch_num; // stores the fetch num
MYSQL_ROW_OFFSET current_position; // Current position used by ::position()
+ /*
+ the range->flag from records_in_range is set to HA_READ_KEY_EXACT
+ for a query of 'SELECT * FROM t1 WHERE id >= 5', when it should be
+ HA_READ_KEY_OR_NEXT, so we need a range value to tell create_where_from_key to
+ append " >= " the the EXPLAIN query records_in_range will call to get the correct
value
+ of numbers
+ */
+ enum range_operation {
+ NO_RANGE, /* WHERE id = .. */
+ MIN_RANGE,
+ MAX_RANGE
+ };
private:
/*
@@ -77,11 +89,11 @@
*/
uint convert_row_to_internal_format(byte *buf, MYSQL_ROW row);
bool create_where_from_key(String *to, KEY *key_info,
- const byte *key, uint key_length);
+ const key_range *range, int range_type);
public:
ha_federated(TABLE *table): handler(table),
- mysql(0), result(0), scan_flag(0),
+ mysql(0), result(0), scan_flag(0),
ref_length(sizeof(MYSQL_ROW_OFFSET)), current_position(0)
{
}
@@ -105,9 +117,9 @@
*/
ulong table_flags() const
{
- return (HA_TABLE_SCAN_ON_INDEX | HA_NOT_EXACT_COUNT |
- HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED |
- HA_AUTO_PART_KEY | HA_CAN_INDEX_BLOBS);
+ return (HA_NOT_EXACT_COUNT |
+ HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED | HA_REC_NOT_IN_SEQ |
+ HA_AUTO_PART_KEY | HA_CAN_INDEX_BLOBS| HA_NO_PREFIX_CHAR_KEYS);
}
/*
This is a bitmap of flags that says how the storage engine
@@ -121,8 +133,9 @@
*/
ulong index_flags(uint inx, uint part, bool all_parts) const
{
- return (HA_READ_NEXT);
- // return (HA_READ_NEXT | HA_ONLY_WHOLE_INDEX);
+ return (HA_READ_NEXT | HA_READ_RANGE | HA_READ_AFTER_KEY);
+ //return (HA_READ_NEXT | HA_READ_RANGE); return (HA_READ_NEXT
+ //| HA_ONLY_WHOLE_INDEX);
}
uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
uint max_supported_keys() const { return MAX_KEY; }
@@ -130,18 +143,27 @@
uint max_supported_key_length() const { return 1024; }
/*
Called in test_quick_select to determine if indexes should be used.
+ Normally, we need to know number of blocks . For federated we need to
+ know number of blocks on remote side, and number of packets and blocks
+ on the network side (?)
+ Talk to Kostja about this - how to get the
+ number of rows * ...
+ disk scan time on other side (block size, size of the row) + network time ...
*/
- virtual double scan_time()
+ double scan_time()
{
- DBUG_PRINT("ha_federated::scan_time",
- ("rows %d", records)); return (double)(records*2);
+ DBUG_PRINT("info",
+ ("records %d", records)); return (double)(records*1000);
}
/*
The next method will never be called if you do not implement indexes.
*/
- virtual double read_time(uint index, uint ranges, ha_rows rows)
- { return (double) rows / 20.0+1; }
+ double read_time(uint index, uint ranges, ha_rows rows)
+ {
+ return (double) rows / 20.0+1;
+ }
+ const key_map *keys_to_use_for_scanning() { return &key_map_full; }
/*
Everything below are methods that we implment in ha_federated.cc.
@@ -161,6 +183,10 @@
uint key_len, enum ha_rkey_function find_flag);
int index_next(byte * buf);
int index_end();
+ int read_range_first(const key_range *start_key,
+ const key_range *end_key,
+ bool eq_range, bool sorted);
+ int read_range_next();
/*
unlike index_init(), rnd_init() can be called two times
without rnd_end() in between (it only makes sense if scan=1).
@@ -179,6 +205,8 @@
int delete_all_rows(void);
int create(const char *name, TABLE *form,
HA_CREATE_INFO *create_info); //required
+ ha_rows records_in_range(uint inx, key_range *min_key,
+ key_range *max_key);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type); //required
| Thread |
|---|
| • bk commit into 5.0 tree (patg:1.1935) | Patrick Galbraith | 7 Jun |